2つの 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 で 2 項目リストを比較したときに見た結果は次のとおりです:

元のリスト編集されたリストオプションオフオプションオン
番号付き 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 は制限付きの評価モードで実行されます。テスト中にそれらの制限を解除するには、一時ライセンス を使用します。

差分を確認: オプションあり・なしでの番号付けの変化

以下のスクリプトは、同じ 2 つの項目を含む 2 つのドキュメントを作成します。最初のドキュメントは番号付きリストを使用し、2 番目は箇条書きリストを使用します。オプションをオフにした状態とオンにした状態でそれぞれ比較するので、オプションがどのように変化するかを正確に確認できます。

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 を使用してデフォルトの番号付きまたは箇条書きリストを開始し、2つの項目を書き込み、そして remove_numbers() を呼び出すことで、以降の段落がリストの一部にならないようにします。
  • CompareOptions.advanced_options は compare_list_definitions を公開し、デフォルトは False です。
  • original.compare(...) は original を edited と比較し、差分を original 内のリビジョンとして記録します。このメソッドは None を返すため、結果は常に呼び出したドキュメントから取得してください。
  • 各リビジョンの parent_node は書式が変更されたリスト段落です。番号付けや箇条書きの変更の場合、revision_type は RevisionType.FORMAT_CHANGE になります。

2つのWordファイル間の番号付け変更の検出

実際のワークフローでは、契約書の2つのバージョンなど、既存の2つのファイルを比較します。これらの比較には通常、他の改訂も含まれるため、以下のスクリプトはリスト段落にある書式変更のみを保持します。

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.

フィルターは 2 つのリスト項目を抽出し、太字の変更はスキップします。これは、そのリビジョンがリスト段落ではなくテキスト上にあるためです。リスト項目の段落レベルの書式変更(インデントの変更など)にも一致し、番号付けだけでなく、すべての変更を対象とすることに留意してください。必要に応じてそれらを区別するには、保存されたドキュメントを確認してください。

番号付けの変更をレビュー、承認、または拒否

番号付けの変更は通常の書式改訂であるため、他の改訂と同じ方法で処理します:

  • revisions.accept_all() は編集されたリストの書式を適用します。最初の例では、両方の項目が箇条書きになります。
  • revisions.reject_all() は元の書式を保持するため、項目は 1. と 2. の番号付きのままです。
  • ドキュメントを保存すると、リビジョンが変更履歴として記録されるため、レビューアは Microsoft Word でファイルを開き、各変更を自分で決定できます。

個々の Revision オブジェクトに対して accept() または reject() を呼び出すこともできます。たとえば、前のセクションの list_changes リスト内の項目だけに対してです。

番号変更の検出タイミング

リストの番号付けがレビューアにとって意味を持つ場合は、このオプションをオンにしてください。法的文書やポリシー文書が典型的な例です。条項の番号を 1. から (a) に変更すると、他の文書での参照方法が変わるため、レビューアはそれを確認する必要があります。また、システム間で文書を移行する際に、リストの番号付けが変更されずに残っていることを確認したい場合にも便利です。

文言だけが重要な場合はオフにしてください。コンテンツレビュー、翻訳チェック、テキストレベルの差分は、書式の変更が混在していない方が読みやすくなります。

Things to Watch For

  • ignore_formatting がオプションを上書きします。 options.ignore_formatting = True を設定すると、compare_list_definitions = True の場合でも、番号変更は報告されません。
  • 比較する前にファイルにリビジョンが含まれていてはいけません。 いずれかのドキュメントにすでに変更履歴がある場合、compare は RuntimeError をスローし、比較対象のドキュメントにリビジョンがあってはならないと通知します。まず既存のリビジョンを受け入れるか破棄してください。これは、最初の比較結果が残っているドキュメントで二度目の比較を実行できないことも意味します。毎回ファイルを再読み込みしてください。
  • 他のリビジョンは依然として表示されます。 リスト項目内の挿入または削除されたテキストは、オプションの有無にかかわらず報告されます。そのため、番号変更と文言変更を区別したい場合は revision_type を確認してください。

次のステップ

Aspose.Words for Python ドキュメントの ドキュメントの比較 記事では、粒度、比較対象、無視オプションなど、他の比較設定について説明しています。

FAQ

  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 で追加されました。

無料ライセンスとサポートを取得