Convertir registros de trabajo en una tabla y gráfico de resumen mensual
Valida las fechas y las horas de trabajo de un CSV y después guarda los recuentos mensuales de registros y las horas totales como un CSV y un gráfico de barras.
Encuentra filas con coincidencia exacta en las cuatro columnas y recopílalas en un nuevo archivo de Excel junto con sus números de fila originales. Revisa cada grupo de duplicados, incluida su primera aparición.
La traducción se ha realizado con IA. Comprueba el código, las unidades y los valores junto con el original. La revisión por hablantes nativos de cada idioma aún no se ha completado. English
Para quién esPersonal de oficina que comprueba entradas duplicadas después de combinar datos de Excel
En este ejemplo, las filas solo son duplicadas cuando coinciden los cuatro valores: order_id, customer, item y quantity. Que coincidan únicamente los números de pedido no convierte las filas en duplicados. Los espacios y el uso de mayúsculas y minúsculas en las cadenas no se modifican automáticamente.
Antes de eliminar nada, recopila en la hoja Duplicates todas las filas con contenidos coincidentes, incluida la primera aparición. Las filas que aparecen una sola vez van a la hoja Unique, de modo que puedes revisar las 8 filas de entrada sin omisiones.
La hoja de orders.xlsx debe llamarse Orders y su primera fila debe contener los nombres de columna y el orden que se muestran a continuación. Añadir columnas también provoca un error de encabezado. En lugar de sustituir inmediatamente el ejemplo por un archivo de trabajo real, crea primero un archivo de práctica copiando únicamente las cuatro columnas requeridas.
| Columna | Propósito | Ejemplo |
|---|---|---|
| order_id | Número de pedido como texto | O-1001 |
| customer | Nombre del cliente como texto | Alpha |
| item | Artículo como texto | Sensor |
| quantity | Cantidad como entero positivo | 2 |
Las filas completamente vacías se omiten. El script se detiene si solo faltan algunos valores o si una fila contiene una fórmula. Los números de pedido, los nombres de cliente y los artículos deben ser cadenas no vacías. Los números de pedido numéricos no se convierten automáticamente; prepáralos como texto en el archivo de entrada.
python --version
python -m pip install -r requirements.txt
python example.pyLa instalación requiere conexión a internet. BASE en el código establece las rutas de entrada y salida relativas a example.py, no a la carpeta actual de la terminal.
El código abre el original con load_workbook en modo de solo lectura y utiliza Counter para contar cuántas veces aparece cada fila. Realiza el seguimiento de los números de fila originales de Excel con enumerate y start=2. Los resultados se guardan en un Workbook nuevo, por lo que el original no vuelve a guardarse.
"""Find repeated business rows. Keep the source workbook unchanged."""
from collections import Counter
from pathlib import Path
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, PatternFill
BASE = Path(__file__).resolve().parent
HEADERS = ("order_id", "customer", "item", "quantity")
def main():
destination = BASE / "outputs"
if destination.exists():
raise ValueError("outputs already exists; rename it before running again.")
source = load_workbook(BASE / "orders.xlsx", read_only=True, data_only=False)
try:
if "Orders" not in source.sheetnames:
raise ValueError("Orders sheet is missing.")
worksheet = source["Orders"]
rows = list(worksheet.iter_rows(values_only=True))
if not rows or tuple(rows[0]) != HEADERS:
raise ValueError(f"Expected headers: {HEADERS}")
records = []
for row_number, row in enumerate(rows[1:], start=2):
if all(value is None for value in row):
continue
if any(value is None for value in row):
raise ValueError(f"Row {row_number}: missing value.")
if any(isinstance(value, str) and value.startswith("=") for value in row):
raise ValueError(f"Row {row_number}: formulas are not supported.")
if not all(isinstance(value, str) and value.strip() for value in row[:3]):
raise ValueError(f"Row {row_number}: first three fields must be text.")
if type(row[3]) is not int or row[3] <= 0:
raise ValueError(f"Row {row_number}: quantity must be a positive integer.")
records.append((row_number, tuple(row)))
if not records:
raise ValueError("No data rows were found.")
finally:
source.close()
counts = Counter(row for _, row in records)
repeated = [(number, row) for number, row in records if counts[row] > 1]
unique = [(number, row) for number, row in records if counts[row] == 1]
book = Workbook()
book.remove(book.active)
for name, selected in (("Duplicates", repeated), ("Unique", unique)):
sheet = book.create_sheet(name)
sheet.append(("source_row", *HEADERS, "occurrences"))
for number, row in selected:
sheet.append((number, *row, counts[row]))
sheet.freeze_panes = "A2"
sheet.auto_filter.ref = sheet.dimensions
sheet.sheet_view.showGridLines = False
for cell in sheet[1]:
cell.font = Font(name="Arial", bold=True, color="FFFFFF")
cell.fill = PatternFill("solid", fgColor="243B53")
for column, width in zip("ABCDEF", (14, 16, 18, 20, 14, 16)):
sheet.column_dimensions[column].width = width
destination.mkdir(exist_ok=False)
book.save(destination / "duplicate_review.xlsx")
book.close()
groups = sum(count > 1 for count in counts.values())
print(f"Input rows: {len(records)}; duplicate groups: {groups}")
print(f"Duplicate rows: {len(repeated)}; unique rows: {len(unique)}")
print("Created outputs/duplicate_review.xlsx (source unchanged).")
if __name__ == "__main__":
try:
main()
except (OSError, ValueError) as error:
raise SystemExit(f"Stopped: {error}") from error
El script crea dos hojas, Duplicates y Unique, en outputs/duplicate_review.xlsx. source_row es el número de fila de Excel en el original y occurrences es el número de veces que el mismo contenido aparece en toda la entrada.
| Elemento | Resultado para los datos incluidos |
|---|---|
| Filas de datos de entrada | 8 |
| Grupos de duplicados | 2 |
| Filas de Duplicates | 4 (filas originales 2, 3, 5, 8) |
| Filas de Unique | 4 (filas originales 4, 6, 7, 9) |
Las 4 filas de Duplicates no significan que deban eliminarse 4 filas. Si conservas una fila de cada grupo, hay 2 entradas adicionales. Decide cuál conservar solo después de revisar los originales.
| Mensaje o síntoma | Qué comprobar |
|---|---|
| Orders sheet is missing | Establece el nombre de la hoja original como Orders. |
| Expected headers | Comprueba los nombres de las columnas, su orden y cualquier columna adicional. |
| missing value / formulas are not supported | Comprueba la fila original indicada y proporciona valores en lugar de fórmulas. |
| quantity must be a positive integer | Introduce una cantidad que sea un entero de 1 o más. |
| outputs already exists | Cambia el nombre de la carpeta de resultados anterior para conservarla. |
| ModuleNotFoundError | Instala los paquetes de requirements.txt usando el mismo python que utilizas para ejecutar el ejemplo. |
Windows 11 (10.0.26200), CPython 3.12.14 (64-bit). openpyxl 3.1.5, Matplotlib 3.10.8. Las bibliotecas utilizadas por cada ejemplo están fijadas en requirements.txt.
Incluye código, datos de entrada e instrucciones de ejecución. Extrae el ZIP y lee primero README.txt.
Descargar ZIP de ejemploEl código de ejemplo, los nombres de archivo y las claves de entrada se mantienen como en el original. Consulta también los comandos y los pasos de comprobación del texto traducido.
Material de práctica original · Guarda los archivos originales por separado antes de ejecutarlo.
Las explicaciones y los ejemplos son de elaboración propia. Puedes consultar los comportamientos y conceptos relacionados en las siguientes fuentes oficiales.