Excel y documentos de trabajo

Encontrar filas duplicadas en Excel y separarlas para revisión

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.

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

Para quién esPersonal de oficina que comprueba entradas duplicadas después de combinar datos de Excel

Preparación
  • Ten preparados Python 3.12 y una terminal. Comprueba la versión con python --version.
  • Extrae por completo el ZIP descargado y abre una terminal en la carpeta que contiene example.py.
  • Empieza con los datos de práctica incluidos y después compara los resultados con los archivos originales.
  • Este ejemplo utiliza la hoja Orders de orders.xlsx y openpyxl. No es necesario tener instalada la aplicación Microsoft Excel para ejecutar el código.

01Definir qué se considera un duplicado

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.

02Inspeccionar la estructura del archivo de entrada

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.

ColumnaPropósitoEjemplo
order_idNúmero de pedido como textoO-1001
customerNombre del cliente como textoAlpha
itemArtículo como textoSensor
quantityCantidad como entero positivo2

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.

03Preparar los archivos y ejecutar el ejemplo

  1. Extrae el ZIP y comprueba que el archivo de entrada indicado en README.txt esté en la misma carpeta que example.py. No ejecutes el ejemplo desde dentro del archivo ZIP.
  2. Ejecuta los comandos siguientes, una línea cada vez, en la carpeta que contiene example.py. En Windows, si python no está disponible pero sí py, sustituye python en cada comando por py -3.12.
  3. Cuando aparezca el mensaje de finalización, abre la nueva carpeta outputs. Si outputs ya existe, cámbiale primero el nombre para conservar los resultados anteriores y después vuelve a ejecutar el ejemplo.
bash
python --version
python -m pip install -r requirements.txt
python example.py

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

04Código completo y orden de procesamiento

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.

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 creados por el script

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.

ElementoResultado para 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 conservas una fila de cada grupo, hay 2 entradas adicionales. Decide cuál conservar solo después de revisar los originales.

06Comprobar los resultados por tu cuenta

  1. En Duplicates, comprueba que source_row 2 y 5 tengan ambos O-1001 y occurrences de 2.
  2. Comprueba que source_row 3 y 8 tengan ambos O-1002.
  3. Suma las 4 filas de Duplicates y las 4 filas 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 permanezcan sin cambios.

07Errores comunes y cómo corregirlos

Mensaje o síntomaQué comprobar
Orders sheet is missingEstablece el nombre de la hoja original como Orders.
Expected headersComprueba los nombres de las columnas, su orden y cualquier columna adicional.
missing value / formulas are not supportedComprueba la fila original indicada y proporciona valores en lugar de fórmulas.
quantity must be a positive integerIntroduce una cantidad que sea un entero de 1 o más.
outputs already existsCambia el nombre de la carpeta de resultados anterior para conservarla.
ModuleNotFoundErrorInstala los paquetes de requirements.txt usando el mismo python que utilizas para ejecutar el ejemplo.

08Lo que este ejemplo no cubre

  • No copia formatos, gráficos, macros, conexiones ni estados de filas ocultas. El resultado contiene únicamente los valores necesarios para la revisión y un formato básico.
  • No elimina espacios, no normaliza mayúsculas y minúsculas ni detecta cadenas similares. Si cambia tu definición de duplicado, diseña criterios de comparación separados.
  • Recopila todo el archivo en memoria, por lo que no garantiza el rendimiento con archivos grandes. No admite archivos cifrados o dañados.
  • Editar valores en el archivo de resultados no recalcula automáticamente el original ni los resultados. Para obtener resultados nuevos, edita una copia del original y vuelve a ejecutar el script.

Registro de ejecución y verificación

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.

  • Se verificaron los recuentos de filas, los números de fila originales y los recuentos de apariciones para los datos válidos
  • Se confirmó que el hash SHA-256 del archivo original no cambió y que se rechazó la sobrescritura en una ejecución repetida
  • Se comprobaron los errores de encabezados no coincidentes, valores ausentes, fórmulas y cantidades no válidas
Límites de la verificación
  • No se verificaron la visualización en la aplicación de escritorio de Excel ni el rendimiento con archivos grandes.

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.