mcpField
D
docx-advanced-patterns

docx-advanced-patterns

github.com/belumumeドキュメント4637 回インストール6 週間前に更新
リポジトリ

docx-advanced-patterns について

docx-advanced-patterns は、python-docx で複雑な DOCX 構造を扱うスキルです。基本的なテキスト抽出では得られない入れ子のテーブルやセルの内容を抽出し、公式 docx スキルを補完します。

主な機能

  1. 01入れ子テーブルのテキスト抽出
  2. 02深い入れ子構造の再帰処理
  3. 03入れ子テーブルを含むセルの検出
  4. 04チェックボックスとフォームの処理
  5. 05改行と構造の保持

活用シーン

  1. 01政府フォームの選択肢の抽出
  2. 02評価フォームの尺度と選択肢の読み取り
  3. 03複雑なテーブルセルのデータ処理

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/belumume/claude-skills --skill docx-advanced-patterns

インストール後、Claude Code で/docx-advanced-patternsを入力して読み込まれたか確認します。

同梱ファイルREADME.md

詳細

DOCX の高度なパターンスキル

基本的な .text 抽出では対応できない複雑なドキュメント構造を処理する、python-docx 向けの特化パターンです。

このスキルを使用するタイミング

次のような DOCX ファイルを扱う場合に、このスキルを呼び出してください。

  • 表のセル内に入れ子になった表がある
  • チェックボックスの選択肢を含むフォームがある
  • 複数行にわたる複雑なセルレイアウトがある
  • 選択肢が埋め込まれたチェックリストがある
  • .text プロパティに表示されないセルコンテンツがある

包括的なドキュメント処理を行う場合は、公式の docx スキルと併用してください。

基本パターン:入れ子になった表の抽出

問題

python-docx の cell.text プロパティで抽出できるのは、直接含まれる段落テキストのみです。セル内にある入れ子の表をたどることはできません。

症状:

cell.text  # Returns: '' or '\n'
# But cell visually contains content!
検出

セルに入れ子の表が含まれているか確認します。

if cell.tables:
    print(f"Found {len(cell.tables)} nested table(s)")
    # Cell has nested content - need special extraction
解決策(簡易版)
def extract_cell_content_with_nested_tables(cell):
    """
    Extract all text from a cell, including text from nested tables.

    Args:
        cell: python-docx _Cell object

    Returns:
        str: Combined text from cell paragraphs and nested tables
    """
    text_parts = []

    # Get direct paragraph text (not inside nested tables)
    for para in cell.paragraphs:
        para_text = para.text.strip()
        if para_text:
            text_parts.append(para_text)

    # Get content from nested tables
    if cell.tables:
        for nested_table in cell.tables:
            for nested_row in nested_table.rows:
                # For checkbox lists: Column 0 = label, Column 1 = checkbox
                # Extract text from first column only
                if nested_row.cells:
                    first_col_text = nested_row.cells[0].text.strip()
                    # Filter out checkbox characters
                    if first_col_text and first_col_text not in ['', '☐', '☑', '☒']:
                        text_parts.append(first_col_text)

    return '\n'.join(text_parts) if text_parts else ''
解決策(深い入れ子に対応する再帰版)

複数階層の表の入れ子があるドキュメントの場合:

def extract_cell_content_recursively(cell):
    """
    Recursively extract text from cell including deeply nested tables.

    Handles arbitrary nesting depth.
    """
    text_parts = []

    def _extract_recursive(cell_obj):
        # Get direct paragraphs
        for para in cell_obj.paragraphs:
            para_text = para.text.strip()
            if para_text and para_text not in ['', '☐', '☑', '☒']:
                text_parts.append(para_text)

        # Recursively get nested tables
        for nested_table in cell_obj.tables:
            for nested_row in nested_table.rows:
                for nested_cell in nested_row.cells:
                    _extract_recursive(nested_cell)

    _extract_recursive(cell)
    return '\n'.join(text_parts) if text_parts else ''

使用例

例 1:フォームのチェックボックス選択肢の抽出

ドキュメント構造:

Table Cell contains:
  Nested Table:
    Row 1: "High potential" | ☐
    Row 2: "Moderate potential" | ☐
    Row 3: "Low potential" | ☐

抽出:

from docx import Document

doc = Document('form.docx')
table = doc.tables[0]
cell = table.rows[1].cells[0]

# Wrong way - returns empty
basic_text = cell.text
print(basic_text)  # Output: '' or '\n'

# Right way - extracts nested content
full_text = extract_cell_content_with_nested_tables(cell)
print(full_text)
# Output:
# High potential
# Moderate potential
# Low potential
例 2:表のすべてのセルの処理
def process_table_with_nested_content(table):
    """Process all cells, handling nested tables"""
    for row in table.rows:
        for cell in row.cells:
            # Extract with nested table support
            content = extract_cell_content_with_nested_tables(cell)

            if content:
                # Process content (translate, analyze, etc.)
                processed = do_something_with(content)
                print(f"Cell content: {processed}")
例 3:入れ子になった表の検出
def analyze_document_structure(doc):
    """Find all cells with nested tables"""
    nested_cells = []

    for t_idx, table in enumerate(doc.tables):
        for r_idx, row in enumerate(table.rows):
            for c_idx, cell in enumerate(row.cells):
                if cell.tables:
                    nested_cells.append({
                        'table': t_idx,
                        'row': r_idx,
                        'col': c_idx,
                        'nested_count': len(cell.tables)
                    })

    return nested_cells

# Usage
doc = Document('complex_form.docx')
nested = analyze_document_structure(doc)

for item in nested:
    print(f"Table {item['table']}, Row {item['row']}, Col {item['col']}: "
          f"{item['nested_count']} nested table(s)")

よくある使用例

1. 政府機関のフォーム

フォームでは、チェックボックスのグリッドに入れ子の表を使用することがよくあります。

def extract_form_responses(doc):
    """Extract all form checkbox options"""
    responses = {}

    for table in doc.tables:
        for row in table.rows:
            # First cell = question
            question = row.cells[0].text.strip()

            # Second cell = checkbox options (nested table)
            if row.cells[1].tables:
                options = extract_cell_content_with_nested_tables(row.cells[1])
                responses[question] = options.split('\n')

    return responses
2. 評価フォーム

評価尺度と選択肢を抽出します。

def extract_evaluation_items(doc):
    """Extract evaluation criteria and options"""
    evaluations = []

    for table in doc.tables:
        for row_idx, row in enumerate(table.rows[1:], 1):
            # Get criterion
            criterion = row.cells[0].text.strip()

            # Get rating options (often nested)
            rating_cell = row.cells[1]
            rating_options = extract_cell_content_with_nested_tables(rating_cell)

            evaluations.append({
                'criterion': criterion,
                'options': rating_options.split('\n')
            })

    return evaluations
3. 複雑なデータテーブル

入れ子のレイアウトがあるセルから、構造化データを抽出します。

def extract_complex_cell_data(cell):
    """Extract data from cells with complex nested structures"""
    data = {
        'main_content': '',
        'nested_items': []
    }

    # Direct paragraphs
    for para in cell.paragraphs:
        if para.text.strip():
            data['main_content'] = para.text.strip()
            break

    # Nested table data
    if cell.tables:
        for nested_table in cell.tables:
            for nested_row in nested_table.rows:
                row_data = [c.text.strip() for c in nested_row.cells]
                data['nested_items'].append(row_data)

    return data

公式の docx スキルとの統合

このスキルは、公式の docx スキルを補完します。

公式の docx スキルでできること:

  • ドキュメントの作成(docx-js)
  • 基本的なテキスト抽出(pandoc)
  • 変更履歴のワークフロー
  • コメントの処理
  • 複雑なケースでの XML アクセス

このスキルでできること:

  • 入れ子になった表の抽出
  • 複雑なセルコンテンツの処理
  • フォームとチェックリストの処理
  • 高度なコンテンツ抽出パターン

併用方法:

# For basic operations: use official skill
from docx import Document

# For nested table handling: use this skill
from docx_advanced import extract_cell_content_with_nested_tables

# Combine both
doc = Document('complex_form.docx')  # Official
for table in doc.tables:            # Official
    for row in table.rows:          # Official
        for cell in row.cells:      # Official
            # Advanced extraction:
            content = extract_cell_content_with_nested_tables(cell)

パフォーマンスに関する考慮事項

大規模なドキュメントの場合:

入れ子の表のチェック結果をキャッシュします。

def build_nested_table_cache(doc):
    """Pre-compute which cells have nested tables"""
    cache = {}

    for t_idx, table in enumerate(doc.tables):
        for r_idx, row in enumerate(table.rows):
            for c_idx, cell in enumerate(row.cells):
                if cell.tables:
                    cache[(t_idx, r_idx, c_idx)] = len(cell.tables)

    return cache

# Usage
cache = build_nested_table_cache(doc)

for t_idx, table in enumerate(doc.tables):
    for r_idx, row in enumerate(table.rows):
        for c_idx, cell in enumerate(row.cells):
            if (t_idx, r_idx, c_idx) in cache:
                # This cell has nested tables
                content = extract_cell_content_with_nested_tables(cell)
            else:
                # Regular extraction
                content = cell.text

トラブルシューティング

問題:コンテンツが表示されているのに、抽出結果が空になる

診断:

cell = table.rows[1].cells[0]
print(f"cell.text: '{cell.text}'")
print(f"cell.tables: {len(cell.tables)}")

if not cell.text.strip() and cell.tables:
    print("Content is in nested tables!")

修正方法: extract_cell_content_with_nested_tables(cell) を使用します。

問題:チェックボックス文字(、☐)が出力に表示される

修正方法: 取り除きます。

text = cell.text.strip()
# Remove checkbox unicode characters
clean_text = text.replace('', '').replace('☐', '').replace('☑', '').replace('☒', '')
問題:複数行のコンテンツが保持されない

修正方法: 改行で結合します。

'\n'.join(text_parts)  # Preserves line structure

ベストプラクティス

  1. 必ず最初に入れ子の表があるか確認してください。

    if cell.tables:
        content = extract_cell_content_with_nested_tables(cell)
    else:
        content = cell.text
    
  2. チェックボックス文字を処理してください。

    CHECKBOX_CHARS = ['', '☐', '☑', '☒']
    if text not in CHECKBOX_CHARS:
        # Process text
    
  3. 構造を保持してください。

    # Use newlines to maintain line breaks
    '\n'.join(lines)
    
  4. サンプルドキュメントでテストしてください。

    def test_extraction():
        doc = Document('sample_form.docx')
        cell = doc.tables[0].rows[1].cells[0]
    
        extracted = extract_cell_content_with_nested_tables(cell)
        assert 'High potential' in extracted
        assert 'Moderate potential' in extracted
    

リファレンス実装

上記のパターンは単体で使用できます。このスキルには個別の REFERENCE.md は含まれていません(以前の参照先は現在使われていません)。実用例、統合パターン、再帰的な抽出、パフォーマンスに関する補足は、上記の各セクションに記載されています。

Anthropic Skills への貢献

このパターンは現在、公式の docx スキルには含まれていません。役立つと感じた場合は、以下の手順で貢献をご検討ください。

  1. https://github.com/anthropics/skills をフォークします
  2. document-skills/docx/SKILL.md に追加します
  3. 次の内容を含むプルリクエストを送信します。
    • パターンの説明
    • コード例
    • 使用例

成功基準

次の条件を満たせば、パターンは正常に機能しています。

  • 入れ子の表があるセルから、完全なコンテンツが返される
  • チェックボックスの選択肢が正しく抽出される
  • フォームのフィールドが読み取れる
  • 抽出時にコンテンツが失われない
  • 構造が保持される(改行が維持される)

コメント