當您比較兩個 Word 檔案,而唯一的差異僅在於清單的編號方式,例如原本的 1. 和 2. 現在變成 a. 和 b.,或是編號清單變成了項目符號清單,Aspose.Words 預設不會報告任何差異。本教學說明如何在 Python 中比較 Word 檔案時偵測編號變更,並解釋如何審閱、接受或拒絕它找到的變更。

主要要點

  • 預設情況下,當您比較 Word 檔案時,列表的編號樣式或項目符號字元的變更不會產生任何修訂。
  • 設定 options.advanced_options.compare_list_definitions = True 會將每個受影響的列表段落報告為 FORMAT_CHANGE 修訂。
  • 列表項目內的文字變更無論如何都會被報告。此選項僅在此基礎上加入編號和項目符號的變更。
  • ignore_formatting=True 即使在啟用此選項時也會隱藏編號變更。

為什麼編號變更預設不會顯示

Word 中的編號和項目符號來自清單定義。它描述每個清單層級的外觀:編號樣式(1.、a.、i.)、項目符號字元以及相關格式設定。當您比較文件時,Aspose.Words 會預設遵循 Microsoft Word,並在比較中省略清單定義。因此,如果僅更改了編號,比較結果將不會顯示任何變更。

compare_list_definitions 選項在 Word 中沒有對應項。它告訴 Aspose.Words 在比較時包含清單定義。以下是我們在版本 26.9 中比較兩項清單時看到的情況:

原始清單編輯後清單關閉選項開啟選項
編號 1. 2.項目符號0 次修訂2 FORMAT_CHANGE
編號 1. 2.字母 a. b.0 次修訂2 FORMAT_CHANGE
編號, “Item 2”項目符號, “Item two”2 (DELETION, INSERTION)4(新增 2 FORMAT_CHANGE)
編號相同的編號列表0 次修訂0 次修訂

在實務上,最後一行很重要。啟用此選項不會為兩個檔案中相同的清單產生額外的修訂。

先決條件

您需要 Aspose.Words for Python via .NET 26.9 或更高版本。從 PyPI 安裝或升級它:

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

如果沒有授權,Aspose.Words 會在評估模式下運行,並受到限制。一個臨時授權可在測試期間移除這些限制。

看看差異:有無選項時編號的變化

以下腳本會建立兩個包含相同兩個項目的文件。第一個使用編號清單,第二個使用項目符號清單。它會比較兩次,一次在關閉選項時,另一次在開啟選項時,讓您能精確看到選項的變化。

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

執行腳本會印出:

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

程式碼運作方式

  • build_list_document 使用 DocumentBuilder.list_format 來開始一個預設的編號或項目符號清單,寫入兩個項目,然後呼叫 remove_numbers(),使之後的段落不再屬於該清單。
  • CompareOptions.advanced_options 會公開 compare_list_definitions,其預設值為 False。
  • original.compare(...) 將 original 與 edited 進行比較,並將差異記錄為 original 內的修訂。此方法回傳 None,因此請始終從呼叫該方法的文件中讀取結果。
  • 每個修訂的 parent_node 為格式變更的清單段落。revision_type 為 RevisionType.FORMAT_CHANGE,表示編號與項目符號的變更。

偵測兩個 Word 檔案之間的編號變更

在實際工作流程中,您會比較兩個現有檔案,例如合約的兩個版本。這些比較通常還包含其他修訂,因此下面的腳本僅保留位於清單段落上的格式變更。

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

在我們的測試中,合約的第 2 版將編號列表更改為項目符號,並且還將一個不相關的句子加粗。輸出是:

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

此過濾器會挑選出兩個清單項目,並跳過粗體變更,因為該修訂作用於文字而非清單段落。請記住,它會匹配清單項目上任何段落層級的格式變更,例如縮排變更,而不僅僅是編號。若需要將它們區分開來,請檢查已儲存的文件。

審閱、接受或拒絕編號變更

因為編號變更屬於普通的格式修訂,您應該以與其他修訂相同的方式處理它們:

  • revisions.accept_all() 應用編輯後的清單格式。在第一個範例中,兩個項目都會變成項目符號。
  • revisions.reject_all() 保持原始格式,因此項目仍保持編號 1. 和 2.。
  • 儲存文件會將修訂寫入為追蹤變更,讓審閱者可以在 Microsoft Word 中開啟檔案,自行決定每項變更。

您也可以對單個 Revision 物件呼叫 accept() 或 reject(),例如僅對前一節中 list_changes 清單中的項目執行此操作。

何時偵測編號變更

當清單的編號對審閱者具有意義時,請開啟此選項。法律和政策文件是常見的情況:將條款編號從 1. 重新編為 (a) 會改變其他文件對其的引用方式,因此審閱者需要看到此變更。當您在系統之間遷移文件並希望確認清單編號在搬移後保持不變時,這也很有用。

當您只關心文字內容時,請將其關閉。內容審閱、翻譯檢查以及文字層級的差異比較,在沒有格式修訂混雜的情況下更容易閱讀。

需要注意的事項

  • ignore_formatting 覆蓋此選項。 如果將 options.ignore_formatting = True 設為 True,則即使 compare_list_definitions = True,編號變更也不會被報告。
  • 比較前文件不得包含修訂。 如果任一文件已經有追蹤變更,compare 會拋出 RuntimeError,提示比較的文件不得有修訂。請先接受或拒絕現有的修訂。這也意味著您不能在已包含第一次比較結果的文件上再次執行比較;每次都需要重新載入文件。
  • 其他修訂仍會顯示。 列表項目中的插入或刪除文字會被報告,無論此選項是否開啟,因此如果需要將編號變更與文字變更分開,請檢查 revision_type。

下一步

Aspose.Words for Python 文檔中的 Compare Documents 文章涵蓋了其他比較設定,包括粒度、比較目標以及忽略選項。

FAQs

  1. 為什麼 Aspose.Words 在比較 Word 檔案時無法偵測編號變更? 預設情況下,Aspose.Words 會遵循 Microsoft Word,並將清單定義(例如編號樣式或項目符號字元)排除在比較之外。除非啟用 compare_list_definitions,否則從編號變更為項目符號的清單不會產生任何修訂。

  2. 如何在 Python 中檢測編號變更? 建立 CompareOptions,將 options.advanced_options.compare_list_definitions 設為 True,然後將此選項傳遞給 Document.compare。每個編號或項目符號發生變更的清單段落都會收到 FORMAT_CHANGE 修訂。

  3. 什麼樣的修訂會因編號變更而產生? 每個受影響的清單段落都會獲得類型為 RevisionType.FORMAT_CHANGE 的修訂。接受它會套用已編輯檔案的清單格式,拒絕則保留原始內容。

  4. 此選項能與 ignore_formatting 一起使用嗎? 不會。當 CompareOptions.ignore_formatting 為 True 時,即使 compare_list_definitions 為 True,也不會報告編號變更。

  5. Document.compare 會回傳什麼? 沒有。它會將差異寫入您呼叫它的文件中作為修訂,您可以從該文件的 revisions 集合中讀取它們。

  6. 哪個版本的 Aspose.Words for Python 添加了此選項?
    AdvancedCompareOptions 的 compare_list_definitions 屬性已在 Aspose.Words for Python via .NET 26.9 中加入。

獲取免費授權與支援