Cuando comparas dos archivos Word y la única diferencia es cómo se numeran las listas, por ejemplo cláusulas que eran 1. y 2. ahora son a. y b., o una lista numerada se ha convertido en una con viñetas, Aspose.Words no informa diferencias por defecto. Este tutorial te muestra cómo detectar cambios de numeración al comparar archivos Word en Python. También explica cómo revisar, aceptar o rechazar los cambios que encuentra.

Puntos clave

  • Por defecto, un cambio en el estilo de numeración o en el carácter de viñeta de una lista no genera revisiones al comparar archivos Word.
  • Configurar options.advanced_options.compare_list_definitions = True informa cada párrafo de lista afectado como una revisión FORMAT_CHANGE.
  • Los cambios de texto dentro de los elementos de la lista se informan de cualquier manera. La opción solo añade cambios de numeración y viñetas por encima.
  • ignore_formatting=True oculta los cambios de numeración incluso cuando la opción está activada.

Por qué los cambios de numeración no se muestran por defecto

La numeración y los viñetas en Word provienen de una definición de lista. Describe cómo se ve cada nivel de la lista: el estilo de número (1., a., i.), el carácter de viñeta y el formato relacionado. Cuando comparas documentos, Aspose.Words sigue a Microsoft Word por defecto y omite las definiciones de lista en la comparación. Por lo tanto, si solo cambió la numeración, la comparación no muestra nada que informar.

La opción compare_list_definitions no tiene equivalente en Word. Indica a Aspose.Words que incluya definiciones de lista en la comparación. Aquí está lo que vimos al comparar listas de dos elementos en la versión 26.9:

Lista originalLista editadaOpción desactivadaOpción activada
Numerado 1. 2.Con viñetas0 revisiones2 FORMAT_CHANGE
Numerado 1. 2.Con letras a. b.0 revisiones2 FORMAT_CHANGE
Numerado, “Elemento 2”Con viñetas, “Elemento dos”2 (DELETION, INSERTION)4 (agrega 2 FORMAT_CHANGE)
NumeradoLista numerada idéntica0 revisiones0 revisiones

La última fila importa en la práctica. Activar la opción no crea revisiones extra para listas que son iguales en ambos archivos.

Requisitos previos

Necesitas Aspose.Words for Python via .NET 26.9 o una versión posterior. Instálalo o actualízalo desde PyPI:

pip install --upgrade "aspose-words>=26.9"

Sin una licencia, Aspose.Words se ejecuta en modo de evaluación con limitaciones. Una licencia temporal las elimina mientras realiza pruebas.

Ver la diferencia: cambios de numeración con y sin la opción

El siguiente script crea dos documentos que contienen los mismos dos elementos. El primero usa una lista numerada y el segundo usa una lista con viñetas. Los compara dos veces, una vez con la opción desactivada y otra vez con ella activada, para que puedas ver exactamente qué cambia la opción.

import datetime
import aspose.words as aw

def build_list_document(bulleted: bool) -> aw.Document:
    """Create a two-item list, either numbered or bulleted."""
    doc = aw.Document()
    builder = aw.DocumentBuilder(doc=doc)
    if bulleted:
        builder.list_format.apply_bullet_default()
    else:
        builder.list_format.apply_number_default()
    builder.writeln("Item 1")
    builder.writeln("Item 2")
    builder.list_format.remove_numbers()
    return doc

def compare_lists(compare_list_definitions: bool) -> aw.Document:
    original = build_list_document(bulleted=False)
    edited = build_list_document(bulleted=True)

options = aw.comparing.CompareOptions()
    options.advanced_options.compare_list_definitions = compare_list_definitions

# compare() writes revisions into `original`; it returns nothing.
    original.compare(
        document=edited,
        author="Reviewer",
        date_time=datetime.datetime.now(),
        options=options,
    )
    return original

for flag in (False, True):
    result = compare_lists(flag)
    print(f"compare_list_definitions={flag}: {result.revisions.count} revision(s)")
    for revision in result.revisions:
        revision_type = aw.RevisionType(revision.revision_type).name
        text = revision.parent_node.get_text().strip()
        print(f"  {revision_type}: {text}")

result.save("compared-lists.docx")

Al ejecutar el script se imprime:

compare_list_definitions=False: 0 revision(s)
compare_list_definitions=True: 2 revision(s)
  FORMAT_CHANGE: Item 1
  FORMAT_CHANGE: Item 2

Cómo funciona el código

  • build_list_document usa DocumentBuilder.list_format para iniciar una lista numerada o con viñetas predeterminada, escribe dos elementos y luego llama a remove_numbers() para que los párrafos posteriores no formen parte de la lista.
  • CompareOptions.advanced_options expone compare_list_definitions, que por defecto es False.
  • original.compare(...) compara original con edited y registra las diferencias como revisiones dentro de original. El método devuelve None, por lo que siempre debe leer los resultados del documento sobre el que lo llamó.
  • El parent_node de cada revisión es el párrafo de la lista cuyo formato cambió. revision_type es RevisionType.FORMAT_CHANGE para cambios de numeración y viñetas.

Detectar cambios de numeración entre dos archivos Word

En un flujo de trabajo real, comparas dos archivos existentes, como dos versiones de un contrato. Esas comparaciones suelen contener también otras revisiones, por lo que el script a continuación conserva solo los cambios de formato que se encuentran en los párrafos de lista.

import datetime
import aspose.words as aw

original = aw.Document("contract-v1.docx")
edited = aw.Document("contract-v2.docx")

options = aw.comparing.CompareOptions()
options.advanced_options.compare_list_definitions = True

original.compare(edited, "Reviewer", datetime.datetime.now(), options)

# Keep only formatting revisions that sit on list paragraphs.
list_changes = [
    rev for rev in original.revisions
    if rev.revision_type == aw.RevisionType.FORMAT_CHANGE
    and rev.parent_node is not None
    and rev.parent_node.node_type == aw.NodeType.PARAGRAPH
    and rev.parent_node.as_paragraph().list_format.is_list_item
]

print(f"Total revisions: {original.revisions.count}")
print(f"Formatting changes on list paragraphs: {len(list_changes)}")
for rev in list_changes:
    print(f"  {rev.parent_node.get_text().strip()}")

original.save("contract-compared.docx")

En nuestra prueba, la versión 2 del contrato cambió una lista numerada a viñetas y también puso en negrita una frase no relacionada. El resultado fue:

Total revisions: 5
Formatting changes on list paragraphs: 2
  Invoices are due in 30 days.
  Late fees apply after 45 days.

El filtro selecciona los dos elementos de la lista y omite el cambio en negrita, porque esa revisión se aplica al texto en lugar de a un párrafo de lista. Ten en cuenta que coincide con cualquier cambio de formato a nivel de párrafo en un elemento de lista, como una sangría modificada, no solo con la numeración. Verifica el documento guardado si necesitas distinguirlos.

Revisar, aceptar o rechazar cambios de numeración

Dado que los cambios de numeración son revisiones de formato ordinarias, los manejas de la misma manera que cualquier otra revisión:

  • revisions.accept_all() aplica el formato de lista editado. En el primer ejemplo, ambos elementos se convierten en viñetas.
  • revisions.reject_all() mantiene el formato original, por lo que los elementos permanecen numerados 1. y 2..
  • Guardar el documento escribe las revisiones como cambios controlados, de modo que los revisores pueden abrir el archivo en Microsoft Word y decidir sobre cada cambio ellos mismos.

También puedes llamar a accept() o reject() en objetos Revision individuales, por ejemplo solo en los elementos de la lista list_changes de la sección anterior.

Cuándo detectar cambios de numeración

Active la opción cuando la numeración de una lista tenga significado para sus revisores. Los documentos legales y de políticas son un caso común: renumerar cláusulas de 1. a (a) cambia la forma en que otros documentos se refieren a ellas, por lo que un revisor necesita verlo. También es útil cuando migra documentos entre sistemas y desea confirmar que la numeración de la lista sobrevivió al traslado sin cambios.

Desactívalo cuando solo te importe la redacción. Las revisiones de contenido, las verificaciones de traducción y los diffs a nivel de texto son más fáciles de leer sin que las revisiones de formato se mezclen.

Cosas a Tener en Cuenta

  • ignore_formatting anula la opción. Si estableces options.ignore_formatting = True, los cambios de numeración no se informan, incluso con compare_list_definitions = True.
  • Los archivos no deben contener revisiones antes de compararlos. Si alguno de los documentos ya tiene cambios controlados, compare genera un RuntimeError indicando que los documentos comparados no deben tener revisiones. Acepta o rechaza las revisiones existentes primero. Esto también significa que no puedes ejecutar una segunda comparación en un documento que ya contiene los resultados de la primera; vuelve a cargar los archivos cada vez.
  • Otras revisiones siguen apareciendo. El texto insertado o eliminado en un elemento de lista se informa tanto si la opción está activada como desactivada, así que verifica revision_type si necesitas separar los cambios de numeración de los cambios de redacción.

Próximos pasos

El artículo Comparar documentos en la documentación de Aspose.Words for Python cubre las demás configuraciones de comparación, incluyendo granularidad, el objetivo de la comparación y las opciones de ignorar.

Preguntas frecuentes

  1. ¿Por qué Aspose.Words no detecta los cambios de numeración al comparar archivos Word? Por defecto, Aspose.Words sigue a Microsoft Word y excluye las definiciones de lista, como el estilo de numeración o el carácter de viñeta, de la comparación. Una lista que cambia de números a viñetas no genera revisiones a menos que habilite compare_list_definitions.

  2. ¿Cómo detecto cambios de numeración en Python? Cree CompareOptions, establezca options.advanced_options.compare_list_definitions en True y pase las opciones a Document.compare. Cada párrafo de lista cuyo número o viñeta haya cambiado recibe una revisión FORMAT_CHANGE.

  3. ¿Qué tipo de revisión crea un cambio de numeración? Cada párrafo de lista afectado recibe una revisión del tipo RevisionType.FORMAT_CHANGE. Aceptarla aplica el formato de lista del archivo editado, y rechazarla mantiene el original.

  4. ¿Funciona la opción junto con ignore_formatting? No. Cuando CompareOptions.ignore_formatting es True, los cambios de numeración no se informan, incluso si compare_list_definitions es True.

  5. ¿Qué devuelve Document.compare? Nada. Escribe las diferencias como revisiones en el documento sobre el que lo llamas, por lo que las lees de la colección revisions de ese documento.

  6. ¿Qué versión de Aspose.Words for Python agregó esta opción? La propiedad compare_list_definitions de AdvancedCompareOptions se agregó en Aspose.Words for Python via .NET 26.9.

Obtenga una Licencia Gratuita y Soporte