Word 排版美化

Model: qwen-plus | ¥0.10/call
Word排版页眉页脚页码样式论文排版标题样式字体设置文档美化

Word 排版美化 docx-styling:一键设置页眉页脚文本、插入自动页码、调整标题样式(字号/颜色/字体)、批量设置正文字体。适合论文、合同、报告定稿前统一格式。输出新文件不改原稿。

Skill Documentation

---

name: docx-styling

description: Word 排版美化 docx-styling:一键设置页眉页脚文本、插入自动页码、调整标题样式(字号/颜色/字体)、批量设置正文字体(中英文 eastAsia)。适合论文排版、报告定稿、合同统一格式、标书美化。输出新文件不改原稿。

---

⚠️ chat 模式使用须知(重要)

本 skill 的真实能力依赖平台后端工具。在网页 / chat 端点下,这些工具可能不可用:

此时**请勿轻信**,请改用 **agent / CLI 路径**运行本 skill 以获取真实结果。任何路径下都**严禁谎称「已调用 / 已搜索完成」而实际未执行**。

Word 排版美化(docx-styling)

给 Word 文档快速排版:页眉、页脚、页码、标题样式、正文字体。适合论文、合同、报告定稿前统一格式。

典型使用场景

**场景 1:毕业论文排版** —— 学校要求:标题用黑体二号深蓝,正文宋体小四,页眉放学号姓名,页码从摘要开始。用 `docx-styling` 一行命令搞定,不用手动一个个改。

**场景 2:公司报告统一格式** —— 公司所有季度报告都要统一标题样式 + 页脚"机密"+ 页码从封面后开始。批量改后输出,不动原稿。

**场景 3:标书美化** —— 投标前要把所有 Word 文档改成:标题深蓝、正文宋体、页眉公司名、页脚页码。一键统一。

适用人群

| 角色 | 典型用途 |

|------|----------|

| 学生 / 研究生 | 论文 / 报告 / 开题定稿 |

| 教师 / 学者 | 课件 / 讲义 / 学术报告 |

| 律师 / 法务 | 法律意见书 / 合同统一格式 |

| 销售 / 商务 | 标书 / 提案 / 商务报告美化 |

| 行政 / 文员 | 公司文档统一样式 |

| 个人用户 | Word 排版美化 |

完整数据示例(实测)

# 1. 加页眉
python scripts/docx_style.py header --input 报告.docx --text "内部资料" --align center --size 10

# 2. 加页脚 + 自动页码
python scripts/docx_style.py pagenum --input 报告.docx --align center --prefix "第 " --suffix " 页"
# 插入 PAGE 域,Word/WPS 打开自动显示实际页码

# 3. 标题样式(标题 1 = 黑体二号深蓝)
python scripts/docx_style.py heading --input 报告.docx --level 1 --size 22 --color 1F4E79 --name 黑体

# 4. 正文字体(宋体小四)
python scripts/docx_style.py font --input 报告.docx --size 12 --name 宋体

为什么选 docx-styling

触发条件

用户要求"加页眉 / 加页脚 / 插入页码 / 设置标题样式 / 标题字号颜色 / 正文改字体 / Word 排版美化"时触发。

触发条件

用户要求"加页眉 / 加页脚 / 插入页码 / 设置标题样式 / 标题字号颜色 / 正文改字体 / Word 排版美化"时触发。

依赖安装

pip install python-docx

使用

页眉

python scripts/docx_style.py header --input 报告.docx --text "内部资料" --align center [--size 10]

`--align`:left / center / right。

页脚文本

python scripts/docx_style.py footer --input 报告.docx --text "第 1 页 / 共 20 页" --align center

插入页码(自动编号域)

python scripts/docx_style.py pagenum --input 报告.docx --align center [--prefix "第 "] [--suffix " 页"]

插入 PAGE 域,Word/WPS 打开自动显示实际页码。

标题样式

python scripts/docx_style.py heading --input 报告.docx --level 1 --size 22 --color 1F4E79 --name 黑体

正文字体

python scripts/docx_style.py font --input 报告.docx --size 12 --name 宋体

批量设置所有段落正文字号/字体(含中文字体 eastAsia)。

处理规则

1. 所有命令默认输出新文件(`--output`),**不覆盖原稿**

2. 无 `--output` 时直接改原文件(需用户明确要求)

3. 输出 JSON:`{"ok": true, "output": "...", "action": "header|pagenum|..."}`

失败处理

| 情况 | 处理 |

|---|---|

| 文件不存在/损坏 | 明确报错 |

| 标题级别不存在 | 报错提示 1/2/3 |

| 颜色格式错误 | 报错提示 RRGGBB 格式 |

安全

<!-- ===== 以下为内嵌脚本代码(agent 安装时按需落盘为 scripts/<name> 并 chmod +x) ===== -->

文件:scripts/docx_style.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Word 排版美化:页眉页脚 / 页码 / 标题样式 / 正文字体。

用法示例:
  python docx_style.py header --input a.docx --text "内部资料" [--output]
  python docx_style.py footer --input a.docx --text "第 1 页" [--output]
  python docx_style.py pagenum --input a.docx --align center [--output]
  python docx_style.py heading --input a.docx --level 1 --size 22 --color 1F4E79 [--output]
  python docx_style.py font --input a.docx --size 12 --name 宋体 [--output]

依赖:pip install python-docx
"""
import argparse
import json
import sys
from pathlib import Path

try:
    from docx import Document
    from docx.shared import Pt, RGBColor
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    from docx.oxml.ns import qn
    from docx.oxml import OxmlElement
except ImportError:  # pragma: no cover
    sys.stderr.write("缺少依赖 python-docx,请先执行: pip install python-docx\n")
    sys.exit(2)


def _load(path) -> Document:
    p = Path(path)
    if not p.exists():
        raise FileNotFoundError(f"文件不存在: {p}")
    return Document(str(p))


def _save(doc, out, input_path):
    o = Path(out or input_path)
    o.parent.mkdir(parents=True, exist_ok=True)
    doc.save(str(o))
    return str(o)


def _set_cn_font(run, name: str | None, size: int | None):
    if name:
        run.font.name = name
        r = run._element.rPr.rFonts
        r.set(qn("w:eastAsia"), name)
    if size:
        run.font.size = Pt(size)


def _header_para(doc, align):
    sec = doc.sections[0]
    p = sec.header.paragraphs[0]
    p.alignment = {"left": WD_ALIGN_PARAGRAPH.LEFT, "center": WD_ALIGN_PARAGRAPH.CENTER,
                   "right": WD_ALIGN_PARAGRAPH.RIGHT}.get(align, WD_ALIGN_PARAGRAPH.LEFT)
    return p


def cmd_header(args) -> dict:
    doc = _load(args.input)
    p = _header_para(doc, args.align)
    run = p.add_run(args.text)
    if args.size:
        run.font.size = Pt(args.size)
    out = _save(doc, args.output, args.input)
    return {"ok": True, "output": out, "action": "header", "text": args.text}


def cmd_footer(args) -> dict:
    doc = _load(args.input)
    sec = doc.sections[0]
    p = sec.footer.paragraphs[0]
    p.alignment = {"left": WD_ALIGN_PARAGRAPH.LEFT, "center": WD_ALIGN_PARAGRAPH.CENTER,
                   "right": WD_ALIGN_PARAGRAPH.RIGHT}.get(args.align, WD_ALIGN_PARAGRAPH.LEFT)
    run = p.add_run(args.text)
    if args.size:
        run.font.size = Pt(args.size)
    out = _save(doc, args.output, args.input)
    return {"ok": True, "output": out, "action": "footer", "text": args.text}


def _add_page_field(p):
    """插入 PAGE 域(显示当前页码)。"""
    run = p.add_run()
    fld = OxmlElement("w:fldSimple")
    fld.set(qn("w:instr"), "PAGE")
    run._r.append(fld)


def cmd_pagenum(args) -> dict:
    doc = _load(args.input)
    for sec in doc.sections:
        sec.footer.is_linked_to_previous = False
        p = sec.footer.paragraphs[0]
        p.alignment = {"left": WD_ALIGN_PARAGRAPH.LEFT, "center": WD_ALIGN_PARAGRAPH.CENTER,
                       "right": WD_ALIGN_PARAGRAPH.RIGHT}.get(args.align, WD_ALIGN_PARAGRAPH.CENTER)
        if args.prefix:
            p.add_run(args.prefix)
        _add_page_field(p)
        if args.suffix:
            p.add_run(args.suffix)
    out = _save(doc, args.output, args.input)
    return {"ok": True, "output": out, "action": "pagenum", "note": "已插入页码域(PAGE),打开后自动显示"}


def cmd_heading(args) -> dict:
    doc = _load(args.input)
    style_name = f"Heading {args.level}"
    try:
        style = doc.styles[style_name]
    except KeyError:
        raise ValueError(f"样式不存在: {style_name}")
    font = style.font
    font.size = Pt(args.size) if args.size else font.size
    if args.color:
        font.color.rgb = RGBColor.from_string(args.color)
    if args.name:
        font.name = args.name
        style.element.rPr.rFonts.set(qn("w:eastAsia"), args.name)
    out = _save(doc, args.output, args.input)
    return {"ok": True, "output": out, "action": "heading", "style": style_name}


def cmd_font(args) -> dict:
    doc = _load(args.input)
    for p in doc.paragraphs:
        if not p.text.strip():
            continue
        for run in p.runs:
            _set_cn_font(run, args.name, args.size)
    out = _save(doc, args.output, args.input)
    return {"ok": True, "output": out, "action": "font", "name": args.name, "size": args.size}


def build_parser() -> argparse.ArgumentParser:
    ap = argparse.ArgumentParser(description="Word 排版美化工具")
    sub = ap.add_subparsers(dest="command", required=True)
    common = {"input": True}

    p = sub.add_parser("header", help="设置页眉文本")
    p.add_argument("--input", required=True)
    p.add_argument("--text", required=True)
    p.add_argument("--align", default="left", choices=["left", "center", "right"])
    p.add_argument("--size", type=int, default=None)
    p.add_argument("--output", default=None)
    p.set_defaults(func=cmd_header)

    p = sub.add_parser("footer", help="设置页脚文本")
    p.add_argument("--input", required=True)
    p.add_argument("--text", required=True)
    p.add_argument("--align", default="center", choices=["left", "center", "right"])
    p.add_argument("--size", type=int, default=None)
    p.add_argument("--output", default=None)
    p.set_defaults(func=cmd_footer)

    p = sub.add_parser("pagenum", help="插入页码域")
    p.add_argument("--input", required=True)
    p.add_argument("--align", default="center", choices=["left", "center", "right"])
    p.add_argument("--prefix", default="第 ")
    p.add_argument("--suffix", default=" 页")
    p.add_argument("--output", default=None)
    p.set_defaults(func=cmd_pagenum)

    p = sub.add_parser("heading", help="设置标题样式")
    p.add_argument("--input", required=True)
    p.add_argument("--level", type=int, default=1, choices=[1, 2, 3])
    p.add_argument("--size", type=int, default=None)
    p.add_argument("--color", default=None, help="RRGGBB 如 1F4E79")
    p.add_argument("--name", default=None, help="字体名(含中文)")
    p.add_argument("--output", default=None)
    p.set_defaults(func=cmd_heading)

    p = sub.add_parser("font", help="设置正文字体/字号")
    p.add_argument("--input", required=True)
    p.add_argument("--size", type=int, default=None)
    p.add_argument("--name", default=None)
    p.add_argument("--output", default=None)
    p.set_defaults(func=cmd_font)

    return ap


def main():
    args = build_parser().parse_args()
    try:
        result = args.func(args)
    except Exception as e:
        print(json.dumps({"ok": False, "error": str(e)}, ensure_ascii=False))
        sys.exit(1)
    print(json.dumps(result, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()