Excel y documentos de trabajo

Detectar filas duplicadas en Excel y separarlas para revisarlas

Busca filas con las cuatro columnas idénticas y reúnelas en un nuevo archivo de Excel junto con sus números de fila originales. Revisa cada grupo de duplicados incluyendo su primera aparición.

Ver el índice

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. 한국어

Para quién esPersonal administrativo que revisa entradas duplicadas después de reunir datos de Excel

Preparación
  • Prepara Python 3.12 y una terminal. Comprueba la versión con python --version.
  • Extrae todo el ZIP descargado y abre la terminal en la carpeta que contiene example.py.
  • Ejecuta primero con los datos de práctica incluidos y compara el resultado con el original.
  • Se usan la hoja Orders de orders.xlsx y openpyxl. No necesitas la aplicación Microsoft Excel para ejecutar el código.

01Definir qué se considera un duplicado

En este ejemplo, una fila es duplicada cuando coinciden los cuatro valores: order_id, customer, item y quantity. Coincidir solo en el número de pedido no basta. Tampoco se cambian automáticamente los espacios ni las mayúsculas y minúsculas de las cadenas.

Antes de eliminar duplicados, se reúnen en la hoja Duplicates todas las filas con el mismo contenido, incluida la primera aparición. Las filas que aparecen una sola vez se guardan en Unique, para poder revisar las 8 filas sin omisiones.

02Revisar la estructura del archivo de entrada

La hoja de orders.xlsx debe llamarse Orders, y los nombres y el orden de las columnas de la primera fila deben ser los indicados abajo. Añadir columnas también provoca un error de cabecera. En lugar de sustituir directamente el ejemplo por un archivo de trabajo, crea uno de práctica copiando las cuatro columnas necesarias.

ColumnaFunciónEjemplo
order_idNúmero de pedido como cadenaO-1001
customerNombre del cliente como cadenaAlpha
itemArtículo como cadenaSensor
quantityCantidad como entero positivo2

Se omiten las filas completamente vacías. Si falta algún valor o hay una fórmula, el programa se detiene. El número de pedido, el nombre del cliente y el artículo deben ser cadenas no vacías; los números de pedido introducidos como valores numéricos no se convierten automáticamente en texto.

03Preparar los archivos y ejecutar

  1. Extrae el ZIP y comprueba que el archivo de entrada indicado en README.txt esté en la misma ubicación que example.py. No ejecutes directamente dentro del ZIP.
  2. Ejecuta los siguientes comandos uno por uno desde la carpeta que contiene example.py. Si en Windows no tienes el comando python pero sí py, sustituye python por py -3.12 en cada comando.
  3. Cuando aparezca el mensaje de finalización, abre la nueva carpeta outputs. Si ya existe outputs, guárdala primero con otro nombre y vuelve a ejecutar.
bash
python --version
python -m pip install -r requirements.txt
python example.py

La instalación requiere conexión a Internet. BASE establece las rutas de entrada y salida a partir de la ubicación de example.py, no de la ubicación actual de la terminal.

04Código completo y orden de procesamiento

Se abre el original en modo de solo lectura con load_workbook y se cuenta cada aparición de una fila con Counter. Los números de fila del Excel original se registran mediante enumerate con start=2. Los resultados se guardan en un nuevo Workbook, por lo que no se vuelve a guardar el archivo original.

example.py
"""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

05Resultados que se generan al ejecutar

Se crean las hojas Duplicates y Unique en outputs/duplicate_review.xlsx. source_row es el número de fila del Excel original, y occurrences indica cuántas veces aparece el mismo contenido en toda la entrada.

ConceptoResultado con los datos incluidos
Filas de datos de entrada8
Grupos de duplicados2
Filas de Duplicates4 (filas originales 2, 3, 5, 8)
Filas de Unique4 (filas originales 4, 6, 7, 9)

Las 4 filas de Duplicates no significan que deban eliminarse 4 filas. Si se conserva una por grupo, hay 2 filas adicionales, pero debes revisar el original antes de decidir cuáles mantener.

06Comprobar el resultado por tu cuenta

  1. Comprueba en Duplicates que las filas con source_row 2 y 5 correspondan a O-1001 y que ambas tengan occurrences igual a 2.
  2. Comprueba que las filas con source_row 3 y 8 correspondan a O-1002.
  3. Suma las 4 filas de Duplicates y las 4 de Unique, y comprueba que coincidan con las 8 filas de entrada.
  4. Vuelve a abrir orders.xlsx y comprueba que las 8 filas de datos sigan intactas.

07Errores habituales y soluciones

Mensaje o síntomaQué comprobar
Orders sheet is missingAsegúrate de que la hoja original se llame Orders.
Expected headersComprueba los nombres, el orden y las columnas adicionales.
missing value / formulas are not supportedRevisa la fila original indicada y prepara valores en lugar de fórmulas.
quantity must be a positive integerIntroduce la cantidad como un entero de 1 o más.
outputs already existsGuarda la carpeta de resultados anterior con otro nombre.
ModuleNotFoundErrorInstala los paquetes de requirements.txt usando el mismo python con el que ejecutas el código.

08Qué no cubre este ejemplo

  • No se copian los formatos, gráficos, macros, conexiones ni el estado de las filas ocultas. El resultado incluye solo los valores necesarios para la revisión y un formato básico.
  • No se eliminan espacios, no se unifican mayúsculas y minúsculas ni se detectan cadenas parecidas. Si cambia la definición de duplicado, debes diseñar por separado los criterios de comparación.
  • Como se carga todo el archivo en memoria, no se garantiza el rendimiento con grandes volúmenes. No se admiten archivos cifrados ni dañados.
  • Modificar valores en el archivo de resultados no recalcula automáticamente el original ni los resultados. Para obtener un nuevo resultado, modifica una copia del original y vuelve a ejecutar.

Registro de ejecución y verificación

Windows 11 (10.0.26200), CPython 3.12.14 (64 bits). openpyxl 3.1.5, Matplotlib 3.10.8. Las versiones de las bibliotecas usadas en cada ejemplo están fijadas en requirements.txt.

  • Verificados los recuentos de filas, los números de fila originales y las frecuencias de duplicación con datos válidos
  • SHA-256 del original sin cambios y rechazo de sobrescritura al volver a ejecutar
  • Comprobados errores de cabeceras distintas, valores ausentes, fórmulas y cantidades incorrectas
Límites de la verificación
  • No se han verificado la visualización en la aplicación de escritorio de Excel ni el rendimiento con grandes volúmenes.

Criterios de redacción y verificación de todo el sitio

Archivos de ejemplo para ejecutar

Incluye código, datos de entrada e instrucciones de ejecución. Extrae el ZIP y lee primero README.txt.

Descargar ZIP de ejemplo

El 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.

Fuentes de referencia

Las explicaciones y los ejemplos son de elaboración propia. Puedes consultar los comportamientos y conceptos relacionados en las siguientes fuentes oficiales.