Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Word文档格式内幕:.docx Open XML原理与排版设计

这是一本深入介绍Word .docx 文档格式的开源书籍,专注于Open XML格式原理,并结合排版设计知识进行讲解。

关于本书

  • 专注:只讲解现代 .docx 格式,不涉及旧式 .doc 二进制格式
  • 深入:从ZIP包结构开始,逐层剖析XML格式
  • 实用:结合排版设计实践,帮助你理解Word排版的本质
  • 开源:内容开源,持续更新

目标读者

  • 需要处理Word文档的开发人员
  • 文档处理系统开发人员
  • 对Word排版感兴趣的高级用户
  • 需要理解Word文档内部结构的设计师

许可证

作者保留本作品的所有权利。

前言

为什么要写这本书

Microsoft Word是世界上使用最广泛的文字处理软件,.docx格式也是目前最流行的文档格式之一。然而,大多数用户甚至很多开发人员对Word文档的内部结构并不了解。

当你需要批量生成Word文档从文档中提取数据修复损坏的文档时,理解.docx的内部结构就变得非常重要。本书从文件格式层面深入讲解.docx,帮助你真正理解Word文档是如何存储的。

同时,Word不仅仅是一个文字编辑工具,它也是一个强大的排版系统。很多用户使用Word多年,依然对样式理解不深,导致排版效率低下。本书结合Open XML格式原理,讲解Word排版的本质,帮助你掌握Word排版的核心思想。

本书特色

  • 专注docx:本书只关注现代的.docx格式,不讨论老旧的.doc二进制格式
  • 原理深入:从ZIP包开始,逐层解剖,展示真实的XML片段
  • 结合实践:不仅讲解格式,还结合排版设计实践,帮助理解
  • 适合中文:专门章节讲解中文排版的特点和最佳实践

读者定位

本书适合:

  • 需要处理Word文档的开发人员阅读,帮助你理解格式,更好地编程处理文档
  • 对Word排版有追求的高级用户阅读,帮助你理解Word设计思想,提升排版水平
  • 文档处理相关的研究人员参考

阅读本书不需要具备特别高深的技术基础,但需要你对技术细节有耐心。如果你只想学习如何点击鼠标使用Word功能,本书可能不太适合你。

本书结构

本书分为四个部分:

第一部分:基础入门 介绍Word文档格式的基本概念和发展历史,帮助你建立对.docx的整体认识。

第二部分:.docx基础结构 讲解.docx的ZIP包本质和Open XML标准,带你入门文档结构。

第三部分:Open XML核心结构 是本书的核心,逐章讲解各个XML部分的结构,包括主文档、样式、字体、段落、表格、图片等。每章都配有真实的XML片段示例。

第四部分:Word排版设计实践 将格式原理与排版实践结合,讲解Word排版原理、样式应用、中文排版最佳实践等。

最后是附录,提供XML命名空间参考、工具列表和进一步阅读资源。

致谢

感谢所有为开放标准和开源软件贡献的开发者,正是因为有了他们,我们才能自由地探索和研究文档格式。


—— 作者

第1章:Word文档格式概述

学习目标

  • 了解什么是Word文档格式
  • 理解为什么需要深入理解Word格式
  • 区分.doc和.docx格式的差异
  • 认识在开发中处理Word文档的常见场景

1.1 什么是Word文档格式

当我们在Microsoft Word中编辑文字、设置格式、插入图片后点击保存,Word会将我们的工作转换成一个文件存储在磁盘上。这个文件遵循特定的结构规范,这个结构规范就是Word文档格式

文档格式就像是一种约定:Word程序按照约定将内容写入文件,下次打开时再按照约定读取出来,就能还原我们编辑的文档。理解了这个约定,我们就可以不通过Word程序,直接读取、创建、修改Word文档。

文档格式包含什么

一个Word文档不仅仅包含纯文本,它还包含:

  • 文本内容:我们输入的文字
  • 格式信息:字体、字号、颜色、对齐方式、缩进等
  • 结构信息:段落、章节、表格、页眉页脚等
  • 嵌入对象:图片、图表、OLE对象等
  • 元数据:作者、创建时间、修改时间、标题等
  • 附加信息:批注、修订、追踪等

为什么要理解文档格式

对于普通用户来说,只需要会用Word编辑文档就够了。但在很多场景下,理解文档格式是非常必要的:

  1. 批量生成文档:根据模板批量生成合同、报告、发票
  2. 批量提取数据:从大量Word文档中提取特定信息
  3. 文档转换:将Word转换为PDF、HTML、Markdown等其他格式
  4. 修复损坏文档:当Word无法打开损坏文档时,可以通过理解格式来提取内容
  5. 开发文档处理系统:开发在线文档编辑、协作文档系统
  6. 自动化处理:文档审核、格式检查、批量转换等自动化任务

1.2 .doc vs .docx:两种格式,两个时代

Word现在主要使用两种文件扩展名:.doc.docx。它们代表了两种完全不同的文件格式。

.doc:二进制格式时代

从Word 1.0到Word 2003,Word默认使用.doc扩展名,这是一种二进制文件格式

二进制格式的特点:

  • 文件内容是二进制字节流,不能直接用文本编辑器查看
  • 格式复杂,不公开(早期),解析难度大
  • 文件体积相对较大
  • 损坏一小块可能导致整个文件无法打开

虽然现在已经很少使用.doc格式了,但在一些旧系统和老旧文档中你仍然可能遇到它。

.docx:Open XML时代

从Word 2007开始,Microsoft Word默认使用.docx扩展名,这是基于Open XML标准的XML格式。

Open XML格式的特点:

  • 本质上是一个ZIP压缩包,包含多个XML文件
  • 每个XML文件存储不同类型的内容
  • 格式开放,符合ECMA/ISO国际标准
  • 基于文本的XML,易于处理和调试
  • 压缩存储,文件体积更小
  • 损坏隔离,一部分损坏不影响其他部分读取

本书只关注.docx格式,这是现在和未来的主流格式。

格式对比

特性.doc.docx
格式类型二进制ZIP + XML
标准私有格式开放标准
文件大小较大较小(压缩)
可解析性困难相对容易
容错性整体损坏部分损坏可恢复
使用现状遗留系统当前主流

1.3 开发中的常见场景

让我们来看几个实际工作中需要处理Word文档的场景,理解理解格式为什么重要。

场景一:批量生成合同

一家企业法务部门每个月要生成几十份劳动合同,员工信息存在数据库里。

如果手动操作:

  1. 打开模板
  2. 替换姓名、职位、日期等占位符
  3. 另存为新文件
  4. 重复几十次

这个过程机械重复,耗时且容易出错。

如果理解.docx格式:

  • 可以编写程序,自动读取模板
  • 从数据库读取数据替换占位符
  • 批量生成所有合同文件
  • 整个过程全自动,几秒钟完成

场景二:从简历中提取信息

HR收到了几百份求职者的Word简历,需要将姓名、电话、工作经验等信息提取到数据库中。

如果手动操作:一个个打开复制粘贴,工作量巨大。

如果理解.docx格式:

  • 编写程序批量遍历所有文件
  • 自动提取文本内容
  • 使用正则表达式或NLP识别关键信息
  • 直接导入数据库

场景三:文档批量转换为PDF

客户要求把网站上的一百多个Word文档全部转换成PDF供用户下载。

手动打开一个个另存为PDF太麻烦,理解格式后可以用程序批量自动转换。

场景四:修复损坏的文档

一个重要的Word文档因为存储介质问题损坏了,Word无法打开,但内容非常重要。

理解格式后:

  • .docx是ZIP包,可以尝试修复ZIP结构
  • XML文件分开存储,好的部分可以提取出来
  • 最大程度挽救内容

1.4 阅读本书需要的基础知识

阅读本书不需要太多前置知识,但了解以下内容会帮助你更好地理解:

推荐基础知识:

  • 基本的XML概念(标签、属性、命名空间)
  • 基本的文件系统知识
  • 至少会一门编程语言(Python/Java/C#等)
  • 会使用Word基本操作

即使你对XML不太熟悉,也不用担心,本书会在合适的地方进行讲解。


本章小结

  • Word文档格式是Word存储内容的约定,理解它才能进行编程处理
  • .doc是旧的二进制格式,.docx是新的Open XML格式
  • 本书只关注.docx格式,这是当前主流
  • 批量生成、批量提取、格式转换、修复损坏文档都需要理解文档格式
  • 具备基本XML和编程知识就可以阅读本书

下一章,我们来了解Word格式从二进制到XML的演化历史。

第2章:Open XML —— Word格式的现代化之路

学习目标

  • 了解Word格式的演化历史
  • 理解为什么会从二进制演变为XML
  • 了解Open XML的标准化过程
  • 理解向后兼容性的挑战

2.1 Word格式的演化简史

1. 二进制时代(1983-2006)

Word 1.0于1983年发布,从那时起一直到Word 2003,Word一直使用自定义的二进制文件格式。

这个阶段的特点:

  • 格式不公开,只有Microsoft掌握完整细节
  • 基于二进制流,解析非常困难
  • 随着Word功能增加,格式越来越复杂
  • 不同Word版本之间存在兼容性问题

即使在今天,一些老旧的文档仍以.doc格式存在。

2. Open XML诞生(2007)

2007年,Microsoft发布Office 2007,带来了全新的Open XML格式,默认扩展名从.doc变为.docx

这次变革的主要原因:

  • 开放性:二进制格式是私有的,XML格式开放标准
  • 可互操作性:其他软件更容易正确处理docx文件
  • 压缩存储:基于ZIP压缩,文件更小
  • 容错性:一个部分损坏不会导致整个文件报废
  • 易于处理:XML是标准格式,有大量工具库支持

3. 标准化(2008至今)

  • 2008年:Ecma International将Open XML批准为标准(ECMA-376)
  • 2012年:ISO/IEC将Open XML批准为国际标准(ISO/IEC 29500)
  • 至今:Open XML持续更新,支持新功能

现在,.docx已经成为事实上的办公文档标准,不仅Microsoft Word,LibreOffice、WPS等都支持。


2.2 为什么选择XML

为什么Microsoft选择XML作为新的格式基础?XML有什么优势?

XML的优势

  1. 结构化:XML使用标签清晰地表达结构,便于计算机解析
  2. 自描述:标签本身说明了内容是什么,可读性好
  3. 标准技术:有大量成熟的工具库处理XML
  4. 易于调试:XML是文本,可以直接用文本编辑器打开查看
  5. 扩展性好:新增功能不需要破坏原有格式

对比二进制格式

方面二进制XML
可读性不可读人类可读
解析难度
文件大小未压缩时较大ZIP压缩后更小
扩展性
容错性差(一点坏全坏)好(部分坏部分坏)
工具支持

关于文件大小

你可能会问:XML是文本,比二进制冗余,文件岂不是更大?

实际上:

  • .docx本质是ZIP压缩包,XML文本压缩率很高
  • 实际测试中,相同内容的.docx通常比.doc小30%-50%
  • 现代存储容量很大,文件大小已经不是主要问题

2.3 Open XML标准是什么

Open XML全称是Office Open XML,简称OOXML,是描述Office文档的开放标准。

标准涵盖什么

Open XML不仅仅涵盖Word文档,它涵盖了整个Office:

  • WordprocessingML:处理文字处理文档(就是.docx)
  • SpreadsheetML:处理电子表格(.xlsx)
  • PresentationML:处理演示文稿(.pptx)

本书只关注WordprocessingML,也就是Word文档部分。

两个标准组织

Open XML有两个版本的标准:

  1. ECMA-376:由Ecma International维护,更新更频繁
  2. ISO/IEC 29500:国际标准化组织的国际标准

两者基本一致,细节略有差异。对于大多数开发者,不需要关心这些细节差异。

在哪里获取标准

官方标准可以从以下位置获取:

  • Ecma官网:https://www.ecma-international.org/publications-and-standards/standards/ecma-376/
  • ISO官网:https://www.iso.org/standard/51407.html

标准文档非常详尽(几千页),但也非常枯燥。本书会提取开发者真正需要知道的内容,不需要你去阅读几千页的原始标准。


2.4 向后兼容性的挑战

格式变革带来了很多好处,但也带来了兼容性问题。

兼容性问题

  • 使用Word 2003及更早版本无法直接打开.docx文件
  • Microsoft为此发布了兼容包,可以让旧版本Word打开docx
  • 现在绝大多数用户已经升级到支持docx的版本
  • 但一些非常老旧的系统仍可能遇到问题

兼容性处理建议

开发中处理Word格式时:

  1. 优先使用.docx:这是现在的主流,几乎所有软件都支持
  2. 只在需要时支持.doc:如果用户确实有旧文档需求再支持
  3. 转换为docx处理:收到doc文件可以先转换为docx再处理
  4. 不要生成新的doc:新生成的文档都应该用docx格式

2.5 当前格式生态

现在的.docx格式生态是怎样的?

支持.docx的软件

  • Microsoft Word 2007及以后版本
  • LibreOffice / OpenOffice
  • WPS Office
  • Google Docs(可导入导出)
  • 大多数现代文字处理软件

编程库支持

因为是开放标准,现在有很多编程语言库可以处理docx:

  • Python:python-docx, python-pptx, docx2txt
  • Java:Apache POI (XWPF)
  • .NET:Open XML SDK, DocX
  • JavaScript:docx, mammoth
  • PHP:phpword

本书后续会介绍一些常用库的使用,但重点还是理解格式本身。掌握了原理,你可以在任何语言上使用这些库。


本章小结

  • Word格式经历了从二进制到Open XML的演化
  • XML带来了开放性、可互操作性、更好的容错性
  • Open XML是开放的国际标准,涵盖Word、Excel、PowerPoint
  • 本书只关注WordprocessingML(.docx)部分
  • .docx是现在的主流格式,优先使用docx

现在我们已经有了基础认识,下一章我们动手实践,打开一个docx文件,看看它的庐山真面目。

第3章:.docx本质 —— ZIP包结构

学习目标

  • 理解.docx本质上是一个ZIP压缩包
  • 学会手动解压.docx查看内部结构
  • 了解.docx包内的主要文件和目录
  • 理解关系文件(.rels)的作用
  • 理解内容类型文件的作用

3.1 .docx就是一个ZIP文件

很多新手不知道:.docx文件本质上就是一个ZIP压缩包

你可以直接验证这一点:

  1. 找一个.docx文件,复制一份
  2. 将扩展名从.docx改成.zip
  3. 用你的解压软件(7-Zip、WinRAR等)解压它
  4. 你会看到里面有很多文件和文件夹

这就是.docx的真相:它不是什么神秘的二进制格式,就是一堆XML文件和其他资源文件打包压缩在一个ZIP包里。

动手实践

练习:找一个你自己的Word文档,按照上面的步骤改后缀解压,看看里面有什么。这会帮助你建立直观认识。


3.2 .docx包内的文件结构

解压一个典型的.docx文件后,你会看到类似这样的结构:

├── _rels/
│   └── .rels
├── docProps/
│   ├── app.xml
│   └── core.xml
├── word/
│   ├── _rels/
│   │   └── document.xml.rels
│   ├── document.xml
│   ├── fontTable.xml
│   ├── footer1.xml
│   ├── header1.xml
│   ├── numbering.xml
│   ├── settings.xml
│   ├── styles.xml
│   ├── theme/
│   │   └── theme1.xml
│   └── media/
│       ├── image1.png
│       ├── image2.jpeg
│       └── ...
└── [Content_Types].xml

这就是一个标准的.docx结构。让我们逐层介绍每个部分是做什么的。

根目录文件

文件作用
[Content_Types].xml定义包内每个部分的内容类型
_rels/.rels定义包级关系,找到主文档在哪里

docProps目录

docProps 存放文档属性:

文件作用
core.xml核心属性:标题、作者、创建时间、修改时间等
app.xml应用属性:Word版本、页数、字数统计等

word目录(核心部分)

这是最重要的目录,文档主要内容都在这里:

文件作用
document.xml主文档内容,正文文字和结构都在这里
styles.xml样式定义
numbering.xml编号列表定义
settings.xml文档设置
fontTable.xml字体表
headerN.xml页眉(多个页眉多个文件)
footerN.xml页脚(多个页脚多个文件)
theme/theme1.xml主题定义
media/存放嵌入的图片等媒体文件
_rels/document.xml.rels文档内部关系,定义图片、页眉页脚等引用

3.3 关系文件(.rels)是什么

你已经看到包里有_rels/.relsword/_rels/document.xml.rels这些文件。这些是关系文件(Relationships)。

关系的作用

Open XML使用关系来表示资源之间的引用关系。为什么不直接用文件路径?

关系的好处:

  1. 解耦:源文件不需要知道目标文件的具体路径
  2. 可移动:移动目标文件只需要更新关系文件,不需要更新所有引用
  3. 类型明确:关系可以指定类型,说明这是什么类型的引用

关系文件格式

关系文件的结构很简单,举个例子,_rels/.rels

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Id="rId1"
                Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
                Target="word/document.xml"/>
  <Relationship Id="rId2"
                Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
                Target="docProps/core.xml"/>
  <Relationship Id="rId3"
                Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/extended-properties"
                Target="docProps/app.xml"/>
</Relationships>

每个<Relationship>元素表示一个关系:

  • Id:关系ID,在这个文件内唯一
  • Type:关系类型,说明这是什么关系
  • Target:目标文件的路径

从上面例子可以看出:

  • rId1指向word/document.xml,这就是主文档
  • 所以任何程序打开docx后,先读_rels/.rels就能找到主文档在哪里

文档内关系

word/_rels/document.xml.rels是主文档的关系文件,用来引用图片、页眉、页脚等:

<Relationships xmlns="...">
  <Relationship Id="rId1" Type="..." Target="header1.xml"/>
  <Relationship Id="rId2" Type="..." Target="footer1.xml"/>
  <Relationship Id="rId3" Type="..." Target="media/image1.png"/>
</Relationships>

在主文档document.xml中,通过r:id="rId1"来引用这些关系。我们后面看具体例子。


3.4 内容类型文件 [Content_Types].xml

根目录下的[Content_Types].xml定义了包内每个部分的内容类型。

为什么需要内容类型

ZIP包本身不知道里面每个文件是什么类型,所以需要一个文件来说明。

一个典型的[Content_Types].xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ContentTypes xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
  <Default Extension="rels"
            ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
  <Default Extension="xml"
            ContentType="application/xml"/>
  <Default Extension="png"
            ContentType="image/png"/>
  <Default Extension="jpeg"
            ContentType="image/jpeg"/>
  <Override PartName="/word/document.xml"
            ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
  <Override PartName="/word/styles.xml"
            ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
</ContentTypes>

两种声明方式

  1. Default:默认,按扩展名定义内容类型。所有扩展名为png的都是image/png类型。

  2. Override:覆盖,对特定路径的文件覆盖其内容类型。主要用于特殊的XML文件需要指定具体类型。

ContentType命名

Open XML的内容类型都遵循命名惯例:

application/vnd.openxmlformats-officedocument.[部分类型]+xml

例如:

  • 主文档:...wordprocessingml.document.main+xml
  • 样式:...wordprocessingml.styles+xml

3.5 文档属性在哪里

文档属性(作者、标题、时间等)存放在docProps目录下。

core.xml 核心属性

docProps/core.xml包含Dublin Core核心元数据:

<cp:coreProperties xmlns:cp="..." xmlns:dc="...">
  <dc:title>我的文档标题</dc:title>
  <dc:creator>张三</dc:creator>
  <cp:lastModifiedBy>张三</cp:lastModifiedBy>
  <dcterms:created>2024-01-01T12:00:00Z</dcterms:created>
  <dcterms:modified>2024-01-02T15:30:00Z</dcterms:modified>
</cp:coreProperties>

常见属性:

  • dc:title:文档标题
  • dc:creator:创建者/作者
  • cp:lastModifiedBy:最后修改者
  • dcterms:created:创建时间
  • dcterms:modified:最后修改时间

app.xml 扩展属性

docProps/app.xml包含应用程序特定属性:

<Properties xmlns="...">
  <Application>Microsoft Office Word</Application>
  <AppVersion>16.0000</AppVersion>
  <Pages>10</Pages>
  <Words>12345</Words>
  <Paragraphs>123</Paragraphs>
</Properties>

包含:

  • 使用的应用程序和版本
  • 页数、字数、段落数统计
  • 文档安全性等信息

3.6 动手解压看看真实结构

理论说了这么多,现在动手实践一下:

  1. 准备一个简单的docx文件:创建一个新Word文档,输入几行文字,插入一张图片,保存。
  2. 复制一份,不要改坏原文件。
  3. 改扩展名:把.docx改成.zip
  4. 解压:用解压软件解压。
  5. 浏览:看看各个文件,用文本编辑器打开XML文件看看内容。

你会看到:

  • XML都是文本,可读性很好
  • 结构和我们讲的一样
  • 你的文字在word/document.xml
  • 图片在word/media/

这个练习非常重要,亲手看过一次胜过读十遍书。


本章小结

  • .docx本质上就是一个ZIP压缩包,改后缀就能解压查看
  • ZIp包内包含多个XML文件和资源文件
  • _rels/.rels是入口,从中可以找到主文档位置
  • [Content_Types].xml定义各文件的内容类型
  • docProps/存放文档属性(作者、时间等)
  • word/document.xml是主文档,存放正文内容
  • word/styles.xml存放样式定义
  • 图片等媒体放在word/media/目录

下一章我们介绍Open XML标准和ECMA-376。

第4章:Open XML标准与ECMA-376

学习目标

  • 了解Open XML标准的组织
  • 理解WordprocessingML的概念
  • 了解XML命名空间在Open XML中的作用
  • 掌握主要的XML命名空间

4.1 什么是Open XML

Open XML全称是Office Open XML,是一个描述Office文档的开放文档标准。

Open XML不是一个单一格式,它是一个标准框架,定义了三种文档类型:

文档类型文件扩展名标记语言名称用途
文字处理.docxWordprocessingMLWord文档
电子表格.xlsxSpreadsheetMLExcel工作簿
演示文稿.pptxPresentationMLPowerPoint演示文稿

本书只关注WordprocessingML,也就是文字处理文档(.docx)部分。

标准的结构

ECMA-376标准分为几个部分:

  • 第1部分:基础知识和标记语言概述
  • 第2部分:开发生信包约定(就是我们讲的ZIP包结构)
  • 第3部分:Markup Compatibility和扩展
  • 第4部分:过渡兼容特性(主要是旧二进制格式相关)
  • 第5部分:WML (WordprocessingML)细节
  • … 其他部分针对Excel和PowerPoint

WordprocessingML的全部细节在第5部分,大约一千多页。本书会提取开发者常用的内容,不需要你去读那一千多页。


4.2 XML命名空间

Open XML使用XML,自然就会用到XML命名空间。如果你对XML命名空间不太熟悉,没关系,这里简单回顾一下。

为什么需要命名空间

当多个XML词汇混合在一起时,可能会有同名的元素。命名空间用来区分它们。

比如,我们说“表格“,在Word里是表格,在HTML里也是表格。如果放在一起,怎么区分?用命名空间。

Open XML中的命名空间

Open XML中的每个词汇都有自己的XML命名空间URI。在根元素上声明,前缀通常简写:

<w:document
  xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
  xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
  xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">

这里:

  • w: 前缀绑定到WordprocessingML主命名空间
  • r: 前缀绑定到关系命名空间
  • a: 前缀绑定到DrawingML(绘图)命名空间

前缀只是简写,真正区分命名空间的是URI。

主要的命名空间

下表列出了你会经常遇到的命名空间:

前缀命名空间URI用途
whttp://schemas.openxmlformats.org/wordprocessingml/2006/mainWordprocessingML主命名空间,绝大多数元素都在这里
rhttp://schemas.openxmlformats.org/officeDocument/2006/relationships关系引用
ahttp://schemas.openxmlformats.org/drawingml/2006/mainDrawingML,绘图(图片、图形)
wphttp://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawingWord绘图
pichttp://schemas.openxmlformats.org/drawingml/2006/picture图片
mchttp://schemas.openxmlformats.org/markup-compatibility/2006标记兼容性
cthttp://schemas.openxmlformats.org/package/2006/content-types内容类型
relhttp://schemas.openxmlformats.org/package/2006/relationships包级关系

本书后面的示例代码中,我们会一直使用这个常用前缀约定。

完整参考

所有命名空间的完整参考放在附录A,需要时可以查阅。


4.3 Open XML设计原则

Open XML在设计上遵循几个重要原则:

1. 显式优于隐式

Open XML尽可能显式地写出格式设置,而不是依赖大量默认值推断。这样更容易处理。

当然,为了文件大小,仍然有很多可选的默认设置,但总体原则是显式。

2. 去中心化结构

不同类型的内容放在不同的XML文件中:

  • 主内容在document.xml
  • 样式在styles.xml
  • 页眉单独文件
  • 图片单独文件

好处:

  • 只需要修改需要改的部分
  • 一部分损坏不影响其他部分
  • 工具可以只处理它关心的部分

3. 向后兼容

通过标记兼容性(Markup Compatibility)机制,新版本可以添加新元素,旧处理器可以安全忽略它们。

4. 开放透明

格式完全开放公开,任何人都可以实现,不需要专利许可。


4.4 标准与实现

标准归标准,实现归实现。实际情况是:

Microsoft Word的实际实现

  • 虽然有标准,但Microsoft Word在实际保存docx时会有自己的一些习惯
  • 偶尔会有一些扩展
  • 绝大多数情况都符合标准
  • 主要功能都兼容

其他软件的实现

  • LibreOffice、WPS等都能读写docx
  • 基本兼容
  • 复杂格式偶尔会有差异

给开发者的建议

  • 遵循标准写法,绝大多数软件都能正确打开
  • 测试的时候最好在Word、LibreOffice都验证一下
  • 复杂格式需要注意兼容性

本章小结

  • Open XML定义了三种文档类型,我们关注WordprocessingML(.docx)
  • XML命名空间用来区分不同XML词汇
  • 记住主要的命名空间前缀约定,本书一直使用这个约定
  • Open XML设计原则:显式、去中心化、向后兼容、开放

下一章我们入门文档结构,看看一个最简单的document.xml长什么样。

第5章:文档结构入门

学习目标

  • 理解Word文档的整体结构
  • 认识document.xml的基本框架
  • 理解块(block)和行(inline)层次
  • 理解段落(paragraph)和运行(run)的概念
  • 理解属性的表示方式

5.1 document.xml 的整体结构

我们已经知道,主文档内容在word/document.xml中。让我们来看一个最简单的完整例子:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:body>
    <w:p>
      <w:r>
        <w:t>你好,Word!</w:t>
      </w:r>
    </w:p>
    <w:sectPr/>
  </w:body>
</w:document>

这就是一个只包含一段文字“你好,Word!“的完整document.xml。我们逐层拆解。

层次结构

w:document
└── w:body          (文档正文)
    ├── w:p          (段落Paragraph)
    │   └── w:r      (运行Run)
    │       └── w:t  (文本Text)
    └── w:sectPr     (节属性Section Properties)

最外层是<w:document>,里面是<w:body>,正文都在body里。


5.2 核心概念:段落(p)和运行(r)

理解段落和运行是理解WordprocessingML的关键。

段落(Paragraph,w:p)

  • 段落是Word中块级内容的基本单位
  • 一个段落对应Word中你敲一个回车产生的段落
  • 每个段落有自己的段落格式(对齐、缩进、间距等)
  • 段落可以包含多个运行(run)

运行(Run,w:r)

  • 运行是段落中具有相同格式的一段文本
  • 同一个段落中,如果文字格式变化了,就需要分成多个run
  • 例如:一句话中,一部分是粗体,一部分不是,就需要两个run

文本(Text,w:t)

  • <w:t>元素包含实际的文本内容
  • 一个run中可以有一个<w:t>

例子:多个run的段落

来看一个例子:这句话“这是粗体文字“,“粗体“两个字是粗体,XML会写成:

<w:p>
  <w:r>
    <w:t>这是</w:t>
  </w:r>
  <w:r>
    <w:rPr>
      <w:b/>
    </w:rPr>
    <w:t>粗体</w:t>
  </w:r>
  <w:r>
    <w:t>文字</w:t>
  </w:r>
</w:p>

看到了吗?因为格式变化了,所以分成了三个run:

  • 第一个run:“这是”,普通格式
  • 第二个run:“粗体”,带有粗体属性<w:b/>
  • 第三个run:“文字”,回到普通格式

这就是run的作用:同一个段落内,不同格式要分开。


5.3 结构层次总结

WordprocessingML的结构层次:

层次元素作用
文档w:document整个文档根
正文w:body正文容器
段落w:p块级单位,一个回车就是一段
运行w:r同一格式的文本片段
文本w:t实际文本内容

为什么这么设计?

这样的设计很灵活:

  • 可以在段落中间改变格式
  • 每个run独立设置格式
  • 结构清晰,容易解析

5.4 属性的表示方式

在Open XML中,格式属性怎么表示?

属性元素

大多数格式属性都有专门的元素表示:

  • 粗体:<w:b/>
  • 斜体:<w:i/>
  • 下划线:<w:u w:val="single"/>

属性存储位置

  • 段落属性存在<w:pPr>(paragraph properties)
  • 运行属性存在<w:rPr>(run properties)

例如:

<w:p>
  <w:pPr>
    <!-- 段落属性在这里 -->
    <w:jc w:val="center"/>  <!-- 居中对齐 -->
  </w:pPr>
  <w:r>
    <w:rPr>
      <!-- 运行属性在这里 -->
      <w:b/>                  <!-- 粗体 -->
      <w:color w:val="FF0000"/> <!-- 红色 -->
    </w:rPr>
    <w:t>居中和红色粗体</w:t>
  </w:r>
</w:p>

w:val 属性

很多属性元素使用w:val属性来指定值:

<w:sz w:val="24"/>  <!-- 字号:24半磅 = 12磅 -->
<w:jc w:val="right"/> <!-- 对齐:右对齐 -->

布尔属性的表示

对于开关类型的属性(开/关),有几种表示方式:

  1. 只写标签,没有val - 表示开

    <w:b/>  <!-- 粗体打开 -->
    
  2. 用val表示 - w:val="1"w:val="true"表示开,w:val="0"w:val="false"表示关

    <w:b w:val="1"/>  <!-- 粗体打开 -->
    <w:b w:val="0"/>  <!-- 粗体关闭 -->
    

两种写法Word都支持,第一种更简洁。


5.5 节属性(sectPr)

w:body的最后,你通常会看到<w:sectPr>元素。

什么是节(section)?

  • 节是Word中页面设置的单位
  • 一个文档可以分成多个节,每节可以有不同的页面设置
  • 节属性包含页面大小、方向、边距等设置
  • 最后一个节的节属性放在body末尾

最简单的情况,文档只有一节,所以body最后放一个sectPr

<w:body>
  <!-- ... 所有内容 ... -->
  <w:sectPr/>
</w:body>

如果有分页设置不同的页面方向(比如前几页纵向,中间一页横向,后面又纵向),就需要分多个节,每个节有自己的sectPr

我们后面讲页眉页脚和分节的时候会详细说。


5.6 一个完整的例子

让我们来看一个稍微完整一点的例子,包含两段不同对齐方式,一些文字格式:

<?xml version="1.0" encoding="UTF-8"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:body>

    <!-- 第一段:居中标题 -->
    <w:p>
      <w:pPr>
        <w:jc w:val="center"/>
      </w:pPr>
      <w:r>
        <w:rPr>
          <w:b/>
          <w:sz w:val="36"/>
        </w:rPr>
        <w:t>标题</w:t>
      </w:r>
    </w:p>

    <!-- 第二段:左对齐正文 -->
    <w:p>
      <w:pPr>
        <w:jc w:val="left"/>
      </w:pPr>
      <w:r>
        <w:t>这是一段普通文字,这里有</w:t>
      </w:r>
      <w:r>
        <w:rPr>
          <w:i/>
        </w:rPr>
        <w:t>斜体</w:t>
      </w:r>
      <w:r>
        <w:t>和</w:t>
      </w:r>
      <w:r>
        <w:rPr>
          <w:b/>
        </w:rPr>
        <w:t>粗体</w:t>
      </w:r>
      <w:r>
        <w:t>。</w:t>
      </w:r>
    </w:p>

    <w:sectPr/>
  </w:body>
</w:document>

这个例子展示了:

  • 段落级格式(对齐)放在w:pPr
  • 运行级格式(粗体、斜体、字号)放在w:rPr
  • 格式变化就分成多个run

现在你应该能看懂基本的document.xml了。


5.7 动手练习

现在你可以自己动手试试:

  1. 解压一个简单的docx文件
  2. 用文本编辑器打开word/document.xml
  3. 找找看:w:document, w:body, w:p, w:r, w:t这些元素
  4. 看看段落属性w:pPr和运行属性w:rPr在哪里
  5. 看看不同格式文字是不是分成不同的run

亲手看一次,你对结构的理解会深刻很多。


本章小结

  • document.xml的基本结构:w:documentw:bodyw:pw:rw:t
  • 段落(p)是块级单位,对应一次回车
  • 运行(r)是同一格式的文本片段,段落内格式变化就分多个run
  • 段落属性在w:pPr,运行属性在w:rPr
  • 属性通常用w:val指定值,布尔属性可以只写标签表示开启
  • w:sectPr是节属性,放在body最后,包含页面设置

现在我们已经入门了,下一章深入讲解主文档结构。

第6章:主文档结构(document.xml)

学习目标

  • 深入理解document.xml的完整结构
  • 理解body的内容模型
  • 掌握块级元素的种类
  • 理解删除标记和批注的存储方式

6.1 document.xml 根结构

我们已经看过基本结构,现在来看完整的根结构:

<?xml version="1.0" encoding="UTF-8"?>
<w:document
  xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
  xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">

  <w:background w:val="FFFFFF"/>

  <w:body>

    <!-- 这里是主要内容:段落、表格... -->
    <w:p>...</w:p>
    <w:tbl>...</w:tbl>

    <!-- 节属性 -->
    <w:sectPr>
      <w:pgSz w:w="12240" w:h="15840"/>  <!-- A4纸 -->
      <w:pgMar w:top="1440" w:right="1440"
               w:bottom="1440" w:left="1440"/> <!-- 页边距 -->
    </w:sectPr>

  </w:body>

</w:document>

根元素

根元素永远是<w:document>,声明必要的命名空间。

背景颜色

<w:background> 指定整个文档的背景颜色,w:val 是RGB十六进制值。如果是白色就是FFFFFF,这个元素可选。

body

<w:body> 包含文档的所有正文内容,以及最后一个节的节属性w:sectPr


6.2 body可以包含什么

<w:body>中,可以包含以下块级元素:

元素说明
w:p段落(Paragraph)
w:tbl表格(Table)
w:sdt结构化文档标签(内容控件Content Control)
w:sectPr节属性,必须在最后

所以body的内容就是一系列的段落和表格,最后跟着节属性。

多级结构

表格内部可以包含段落,所以结构可以嵌套:

body
├── p
├── tbl
│   └── tr
│       └── tc
│           └── p
└── sectPr

6.3 段落(p)的完整结构

我们已经知道段落基本结构,现在看完整的段落结构:

<w:p>
  <w:pPr>             <!-- 段落属性 -->
    <w:pStyle w:val="Heading1"/>  <!-- 样式引用 -->
    <w:jc w:val="center"/>        <!-- 对齐方式 -->
    <w:ind w:left="480"/>         <!-- 左缩进 -->
    <w:spacing w:line="360"/>      <!-- 行间距 -->
    <!-- ... 其他段落属性 ... -->
  </w:pPr>

  <!-- 段落内容:一系列run和其他元素 -->
  <w:r>
    <w:rPr>...</w:rPr>
    <w:t>文本</w:t>
  </w:r>
  <w:br/>  <!-- 换行符 -->
  <w:r>...</w:r>

</w:p>

pPr(段落属性)

pPr包含该段落的所有格式属性:

  • 样式引用:w:pStyle
  • 对齐:w:jc
  • 缩进:w:ind
  • 间距:w:spacing
  • 边框:w:pBdr
  • 分页设置:w:pageBreakBefore
  • …等等

我们后面会分章节详细讲解这些属性。

段落内容

段落属性之后,是段落内容,可以包含:

元素说明
w:r文本运行
w:br手动换行(软回车)
w:cr回车(很少用)
w:tab制表符
w:drawing绘图(图片、形状)
w:hyperlink超链接
w:commentRangeStart / w:commentRangeEnd批注范围
w:pict旧版图片(VML)

最常见的就是多个w:r(运行)。


6.4 运行(r)的完整结构

运行的完整结构:

<w:r>
  <w:rPr>             <!-- 运行属性 -->
    <w:rStyle w:val="Emphasis"/>  <!-- 字符样式引用 -->
    <w:b/>                       <!-- 粗体 -->
    <w:i/>                       <!-- 斜体 -->
    <w:color w:val="FF0000"/>    <!-- 字体颜色 -->
    <w:sz w:val="24"/>           <!-- 字号 -->
    <!-- ... 其他字符属性 ... -->
  </w:rPr>

  <w:t>文本内容</w:t>  <!-- 文本 -->
</w:r>

rPr(运行属性)

rPr包含字符级别格式:

  • 样式引用:w:rStyle
  • 粗体:w:b
  • 斜体:w:i
  • 下划线:w:u
  • 删除线:w:strike
  • 字体:w:rFonts
  • 字号:w:sz
  • 颜色:w:color
  • …等等

t(文本)元素

<w:t>包含实际文本。需要注意:

  • XML会自动处理特殊字符:< 要写成 &lt;& 要写成 &amp;
  • 如果文本开头或结尾有空格,需要加xml:space="preserve"保留空格:
    <w:t xml:space="preserve"> 两边有空格 </w:t>
    

6.5 特殊内容

让我们看看一些常见的特殊内容在XML中是怎么表示的。

换行符

手动换行(软换行,Shift+Enter)用<w:br/>表示:

<w:r>
  <w:t>第一行</w:t>
</w:r>
<w:br/>
<w:r>
  <w:t>第二行</w:t>
</w:r>

换行仍然在同一个段落内,只是换行。

制表符

制表符用<w:tab/>表示:

<w:r>
  <w:t>开头</w:t>
  <w:tab/>
  <w:t>缩进内容</w:t>
</w:r>

分页符

硬分页符(插入分页)一般表示为段落前分页,在段落属性里:

<w:p>
  <w:pPr>
    <w:pageBreakBefore/>
  </w:pPr>
  ...
</w:p>

表示这个段落要放在新的一页。


6.6 修订(Track Changes)

当开启修订功能后,删除和插入的内容怎么存储?

删除的内容

删除的内容放在<w:del>里:

<w:del w:id="1" w:author="张三" w:date="2024-01-01T10:00:00Z">
  <w:p>
    <w:r>
      <w:delText>被删除的文字</w:delText>
    </w:r>
  </w:p>
</w:del>

删除的内容仍然保存在文档中,Word会显示删除线,用户可以选择接受或拒绝。

插入的内容

插入的内容用<w:ins>包裹:

<w:ins w:id="2" w:author="张三" w:date="2024-01-01T10:00:00Z">
  <w:r>
    <w:t>新插入的文字</w:t>
  </w:r>
</w:ins>

Word会用下划线标记插入内容。

作者和日期

每个插入删除都记录:

  • w:id:修订ID
  • w:author:作者名称
  • w:date:修改日期

6.7 批注(Comment)

批注怎么存储?

批注本身存在word/comments.xml文件中,正文里只有范围标记:

<!-- 在document.xml中 -->
<w:commentRangeStart w:id="1"/>
<w:p>
  <w:r>
    <w:t>被批注的文字</w:t>
  </w:r>
</w:p>
<w:commentRangeEnd w:id="1"/>
<w:commentReference w:id="1"/>

真正的批注内容在comments.xml

<w:comments>
  <w:comment w:id="1" w:author="张三" w:date="...">
    <w:p>
      <w:r>
        <w:t>这是批注内容</w:t>
      </w:r>
    </w:p>
  </w:comment>
</w:comments>

这样设计的好处是批注内容集中存放,正文只需要标记范围。


6.8 超链接

超链接用<w:hyperlink>表示:

<w:hyperlink r:id="rId1">
  <w:r>
    <w:rPr>
      <w:rStyle w:val="Hyperlink"/>
      <w:color w:val="0000FF"/>
      <w:u w:val="single"/>
    </w:rPr>
    <w:t>点击这里</w:t>
  </w:r>
</w:hyperlink>

超链接的目标URL存在关系文件document.xml.rels中:

<Relationship Id="rId1" Type="..." Target="https://example.com"/>

本章小结

  • document.xml根结构:w:documentw:body → 内容 + w:sectPr
  • body可以包含段落和表格等块级元素
  • 段落结构:w:pw:pPr(属性) + 内容(多个w:r
  • 运行结构:w:rw:rPr(属性) + w:t(文本)
  • 删除内容放在w:del,插入内容放在w:ins(修订追踪)
  • 批注范围标记在正文,内容在comments.xml

下一章我们讲解样式定义机制,这是Word格式理解的重点和难点。

第7章:样式定义机制(styles.xml)

学习目标

  • 理解Word样式体系架构
  • 理解内嵌样式和命名样式
  • 理解段落样式和字符样式的区别
  • 理解样式继承机制
  • 掌握styles.xml的结构
  • 理解默认样式的作用

7.1 为什么需要样式

样式是Word排版的核心机制。理解了样式,你才能真正理解Word排版。

如果没有样式:

  • 你需要手动给每一段文字设置字体、字号、对齐、间距
  • 修改格式需要一处处改,非常麻烦
  • 格式很难保持一致

使用样式:

  • 把一套格式属性命名保存为样式
  • 给段落应用样式,就自动应用所有格式
  • 修改样式,所有应用该样式的地方自动更新
  • 整个文档格式保持一致
  • 可以自动生成目录

在docx中,所有样式定义都集中放在word/styles.xml


7.2 样式的分类

Word中的样式分为几类:

按应用对象分

类型说明存储位置引用
段落样式应用于整个段落pPr中用pStyle引用
字符样式应用于部分文字rPr中用rStyle引用
链接样式既是段落也是字符Word UI中可以两种方式用
表格样式应用于表格表格引用
列表样式应用于编号列表numbering.xml引用

最常用的是段落样式字符样式

按来源分

  • 内置样式:Word自带的样式,比如“标题1“、“标题2”、“正文“等
  • 自定义样式:用户自己创建的样式

保存在哪里

  • 所有样式定义都在styles.xml
  • 每个样式一个<w:style>元素
  • 每个样式有唯一的样式ID和名称

7.3 styles.xml 的整体结构

一个典型的styles.xml结构:

<w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">

  <!-- 默认格式定义 -->
  <w:docDefaults>
    <w:rPrDefault>...</w:rPrDefault>  <!-- 默认字符格式 -->
    <w:pPrDefault>...</w:pPrDefault>  <!-- 默认段落格式 -->
  </w:docDefaults>

  <!-- 样式定义 -->
  <w:style w:type="paragraph" w:styleId="Normal" w:default="1">
    <w:name w:val="Normal"/>
    <w:basedOn w:val="Normal"/>
    <w:pPr>...</w:pPr>  <!-- 段落属性 -->
    <w:rPr>...</w:rPr>  <!-- 字符属性 -->
  </w:style>

  <w:style w:type="paragraph" w:styleId="Heading1">
    <w:name w:val="Heading 1"/>
    <w:basedOn w:val="Normal"/>
    <w:next w:val="Normal"/>
    <w:pPr>...</w:pPr>
    <w:rPr>...</w:rPr>
  </w:style>

  <w:style w:type="character" w:styleId="Emphasis">
    <w:name w:val="强调"/>
    <w:rPr>...</w:rPr>
  </w:style>

</w:styles>

结构很清晰:

  1. 开头是docDefaults定义默认格式
  2. 然后是每个样式一个w:style元素

7.4 w:style 元素详解

我们来看一个完整的样式定义:

<w:style w:type="paragraph" w:styleId="Heading1" w:default="0" w:customStyle="1">
  <w:name w:val="标题 1"/>
  <w:basedOn w:val="Normal"/>
  <w:next w:val="Normal"/>
  <w:link w:val="Heading1Char"/>
  <w:uiPriority w:val="1"/>
  <w:rsid w:val="00B63F5E"/>
  <w:pPr>
    <w:outlineLvl w:val="0"/>
    <w:spacing w:before="360" w:after="240"/>
    <w:keepNext/>
  </w:pPr>
  <w:rPr>
    <w:sz w:val="36"/>
    <w:b/>
  </w:rPr>
</w:style>

属性

属性说明
w:type样式类型:paragraph段落,character字符,table表格,numbering列表
w:styleId样式ID,文档内唯一,用来引用,程序用这个
w:default是否是该类型的默认样式,1表示默认
w:customStyle1表示是用户自定义样式,0表示内置样式

子元素

元素说明
w:name样式的显示名称,用户在Word界面看到的名称
w:basedOn基于哪个样式,样式继承
w:next应用此样式段落回车后下一段默认样式
w:pPr段落属性,应用此样式的段落默认格式
w:rPr字符属性,应用此样式的文字默认格式

样式ID vs 名称

  • styleId 是内部ID,通常是英文不变,比如Heading1
  • name 是显示名称,本地化会变,中文就是“标题 1“
  • 程序引用样式用styleId,不是name

7.5 样式继承机制

样式支持继承:一个样式可以基于另一个样式,继承它的所有属性,然后覆盖自己需要改的部分。

继承语法

<w:style w:type="paragraph" w:styleId="MyHeading">
  <w:name w:val="我的标题"/>
  <w:basedOn w:val="Heading1"/>  <!-- 基于标题1 -->
  <w:pPr>
    <w:spacing w:before="480"/> <!-- 只改段前间距,其他继承Heading1 -->
  </w:pPr>
</w:style>

属性查找顺序

当应用一个样式时,属性查找顺序:

  1. 当前样式定义的属性 → 使用
  2. 如果没有,找basedOn父样式 → 使用父样式定义
  3. 如果父样式也没有,继续找祖父样式…
  4. 最后找默认样式 → 使用默认

为什么要继承

  • 减少重复定义
  • 修改共同属性只需要改父样式
  • 保持一致性
  • 方便批量修改

Normal正文样式

通常Normal(正文)是最基础的样式,大部分段落样式都基于它:

<w:style w:type="paragraph" w:styleId="Normal" w:default="1">
  <w:name w:val="正文"/>
  <!-- 定义默认字体、字号、行间距等 -->
</w:style>

<w:style w:type="paragraph" w:styleId="Heading1">
  <w:basedOn w:val="Normal"/> <!-- 继承正文 -->
  <!-- 只覆盖需要变化的属性 -->
</w:style>

7.6 默认格式 docDefaults

styles.xml开头,有个docDefaults元素,定义文档的默认格式

<w:docDefaults>
  <w:rPrDefault>
    <w:rPr>
      <!-- 默认字符格式 -->
      <w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体"/>
      <w:sz w:val="24"/>  <!-- 默认12磅 -->
    </w:rPr>
  </w:rPrDefault>
  <w:pPrDefault>
    <w:pPr>
      <!-- 默认段落格式 -->
      <w:spacing w:line="360"/> <!-- 默认单倍行距 -->
    </w:pPr>
  </w:pPrDefault>
</w:docDefaults>

默认格式的作用

如果:

  • 段落没有应用任何样式
  • 样式中没有定义某个属性
  • 继承链上都没有找到

就使用docDefaults中的默认格式。

可以把它理解为最基础的默认值


7.7 段落样式 vs 字符样式

让我们再明确一下两者的区别:

段落样式

  • 应用于整个段落
  • 在段落属性中引用:
    <w:p>
      <w:pPr>
        <w:pStyle w:val="Heading1"/> <!-- 引用段落样式 -->
      </w:pPr>
    </w:p>
    
  • 包含段落属性和字符属性
  • 整个段落都使用该样式的字符属性

字符样式

  • 应用于段落内部分文字
  • 在运行属性中引用:
    <w:r>
      <w:rPr>
        <w:rStyle w:val="Emphasis"/> <!-- 引用字符样式 -->
      </w:rPr>
    </w:r>
    
  • 只包含字符属性
  • 只影响应用的那部分文字

例子:段落样式+字符样式

<!-- 段落应用"标题1"段落样式 -->
<w:p>
  <w:pPr>
    <w:pStyle w:val="Heading1"/>
  </w:pPr>

  <!-- 标题前几个字使用"强调"字符样式 -->
  <w:r>
    <w:rPr>
      <w:rStyle w:val="Emphasis"/>
    </w:rPr>
    <w:t>开头</w:t>
  </w:r>

  <!-- 剩下的字使用段落样式的默认字符格式 -->
  <w:r>
    <w:t>其他文字</w:t>
  </w:r>
</w:p>

这样很灵活:整个段落是标题样式,局部可以再应用字符样式变化格式。


7.8 样式优先级

如果多个格式设置作用于同一个文字,优先级是怎样的?

优先级从高到低:

  1. 直接格式(直接在rPr/pPr设置的属性)- 最高
  2. 字符样式 - 高于段落样式
  3. 段落样式 - 低于字符样式
  4. 默认样式(Normal)
  5. docDefaults默认格式 - 最低

举个例子:

  • 段落应用“正文“样式,字体宋体,五号
  • 段落中某个run应用“强调“字符样式,斜体
  • 这个run还直接设置了蓝色

最终结果:宋体,五号,斜体,蓝色。


7.9 内置样式ID参考

常用的内置样式styleId你可以直接用:

styleId中文名称类型
Normal正文段落
Heading1标题 1段落
Heading2标题 2段落
Heading3标题 3段落
Title标题段落
Subtitle副标题段落
Emphasis强调字符
Strong加粗字符
Hyperlink超链接字符
FootnoteText脚注文字段落

7.10 实际例子:一个简单的styles.xml

让我们看一个完整简单的例子:

<?xml version="1.0" encoding="UTF-8"?>
<w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">

  <!-- 默认格式 -->
  <w:docDefaults>
    <w:rPrDefault>
      <w:rPr>
        <w:rFonts w:ascii="仿宋_GB2312" w:eastAsia="仿宋_GB2312"
                  w:hAnsi="仿宋_GB2312"/>
        <w:sz w:val="24"/> <!-- 12磅 -->
      </w:rPr>
    </w:rPrDefault>
    <w:pPrDefault>
      <w:pPr>
        <w:spacing w:line="360"/> <!-- 单倍行距 -->
      </w:pPr>
    </w:pPrDefault>
  </w:docDefaults>

  <!-- 正文样式(默认段落样式) -->
  <w:style w:type="paragraph" w:styleId="Normal" w:default="1">
    <w:name w:val="正文"/>
  </w:style>

  <!-- 标题1 -->
  <w:style w:type="paragraph" w:styleId="Heading1">
    <w:name w:val="标题 1"/>
    <w:basedOn w:val="Normal"/>
    <w:next w:val="Normal"/>
    <w:pPr>
      <w:outlineLvl w:val="0"/>
      <w:spacing w:before="360" w:after="240"/>
    </w:pPr>
    <w:rPr>
      <w:sz w:val="36"/> <!-- 18磅 -->
      <w:b/>
      <w:rFonts w:ascii="黑体" w:eastAsia="黑体" w:hAnsi="黑体"/>
    </w:rPr>
  </w:style>

  <!-- 标题2 -->
  <w:style w:type="paragraph" w:styleId="Heading2">
    <w:name w:val="标题 2"/>
    <w:basedOn w:val="Normal"/>
    <w:next w:val="Normal"/>
    <w:pPr>
      <w:outlineLvl w:val="1"/>
      <w:spacing w:before="240" w:after="120"/>
    </w:pPr>
    <w:rPr>
      <w:sz w:val="28"/> <!-- 14磅 -->
      <w:b/>
    </w:rPr>
  </w:style>

  <!-- 强调字符样式 -->
  <w:style w:type="character" w:styleId="Emphasis">
    <w:name w:val="强调"/>
    <w:basedOn w:val="DefaultParagraphFont"/>
    <w:rPr>
      <w:i/>
      <w:color w:val="800000"/>
    </w:rPr>
  </w:style>

</w:styles>

这个例子定义了:

  • 默认字体:仿宋,12磅,单倍行距
  • 正文样式:使用默认
  • 标题1:黑体,18磅加粗,段前间距360半磅,段后240半磅
  • 标题2:14磅加粗,间距小一点
  • 强调字符:斜体,棕色

本章小结

  • 所有样式定义都在word/styles.xml
  • 样式主要分为段落样式和字符样式
  • 段落样式在pPr中用pStyle引用,影响整个段落
  • 字符样式在rPr中用rStyle引用,影响局部文字
  • 样式支持继承,通过basedOn基于另一个样式
  • docDefaults定义最基础的默认格式
  • 优先级:直接格式 > 字符样式 > 段落样式 > 默认

样式是Word排版的核心,理解样式机制对你无论是编程处理文档还是手动排版都非常重要。

下一章我们讲解字体与字号设置。

第8章:字体与字号设置

学习目标

  • 理解Word中字体信息的存储方式
  • 掌握字号单位(半磅)
  • 理解字体嵌入机制
  • 了解中文字体处理的特点
  • 理解字体查找回退机制

8.1 字体信息存储在哪里

字体信息可以存储在多个层级:

  1. docDefaults - 文档默认字体
  2. 样式 - 每个样式可以定义自己的字体
  3. 运行rPr - 单个run可以直接指定字体

优先级:直接run指定 > 样式 > docDefaults。

字体元素 w:rFonts

字体信息用<w:rFonts>元素表示,位于rPr内:

<w:rPr>
  <w:rFonts
    w:ascii="宋体"
    w:eastAsia="宋体"
    w:hAnsi="宋体"
    w:cs="宋体"/>
</w:rPr>

四个属性分别对应不同字符编码范围:

属性作用
w:asciiASCII字符(0-127)使用的字体
w:eastAsia东亚字符(中日韩)使用的字体
w:hAnsiWindows ANSI字符(128-255)使用的字体
w:cs复杂文种(Complex Script,如阿拉伯语、印地语等)

中文字体的写法

对于中文文档,通常四个属性都设为同一个中文字体就可以:

<w:rFonts w:ascii="黑体" w:eastAsia="黑体" w:hAnsi="黑体" w:cs="黑体"/>

这样不管什么字符都用这个字体。

只指定部分属性

如果只需要改东亚字体,其他用继承,可以只写eastAsia

<w:rFonts w:eastAsia="微软雅黑"/>

其他属性继承自父样式或默认。


8.2 字号设置

单位:半磅

Word中字号单位是半磅(half-points)。也就是说:

  • 1磅 = 2半磅
  • 所以 12磅 = 24半磅

为什么用半磅?历史原因,Word早期这样设计,一直保留下来了。

w:sz 元素

字号用<w:sz>元素表示,值是半磅数:

<w:rPr>
  <w:sz w:val="24"/>  <!-- 24半磅 = 12磅 -->
</w:rPr>

字号对照

常见中文字号对应的磅值和半磅数:

中文字号磅值半磅数(w:val)
八号510
七号5.511
小六号6.513
六号7.515
小五号918
五号10.521
小四1224
四号1428
小三1530
三号1632
小二1836
二号2244
小一2448
一号2652
小初3672
初号4284

记忆要点:五号=21,小四=24,四号=28,二号=44。

中文简体和中文繁体字体名称差异

注意字体名称在不同地区版本中名称可能不同:

  • 简体中文Word:宋体黑体仿宋_GB2312楷体_GB2312
  • 繁体中文Word:新细明体标楷体微软正黑体

如果是给简体中文用户用,使用简体名称。兼容性会更好。


8.3 字体颜色

字体颜色用<w:color>元素:

<w:rPr>
  <w:color w:val="FF0000"/>  <!-- 红色 RGB -->
</w:rPr>

w:val是十六进制RGB值,不带#号:

  • 红色:FF0000
  • 绿色:00FF00
  • 蓝色:0000FF
  • 黑色:000000
  • 白色:FFFFFF

也可以使用主题颜色:

<w:color w:themeColor="accent1" w:themeShade="80"/>

但直接用RGB更直观,兼容性更好。


8.4 字体效果

常见字体效果元素:

效果元素说明
粗体<w:b/>布尔,存在即开启
斜体<w:i/>布尔,存在即开启
删除线<w:strike/>删除线
双删除线<w:dstrike/>双删除线
下划线<w:u w:val="single"/>下划线类型
上标<w:vertAlign w:val="superscript"/>上标
下标<w:vertAlign w:val="subscript"/>下标
小型大写<w:smallCaps/>小型大写字母
全部大写<w:caps/>全部大写
隐藏文字<w:vanish/>隐藏文字

下划线类型

w:uw:val常见值:

说明
single单下划线
double双下划线
dotted点线
dash虚线
wave波浪线
none无下划线(取消)

例子:组合效果

<w:rPr>
  <w:b/>
  <w:i/>
  <w:color w:val="0000FF"/>
  <w:u w:val="single"/>
</w:rPr>

这就是蓝色粗斜体带下划线。


8.5 字体嵌入

Word可以把字体嵌入到文档中,这样即使对方电脑没有这个字体,也能正确显示和打印。

字体嵌入存储在哪里

字体数据存储在word/fontTable.xml中。

<w:fontTable xmlns:w="...">
  <w:font w:name="宋体">
    <w:embedFont w:id="1"/>
  </w:font>
</w:fontTable>

实际字体数据作为嵌入font文件存在ZIP包内,通过关系引用。

嵌入方式

有两种嵌入方式:

  1. 完全嵌入:嵌入整个字体文件,文件变大,但可以编辑
  2. 子集嵌入:只嵌入文档中用到的字符,文件小,但不能编辑(只能显示打印)

法律问题

⚠️ 重要提示

  • 大多数商业字体是有许可证的,不允许随意嵌入分发
  • 嵌入字体可能违反字体的使用许可
  • 在文档中嵌入字体之前,请确认你有嵌入权限
  • 开源字体一般允许嵌入

开发建议

  • 如果是内部使用,考虑字体嵌入
  • 如果是公开发布,尽量使用系统默认字体
  • PDF格式导出后再分发,可以避免字体问题

8.6 字体查找与回退

当Word打开文档,找不到指定字体时,会怎么处理?

字体回退机制

  1. Word按名称找字体
  2. 如果找不到,根据字体特征找相似字体替代
  3. 如果还是找不到,用默认替代字体(通常是Times New Roman + 宋体)

兼容性问题

  • 同样字体在不同系统名称可能不同
  • Mac和Windows字体名称不一样
  • Windows字体搬到Mac可能找不到
  • 开源系统(Linux)一般没有微软默认字体

解决建议

  1. 使用系统自带字体:Windows自带的宋体、黑体、仿宋、楷体一般不用嵌入
  2. 使用通用名称:尽量使用标准名称
  3. PDF导出:如果需要分发,导出PDF最安全
  4. Web字体:不要用奇怪的字体,保持兼容性

8.7 fontTable.xml 是什么

我们提到了word/fontTable.xml,这是什么?

<w:fontTable xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:font w:name="宋体">
    <w:panose w:val="02020603050405020304"/>
    <w:charset w:val="86"/>
    <w:pitch w:val="variable"/>
  </w:font>
  <w:font w:name="黑体">
    <!-- ... -->
  </w:font>
</w:fontTable>

fontTable列出文档中用到的所有字体,包含一些字体特征信息(Panose分类、字符集等),帮助Word在找不到字体时找替代。嵌入字体也在这里记录。

如果文档没有嵌入字体,这个文件很小,只是列出字体名称和特征。


8.8 实际例子

一个完整的字体设置例子:

<!-- 小四,宋体,黑色,常规 -->
<w:rPr>
  <w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体" w:cs="宋体"/>
  <w:sz w:val="24"/>
  <w:color w:val="000000"/>
</w:rPr>

<!-- 二号,黑体,红色,粗体 -->
<w:rPr>
  <w:rFonts w:ascii="黑体" w:eastAsia="黑体" w:hAnsi="黑体" w:cs="黑体"/>
  <w:sz w:val="44"/>
  <w:color w:val="FF0000"/>
  <w:b/>
</w:rPr>

<!-- 斜体带下划线 -->
<w:rPr>
  <w:i/>
  <w:u w:val="single"/>
</w:rPr>

<!-- 上标 -->
<w:rPr>
  <w:vertAlign w:val="superscript"/>
  <w:sz w:val="16"/>
</w:rPr>

本章小结

  • 字体信息在w:rFonts中,分为ascii、eastAsia、hAnsi、cs四个属性
  • 中文字体四个属性一般设置为同一个
  • 字号单位是半磅,1磅=2半磅,五号=21,小四=24
  • 颜色用RGB十六进制表示,不带#号
  • 粗体斜体等效果用布尔元素表示,存在即开启
  • 字体嵌入可以保证显示一致,但要注意版权
  • 找不到字体时Word会自动回退找替代

下一章我们讲解段落格式与缩进。

第9章:段落格式与缩进

学习目标

  • 理解段落格式存储位置
  • 掌握对齐方式的设置
  • 掌握各种缩进的设置
  • 理解行间距和段间距
  • 掌握段落边框和底纹的设置

9.1 段落格式存储在哪里

段落格式都存储在<w:pPr>(paragraph properties)中,每个段落可以有自己的段落格式:

<w:p>
  <w:pPr>
    <!-- 所有段落格式都在这里 -->
    <w:pStyle w:val="Heading1"/> <!-- 样式引用 -->
    <w:jc w:val="center"/>       <!-- 对齐 -->
    <w:ind w:left="480"/>        <!-- 左缩进 -->
    <w:spacing w:line="360"/>     <!-- 行间距 -->
    <!-- ... -->
  </w:pPr>
  <w:r>...</w:r>
</w:p>

样式中也可以定义段落格式,如果段落没有直接设置,就从样式继承。


9.2 对齐方式 w:jc

对齐方式用<w:jc>(justification)设置:

<w:jc w:val="left"/>     <!-- 左对齐 -->
<w:jc w:val="center"/>   <!-- 居中 -->
<w:jc w:val="right"/>    <!-- 右对齐 -->
<w:jc w:val="both"/>     <!-- 两端对齐 -->
<w:jc w:val="distribute"/> <!-- 分散对齐 -->

w:val常见值:

说明
left左对齐
center居中
right右对齐
both两端对齐(中文文档常用)
justify等价于both

中文排版习惯:正文一般用两端对齐,标题常用居中。


9.3 缩进 w:ind

缩进用<w:ind>元素,有几个属性:

<w:ind w:firstLine="480" w:left="240" w:right="240"/>

各个属性说明

属性说明单位
w:firstLine首行缩进缇(twips)
w:left整体左缩进
w:right整体右缩进
w:hanging悬挂缩进

单位:缇(twips)

缩进单位是,1英寸 = 1440缇 = 72磅。换算:

  • 1磅 = 20缇
  • 1厘米 ≈ 567缇

所以:

  • 中文习惯首行缩进2字符 ≈ 420-480缇(根据字号)
  • 五号字(10.5磅),2字符 ≈ 420缇
  • 小四(12磅),2字符 ≈ 480缇

常见缩进设置

首行缩进2字符(小四):

<w:ind w:firstLine="480"/>

悬挂缩进:

<w:ind w:hanging="480"/>

整体左右缩进:

<w:ind w:left="240" w:right="240"/>

9.4 间距 w:spacing

间距包括行间距(行与行之间)和段间距(段前、段后),都在<w:spacing>元素:

<w:spacing w:line="360" w:before="240" w:after="240" w:lineRule="auto"/>

属性说明

属性说明
w:line行间距值
w:before段前间距(缇)
w:after段后间距(缇)
w:lineRule行间距计算规则

行间距单位和规则

w:lineRule决定了w:line值的单位:

lineRuleline的单位说明
auto1/20磅自动,最常用
exact精确值
multiple1/20磅倍数

常见行间距值

  • 单倍行距w:line="360" (12磅 × 3 = 36,×10 = 360)
  • 1.5倍行距w:line="540"
  • 双倍行距w:line="720"

所以记住:单倍=360,1.5倍=540,双倍=720。

段间距

段前和段后单位都是缇:

<!-- 段前1行,段后1行 -->
<w:spacing w:before="240" w:after="240"/>

标题一般段前间距大一点:

<!-- 标题1:段前18磅,段后12磅 -->
<w:spacing w:before="360" w:after="240"/>

9.5 分页设置

段落相关的分页设置:

元素作用
<w:pageBreakBefore/>此段落前分页(这个段落放在新页开始)
<w:keepNext/>此段落和下一段放在同一页
<w:keepLines/>段落所有行放在同一页,不要跨页断行
<w:widowControl/>孤行控制(不把段落第一行留在上页,不把最后一行留在下页)

都是布尔元素,存在即开启:

<w:pPr>
  <w:pageBreakBefore/> <!-- 段前分页 -->
  <w:keepNext/>
  <w:keepLines/>
</w:pPr>

标题一般设置keepNext,确保标题不和正文分家。


9.6 边框 w:pBdr

段落边框用<w:pBdr>元素,可以设置上下左右四条边:

<w:pBdr>
  <w:top w:val="single" w:sz="4" w:space="1" w:color="000000"/>
  <w:left w:val="single" w:sz="4" w:space="1" w:color="000000"/>
  <w:bottom w:val="single" w:sz="4" w:space="1" w:color="000000"/>
  <w:right w:val="single" w:sz="4" w:space="1" w:color="000000"/>
</w:pBdr>

属性说明

每个边元素(top, left, bottom, right)都有:

属性说明
w:val边框样式
w:sz边框粗细,单位是1/8磅
w:space边框与文字之间的间距,磅
w:color边框颜色RGB

常见边框样式

w:val常见值:

样式
none无边框
single单线
double双线
dotted点线
dashed虚线
thick粗线

段落底纹

底纹(背景色)不在pBdr,在<w:shd>

<w:shd w:val="clear" w:fill="FFFFCC"/> <!-- 浅黄色背景 -->
  • w:fill 是背景色RGB
  • w:val 一般用clear表示纯色填充

9.7 大纲级别 w:outlineLvl

大纲级别用于导航和生成目录:

<w:pPr>
  <w:outlineLvl w:val="0"/> <!-- 大纲级别1级 -->
</w:pPr>

值从0到9:

  • 0 → 级别1(对应标题1)
  • 1 → 级别2(对应标题2)
  • 2 → 级别3(对应标题3)
  • 9 → 级别10

正文一般不设置或者级别9。大纲级别正确才能正确生成目录。


9.8 项目符号和编号

项目符号和编号定义在numbering.xml,段落引用对应的编号:

<w:pPr>
  <w:numPr>
    <w:ilvl w:val="0"/> <!-- 级别 -->
    <w:numId w:val="1"/> <!-- 编号ID -->
  </w:numPr>
</w:pPr>

我们这里不展开,专门讲编号的时候再细说。


9.9 完整例子

一个典型的中文正文段落:

<w:p>
  <w:pPr>
    <w:pStyle w:val="Normal"/>
    <w:jc w:val="both"/>         <!-- 两端对齐 -->
    <w:ind w:firstLine="480"/>   <!-- 首行缩进2字符(小四) -->
    <w:spacing w:line="360"/>     <!-- 单倍行距 -->
  </w:pPr>
  <w:r>
    <w:t>这是一段中文正文,按照中文排版习惯首行缩进两个字符,两端对齐,单倍行距。</w:t>
  </w:r>
</w:p>

一个典型的标题段落:

<w:p>
  <w:pPr>
    <w:pStyle w:val="Heading1"/>
    <w:jc w:val="center"/>       <!-- 居中 -->
    <w:outlineLvl w:val="0"/>    <!-- 大纲1级 -->
    <w:spacing w:before="360" w:after="240"/> <!-- 段前段后间距 -->
    <w:keepNext/>                <!-- 和下一段同页 -->
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:b/>
      <w:rFonts w:ascii="黑体" w:eastAsia="黑体" w:hAnsi="黑体" w:cs="黑体"/>
      <w:sz w:val="36"/>
    </w:rPr>
    <w:t>第一章 标题</w:t>
  </w:r>
</w:p>

本章小结

  • 段落格式都在w:pPr
  • 对齐用w:jc,可选左、中、右、两端对齐
  • 缩进用w:ind,单位缇,首行缩进常用420-480缇
  • 间距用w:spacing,单倍行距是360,1.5倍是540
  • 边框在w:pBdr,底纹用w:shd
  • 大纲级别用w:outlineLvl,影响目录生成

下一章我们讲解页面设置与分页。

第10章:页面设置与分页

学习目标

  • 理解节(section)的概念
  • 理解节属性sectPr存放位置
  • 掌握纸张大小和页边距设置
  • 理解纸张方向(纵向横向)设置
  • 了解不同节可以有不同页面设置

10.1 什么是节

在Word中,是页面设置的基本单位。

一个Word文档可以分成多个节,每一节可以有:

  • 不同的纸张大小
  • 不同的页边距
  • 不同的纸张方向(纵向/横向)
  • 不同的页眉页脚
  • 不同的页码格式

如果整个文档页面设置都一样,只需要一节就够了。如果需要在文档中间改变页面设置,就需要分节。


10.2 节属性sectPr放在哪里

节属性(Section Properties,sectPr)存放位置:

  • 如果文档只有一节:sectPr放在w:body的最后
  • 如果文档有多节:每一节的末尾放该节的sectPr

结构示意:

<w:body>
  <!-- 第一节内容... -->
  <w:p>...</w:p>
  <w:sectPr> 第一节的属性在这里 </w:sectPr>

  <!-- 第二节内容... -->
  <w:p>...</w:p>
  <w:sectPr> 第二节的属性在这里 </w:sectPr>
</w:body>

10.3 纸张大小 w:pgSz

纸张大小用<w:pgSz>设置,w:w是宽度,w:h是高度,单位是(twips):

<w:sectPr>
  <w:pgSz w:w="12240" w:h="15840"/> <!-- A4 纵向 -->
</w:sectPr>

常见纸张尺寸

常见纸张尺寸(单位缇,纵向):

纸张宽度w:w高度w:h备注
A41224015840默认标准
A31584024480
B5936013680
16开960014400中文16开
Letter1224015840Letter尺寸和A4接近,略有差异

纵向 vs 横向

纸张方向就是交换宽度和高度:

A4纵向<w:pgSz w:w="12240" w:h="15840"/> (宽 < 高)

A4横向<w:pgSz w:w="15840" w:h="12240"/> (宽 > 高)

就是这么简单。


10.4 页边距 w:pgMar

页边距用<w:pgMar>设置,四个边,单位都是缇:

<w:sectPr>
  <w:pgSz w:w="12240" w:h="15840"/>
  <w:pgMar w:top="1440" w:right="1440"
           w:bottom="1440" w:left="1440"
           w:header="720" w:footer="720"
           w:gutter="0"/>
</w:sectPr>

属性说明

属性说明
w:top上边距
w:right右边距
w:bottom下边距
w:left左边距
w:header页眉距顶部距离
w:footer页脚距底部距离
w:gutter装订线

常见默认值

Word默认A4边距(单位缇):

  • 上下左右:1440 = 1英寸
  • 页眉页脚:720 = 0.5英寸

装订线一般0,不需要装订就不用设置。如果你需要装订,可以设置左边增加gutter。


10.5 分节符

在Word UI中插入分节符,在XML中怎么表示?

分节符其实就是上一节结束,加上上一节的sectPr:

<!-- 第一节内容结束 -->
<w:p>
  <w:pPr>
    <w:sectPr>
      <!-- 第一节的属性在这里 -->
    </w:sectPr>
  </w:pPr>
</w:p>

<!-- 第二节内容开始 -->

分节符的类型(下一页、连续、偶数页、奇数页)用w:type表示:

<w:sectPr>
  <w:type w:val="nextPage"/> <!-- 下一页开始新节 -->
</w:sectPr>

常见类型:

说明
nextPage下一页开始新节
continuous同一页连续开始新节
evenPage下一个偶数页开始
oddPage下一个奇数页开始

整个文档最后一节不需要w:type


10.6 页码设置

页码设置也在sectPr中:

<w:sectPr>
  <w:pgNumType w:start="1" w:fmt="decimal"/>
</w:sectPr>

属性说明

属性说明
w:start起始页码
w:fmt页码格式

常见页码格式

fmt值格式
decimal阿拉伯数字 1, 2, 3…
upperRoman大写罗马 I, II, III…
lowerRoman小写罗马 i, ii, iii…
upperLetter大写字母 A, B, C…
lowerLetter小写字母 a, b, c…
chineseCounting中文数字一、二、三…

例子:前言用罗马编号,正文用阿拉伯

<!-- 第一节(目录前言) -->
<w:sectPr>
  <w:pgNumType w:start="i" w:fmt="lowerRoman"/>
</w:sectPr>

<!-- 第二节(正文) -->
<w:sectPr>
  <w:pgNumType w:start="1" w:fmt="decimal"/>
</w:sectPr>

这样前言页码是i, ii, iii…,正文从1开始重新计数。


10.7 竖排文字

如果需要竖排文字,在sectPr设置:

<w:sectPr>
  <w:textDirection w:val="tbRl"/>
</w:sectPr>

方向值:

方向
tbRl从上到下,从右到左(中文竖排传统方向)
tbLr从上到下,从左到右
lrTb从左到右,从上到下(横排默认)

10.8 例子:完整的A4页面设置

标准A4纵向默认设置:

<w:sectPr>
  <w:pgSz w:w="12240" w:h="15840"/>                 <!-- A4纵向 -->
  <w:pgMar w:top="1440" w:right="1440"             <!-- 边距1英寸 -->
           w:bottom="1440" w:left="1440"
           w:header="720" w:footer="720"
           w:gutter="0"/>                           <!-- 无装订线 -->
  <w:cols w:space="420"/>                            <!-- 分栏间距 -->
  <w:docGrid w:linePitch="360"/>                     <!-- 文档网格 -->
</w:sectPr>

就是Word新建空白文档的默认设置。

例子:A4横向表格页:

<w:sectPr>
  <w:pgSz w:w="15840" w:h="12240"/>                 <!-- A4横向 -->
  <w:pgMar w:top="1440" w:right="1440"
           w:bottom="1440" w:left="1440"
           w:header="720" w:footer="720"/>
  <w:type w:val="nextPage"/>                         <!-- 下一页开始 -->
</w:sectPr>

本章小结

  • 节是页面设置的单位,整个文档至少一节
  • 节属性sectPr放在每节的末尾
  • 纸张大小用w:pgSz,单位缇,A4纵向是w:12240 h:15840
  • 横向就是交换宽和高
  • 页边距用w:pgMar,默认上下左右1440缇(1英寸)
  • 不同节可以有不同页码,从指定数字开始重新编号
  • 需要改变页面设置就插入分节符

下一章我们讲解表格结构与格式。

第11章:表格结构与格式

学习目标

  • 理解表格的XML结构层次
  • 掌握表格、行、单元格的结构
  • 理解单元格合并怎么表示
  • 掌握表格宽度和边框设置
  • 理解表格样式的作用

11.1 表格整体结构

在Word中,表格是块级元素,和段落同级别,直接放在body中。

表格的XML结构层次:

<w:tbl>                       <!-- 表格 Table -->
  <w:tblPr>                   <!-- 表格属性 -->
    <!-- 表格级别格式设置 -->
  </w:tblPr>
  <w:tblGrid>                 <!-- 表格网格定义列宽度 -->
    <w:gridCol w:w="2880"/>   <!-- 第一列 -->
    <w:gridCol w:w="2880"/>   <!-- 第二列 -->
    <w:gridCol w:w="2880"/>   <!-- 第三列 -->
  </w:tblGrid>
  <w:tr>                      <!-- 行 Table Row -->
    <w:trPr>                  <!-- 行属性 -->
    </w:trPr>
    <w:tc>                    <!-- 单元格 Table Cell -->
      <w:tcPr>                <!-- 单元格属性 -->
      </w:tcPr>
      <w:p>...</w:p>          <!-- 单元格内容:可以放段落 -->
    </w:tc>
    <w:tc>...</w:tc>
    <!-- ... 更多单元格 ... -->
  </w:tr>
  <w:tr>...</w:tr>
  <!-- ... 更多行 ... -->
</w:tbl>

层次很清晰:

  • w:tbl → 整个表格
  • w:tblPr → 表格属性
  • w:tblGrid → 定义列网格
  • w:tr → 每一行
  • w:tc → 每个单元格
  • 单元格内可以放段落、甚至嵌套表格

11.2 表格属性 tblPr

表格属性包含整个表格的格式设置。

表格宽度 w:tblW

<w:tblPr>
  <w:tblW w:w="5000" w:type="pct"/>  <!-- 宽度50%页面宽度 -->
</w:tblPr>

w:type有两种:

type说明
pct百分比,w:w 单位是百分之一百分点(50% → 5000)
dxa绝对宽度,单位缇

例子:

  • 宽度100%:<w:tblW w:w="10000" w:type="pct"/>
  • 宽度10厘米:大概5670缇 → <w:tblW w:w="5670" w:type="dxa"/>

对齐方式 w:jc

表格对齐和段落对齐类似:

<w:jc w:val="center"/>  <!-- 表格居中 -->

值:left, center, right

表格边框 w:tblBorders

设置整个表格边框:

<w:tblBorders>
  <w:top w:val="single" w:sz="4" w:color="000000"/>
  <w:left w:val="single" w:sz="4" w:color="000000"/>
  <w:bottom w:val="single" w:sz="4" w:color="000000"/>
  <w:right w:val="single" w:sz="4" w:color="000000"/>
  <w:insideH w:val="single" w:sz="4" w:color="000000"/>
  <w:insideV w:val="single" w:sz="4" w:color="000000"/>
</w:tblBorders>
  • top, left, bottom, right:四条外边框
  • insideH:内部水平边框(行之间)
  • insideV:内部垂直边框(列之间)

属性和段落边框一样:

  • w:val:样式(single单线,double双线等)
  • w:sz:粗细,1/8磅
  • w:color:RGB颜色

所以所有框都有就是上面例子那样,如果要无框就都设为none

表格样式 w:tblStyle

可以引用表格样式:

<w:tblPr>
  <w:tblStyle w:val="TableGrid"/>
</w:tblPr>

TableGrid是Word内置的网格表格样式。


11.3 网格定义 tblGrid

tblGrid定义表格有多少列,每列宽度:

<w:tblGrid>
  <w:gridCol w:w="2000"/>  <!-- 第一列宽度 2000缇 -->
  <w:gridCol w:w="3000"/>  <!-- 第二列宽度 3000缇 -->
  <w:gridCol w:w="2000"/>  <!-- 第三列宽度 2000缇 -->
</w:tblGrid>

即使后来单元格合并了,原来的gridCol定义还是保留,这是网格基础。


11.4 行 tr

每一行用<w:tr>表示:

<w:tr>
  <w:trPr>
    <!-- 行属性 -->
    <w:cantSplit/>  <!-- 不允许跨页断行 -->
  </w:trPr>
  <!-- 单元格 -->
  <w:tc>...</w:tc>
  <w:tc>...</w:tc>
</w:tr>

常用行属性:

元素作用
<w:cantSplit/>整行不允许跨页断行
<w:trHeight w:val="..." w:hRule="..."/>行高设置

行高

<w:trHeight w:val="600" w:hRule="atLeast"/>

hRule

  • atLeast:最小值,至少这么高,内容多可以撑开
  • exact:精确高度,内容多了也不变
  • auto:自动高度

11.5 单元格 tc

每个单元格用<w:tc>表示:

<w:tc>
  <w:tcPr>
    <!-- 单元格属性 -->
    <w:tcW w:w="2880" w:type="dxa"/>  <!-- 单元格宽度 -->
    <w:vMerge/>                       <!-- 垂直合并 -->
    <w:gridSpan w:val="2"/>           <!-- 水平合并跨2列 -->
  </w:tcPr>
  <w:p>
    <!-- 单元格内容,至少一个段落 -->
    <w:r><w:t>单元格内容</w:t></w:r>
  </w:p>
</w:tc>

单元格宽度 w:tcW

<w:tcW w:w="2880" w:type="dxa"/>

单位通常是dxa(缇)。

单元格垂直对齐 w:vAlign

<w:vAlign w:val="center"/>  <!-- 垂直居中 -->

值:top, center, bottom, both

边框

单元格也可以单独设置边框:

<w:tcPr>
  <w:tcBorders>
    <w:top w:val="single" w:sz="4" w:color="000000"/>
    <!-- ...其他边... -->
  </w:tcBorders>
</w:tcPr>

单元格边框优先级高于表格边框。

背景底纹

<w:shd w:fill="EEEEEE"/>  <!-- 灰色背景 -->

11.6 单元格合并

单元格合并分水平合并和垂直合并。

水平合并

水平合并用w:gridSpan,表示跨几列:

<!-- 第一行第一单元格,跨2列 -->
<w:tc>
  <w:tcPr>
    <w:gridSpan w:val="2"/>  <!-- 跨2列 -->
  </w:tcPr>
</w:tc>

意思就是:这个单元格占据原来网格的2列宽度。剩下的单元格还是每列一个。

很简单,一句话:跨n列就写gridSpan=“n”,其他被跨的列不需要格子

垂直合并

垂直合并用w:vMerge,稍微复杂一点:

<!-- 第一行 -->
<w:tr>
  <w:tc>
    <w:tcPr>
      <w:vMerge w:val="restart"/>  <!-- 开始垂直合并 -->
    </w:tcPr>
  </w:tc>
</w:tr>

<!-- 第二行 -->
<w:tr>
  <w:tc>
    <w:tcPr>
      <w:vMerge/>  <!-- 继续合并,没有val就是继续 -->
    </w:tcPr>
  </w:tc>
</w:tr>

<!-- 第三行 -->
<w:tr>
  <w:tc>
    <w:tcPr>
      <w:vMerge/>  <!-- 继续合并 -->
    </w:tcPr>
  </w:tc>
</w:tr>

规则:

  • 第一个单元格:<w:vMerge w:val="restart"/> 开始合并
  • 后续要合并的单元格:只写<w:vMerge/> 不写val,表示继续
  • 合并到哪里就到哪里结束

这样就从第一行开始垂直合并了3行。


11.7 嵌套表格

单元格里面可以再放表格,实现复杂布局:

<w:tc>
  <w:p>...</w:p>
  <w:tbl>  <!-- 嵌套表格 -->
    <!-- ...表格结构... -->
  </w:tbl>
  <w:p>...</w:p>
</w:tc>

Word支持任意嵌套,只要你需要。


11.8 完整例子:简单的两列表格

让我们看一个完整的简单例子:

<w:tbl>
  <w:tblPr>
    <w:tblW w:w="10000" w:type="pct"/>  <!-- 100%宽度 -->
    <w:jc w:val="center"/>
    <w:tblBorders>
      <w:top w:val="single" w:sz="4" w:color="000000"/>
      <w:left w:val="single" w:sz="4" w:color="000000"/>
      <w:bottom w:val="single" w:sz="4" w:color="000000"/>
      <w:right w:val="single" w:sz="4" w:color="000000"/>
      <w:insideH w:val="single" w:sz="4" w:color="000000"/>
      <w:insideV w:val="single" w:sz="4" w:color="000000"/>
    </w:tblBorders>
  </w:tblPr>
  <w:tblGrid>
    <w:gridCol w:w="3000"/>
    <w:gridCol w:w="5000"/>
  </w:tblGrid>

  <!-- 表头行 -->
  <w:tr>
    <w:tc>
      <w:tcPr>
        <w:shd w:fill="DDDDDD"/>
      </w:tcPr>
      <w:p><w:r><w:t>姓名</w:t></w:r></w:p>
    </w:tc>
    <w:tc>
      <w:tcPr>
        <w:shd w:fill="DDDDDD"/>
      </w:tcPr>
      <w:p><w:r><w:t>职业</w:t></w:r></w:p>
    </w:tc>
  </w:tr>

  <!-- 数据行1 -->
  <w:tr>
    <w:tc><w:p><w:r><w:t>张三</w:t></w:r></w:p></w:tc>
    <w:tc><w:p><w:r><w:t>工程师</w:t></w:r></w:p></w:tc>
  </w:tr>

  <!-- 数据行2 -->
  <w:tr>
    <w:tc><w:p><w:r><w:t>李四</w:t></w:r></w:p></w:tc>
    <w:tc><w:p><w:r><w:t>设计师</w:t></w:r></w:p></w:tc>
  </w:tr>
</w:tbl>

这个例子:

  • 表格宽度100%页面宽度
  • 全部边框黑色单线
  • 两列,第一列3000缇,第二列5000缇
  • 表头灰色背景
  • 两行数据

11.9 完整例子:合并单元格

带合并单元格的例子:

<w:tbl>
  <w:tblPr>
    <w:tblW w:w="10000" w:type="pct"/>
    <w:tblBorders>
      <!-- 边框... -->
    </w:tblBorders>
  </w:tblPr>
  <w:tblGrid>
    <w:gridCol w:w="2000"/>
    <w:gridCol w:w="2000"/>
    <w:gridCol w:w="2000"/>
  </w:tblGrid>

  <!-- 第一行:第一格跨3列 -->
  <w:tr>
    <w:tc>
      <w:tcPr>
        <w:gridSpan w:val="3"/>  <!-- 水平跨3列 -->
      </w:tcPr>
      <w:p><w:r><w:t>跨三列表头</w:t></w:r></w:p>
    </w:tc>
  </w:tr>

  <!-- 第二行 -->
  <w:tr>
    <w:tc>
      <w:tcPr>
        <w:vMerge w:val="restart"/>  <!-- 开始垂直合并 -->
      </w:tcPr>
      <w:p><w:r><w:t>左列</w:t></w:r></w:p>
    </w:tc>
    <w:tc><w:p><w:r><w:t>中1</w:t></w:r></w:p></w:tc>
    <w:tc><w:p><w:r><w:t>右1</w:t></w:r></w:p></w:tc>
  </w:tr>

  <!-- 第三行 -->
  <w:tr>
    <w:tc>
      <w:tcPr>
        <w:vMerge/>  <!-- 继续合并 -->
      </w:tcPr>
    </w:tc>
    <w:tc><w:p><w:r><w:t>中2</w:t></w:r></w:p></w:tc>
    <w:tc><w:p><w:r><w:t>右2</w:t></w:r></w:p></w:tc>
  </w:tr>
</w:tbl>

本章小结

  • 表格结构:w:tblw:tblPr + w:tblGrid + 多个w:tr
  • 行:w:trw:trPr + 多个w:tc
  • 单元格:w:tcw:tcPr + 内容(段落等)
  • 水平合并:用gridSpan指定跨几列,只放一个格子
  • 垂直合并:第一个格子vMerge="restart",后续格子只放vMerge
  • 表格宽度可以是百分比或绝对宽度
  • 边框在表格级别设置内部和外部边框,单元格可以单独覆盖

下一章我们讲解图片和嵌入式对象。

第12章:图片和嵌入式对象

学习目标

  • 理解docx中图片的存储方式
  • 理解关系引用机制
  • 掌握图片在XML中的表示方式
  • 了解嵌入式OLE对象

12.1 图片存储在哪里

在docx中,图片文件本身不放在XML里,而是:

  1. 原始图片文件放在word/media/目录下
  2. 在关系文件word/_rels/document.xml.rels中注册关系ID
  3. 在document.xml中通过关系ID引用图片

这种分离存储的好处:

  • XML保持干净,只包含引用
  • 图片保持原有格式
  • 可以直接提取图片文件

文件位置

图片文件通常命名为:

word/media/image1.png
word/media/image2.jpeg
word/media/image3.emf
...

按顺序编号,扩展名保持原格式。


12.2 关系注册

word/_rels/document.xml.rels中添加一条关系:

<Relationships
  xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <!-- 其他关系... -->
  <Relationship Id="rId3"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
    Target="media/image1.png"/>
</Relationships>
  • Type固定是图片类型
  • Target指向media目录下的图片文件
  • Id就是关系ID,在document.xml中用这个Id引用

12.3 在文档中插入图片

图片使用DrawingML表示,放在<w:drawing>中:

<w:p>
  <w:r>
    <w:drawing>
      <wp:inline distT="0" distB="0" distL="0" distR="0">
        <wp:extent cx="2880000" cy="2160000"/>
        <wp:docPr id="1" name="图片1"/>
        <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
          <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
            <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
              <pic:nvPicPr>
                <pic:cNvPr id="0" name="image1.png"/>
                <pic:cNvPicPr/>
              </pic:nvPicPr>
              <pic:blipFill>
                <a:blip r:embed="rId3"/>
                <a:stretch><a:fillRect/></a:stretch>
              </pic:blipFill>
              <pic:spPr>
                <a:xfrm>
                  <a:off x="0" y="0"/>
                  <a:cx>2880000</a:cx>
                  <a:cy>2160000</a:cy>
                </a:xfrm>
              </pic:spPr>
            </pic:pic>
          </a:graphicData>
        </a:graphic>
      </wp:inline>
    </w:drawing>
  </w:r>
</w:p>

看起来层级很多,我们逐层解释。

层级说明

w:drawing          表示这是一个绘图对象
  └── wp:inline     inline表示嵌入在文本行中
        ├── wp:extent   指定图片大小(EMU单位)
        ├── wp:docPr   文档属性(id、名称)
        └── a:graphic  DrawingML图形
            └── a:graphicData
                └── pic:pic  图片
                      ├── pic:nvPicPr  非可视属性
                      ├── pic:blipFill  图片填充
                            └── a:blip r:embed="rId3"  <!-- 这里引用关系ID -->
                      └── pic:spPr  形状属性(大小位置)

关键部分

  1. 关系引用<a:blip r:embed="rId3"/> 这里的r:embed就是关系ID,对应rels里的Id。

  2. 大小单位EMU:尺寸单位是English Metric Unit,换算:

    • 1英寸 = 914400 EMU
    • 1厘米 = 360000 EMU
    • 1磅 = 12700 EMU

    所以,一张10cm × 7.5cm的图片就是:cx="3600000" cy="2700000"

  3. inline vs anchor

    • wp:inline:图片跟随文字,在line中
    • wp:anchor:图片浮动,可以设置文字环绕方式

环绕方式

如果是浮动锚点,用wp:anchor

<wp:anchor distT="0" distB="0" distL="0" distR="0"
           wrapType="square">
  <!-- 正方形环绕文字 -->
  ...
</wp:anchor>

常见wrapType:

环绕方式
square四周环绕
tight紧密环绕
through穿透环绕
topAndBottom上下型
wrapNone浮于文字上方

12.4 图片大小

如果要保持图片原始比例,怎么计算?

原始图片像素是 width × height 像素,DPI是 96 DPI:

宽度厘米 = (width / 96) × 2.54
宽度EMU = 宽度厘米 × 360000

一般:

  • 想让图片宽度刚好占满页面:A4宽度减去左右边距大概是 14.5cm → 宽度EMU = 14.5 × 360000 = 5220000

然后高度按比例缩放就行。


12.5 旧格式图片 VML

很老的Word版本可能用VML格式存图片:

<w:pict>
  <v:shape>
    ... VML ...
  </v:shape>
</w:pict>

现代Word都用DrawingML了,遇到VML一般是旧文档转换来的。现代处理一般不用生成VML。


12.6 嵌入式OLE对象

如果嵌入Excel图表、PowerPoint幻灯片,或者其他OLE对象,怎么存?

和图片类似:

  1. OLE对象数据存在word/embeddings/目录下
  2. 在关系文件注册关系
  3. 在文档中用<o:OLEObject>引用

一般开发中很少需要处理嵌入OLE对象,知道位置就可以了。


12.7 完整示例总结

插入一张图片需要做三件事:

  1. 复制图片文件word/media/imageN.png
  2. document.xml.rels添加关系
    <Relationship Id="rIdX" Type="...image" Target="media/imageN.png"/>
    
  3. 在document.xml插入DrawingML引用关系ID:
    <w:drawing>
      <wp:inline>
        <wp:extent cx="..." cy="..."/>
        <a:graphic>
          <a:graphicData>
            <pic:pic>
              <pic:blipFill>
                <a:blip r:embed="rIdX"/>
              </pic:blipFill>
            </pic:pic>
          </a:graphicData>
        </a:graphic>
      </wp:inline>
    </w:drawing>
    

就是这么三步。理解了结构,插入图片其实不复杂。


本章小结

  • 图片文件存在word/media/目录,XML中只放引用
  • 需要在关系文件document.xml.rels中注册关系ID
  • 在文档中用DrawingML表示,通过r:embed引用关系ID
  • 大小单位是EMU,1厘米 = 360000 EMU
  • inline是随文嵌入,anchor是浮动可以设置环绕

下一章我们讲解页眉页脚与分节。

第13章:页眉页脚与分节

学习目标

  • 理解页眉页脚和节的关系
  • 理解页眉页脚的存储方式
  • 掌握奇偶页不同、首页不同的设置
  • 理解分节的作用

13.1 页眉页脚存在哪里

页眉和页脚不放在主文档document.xml中,而是单独存放

word/
  ├── header1.xml  <!-- 第一个页眉 -->
  ├── header2.xml  <!-- 第二个页眉 -->
  ├── footer1.xml  <!-- 第一个页脚 -->
  ├── footer2.xml  <!-- 第二个页脚 -->
  └── ...

每个页眉或页脚一个单独的XML文件。

在主文档中,只在节属性里引用它们的关系ID。


13.2 关系引用

每个页眉页脚都需要在document.xml.rels中添加关系:

<Relationships ...>
  <Relationship Id="rId1"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header"
    Target="header1.xml"/>
  <Relationship Id="rId2"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"
    Target="footer1.xml"/>
</Relationships>
  • 类型:页眉是.../header,页脚是.../footer
  • Target指向对应的xml文件

然后在节属性中引用这些关系ID:

<w:sectPr>
  <w:headerReference w:type="default" r:id="rId1"/>
  <w:footerReference w:type="default" r:id="rId2"/>
  ...
</w:sectPr>

13.3 不同类型的页眉页脚

一个节可以有最多四个页眉页脚:

类型w:type值说明
默认default所有页默认
首页first本第一节首页
偶数页even偶数页
奇数页odd奇数页

首页不同

如果要设置首页不同,在节属性中:

<w:sectPr>
  <w:titlePage/>              <!-- 首页不同 -->
  <w:headerReference w:type="first" r:id="rId1"/>     <!-- 首页页眉 -->
  <w:footerReference w:type="first" r:id="rId2"/>     <!-- 首页页脚 -->
  <w:headerReference w:type="default" r:id="rId3"/>  <!-- 其他页默认页眉 -->
  <w:footerReference w:type="default" r:id="rId4"/>  <!-- 其他页默认页脚 -->
</w:sectPr>

<w:titlePage/>表示开启首页不同。

奇偶页不同

如果要奇偶页不同,在文档设置中:

<w:settings>
  <w:evenAndOddHeaders/>  <!-- 奇偶页不同 -->
</w:settings>

然后你需要提供:

<w:headerReference w:type="even" r:id="rId1"/>
<w:headerReference w:type="odd" r:id="rId2"/>

这样奇数页用odd页眉,偶数页用even页眉。

同时首页不同和奇偶不同

可以同时开启:

  • 开启w:titlePage → 首页单独
  • 开启w:evenAndOddHeaders → 奇偶不同
  • 所以你需要准备四个页眉:首页、奇数、偶数

13.4 页眉页脚内容结构

页眉文件header1.xml里面是什么样的?

其实和document.xml的body里面结构一样,可以放段落、表格:

<?xml version="1.0" encoding="UTF-8"?>
<w:hdr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:p>
    <w:pPr>
      <w:jc w:val="right"/>  <!-- 右对齐 -->
    </w:pPr>
    <w:r>
      <w:t>文档标题</w:t>
    </w:r>
  </w:p>
</w:hdr>

根元素是<w:hdr>,里面和正文一样,可以放段落、表格等。页脚根元素是<w:ftr>,内容结构一样:

<w:ftr>
  <w:p>
    <w:r>
      <w:t>第 </w:t>
    </w:r>
    <w:r>
      <w:fldChar w:fldCharType="begin"/>
    </w:r>
    <w:r>
      <w:instrText>PAGE</w:instrText>
    </w:r>
    <w:r>
      <w:fldChar w:fldCharType="end"/>
    </w:r>
    <w:r>
      <w:t> 页</w:t>
    </w:r>
  </w:p>
</w:ftr>

看到那个PAGE了吗?这就是页码域,Word会自动替换成当前页码。我们后面讲域的时候再说。


13.5 与节的关系

页眉页脚是按节来的,每一节可以有自己的页眉页脚

默认情况下,新节会继承上一节的页眉页脚。如果你想不同节不同页眉,需要设置:

<w:hdr w:rsidR="00000000">
  <!-- 内容 -->
</w:hdr>

然后在新节的sectPr中引用你自己的页眉,它就会用新的,不继承上一节。

为什么要分节改变页眉

常见场景:

  • 封面:不需要页眉页码
  • 目录:不需要页码或用罗马页码
  • 正文:需要页眉页码
  • 章节:每章页眉不同(比如显示章标题)

这种情况你就需要把文档分成多个节,每个节设置自己的页眉页脚。


13.6 页眉位置

页眉距离顶部多少,页脚距离底部多少,在哪里设置?

在页边距设置里面:

<w:sectPr>
  <w:pgMar w:top="1440" w:header="720" ... />
</w:sectPr>
  • w:header 就是页眉距离顶部的距离(单位缇)
  • w:footer 就是页脚距离底部的距离

默认一般是720缇(0.5英寸)。


13.7 链接到前一条页眉

Word UI中有个“链接到前一条页眉“按钮,这个在XML中怎么表示?

其实很简单:如果当前节没有定义自己的页眉引用,就用前一节的,这就是“链接到前一条“。如果定义了自己的引用,就断开链接用自己的。

所以:

  • 链接到前一条 → 当前节sectPr中不写页眉引用
  • 不链接 → 当前节sectPr中写自己的页眉引用

13.8 完整例子

我们来看一个完整例子:文档有两节,第一节是封面,第二节正文,首页不同,正文有页码。

关系 (document.xml.rels)

<Relationship Id="rId1" Type="...header" Target="header1.xml"/>
<Relationship Id="rId2" Type="...footer" Target="footer1.xml"/>
<Relationship Id="rId3" Type="...header" Target="header2.xml"/>
<Relationship Id="rId4" Type="...footer" Target="footer2.xml"/>

第一节(封面)sectPr

<w:sectPr>
  <w:titlePage/>  <!-- 首页不同 -->
  <!-- 首页不需要页眉页脚,所以不引用,或者引用空的 -->
  <w:type w:val="nextPage"/>
</w:sectPr>

第二节(正文)sectPr

<w:sectPr>
  <w:headerReference w:type="default" r:id="rId3"/>
  <w:footerReference w:type="default" r:id="rId4"/>
  <w:pgSz w:w="12240" w:h="15840"/>
  <w:pgMar w:top="1440" w:bottom="1440" w:left="1440" w:right="1440"
           w:header="720" w:footer="720"/>
</w:sectPr>

页眉header2.xml

<w:hdr>
  <w:p>
    <w:r><w:t>我的文档标题</w:t></w:r>
  </w:p>
</w:hdr>

页脚footer2.xml

<w:ftr>
  <w:p>
    <w:jc w:val="center"/>
    <w:r>
      <w:t>第</w:t>
      <w:fldChar w:fldCharType="begin"/>
      <w:instrText>PAGE</w:instrText>
      <w:fldChar w:fldCharType="end"/>
      <w:t>页</w:t>
    </w:r>
  </w:p>
</w:ftr>

这样就实现了:封面没有页眉页脚,正文有页眉居左,页码居中在页脚。


本章小结

  • 每个页眉页脚单独XML文件存放,headerN.xml / footerN.xml
  • 在document.xml.rels中注册关系,在sectPr中引用
  • 可以设置首页不同(titlePage)和奇偶页不同(evenAndOddHeaders)
  • 页眉内容结构和正文一样,根元素是w:hdr,页脚是w:ftr
  • 每一节可以有自己的页眉页脚,不同节不同页眉需要分节
  • 不定义引用就是继承前一节(链接到前一条)

下一章我们讲解分栏布局。

第14章:分栏布局

学习目标

  • 理解分栏在哪里设置
  • 掌握多栏的设置方法
  • 理解分栏与节的关系
  • 掌握栏宽、间距、分隔线的设置

14.1 分栏设置在哪里

分栏设置在节属性sectPr中:

<w:sectPr>
  <w:cols w:num="2" w:space="420" w:equalWidth="1"/>
</w:sectPr>

所以:分栏是按节设置的,一个节内统一分栏,不同节可以不同分栏。


14.2 等宽分栏

最简单的就是等宽多栏

<w:cols
  w:num="2"          <!-- 两栏 -->
  w:space="420"       <!-- 栏间距,单位缇 -->
  w:equalWidth="1"/>  <!-- 等宽 -->

属性说明:

属性说明
w:num栏数
w:space栏间距,单位缇,只有等宽时有效
w:equalWidth1表示等宽,0表示不等宽自定义

例子:

  • 两栏等宽,间距1厘米(约567缇):
    <w:cols w:num="2" w:space="567" w:equalWidth="1"/>
    

14.3 不等宽分栏

如果需要不等宽,设置equalWidth="0",然后每个栏用<w:col>定义宽度:

<w:cols w:num="3" w:equalWidth="0">
  <w:col w:w="2000" w:space="420"/>  <!-- 第一栏宽2000缇,间距420 -->
  <w:col w:w="3000" w:space="420"/>  <!-- 第二栏宽3000缇,间距420 -->
  <w:col w:w="2000"/>               <!-- 最后一栏不需要间距 -->
</w:cols>

每个w:col

  • w:w 栏宽度,单位缇
  • w:space 本栏右侧的间距

这样可以自由定义每栏宽度。


14.4 分隔线

想要两栏之间加分隔线,设置w:sep

<w:cols w:num="2" w:space="420" w:equalWidth="1" w:sep="1"/>

w:sep="1"就是添加分隔线。分隔线是一条竖线,从页面顶部到底部。


14.5 分栏与节的关系

因为分栏是节属性,所以:

整个文档分栏

文档只有一节,在最后sectPr设置分栏,整个文档都分栏。

部分内容分栏

如果你只需要一部分内容分栏,另一部分不分栏:

  1. 在分栏开始前插入分节符(连续)
  2. 在分栏结束后再插入分节符
  3. 给中间那节设置分栏,前后节不设置(或设置单栏)

这样就能实现一页内一部分单栏一部分双栏。

例子:标题单栏,正文双栏

<!-- 第一节:标题,单栏 -->
<w:sectPr>
  <w:cols w:num="1"/>
  <w:type w:val="continuous"/>
</w:sectPr>

<!-- 第二节:正文,双栏 -->
<w:sectPr>
  <w:cols w:num="2" w:space="420" w:equalWidth="1"/>
</w:sectPr>

14.6 强制分栏换行

如果想在某个位置强行换到下一栏,插入分栏符

<w:p>
  <w:r>
    <w:br w:type="column"/>
  </w:r>
</w:p>

<w:br>w:type="column"就是分栏符,后面内容从下一栏开始。


14.7 完整例子

整个文档两栏等宽,带分隔线,间距0.5厘米:

<w:sectPr>
  <w:pgSz w:w="12240" w:h="15840"/>
  <w:pgMar w:top="1440" w:right="1440"
           w:bottom="1440" w:left="1440"
           w:header="720" w:footer="720"/>
  <w:cols w:num="2" w:space="284" w:equalWidth="1" w:sep="1"/>
</w:sectPr>

0.5厘米 = 0.5 × 567 ≈ 284缇。


本章小结

  • 分栏设置在节属性sectPrw:cols
  • 整个节使用相同分栏设置
  • 等宽分栏用equalWidth="1",指定num和space
  • 不等宽用equalWidth="0",每个栏用w:col指定宽度
  • w:sep="1"添加分隔线
  • 要部分分栏就分节,每节不同设置

下一章我们讲解目录与域。

第15章:目录与域

学习目标

  • 理解什么是域
  • 理解域的表示方式
  • 掌握常见域:TOC(目录)、PAGE、REF等
  • 理解目录是怎么生成的

15.1 什么是域

域是Word中的动态内容,可以根据文档上下文自动更新。

常见的域:

  • PAGE:自动页码
  • TOC:自动目录(根据标题样式生成)
  • REF:交叉引用
  • DATE:当前日期
  • HYPERLINK:超链接
  • STYLEREF:引用样式内容

15.2 域在XML中怎么表示

域分成几个部分:begin → instructions → end

<w:r>
  <w:fldChar w:fldCharType="begin"/>  <!-- 开始标记 -->
</w:r>
<w:r>
  <w:instrText>PAGE</w:instrText>       <!-- 域指令 -->
</w:r>
<w:r>
  <w:fldChar w:fldCharType="separate"/> <!-- 分隔,结果在后面 -->
</w:r>
<w:r>
  <w:t>3</w:t>                         <!-- 当前缓存的结果 -->
</w:r>
<w:r>
  <w:fldChar w:fldCharType="end"/>     <!-- 结束标记 -->
</w:r>

结构:

  1. w:fldChar w:fldCharType="begin" - 域开始
  2. w:instrText - 域指令(就是域代码)
  3. w:fldChar w:fldCharType="separate" - 分隔指令和结果
  4. 结果内容 - 缓存的上次计算结果
  5. w:fldChar w:fldCharType="end" - 域结束

如果不需要分开保存结果,可以没有separate和结果部分,只有begin → instr → end。


15.3 常见域例子

PAGE 页码

我们已经见过:

<w:r>
  <w:fldChar w:fldCharType="begin"/>
  <w:instrText>PAGE</w:instrText>
  <w:fldChar w:fldCharType="separate"/>
  <w:t>5</w:t>
  <w:fldChar w:fldCharType="end"/>
</w:r>

Word打开后会自动替换成当前页码。

NUMPAGES 总页数

<w:instrText>NUMPAGES</w:instrText>

用来显示总页数,常见用法:“第 5 页,共 10 页”

DATE 当前日期

<w:instrText>DATE \@ "YYYY年MM月DD日"</w:instrText>

\@ 指定日期格式。

TOC 目录

<w:r>
  <w:fldChar w:fldCharType="begin"/>
  <w:instrText>TOC \o "1-3" \h \z</w:instrText>
  <w:fldChar w:fldCharType="separate"/>
  <!-- 目录生成后结果在这里 -->
  <w:fldChar w:fldCharType="end"/>
</w:r>

TOC指令参数:

  • \o "1-3" 包含大纲级别1-3级(标题1到标题3)
  • \h 超链接
  • \z 隐藏页码边框
  • \u 保留样式

更新域的时候,Word会自动扫描所有标题,生成目录。所以你只要放对TOC域,Word会自动生成。


15.4 自动目录怎么工作

Word的自动目录工作原理:

  1. 你给各个标题应用了标题样式(Heading1, Heading2…)或者设置了大纲级别
  2. 你插入TOC域
  3. Word更新域时,扫描整个文档,收集所有有大纲级别的段落
  4. 根据级别生成目录条目,每个条目带页码和超链接
  5. 放在TOC域的位置

所以,生成目录的关键是:正确设置标题的大纲级别

只要标题大纲级别正确,TOC域就能正确生成目录。


15.5 交叉引用 REF

交叉引用用REF域:

<w:r>
  <w:fldChar w:fldCharType="begin"/>
  <w:instrText>REF _Ref123456789 \h</w:instrText>
  <w:fldChar w:fldCharType="separate"/>
  <w:t>第3章</w:t>
  <w:fldChar w:fldCharType="end"/>
</w:r>

\h 表示超链接。点击交叉引用会跳转到引用位置。


15.6 什么时候更新域

  • 用户打开文档可以手动更新域(右键 → 更新域)
  • Word打印的时候通常会自动更新
  • 编程生成文档后,如果有TOC,最好告诉用户打开后需要更新域

15.7 例子:页脚的“第X页,共Y页“

<w:ftr>
  <w:p>
    <w:pPr>
      <w:jc w:val="center"/>
    </w:pPr>
    <w:r>
      <w:t>第 </w:t>
    </w:r>
    <w:r>
      <w:fldChar w:fldCharType="begin"/>
      <w:instrText>PAGE</w:instrText>
      <w:fldChar w:fldCharType="separate"/>
      <w:t>1</w:t>
      <w:fldChar w:fldCharType="end"/>
    </w:r>
    <w:r>
      <w:t> 页,共 </w:t>
    </w:r>
    <w:r>
      <w:fldChar w:fldCharType="begin"/>
      <w:instrText>NUMPAGES</w:instrText>
      <w:fldChar w:fldCharType="separate"/>
      <w:t>10</w:t>
      <w:fldChar w:fldCharType="end"/>
    </w:r>
    <w:r>
      <w:t> 页</w:t>
    </w:r>
  </w:p>
</w:ftr>

就是我们常见的页码格式。


本章小结

  • 域是动态内容,Word会自动计算更新
  • 域结构:begin → instrText(指令) → separate → 结果 → end
  • PAGE显示当前页码,NUMPAGES显示总页数
  • TOC域自动生成目录,基于标题大纲级别
  • 更新域后才能看到最新结果

这是第三部分Open XML核心结构的最后一章。第三部分我们已经完整讲解了docx各个主要部分的结构。现在我们进入第四部分:Word排版设计实践。

第16章:Word排版原理

本章要点

  • 理解Word排版的核心思想
  • 区别手工排版和样式排版
  • 理解Word的盒子模型
  • 建立正确的排版思维

16.1 Word排版不是打字

很多人使用Word,只是把它当成“电子打字机“,需要什么格式就手工选中改字体、改字号、改颜色。这种方式做短文档还凑合,长文档就会乱掉。

Word不仅仅是打字机,它是一个自动化排版系统。理解了这一点,你才能用好Word排版。

手工排版的问题

手工排版(改一处是一处)的问题:

  • 效率低:重复劳动,同样的格式一次次设置
  • 不一致:同样是标题,这里字号18,那里17,格式不统一
  • 难修改:要改标题格式,需要一个个改,容易漏
  • 难生成目录:Word识别不了哪些是标题,自动目录出不来

样式排版的优势

使用样式排版:

  • 一次定义,到处使用
  • 统一格式,改样式自动全文档更新
  • 自动目录一键生成
  • 效率高,一致性好

核心原则:用样式,不要手工一个个改。


16.2 Word的排版模型:盒子套盒子

Word的文档结构其实就是一个盒子模型:

文档
└── 节 (section) - 页面设置容器
    └── 段落 (paragraph) - 块级盒子
        └── 运行 (run) - 行内盒子
            └── 文本

这个结构和CSS的盒子模型很像:

  • 节 → 页面
  • 段落 → 块级元素
  • 运行 → 行内元素

理解了这个模型,你就理解了Word排版的基本框架。

块级 vs 行内

类型元素作用
块级段落p占一整行,有段落级格式
行内运行r在段落内,同一行内,有字符格式

每个回车就是一个新段落,这是Word最基本的规则。


16.3 格式优先级

我们之前讲过格式优先级,这里再强调一下:

优先级从高到低:

  1. 直接格式(run或p上直接设置)→ 最高
  2. 字符样式 → 高于段落样式
  3. 段落样式 → 低于字符样式
  4. 默认样式
  5. docDefaults → 最低

最佳实践:尽量用样式,少用直接格式。直接格式会覆盖样式,以后难修改。


16.4 排版的层次结构

一篇好的文档,应该有清晰的层次结构:

文档
├── 封面
├── 摘要
├── 目录
├── 第1章
│   ├── 1.1 节标题
│   │   └── 1.1.1 小节
│   └── 1.2 节标题
├── 第2章
│   └── ...
└── 参考文献

对应Word里就是:

  • 标题1 → 章标题
  • 标题2 → 节标题
  • 标题3 → 小节标题
  • 正文 → 正文样式

层次清晰,不仅读者看着舒服,Word也能自动生成目录。


16.5 留白的艺术

排版不是信息越满越好,适当留白很重要。

留白包括:

  • 页边距:内容不要贴到纸边上,默认边距1英寸就很好
  • 段间距:段落之间留出空隙,比全靠行间距分开好看
  • 标题上下间距:标题上下多留点空白,层次感就出来了
  • 行间距:不要太挤,单倍或1.5倍适合中文

中文阅读习惯:

  • 正文单倍或1.5倍行距合适
  • 标题段前比段后稍大一点
  • 首行缩进两字符,帮助读者找到段落开头

16.6 对齐的原则

对齐的目的是建立清晰的视觉秩序。

常用对齐方式:

  • 标题:居中或左对齐,看风格
  • 正文:两端对齐,中文正文一般用两端对齐,右侧比较整齐
  • 图片表格:一般居中比较好看
  • 页码:一般居中放页脚

不要用分散对齐做正文,字间距会拉得很开,不好看。


16.7 字体选择

字体选择原则:

正文

  • 宋体:传统正式,正式公文常用
  • 仿宋:公文正文常用,清晰
  • 微软雅黑:现代,屏幕阅读舒服
  • 黑体不适合做正文,太粗太重了,长时间阅读累

标题

  • 黑体:粗黑醒目,常用标题
  • 微软雅黑:现代清晰
  • 宋体加粗:也可以,比较传统

字数多正文用衬线字体(宋体、仿宋),屏幕阅读可以用无衬线(微软雅黑)。


16.8 分页和孤行控制

孤行寡妇

  • 孤行:段落第一行单独留在页面底部
  • 寡妇:段落最后一行单独留在页面顶部

不好看,所以一般开启孤行控制。Word默认就开着。

标题和正文不要分开

标题不要留在页面底部,正文跑到下一页。所以标题一般设置keepNext,保证标题和下一段在同一页。

分页原则

  • 新章一般从奇数页开始
  • 不要硬插很多手动分页,让Word自动分页
  • 改了内容后,Word会自动重新分页

16.9 正确使用制表位和表格

不要用多个空格来对齐,用:

  • 制表位:需要对齐到特定位置
  • 表格:需要整齐的多列对齐

空格对齐在不同字体不同打印机可能不对齐,制表位和表格是精确对齐。


本章小结

  • Word是自动化排版系统,不是电子打字机
  • 用样式排版,不要手工一个个改
  • 结构是盒子套盒子:节 → 段落 → 运行
  • 建立清晰的标题层次结构,方便自动生成目录
  • 适当留白,层次分明
  • 保持对齐,建立视觉秩序
  • 控制孤行,不要让标题和正文分家

下一章我们讲解样式与排版的关系,深入讲样式怎么用。

第17章:样式与排版的关系

学习目标

  • 理解样式在排版中的核心作用
  • 掌握段落样式和字符样式的正确用法
  • 学会基于继承建立样式体系
  • 理解快速样式库的作用

17.1 样式是排版的骨架

样式是什么?样式就是一组格式设置的集合,给它起个名字,应用到段落或文字。

样式的好处:

  • 一致性:同一个样式格式完全一致
  • 可维护性:改样式定义,所有应用处自动更新
  • 结构化:Word能识别文档结构,生成目录
  • 效率:定义一次,重复使用,不用重复设置

可以说:没有样式就没有专业的Word排版


17.2 样式类型回顾

Word有几种样式类型,每种用在不同地方:

类型用途应用于
段落样式整个段落的格式(包括段落格式和默认字符格式)整个段落
字符样式文字局部格式段落内部分文字
链接样式既是段落也是字符可以当两种用
表格样式表格格式整个表格
列表样式编号列表格式列表

日常排版最常用:段落样式 + 字符样式


17.3 段落样式怎么用

段落样式应该对应文档结构:

推荐用法:

  • Normal / 正文 → 正文段落
  • Heading 1 / 标题1 → 章标题
  • Heading 2 / 标题2 → 节标题
  • Heading 3 / 标题3 → 小节标题
  • 可再加自定义样式:题注、插图说明、参考文献、摘要等

这样,每个段落都有一个样式,代表它是什么结构,Word就认识了。

标题样式的推荐设置

以标题1(章标题)为例:

<!-- 样式定义 -->
<w:style w:type="paragraph" w:styleId="Heading1">
  <w:name w:val="标题 1"/>
  <w:basedOn w:val="Normal"/>
  <w:next w:val="Normal"/> <!-- 回车后下一段默认正文 -->
  <w:pPr>
    <w:outlineLvl w:val="0"/> <!-- 大纲级别1,目录识别 -->
    <w:keepNext/> <!-- 和下一段同页,不要分家 -->
    <w:spacing w:before="360" w:after="240"/> <!-- 段前18磅,段后12磅 -->
    <w:jc w:val="center"/> <!-- 居中 -->
  </w:pPr>
  <w:rPr>
    <w:rFonts w:ascii="黑体" w:eastAsia="黑体" w:hAnsi="黑体"/>
    <w:sz w:val="36"/> <!-- 二号 → 36半磅=18磅 -->
    <w:b/>
  </w:rPr>
</w:style>

关键点:

  1. outlineLvl 设置正确,才能进目录
  2. keepNext 保证标题不和正文分页分开
  3. next 设置回车后回到正文样式,不用每次手动切
  4. 段前间距大于段后,留白好看

17.4 字符样式怎么用

字符样式用于段落内局部变化:

常见用法:

  • 强调 → 斜体或变色
  • 关键词 → 加粗
  • 代码 → 等宽字体
  • 超链接 → 蓝色带下划线

字符样式不要设置字体大小,继承段落的大小就好,除非特意需要变大变小。

例子:“强调“字符样式:

<w:style w:type="character" w:styleId="Emphasis">
  <w:name w:val="强调"/>
  <w:basedOn w:val="DefaultParagraphFont"/>
  <w:rPr>
    <w:i/> <!-- 斜体 -->
    <w:color w:val="800000"/> <!-- 暗红色 -->
  </w:rPr>
</w:style>

用的时候,给需要强调的文字应用这个字符样式就可以了。


17.5 样式继承:建立自己的样式体系

样式支持继承,可以基于已有样式建立新样式,只改需要改的属性。这样建立层级体系,便于维护。

例子:基于正文建立标题

正文Normal定义了字体宋体,五号,单倍行距。标题1基于正文,只改字号、加粗、对齐、间距,字体继承正文。如果你后来改了正文字体,标题字体自动跟着改。

继承关系:

docDefaults
  └── Normal(正文)
        ├── Heading 1(标题1)
        │    └── 我的自定义标题
        ├── Heading 2(标题2)
        └── 正文缩进(首行缩进的正文)

好处:

  • 改一处影响全体系
  • 减少重复定义
  • 整体风格统一

使用继承的建议

  • 所有段落样式最终都基于Normal
  • 只覆盖需要变化的属性,其他继承
  • 不要每个样式都从头定义一遍字体字号,浪费

17.6 样式快捷键

给常用样式设置快捷键,排版效率提高很多:

推荐:

  • Ctrl+Alt+1 → 标题1
  • Ctrl+Alt+2 → 标题2
  • Ctrl+Alt+3 → 标题3
  • Ctrl+Alt+N → 正文

不用去鼠标点选,键盘快捷键一秒应用,效率高很多。


17.7 修改样式技巧

修改样式很简单:

  1. 在样式库找到那个样式
  2. 右键 → 修改
  3. 在修改对话框改格式
  4. 确定 → 全文档所有应用这个样式的地方自动更新

比你一个个手动改快一百倍。

批量改示例

老板说:“所有标题都从二号改成一号,整体大一点。”

如果手工改:一个个找,改一百个标题,累死,还可能漏。

用样式:打开修改标题1,改字号,确定,搞定。十秒钟。

这就是样式的威力。


17.8 快速样式库

Word的快速样式库显示常用样式,点一下就应用。建议:

  • 把你文档用到的所有样式都放进快速样式库
  • 按顺序排列:正文、标题1、标题2、标题3…
  • 用的时候直接点,不用去深层菜单找

清爽干净的快速样式库,排版的时候心情都好。


17.9 清除格式

如果弄乱了,想清除格式回到默认:

  • 选中内容
  • 点击“清除格式“
  • 回到Normal正文样式,所有直接格式都清掉

重新应用样式就干净了。


17.10 最佳实践总结

  1. 每个段落都必须应用样式,不要留“正文“直接就是无样式
  2. 多用样式,少用直接格式,能靠样式做到的就不要手工改
  3. 善用继承,减少重复,方便维护
  4. 给常用样式设快捷键,提高效率
  5. 标题一定要设正确大纲级别,才能自动生成目录
  6. 新章前分页放在段落属性里(pageBreakBefore),不要手动插分页

遵循这些实践,你排版又快又好,改起来也方便。


本章小结

  • 样式是排版的骨架,所有专业排版都基于样式
  • 段落样式对应文档结构,字符样式处理局部格式
  • 利用样式继承建立层级体系,减少重复便于维护
  • 修改样式自动更新全文档,比手工改高效太多
  • 快捷键和快速样式库进一步提高效率

下一章我们讲解中文排版的最佳实践。

第18章:中文排版最佳实践

学习目标

  • 了解中文排版和英文排版的差异
  • 掌握中文排版的基本原则
  • 学会处理中文标点、空格、缩进等细节
  • 输出符合中文阅读习惯的文档

18.1 中文排版的特点

中文和英文排版有很多不同:

项目英文中文
文字方向横排从左到右横排从左到右(传统竖排从上到下从右到左)
字体大小单词间有空格分开汉字方块字,不需要空格
标点标点占一个英文字符宽度标点占一个汉字宽度
段落缩进一般顶格,空行分段习惯首行缩进两字符

我们现在主要说现代横排中文排版。


18.2 首行缩进

中文排版习惯:每个段落首行缩进两个汉字宽度

怎么设置正确?

  • 不要用四个空格去缩进!
  • 不要用制表位去缩进!
  • 正确方法:在段落设置里设置首行缩进 2字符(对应XML就是w:firstLine="480" 小四,字号不同值不同)。

为什么不要用空格:

  • 如果字号变了,空格宽度不对
  • 如果换行,可能多出来空格不好看
  • 复制粘贴会把空格也复制走

样式里设置好首行缩进,每次应用正文样式自动就对了。

为什么要首行缩进

首行缩进帮助读者一眼找到段落开头,区分段落。没有首行缩进又没有空行,读者分不清哪里是段落开头。


18.3 段落之间是否需要空行

两种方式:

  1. 首行缩进 + 无空行:传统中文书籍,节省空间
  2. 无首行缩进 + 段间空行:网络文章、博客,看起来更松快

正式文档、书籍、论文一般用第一种:首行缩进,段间不需要额外空行。

PPT、网页、博客用第二种更现代。

选择一种就坚持从头到尾一致,不要混着来。


18.4 标点处理

全角标点

中文排版用全角标点,标点占一个汉字宽度。

正确:你好,世界。 (逗号句号都是全角) 错误:你好,世界. (半角英文标点)

例外:

  • 英文单词、缩写里面的标点用半角
  • 代码里面的标点用半角
  • 括号引号要配对

标点溢出悬挂

有些排版规则说,标点放在行尾可以溢出悬挂,让出边更整齐。Word不支持自动悬挂,一般用户也不需要纠结,就放里面就好了。

引号使用顺序

中文引号规则:

  • 第一层:「」
  • 第二层:『』
  • 或者:“” 里面放 ‘’

不同地区习惯不同,按照你的读者习惯来。大陆一般用“”里面放‘’。


18.5 空格使用

中文排版原则:除了特殊情况,汉字和标点之间不需要空格

需要加空格的情况

  1. 中英文混排:英文单词前后加空格

    • 正确:使用 Word 编辑文档
    • 错误:使用Word编辑文档
    • 原因:英文单词和汉字分开,看起来舒服
  2. 数字前后:数字和中文之间加空格

    • 正确:一共 123 页
    • 错误:一共123页
  3. 百分比单位:数字和百分号之间不用空格:50%

不需要加空格的情况

  • 中文标点前后不需要空格
  • 全角标点已经占了位置

记住一个简单规则:只有英文单词、阿拉伯数字前后加空格,其他都不加。


18.6 字体选择

正文

正式公文常用:

  • 正文:仿宋_GB2312,三号 (公文标准)
  • 一般文档:宋体 五号 / 宋体 小四 都可以
  • 屏幕阅读:微软雅黑 五号,清晰不累

标题

  • 一级标题:黑体 二号或一号
  • 二级标题:黑体 三号
  • 三级标题:黑体 四号

注意字体版权

  • Windows自带字体可以在Windows上用
  • 分发电子版一般没问题
  • 如果要嵌入字体,确认许可证允许嵌入
  • 商业发布尽量用有授权的字体

18.7 行间距

行间距推荐:

  • 五号字:12磅字 → 单倍行距(360)合适
  • 小四号:可以用1.5倍行距,更透气
  • 大段文字不要用双倍行距,太散

正文行间距太挤读者累,太松浪费纸,自己把握平衡。


18.8 页边距

标准A4纸默认边距:上下左右各1英寸(1440缇)就很好。

如果需要装订,可以在左边加装订线(一般300-600缇)。


18.9 标题排版

标题排版原则:

  1. 层级清晰:字号从大到小,字体区分
  2. 留白足够:标题段前比段后多留点空白
    • 比如:一级标题段前18磅,段后12磅
  3. 对齐一致:同级标题对齐方式一致,都居中就都居中,都左对齐就都左对齐
  4. 不要孤行:标题不要留在页底,和正文分开,设置keepNext

章节编号

用Word自动编号:

  • 好处:插入删除章节,编号自动更新
  • 设置:开始 → 编号 → 定义新的多级列表,链接到标题样式
  • 不要手动打编号,删改麻烦

18.10 表格排版

中文表格习惯:

  • 标题行一般灰色底纹加粗
  • 边框:外框粗一点,内框细一点,或者都单线也可以
  • 文字单元格垂直居中好看
  • 内容少的表格可以适当增加行高,不要挤在一起

18.11 目录

目录自动生成,要点:

  1. 标题用标题样式
  2. 大纲级别正确
  3. 插入TOC域,自动生成
  4. 修改文档后更新域就可以了

目录一般放在正文前面,页码用罗马数字,正文重新从1开始阿拉伯,分节设置不同页码就可以了。


18.12 页码

页码一般放页脚居中,也可以放外侧(奇偶页不同,奇数在右,偶数在左),装订成册阅读方便。

常见格式:第 5 页,共 10 页,用PAGE和NUMPAGES域自动更新。


18.13 最佳实践检查清单

写完文档可以检查一遍:

  • 每个段落都应用了正确样式
  • 正文首行缩进两字符(用段落设置,不是空格)
  • 标点都是全角(英文数字除外)
  • 中英文混排,英文数字前后加了空格
  • 标题大纲级别正确,可以生成目录
  • 标题设置了keepNext,不会和正文分页分开
  • 行间距合适,不挤不散
  • 层级清晰,标题字号逐级减小
  • 没有多余手动分页,自动分页就好
  • 目录自动生成,不是手敲

都检查过,就是一份符合中文排版习惯的好文档了。


本章小结

  • 中文排版有自己的习惯,和英文不一样
  • 首行缩进两字符用段落设置,不要用空格
  • 中文用全角标点,中英文混排英文前后加空格
  • 层级清晰,标题字号逐级减小,留白足够
  • 用自动编号,自动目录,不要手动
  • 最后按照检查清单过一遍,细节对了整体就专业了

下一章我们讲解目录与交叉引用。

第19章:目录与交叉引用

学习目标

  • 掌握自动目录的正确做法
  • 理解目录基于什么生成
  • 学会使用交叉引用
  • 掌握更新域的方法

19.1 自动目录的原理

我们之前讲过,Word自动目录基于标题样式大纲级别生成。

工作原理:

  1. 你给各级标题应用对应的样式
  2. 每个标题样式已经设置了对应的大纲级别
  3. 插入TOC域
  4. Word更新时扫描文档,收集所有标题,按级别生成目录
  5. 每个目录条目自动带页码,还可以点击跳转

所以,正确设置标题样式是自动目录的前提。手敲目录,加完删改章节还要手改页码,太麻烦了。


19.2 正确步骤生成自动目录

第一步:给标题应用样式

确保:

  • 章标题 → 标题1样式
  • 节标题 → 标题2样式
  • 小节标题 → 标题3样式
  • …以此类推

不用改Word默认的,默认已经对应了正确的大纲级别。

第二步:插入目录

把光标放在你想放目录的位置(一般在封面之后,正文之前),然后:

引用 → 目录 → 自动目录

Word就会插入TOC域,自动生成目录。

在XML中就是我们之前讲的:

<w:r>
  <w:fldChar w:fldCharType="begin"/>
  <w:instrText>TOC \o "1-3" \h \z</w:instrText>
  <w:fldChar w:fldCharType="end"/>
</w:r>
  • \o "1-3" 包含大纲级别1到3级
  • \h 生成超链接
  • \z 去掉页码边框

19.3 更新目录

你修改了文档,增加删除了章节,页码变了,需要更新目录:

  1. 右键点击目录区域
  2. 选择“更新域“
  3. 选择“只更新页码“或者“更新整个目录“
  4. 确定

如果只是页码变了,选只更新页码,快。如果加删了标题,选更新整个目录。


19.4 自定义目录

你可以选择包含哪些级别:

  • 如果你的文档只有两级标题,就 \o "1-2"
  • 如果有四级,就 \o "1-4"

插入目录时在对话框里设置起始级别和结束级别就可以了。

你也可以自定义目录样式,目录本身用什么格式,改目录样式就可以,所有目录自动更新。


19.5 图表目录

如果你的文档有很多图或表,可以做图表目录:

前提:

  • 所有图表题注都用Word的插入题注功能插入
  • 图用“图“标签,表用“表“标签

然后:

  • 引用 → 插入图表目录
  • 选择标签,生成

就自动生成带页码的图表目录了。原理和目录一样,也是基于题注收集。


19.6 交叉引用是什么

交叉引用就是:“详见 第3章”,那个“第3章“如果是手敲的,你把第3章挪到第4章了,这里还要手改。用交叉引用,自动更新。

使用交叉引用步骤

  1. 光标放在你要放引用的地方
  2. 引用 → 交叉引用
  3. 选择引用类型:标题、书签、编号、图表等
  4. 选择要引用的目标
  5. 插入

Word就会插入一个REF域,自动引用目标标题文字和页码。

在XML中的样子

<w:r>
  <w:t>详见</w:t>
  <w:fldChar w:fldCharType="begin"/>
  <w:instrText>REF _Ref123456789 \h</w:instrText>
  <w:fldChar w:fldCharType="separate"/>
  <w:t>第3章 开头</w:t>
  <w:fldChar w:fldCharType="end"/>
  <w:t>。</w:t>
</w:r>

\h 表示加上超链接,点击可以跳过去,很好用。


19.7 更新交叉引用

和目录一样,改了文档之后,全选文档,按F9,更新所有域,所有交叉引用、页码、目录都更新了。

养成习惯:最后输出PDF之前,全选 → F9 更新所有域,检查一遍,确保所有引用页码都对。


19.8 书签

书签是什么?书签就是给文档中某个位置打个标记,可以交叉引用跳过去。

插入书签:

  1. 选中位置或文字
  2. 插入 → 书签
  3. 书签名 → 添加

你可以在书签对话框跳到某个书签,交叉引用也可以引用书签。长文档善用书签,跳转很方便。


19.9 最佳实践

  • 永远用自动目录,不要手敲目录
  • 善用交叉引用,不要手敲章节号页码
  • 修改完文档最后一定要更新所有域
  • 多级列表链接到标题样式,编号自动更新
  • 图表用题注,做图表目录方便

本章小结

  • 自动目录基于标题样式/大纲级别,正确设置标题就可以一键生成
  • 修改文档后右键更新域就可以更新目录
  • 交叉引用自动引用目标,章节移动自动更新,不用手改
  • 全选文档按F9可以更新所有域
  • 图表用题注可以生成图表目录

下一章我们讲解样式自动化排版技巧。

第20章:样式自动化排版技巧

学习目标

  • 掌握提高排版效率的技巧
  • 学会使用样式集和模板
  • 了解VBA宏自动化批量处理
  • 养成好的排版工作流

20.1 使用模板

模板是 .dotx 文件,保存了样式和格式设置,新建文档基于模板。

为什么用模板

  • 一次设置好所有样式,每次新建直接用
  • 团队协作,所有人用同一个模板,格式统一
  • 省去每次重复设置的麻烦

怎么做

  1. 新建一个空白文档
  2. 设置好所有需要的样式:正文、各级标题、题注等
  3. 文件 → 另存为 → 保存类型选择 “Word 模板 (*.dotx)”
  4. 以后新建文档,基于这个模板就好了

如果你经常写同类型的文档(比如论文、报告),做个模板,一了百了。


20.2 样式集

Word 支持样式集,把一套样式保存为样式集,可以套用给现有文档:

  • 设计好你的样式
  • 设计 → 样式集 → 保存为新样式集
  • 以后换风格直接点一下样式集就换了,全文档样式自动更新

适合给文档换整体风格,很快。


20.3 格式刷的正确用法

格式刷可以复制格式:

  • 点一下格式刷 → 复制一次格式
  • 双击格式刷 → 可以复制给多个地方,按ESC结束

很多人不知道双击可以重复用,这个技巧节省很多时间。


20.4 查找替换格式

Word查找替换不仅可以替换文字,还可以替换格式。

例子:把所有蓝色粗体改成红色斜体:

  1. 查找 → 更多 → 格式 → 选蓝色粗体
  2. 替换为 → 格式 → 选红色斜体
  3. 全部替换

一下子全换完,比你一个个找快太多了。

批量改格式非常有用。


20.5 多级列表链接到标题样式

这是非常有用的技巧:把自动编号链接到标题样式,各级标题自动编号,插入删除自动更新。

设置步骤:

  1. 开始 → 多级列表 → 定义新的多级列表
  2. 级别1链接到标题1,编号格式比如 “第1章”
  3. 级别2链接到标题2,编号格式比如 “1.1”
  4. 级别3链接到标题3,编号格式比如 “1.1.1”
  5. 确定

之后你每次应用标题1,自动就加上“第1章“、“第2章”…,插入一章前面,所有编号自动更新,太爽了。

不要再手动打章节编号了!


20.6 使用样式快捷键

给常用样式设置快捷键:

  • 标题1:Ctrl+Alt+1
  • 标题2:Ctrl+Alt+2
  • 标题3:Ctrl+Alt+3
  • 正文:Ctrl+Alt+N

手不用离开键盘,应用样式一秒钟,效率比鼠标点快很多。


20.7 导航窗格

开着导航窗格(视图 → 导航窗格),它会根据标题样式生成目录树:

  • 可以点击跳转
  • 可以拖动调整章节顺序
  • 一目了然整个文档结构

长文档一定要开导航窗格,太方便了。


20.8 显示格式窗格

选中文字,开显示格式,可以看到这个文字到底用了什么样式,有哪些直接格式覆盖,哪里不对一眼看到。

排错很有用,为什么格式不对,一看就知道了。


20.9 VBA宏自动化

如果你需要重复做很多相同的操作,可以写VBA宏自动化:

例子:

  • 批量把所有标题改成某种格式
  • 批量处理图片大小
  • 批量转换全角标点
  • 批量生成多个文档

Word支持VBA编程,可以省很多手工劳动。如果你经常要做重复的事,花半小时写个宏,以后每次点一下就好了。


20.10 长文档排版工作流推荐

一个推荐的工作流:

  1. 准备模板:提前做好模板,设置好所有样式、多级列表
  2. 写作:写作的时候,正确应用样式,标题就用标题1标题2,正文就用正文,不要乱改格式
  3. 插图插表:用题注,自动编号
  4. 引用交叉:需要引用就用交叉引用
  5. 最后整理
    • 更新所有域(全选 → F9)
    • 检查目录页码
    • 检查交叉引用
    • 检查格式一致性

这样出来的文档,结构清晰,格式一致,容易修改,非常专业。


20.11 常见错误要避免

  • ❌ 不用样式,所有格式手工调 → 乱,难改
  • ❌ 手工打章节编号 → 插入删除要全改
  • ❌ 用空格缩进首行 → 不对齐,难改
  • ❌ 硬插很多手动分页 → 内容变了分页全错
  • ❌ 手敲目录 → 改了内容页码不对

这些错很多人都犯,其实只要用对Word功能,这些问题都不存在。


本章小结

  • 用模板,一次设置永久用
  • 多级列表链接标题样式,自动编号不用管
  • 查找替换可以批量改格式
  • 设置样式快捷键,提高效率
  • 导航窗格方便长文档导航
  • 自动化做重复工作,省时间
  • 遵循好的工作流,出来的文档专业好改

这就是第四排版设计实践的最后一章了。整个第四部分我们从排版原理讲到样式,讲到中文实践,讲到目录交叉引用,讲到自动化技巧,相信你现在对Word排版已经有了深入理解。

附录A:XML命名空间参考

本书常用的XML命名空间参考表:

前缀命名空间URI用途
whttp://schemas.openxmlformats.org/wordprocessingml/2006/mainWordprocessingML主命名空间,绝大多数元素
rhttp://schemas.openxmlformats.org/officeDocument/2006/relationships关系引用
ahttp://schemas.openxmlformats.org/drawingml/2006/mainDrawingML绘图
wphttp://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawingWord绘图
pichttp://schemas.openxmlformats.org/drawingml/2006/picture图片
mchttp://schemas.openxmlformats.org/markup-compatibility/2006标记兼容性
cthttp://schemas.openxmlformats.org/package/2006/content-types内容类型
relhttp://schemas.openxmlformats.org/package/2006/relationships包级关系
cphttp://schemas.openxmlformats.org/package/2006/metadata/core-properties核心属性
dchttp://purl.org/dc/elements/1.1/Dublin Core元数据

在根元素上声明例子:

<w:document
  xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
  xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
  xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
  xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">

前缀可以自己定,只要绑定到正确的URI就行。本书统一使用上面的前缀约定。

附录B:常用工具列表

这里列出一些处理docx有用的工具。

查看和解压

  • 7-Zip:免费解压软件,可以直接解压docx,查看内部文件
    • 官网:https://www.7-zip.org/
  • XML Notepad:微软免费XML查看编辑器,树形浏览很方便
    • 官网:https://github.com/microsoft/XmlNotepad
  • Visual Studio Code:带XML语法高亮,很好用
    • 官网:https://code.visualstudio.com/
  • OleTools:如果需要看旧.doc,可以用oletools解析
    • GitHub:https://github.com/decalage2/oletools

编程库

Python

  • python-docx:最常用的Python处理docx库
    • GitHub:https://github.com/python-openxml/python-docx
  • docx2txt:提取文本
    • https://pypi.org/project/docx2txt/
  • mammoth:转换docx到HTML
    • https://github.com/mwilliamson/mammoth.js

Java

  • Apache POI - HWPF/XWPF 处理doc/docx
    • 官网:https://poi.apache.org/

.NET

  • Open XML SDK - Microsoft官方SDK
    • GitHub:https://github.com/dotnet/Open-XML-SDK
  • DocX - 更易用的封装
    • GitHub:https://github.com/xceedsoftware/DocX

JavaScript

  • docx - 生成docx
    • GitHub:https://github.com/dolanmiu/docx

在线工具

  • Aspose Viewer:在线查看docx
  • CloudConvert:在线格式转换

验证工具

  • Office Open XML SDK Productivity Tool:可以验证和查看Open XML
  • XML Validator:在线验证XML格式是否正确

推荐阅读工具

如果你要阅读本书的markdown,可以用:

  • GitBook:生成美观的HTML书籍
  • MDBook:现代rust版本,更快
  • VS Code + Markdown Preview:本地阅读

附录C:进一步阅读资源

如果你想更深入学习,可以参考以下资源:

官方标准

  • ECMA-376 Standard:官方标准,最权威,但非常厚

    • https://www.ecma-international.org/publications-and-standards/standards/ecma-376/
  • ISO/IEC 29500:国际标准版本

    • https://www.iso.org/standard/51407.html

书籍

  • Open XML Explained - Wouter Van Vugt
    • 开源免费介绍Open XML
  • Professional Open XML Development - 针对开发人员
  • Word Processing with Open XML XML - Microsoft Press

博客和网站

  • Eric White’s Blog:很多Open XML技术文章
    • https://www.ericwhite.com/blog/
  • Open XML Developer:开发资源网站

源码

  • 各语言开源处理库的源码本身就是很好的学习材料:
    • python-docx:https://github.com/python-openxml/python-docx
    • Apache POI:https://poi.apache.org/
    • Open XML SDK:https://github.com/dotnet/Open-XML-SDK

规范速查

  • Office Open XML 维基百科:https://en.wikipedia.org/wiki/Office_Open_XML
  • Microsoft docs:https://learn.microsoft.com/en-us/office/open-xml/word-processing