When you compare two Word files and the only difference is how a list is numbered, say clauses that were 1. and 2. are now a. and b., or a numbered list has become a bulleted one, Aspose.Words reports no differences by default. This tutorial shows you how to detect numbering changes when comparing Word files in Python. It also explains how to review, accept, or reject the changes it finds.

Key Takeaways

  • By default, a change to a list’s numbering style or bullet character produces no revisions when you compare Word files.
  • Setting options.advanced_options.compare_list_definitions = True reports each affected list paragraph as a FORMAT_CHANGE revision.
  • Text changes inside list items are reported either way. The option only adds numbering and bullet changes on top.
  • ignore_formatting=True hides numbering changes even when the option is on.

Why Numbering Changes Don’t Show Up by Default

Numbering and bullets in Word come from a list definition. It describes how each list level looks: the number style (1., a., i.), the bullet character, and related formatting. When you compare documents, Aspose.Words follows Microsoft Word by default and leaves list definitions out of the comparison. So if only the numbering changed, the comparison sees nothing to report.

The compare_list_definitions option has no equivalent in Word. It tells Aspose.Words to include list definitions in the comparison. Here is what we saw when comparing two-item lists in version 26.9:

Original listEdited listOption offOption on
Numbered 1. 2.Bulleted0 revisions2 FORMAT_CHANGE
Numbered 1. 2.Lettered a. b.0 revisions2 FORMAT_CHANGE
Numbered, “Item 2”Bulleted, “Item two”2 (DELETION, INSERTION)4 (adds 2 FORMAT_CHANGE)
NumberedIdentical numbered list0 revisions0 revisions

The last row matters in practice. Turning the option on does not create extra revisions for lists that are the same in both files.

Prerequisites

You need Aspose.Words for Python via .NET 26.9 or later. Install or upgrade it from PyPI:

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

Without a license, Aspose.Words runs in evaluation mode with limitations. A temporary license removes them while you test.

See the Difference: Numbering Changes With and Without the Option

The following script builds two documents that contain the same two items. The first uses a numbered list, and the second uses a bulleted list. It compares them twice, once with the option off and once with it on, so you can see exactly what the option changes.

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")

Running the script prints:

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

How the Code Works

  • build_list_document uses DocumentBuilder.list_format to start a default numbered or bulleted list, writes two items, and then calls remove_numbers() so any later paragraphs are not part of the list.
  • CompareOptions.advanced_options exposes compare_list_definitions, which defaults to False.
  • original.compare(...) compares original against edited and records the differences as revisions inside original. The method returns None, so always read the results from the document you called it on.
  • Each revision’s parent_node is the list paragraph whose formatting changed. revision_type is RevisionType.FORMAT_CHANGE for numbering and bullet changes.

Detect Numbering Changes Between Two Word Files

In a real workflow, you compare two existing files, such as two versions of a contract. Those comparisons usually contain other revisions too, so the script below keeps only the formatting changes that sit on list paragraphs.

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")

In our test, version 2 of the contract changed a numbered list to bullets and also made an unrelated sentence bold. The output was:

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

The filter picks out the two list items and skips the bold change, because that revision sits on text rather than on a list paragraph. Keep in mind that it matches any paragraph-level formatting change on a list item, such as a changed indent, not only numbering. Check the saved document if you need to tell those apart.

Review, Accept, or Reject Numbering Changes

Because numbering changes are ordinary format revisions, you handle them the same way as any other revision:

  • revisions.accept_all() applies the edited list formatting. In the first example, both items become bullets.
  • revisions.reject_all() keeps the original formatting, so the items stay numbered 1. and 2..
  • Saving the document writes the revisions as tracked changes, so reviewers can open the file in Microsoft Word and decide on each change themselves.

You can also call accept() or reject() on individual Revision objects, for example on only the items in the list_changes list from the previous section.

When to Detect Numbering Changes

Turn the option on when the numbering of a list carries meaning for your reviewers. Legal and policy documents are a common case: renumbering clauses from 1. to (a) changes how other documents refer to them, so a reviewer needs to see it. It is also useful when you migrate documents between systems and want to confirm that list numbering survived the move unchanged.

Leave it off when you only care about wording. Content reviews, translation checks, and text-level diffs are easier to read without formatting revisions mixed in.

Things to Watch For

  • ignore_formatting overrides the option. If you set options.ignore_formatting = True, numbering changes are not reported, even with compare_list_definitions = True.
  • Files must not contain revisions before you compare them. If either document already has tracked changes, compare raises a RuntimeError saying that compared documents must not have revisions. Accept or reject existing revisions first. This also means you can’t run a second comparison on a document that already holds the results of the first; reload the files each time.
  • Other revisions still appear. Inserted or deleted text in a list item is reported whether the option is on or off, so check revision_type if you need to separate numbering changes from wording changes.

Next Steps

The Compare Documents article in the Aspose.Words for Python documentation covers the other comparison settings, including granularity, the comparison target, and the ignore options.

FAQs

  1. Why doesn’t Aspose.Words detect numbering changes when comparing Word files? By default, Aspose.Words follows Microsoft Word and leaves list definitions, such as the numbering style or bullet character, out of the comparison. A list that changes from numbers to bullets produces no revisions unless you enable compare_list_definitions.

  2. How do I detect numbering changes in Python? Create CompareOptions, set options.advanced_options.compare_list_definitions to True, and pass the options to Document.compare. Each list paragraph whose numbering or bullet changed receives a FORMAT_CHANGE revision.

  3. What kind of revision does a numbering change create? Each affected list paragraph gets a revision of type RevisionType.FORMAT_CHANGE. Accepting it applies the edited file’s list formatting, and rejecting it keeps the original.

  4. Does the option work together with ignore_formatting? No. When CompareOptions.ignore_formatting is True, numbering changes are not reported, even if compare_list_definitions is True.

  5. What does Document.compare return? Nothing. It writes the differences as revisions into the document you call it on, so you read them from that document’s revisions collection.

  6. Which version of Aspose.Words for Python added this option? The compare_list_definitions property of AdvancedCompareOptions was added in Aspose.Words for Python via .NET 26.9.

Get a Free License and Support