mcpField
D
docx-processing

docx-processing

github.com/pixel-process-ug文档处理385 次安装33 周前更新
代码仓库

关于 docx-processing

面向通过代码生成、填充和转换 Word 文档的技能,适用于文档自动化流程。它涵盖 python-docx 与 docxtpl,可按需求选择直接创建文档或使用模板。

主要功能

  1. 01使用 python-docx 创建文档
  2. 02通过 docxtpl 填充模板
  3. 03控制样式、表格、页眉和页脚
  4. 04批量生成邮件合并文档
  5. 05规划 DOCX 到 PDF 的转换

适用场景

  1. 01生成格式化报告
  2. 02用数据填充固定版式模板
  3. 03批量制作个性化信函
  4. 04将 Word 文档转换为 PDF

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/pixel-process-ug/superkit-agents --skill docx-processing

安装后在 Claude Code 中输入/docx-processing确认已加载。

详细介绍

DOCX 处理

概述

以编程方式生成、操作和套用 Word 文档模板。本技能涵盖用于直接创建文档的 python-docx、基于 Jinja2 填充模板的 docxtpl、格式控制(标题、表格、图片、页眉/页脚)、邮件合并操作、样式管理和转换策略。

当需要通过代码而非手动编辑来创建、填充或转换 Word 文档时,请使用本技能。

多阶段流程

阶段 1:需求分析
  1. 确定是从头创建还是填充模板
  2. 确定文档结构(章节、页眉、表格、图片)
  3. 定义数据来源(JSON、CSV、数据库、API)
  4. 规划样式要求(字体、颜色、页边距)
  5. 确定输出格式(DOCX,是否需要转换为 PDF)

停止 — 在确定方案(从头创建还是使用模板)并确认数据来源之前,不要开始实施。

阶段 2:实施
  1. 设置文档模板或从头创建文档
  2. 实现数据绑定和内容生成
  3. 应用格式和样式
  4. 添加页眉、页脚和页码
  5. 处理图片和嵌入对象

停止 — 实现所有文档章节后,才能进入验证阶段。

阶段 3:验证
  1. 验证文档在 Word/LibreOffice 中的呈现效果
  2. 检查各页格式是否一致
  3. 验证生成文档中的数据准确性
  4. 使用边界情况进行测试(长文本、缺失数据、特殊字符)
  5. 如有需要,验证 PDF 转换效果

方案选择表

场景方案库原因
一次性报告生成从头创建python-docx完全以编程方式控制
布局固定的定期报告模板docxtpl在 Word 中设计布局,再填充数据
批量生成信件(邮件合并)模板docxtpl一个模板,生成多个输出
复杂格式、自定义样式从头创建python-docx可直接访问文档模型
由非技术用户设计模板模板docxtpl用户在 Word 中编辑,开发者绑定数据
需要 PDF 输出任一方案 + 转换libreoffice / docx2pdf后处理步骤

python-docx 模式

创建文档
from docx import Document
from docx.shared import Inches, Pt, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT

doc = Document()

# Set default font
style = doc.styles['Normal']
font = style.font
font.name = 'Calibri'
font.size = Pt(11)

# Add heading
doc.add_heading('Monthly Report', level=0)

# Add paragraph with formatting
para = doc.add_paragraph()
run = para.add_run('Important: ')
run.bold = True
run.font.color.rgb = RGBColor(0xCC, 0x00, 0x00)
para.add_run('This section requires attention.')

# Add table
table = doc.add_table(rows=1, cols=3, style='Light Grid Accent 1')
hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Name'
hdr_cells[1].text = 'Department'
hdr_cells[2].text = 'Revenue'

for name, dept, rev in data:
    row_cells = table.add_row().cells
    row_cells[0].text = name
    row_cells[1].text = dept
    row_cells[2].text = f'${rev:,.2f}'

# Add image
doc.add_picture('chart.png', width=Inches(5.5))

# Save
doc.save('report.docx')
页眉和页脚
from docx.enum.section import WD_ORIENT
from docx.oxml.ns import qn
from docx.oxml import OxmlElement

section = doc.sections[0]

# Page setup
section.page_width = Cm(21)
section.page_height = Cm(29.7)
section.left_margin = Cm(2.5)
section.right_margin = Cm(2.5)
section.top_margin = Cm(2.5)
section.bottom_margin = Cm(2.5)

# Header
header = section.header
header_para = header.paragraphs[0]
header_para.text = 'Company Name — Confidential'
header_para.alignment = WD_ALIGN_PARAGRAPH.RIGHT
header_para.style.font.size = Pt(9)
header_para.style.font.color.rgb = RGBColor(0x88, 0x88, 0x88)

# Footer with page numbers
footer = section.footer
footer_para = footer.paragraphs[0]
footer_para.alignment = WD_ALIGN_PARAGRAPH.CENTER

# Add page number field
run = footer_para.add_run()
fldChar = OxmlElement('w:fldChar')
fldChar.set(qn('w:fldCharType'), 'begin')
run._r.append(fldChar)

run2 = footer_para.add_run()
instrText = OxmlElement('w:instrText')
instrText.set(qn('xml:space'), 'preserve')
instrText.text = ' PAGE '
run2._r.append(instrText)

run3 = footer_para.add_run()
fldChar2 = OxmlElement('w:fldChar')
fldChar2.set(qn('w:fldCharType'), 'end')
run3._r.append(fldChar2)
表格格式
from docx.shared import Cm, Pt
from docx.oxml.ns import nsdecls
from docx.oxml import parse_xml

# Set column widths
table.columns[0].width = Cm(4)
table.columns[1].width = Cm(6)
table.columns[2].width = Cm(3)

# Cell shading
for cell in table.rows[0].cells:
    shading = parse_xml(f'<w:shd {nsdecls("w")} w:fill="2F5496"/>')
    cell._tc.get_or_add_tcPr().append(shading)
    for paragraph in cell.paragraphs:
        for run in paragraph.runs:
            run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
            run.font.bold = True

# Cell alignment
for row in table.rows:
    for cell in row.cells:
        cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER

docxtpl 模板模式

模板语法(Jinja2)
Template file (template.docx) contains:

{{ company_name }}
Date: {{ report_date }}

Dear {{ recipient_name }},

{% for item in items %}
- {{ item.name }}: ${{ item.price }}
{% endfor %}

Total: ${{ total }}

{%if urgent %}
URGENT: This requires immediate attention.
{%endif %}
模板渲染
from docxtpl import DocxTemplate, InlineImage
from docx.shared import Mm

tpl = DocxTemplate('template.docx')

context = {
    'company_name': 'Acme Corp',
    'report_date': '2025-03-15',
    'recipient_name': 'Alice Johnson',
    'items': [
        {'name': 'Widget A', 'price': '29.99'},
        {'name': 'Widget B', 'price': '49.99'},
    ],
    'total': '79.98',
    'urgent': True,
    'chart': InlineImage(tpl, 'chart.png', width=Mm(120)),
}

tpl.render(context)
tpl.save('output.docx')
模板中的富文本
from docxtpl import RichText

rt = RichText()
rt.add('Normal text ')
rt.add('bold text', bold=True)
rt.add(' and ')
rt.add('red text', color='FF0000')
rt.add(' with ')
rt.add('a link', url_id=tpl.build_url_id('https://example.com'))

context = {'formatted_text': rt}
模板中的表格
Template table row with loop:
{% tr for row in table_data %}
{{ row.name }} | {{ row.value }} | {{ row.status }}
{% endtr %}

邮件合并

from docxtpl import DocxTemplate
import csv

template = DocxTemplate('letter_template.docx')

with open('recipients.csv') as f:
    reader = csv.DictReader(f)
    for i, row in enumerate(reader):
        context = {
            'name': row['name'],
            'address': row['address'],
            'amount': row['amount'],
            'due_date': row['due_date'],
        }
        template.render(context)
        template.save(f'letters/letter_{i:04d}_{row["name"]}.docx')
        template = DocxTemplate('letter_template.docx')  # Re-load for next iteration

样式管理

自定义样式
from docx.enum.style import WD_STYLE_TYPE

# Create custom paragraph style
style = doc.styles.add_style('CustomHeading', WD_STYLE_TYPE.PARAGRAPH)
style.font.name = 'Arial'
style.font.size = Pt(16)
style.font.bold = True
style.font.color.rgb = RGBColor(0x2F, 0x54, 0x96)
style.paragraph_format.space_before = Pt(12)
style.paragraph_format.space_after = Pt(6)

# Apply custom style
doc.add_paragraph('Section Title', style='CustomHeading')
样式继承
Normal → Heading 1 → Heading 2 → ...
Normal → Body Text → List Paragraph
Normal → Table Normal → Table Grid

转换策略

DOCX 转 PDF
# Option 1: LibreOffice (most reliable, server-friendly)
import subprocess
subprocess.run([
    'libreoffice', '--headless', '--convert-to', 'pdf',
    '--outdir', output_dir, input_file
])

# Option 2: docx2pdf (Windows/macOS with Word installed)
from docx2pdf import convert
convert('input.docx', 'output.pdf')

# Option 3: Generate PDF directly with reportlab for full control

错误处理

import jinja2

def safe_generate_document(template_path, context, output_path):
    try:
        tpl = DocxTemplate(template_path)
        tpl.render(context)
        tpl.save(output_path)
        return True
    except jinja2.UndefinedError as e:
        print(f"Missing template variable: {e}")
        return False
    except FileNotFoundError as e:
        print(f"Template not found: {e}")
        return False
    except Exception as e:
        print(f"Document generation failed: {e}")
        return False

反模式 / 常见错误

反模式失败原因替代做法
硬编码字号,而不是使用样式格式不一致,难以维护一次定义样式,随处应用
不处理缺失的模板变量数据不完整时会导致运行时崩溃使用 jinja2.Undefined 或默认过滤器
表格过大却不分页输出难以阅读,布局错乱将表格拆分到多页,或进行摘要
使用绝对图片路径在不同环境中无法移植使用相对路径或嵌入图片
不使用不同版本的 Word 进行测试格式问题可能悄然出现在 Word、LibreOffice 和 Google Docs 中测试
有 API 可用时仍直接修改 XML代码脆弱且依赖版本优先使用 python-docx API 方法
全部使用直接格式设置,不使用样式无法保持格式一致创建并应用命名样式
忽略 Unicode 字符生成的文档中会出现乱码使用带重音符号的字符、CJK 字符和符号进行测试
邮件合并时不重新加载模板首次渲染后输出可能损坏每次迭代都重新实例化 DocxTemplate

防止自我合理化

  • 不要跳过方案决策(从头编写还是使用模板)——这会决定整个实现方案。
  • 不要在未至少使用 Word 和另一款查看器进行测试的情况下生成文档。
  • 不要忽略缺失数据——应为为空或 null 的字段设置默认值,或使用条件章节。
  • 不要在生产环境的文档生成流水线中跳过错误处理。
  • 当可以使用样式时,不要硬编码格式。

集成点

技能关联方式
pdf-processingDOCX 转 PDF,或直接选择生成 PDF
xlsx-processingExcel 中的数据会输入文档生成上下文
email-composer将生成的文档附加到专业邮件中
content-research-writer将研究内容排版为白皮书和报告
file-organizer输出文件命名和目录结构约定
deploymentCI/CD 或服务器环境中的文档生成流水线

技能类型

灵活 — 根据文档复杂程度,在 python-docx(程序化)和 docxtpl(基于模板)之间进行选择。简单报告可能不需要模板;复杂的重复性文档则适合使用模板。

评论

支持 Markdown