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编辑文档就够了。但在很多场景下,理解文档格式是非常必要的:
- 批量生成文档:根据模板批量生成合同、报告、发票
- 批量提取数据:从大量Word文档中提取特定信息
- 文档转换:将Word转换为PDF、HTML、Markdown等其他格式
- 修复损坏文档:当Word无法打开损坏文档时,可以通过理解格式来提取内容
- 开发文档处理系统:开发在线文档编辑、协作文档系统
- 自动化处理:文档审核、格式检查、批量转换等自动化任务
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文档的场景,理解理解格式为什么重要。
场景一:批量生成合同
一家企业法务部门每个月要生成几十份劳动合同,员工信息存在数据库里。
如果手动操作:
- 打开模板
- 替换姓名、职位、日期等占位符
- 另存为新文件
- 重复几十次
这个过程机械重复,耗时且容易出错。
如果理解.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的优势
- 结构化:XML使用标签清晰地表达结构,便于计算机解析
- 自描述:标签本身说明了内容是什么,可读性好
- 标准技术:有大量成熟的工具库处理XML
- 易于调试:XML是文本,可以直接用文本编辑器打开查看
- 扩展性好:新增功能不需要破坏原有格式
对比二进制格式
| 方面 | 二进制 | 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有两个版本的标准:
- ECMA-376:由Ecma International维护,更新更频繁
- 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格式时:
- 优先使用.docx:这是现在的主流,几乎所有软件都支持
- 只在需要时支持.doc:如果用户确实有旧文档需求再支持
- 转换为docx处理:收到doc文件可以先转换为docx再处理
- 不要生成新的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压缩包。
你可以直接验证这一点:
- 找一个.docx文件,复制一份
- 将扩展名从
.docx改成.zip - 用你的解压软件(7-Zip、WinRAR等)解压它
- 你会看到里面有很多文件和文件夹
这就是.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/.rels和word/_rels/document.xml.rels这些文件。这些是关系文件(Relationships)。
关系的作用
Open XML使用关系来表示资源之间的引用关系。为什么不直接用文件路径?
关系的好处:
- 解耦:源文件不需要知道目标文件的具体路径
- 可移动:移动目标文件只需要更新关系文件,不需要更新所有引用
- 类型明确:关系可以指定类型,说明这是什么类型的引用
关系文件格式
关系文件的结构很简单,举个例子,_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>
两种声明方式
-
Default:默认,按扩展名定义内容类型。所有扩展名为png的都是image/png类型。
-
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 动手解压看看真实结构
理论说了这么多,现在动手实践一下:
- 准备一个简单的docx文件:创建一个新Word文档,输入几行文字,插入一张图片,保存。
- 复制一份,不要改坏原文件。
- 改扩展名:把
.docx改成.zip。 - 解压:用解压软件解压。
- 浏览:看看各个文件,用文本编辑器打开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不是一个单一格式,它是一个标准框架,定义了三种文档类型:
| 文档类型 | 文件扩展名 | 标记语言名称 | 用途 |
|---|---|---|---|
| 文字处理 | .docx | WordprocessingML | Word文档 |
| 电子表格 | .xlsx | SpreadsheetML | Excel工作簿 |
| 演示文稿 | .pptx | PresentationML | PowerPoint演示文稿 |
本书只关注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 | 用途 |
|---|---|---|
w | http://schemas.openxmlformats.org/wordprocessingml/2006/main | WordprocessingML主命名空间,绝大多数元素都在这里 |
r | http://schemas.openxmlformats.org/officeDocument/2006/relationships | 关系引用 |
a | http://schemas.openxmlformats.org/drawingml/2006/main | DrawingML,绘图(图片、图形) |
wp | http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing | Word绘图 |
pic | http://schemas.openxmlformats.org/drawingml/2006/picture | 图片 |
mc | http://schemas.openxmlformats.org/markup-compatibility/2006 | 标记兼容性 |
ct | http://schemas.openxmlformats.org/package/2006/content-types | 内容类型 |
rel | http://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"/> <!-- 对齐:右对齐 -->
布尔属性的表示
对于开关类型的属性(开/关),有几种表示方式:
-
只写标签,没有val - 表示开
<w:b/> <!-- 粗体打开 --> -
用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 动手练习
现在你可以自己动手试试:
- 解压一个简单的docx文件
- 用文本编辑器打开
word/document.xml - 找找看:
w:document,w:body,w:p,w:r,w:t这些元素 - 看看段落属性
w:pPr和运行属性w:rPr在哪里 - 看看不同格式文字是不是分成不同的run
亲手看一次,你对结构的理解会深刻很多。
本章小结
document.xml的基本结构:w:document→w:body→w:p→w:r→w: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会自动处理特殊字符:
<要写成<,&要写成& - 如果文本开头或结尾有空格,需要加
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:修订IDw: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:document→w:body→ 内容 +w:sectPr - body可以包含段落和表格等块级元素
- 段落结构:
w:p→w:pPr(属性) + 内容(多个w:r) - 运行结构:
w:r→w: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>
结构很清晰:
- 开头是
docDefaults定义默认格式 - 然后是每个样式一个
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:customStyle | 1表示是用户自定义样式,0表示内置样式 |
子元素
| 元素 | 说明 |
|---|---|
w:name | 样式的显示名称,用户在Word界面看到的名称 |
w:basedOn | 基于哪个样式,样式继承 |
w:next | 应用此样式段落回车后下一段默认样式 |
w:pPr | 段落属性,应用此样式的段落默认格式 |
w:rPr | 字符属性,应用此样式的文字默认格式 |
样式ID vs 名称
styleId是内部ID,通常是英文不变,比如Heading1name是显示名称,本地化会变,中文就是“标题 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>
属性查找顺序
当应用一个样式时,属性查找顺序:
- 当前样式定义的属性 → 使用
- 如果没有,找
basedOn父样式 → 使用父样式定义 - 如果父样式也没有,继续找祖父样式…
- 最后找默认样式 → 使用默认
为什么要继承
- 减少重复定义
- 修改共同属性只需要改父样式
- 保持一致性
- 方便批量修改
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 样式优先级
如果多个格式设置作用于同一个文字,优先级是怎样的?
优先级从高到低:
- 直接格式(直接在rPr/pPr设置的属性)- 最高
- 字符样式 - 高于段落样式
- 段落样式 - 低于字符样式
- 默认样式(Normal)
- 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 字体信息存储在哪里
字体信息可以存储在多个层级:
- docDefaults - 文档默认字体
- 样式 - 每个样式可以定义自己的字体
- 运行rPr - 单个run可以直接指定字体
优先级:直接run指定 > 样式 > docDefaults。
字体元素 w:rFonts
字体信息用<w:rFonts>元素表示,位于rPr内:
<w:rPr>
<w:rFonts
w:ascii="宋体"
w:eastAsia="宋体"
w:hAnsi="宋体"
w:cs="宋体"/>
</w:rPr>
四个属性分别对应不同字符编码范围:
| 属性 | 作用 |
|---|---|
w:ascii | ASCII字符(0-127)使用的字体 |
w:eastAsia | 东亚字符(中日韩)使用的字体 |
w:hAnsi | Windows 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) |
|---|---|---|
| 八号 | 5 | 10 |
| 七号 | 5.5 | 11 |
| 小六号 | 6.5 | 13 |
| 六号 | 7.5 | 15 |
| 小五号 | 9 | 18 |
| 五号 | 10.5 | 21 |
| 小四 | 12 | 24 |
| 四号 | 14 | 28 |
| 小三 | 15 | 30 |
| 三号 | 16 | 32 |
| 小二 | 18 | 36 |
| 二号 | 22 | 44 |
| 小一 | 24 | 48 |
| 一号 | 26 | 52 |
| 小初 | 36 | 72 |
| 初号 | 42 | 84 |
记忆要点:五号=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:u的w: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包内,通过关系引用。
嵌入方式
有两种嵌入方式:
- 完全嵌入:嵌入整个字体文件,文件变大,但可以编辑
- 子集嵌入:只嵌入文档中用到的字符,文件小,但不能编辑(只能显示打印)
法律问题
⚠️ 重要提示:
- 大多数商业字体是有许可证的,不允许随意嵌入分发
- 嵌入字体可能违反字体的使用许可
- 在文档中嵌入字体之前,请确认你有嵌入权限
- 开源字体一般允许嵌入
开发建议
- 如果是内部使用,考虑字体嵌入
- 如果是公开发布,尽量使用系统默认字体
- PDF格式导出后再分发,可以避免字体问题
8.6 字体查找与回退
当Word打开文档,找不到指定字体时,会怎么处理?
字体回退机制
- Word按名称找字体
- 如果找不到,根据字体特征找相似字体替代
- 如果还是找不到,用默认替代字体(通常是Times New Roman + 宋体)
兼容性问题
- 同样字体在不同系统名称可能不同
- Mac和Windows字体名称不一样
- Windows字体搬到Mac可能找不到
- 开源系统(Linux)一般没有微软默认字体
解决建议
- 使用系统自带字体:Windows自带的宋体、黑体、仿宋、楷体一般不用嵌入
- 使用通用名称:尽量使用标准名称
- PDF导出:如果需要分发,导出PDF最安全
- 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值的单位:
| lineRule | line的单位 | 说明 |
|---|---|---|
auto | 1/20磅 | 自动,最常用 |
exact | 缇 | 精确值 |
multiple | 1/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是背景色RGBw: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 | 备注 |
|---|---|---|---|
| A4 | 12240 | 15840 | 默认标准 |
| A3 | 15840 | 24480 | |
| B5 | 9360 | 13680 | |
| 16开 | 9600 | 14400 | 中文16开 |
| Letter | 12240 | 15840 | Letter尺寸和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:tbl→w:tblPr+w:tblGrid+ 多个w:tr - 行:
w:tr→w:trPr+ 多个w:tc - 单元格:
w:tc→w:tcPr+ 内容(段落等) - 水平合并:用
gridSpan指定跨几列,只放一个格子 - 垂直合并:第一个格子
vMerge="restart",后续格子只放vMerge - 表格宽度可以是百分比或绝对宽度
- 边框在表格级别设置内部和外部边框,单元格可以单独覆盖
下一章我们讲解图片和嵌入式对象。
第12章:图片和嵌入式对象
学习目标
- 理解docx中图片的存储方式
- 理解关系引用机制
- 掌握图片在XML中的表示方式
- 了解嵌入式OLE对象
12.1 图片存储在哪里
在docx中,图片文件本身不放在XML里,而是:
- 原始图片文件放在
word/media/目录下 - 在关系文件
word/_rels/document.xml.rels中注册关系ID - 在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 形状属性(大小位置)
关键部分
-
关系引用:
<a:blip r:embed="rId3"/>这里的r:embed就是关系ID,对应rels里的Id。 -
大小单位EMU:尺寸单位是English Metric Unit,换算:
- 1英寸 = 914400 EMU
- 1厘米 = 360000 EMU
- 1磅 = 12700 EMU
所以,一张10cm × 7.5cm的图片就是:
cx="3600000" cy="2700000" -
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对象,怎么存?
和图片类似:
- OLE对象数据存在
word/embeddings/目录下 - 在关系文件注册关系
- 在文档中用
<o:OLEObject>引用
一般开发中很少需要处理嵌入OLE对象,知道位置就可以了。
12.7 完整示例总结
插入一张图片需要做三件事:
- 复制图片文件到
word/media/imageN.png - 在
document.xml.rels添加关系:<Relationship Id="rIdX" Type="...image" Target="media/imageN.png"/> - 在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:equalWidth | 1表示等宽,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设置分栏,整个文档都分栏。
部分内容分栏
如果你只需要一部分内容分栏,另一部分不分栏:
- 在分栏开始前插入分节符(连续)
- 在分栏结束后再插入分节符
- 给中间那节设置分栏,前后节不设置(或设置单栏)
这样就能实现一页内一部分单栏一部分双栏。
例子:标题单栏,正文双栏
<!-- 第一节:标题,单栏 -->
<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缇。
本章小结
- 分栏设置在节属性
sectPr的w: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>
结构:
w:fldChar w:fldCharType="begin"- 域开始w:instrText- 域指令(就是域代码)w:fldChar w:fldCharType="separate"- 分隔指令和结果- 结果内容 - 缓存的上次计算结果
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的自动目录工作原理:
- 你给各个标题应用了标题样式(Heading1, Heading2…)或者设置了大纲级别
- 你插入TOC域
- Word更新域时,扫描整个文档,收集所有有大纲级别的段落
- 根据级别生成目录条目,每个条目带页码和超链接
- 放在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 格式优先级
我们之前讲过格式优先级,这里再强调一下:
优先级从高到低:
- 直接格式(run或p上直接设置)→ 最高
- 字符样式 → 高于段落样式
- 段落样式 → 低于字符样式
- 默认样式 →
- 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>
关键点:
outlineLvl设置正确,才能进目录keepNext保证标题不和正文分页分开next设置回车后回到正文样式,不用每次手动切- 段前间距大于段后,留白好看
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→ 标题1Ctrl+Alt+2→ 标题2Ctrl+Alt+3→ 标题3Ctrl+Alt+N→ 正文
不用去鼠标点选,键盘快捷键一秒应用,效率高很多。
17.7 修改样式技巧
修改样式很简单:
- 在样式库找到那个样式
- 右键 → 修改
- 在修改对话框改格式
- 确定 → 全文档所有应用这个样式的地方自动更新
比你一个个手动改快一百倍。
批量改示例
老板说:“所有标题都从二号改成一号,整体大一点。”
如果手工改:一个个找,改一百个标题,累死,还可能漏。
用样式:打开修改标题1,改字号,确定,搞定。十秒钟。
这就是样式的威力。
17.8 快速样式库
Word的快速样式库显示常用样式,点一下就应用。建议:
- 把你文档用到的所有样式都放进快速样式库
- 按顺序排列:正文、标题1、标题2、标题3…
- 用的时候直接点,不用去深层菜单找
清爽干净的快速样式库,排版的时候心情都好。
17.9 清除格式
如果弄乱了,想清除格式回到默认:
- 选中内容
- 点击“清除格式“
- 回到Normal正文样式,所有直接格式都清掉
重新应用样式就干净了。
17.10 最佳实践总结
- 每个段落都必须应用样式,不要留“正文“直接就是无样式
- 多用样式,少用直接格式,能靠样式做到的就不要手工改
- 善用继承,减少重复,方便维护
- 给常用样式设快捷键,提高效率
- 标题一定要设正确大纲级别,才能自动生成目录
- 新章前分页放在段落属性里(pageBreakBefore),不要手动插分页
遵循这些实践,你排版又快又好,改起来也方便。
本章小结
- 样式是排版的骨架,所有专业排版都基于样式
- 段落样式对应文档结构,字符样式处理局部格式
- 利用样式继承建立层级体系,减少重复便于维护
- 修改样式自动更新全文档,比手工改高效太多
- 快捷键和快速样式库进一步提高效率
下一章我们讲解中文排版的最佳实践。
第18章:中文排版最佳实践
学习目标
- 了解中文排版和英文排版的差异
- 掌握中文排版的基本原则
- 学会处理中文标点、空格、缩进等细节
- 输出符合中文阅读习惯的文档
18.1 中文排版的特点
中文和英文排版有很多不同:
| 项目 | 英文 | 中文 |
|---|---|---|
| 文字方向 | 横排从左到右 | 横排从左到右(传统竖排从上到下从右到左) |
| 字体大小 | 单词间有空格分开 | 汉字方块字,不需要空格 |
| 标点 | 标点占一个英文字符宽度 | 标点占一个汉字宽度 |
| 段落缩进 | 一般顶格,空行分段 | 习惯首行缩进两字符 |
我们现在主要说现代横排中文排版。
18.2 首行缩进
中文排版习惯:每个段落首行缩进两个汉字宽度。
怎么设置正确?
- 不要用四个空格去缩进!
- 不要用制表位去缩进!
- 正确方法:在段落设置里设置首行缩进 2字符(对应XML就是
w:firstLine="480"小四,字号不同值不同)。
为什么不要用空格:
- 如果字号变了,空格宽度不对
- 如果换行,可能多出来空格不好看
- 复制粘贴会把空格也复制走
样式里设置好首行缩进,每次应用正文样式自动就对了。
为什么要首行缩进
首行缩进帮助读者一眼找到段落开头,区分段落。没有首行缩进又没有空行,读者分不清哪里是段落开头。
18.3 段落之间是否需要空行
两种方式:
- 首行缩进 + 无空行:传统中文书籍,节省空间
- 无首行缩进 + 段间空行:网络文章、博客,看起来更松快
正式文档、书籍、论文一般用第一种:首行缩进,段间不需要额外空行。
PPT、网页、博客用第二种更现代。
选择一种就坚持从头到尾一致,不要混着来。
18.4 标点处理
全角标点
中文排版用全角标点,标点占一个汉字宽度。
正确:你好,世界。 (逗号句号都是全角)
错误:你好,世界. (半角英文标点)
例外:
- 英文单词、缩写里面的标点用半角
- 代码里面的标点用半角
- 括号引号要配对
标点溢出悬挂
有些排版规则说,标点放在行尾可以溢出悬挂,让出边更整齐。Word不支持自动悬挂,一般用户也不需要纠结,就放里面就好了。
引号使用顺序
中文引号规则:
- 第一层:「」
- 第二层:『』
- 或者:“” 里面放 ‘’
不同地区习惯不同,按照你的读者习惯来。大陆一般用“”里面放‘’。
18.5 空格使用
中文排版原则:除了特殊情况,汉字和标点之间不需要空格。
需要加空格的情况
-
中英文混排:英文单词前后加空格
- 正确:使用 Word 编辑文档
- 错误:使用Word编辑文档
- 原因:英文单词和汉字分开,看起来舒服
-
数字前后:数字和中文之间加空格
- 正确:一共 123 页
- 错误:一共123页
-
百分比单位:数字和百分号之间不用空格:
50%
不需要加空格的情况
- 中文标点前后不需要空格
- 全角标点已经占了位置
记住一个简单规则:只有英文单词、阿拉伯数字前后加空格,其他都不加。
18.6 字体选择
正文
正式公文常用:
- 正文:仿宋_GB2312,三号 (公文标准)
- 一般文档:宋体 五号 / 宋体 小四 都可以
- 屏幕阅读:微软雅黑 五号,清晰不累
标题
- 一级标题:黑体 二号或一号
- 二级标题:黑体 三号
- 三级标题:黑体 四号
注意字体版权
- Windows自带字体可以在Windows上用
- 分发电子版一般没问题
- 如果要嵌入字体,确认许可证允许嵌入
- 商业发布尽量用有授权的字体
18.7 行间距
行间距推荐:
- 五号字:12磅字 → 单倍行距(360)合适
- 小四号:可以用1.5倍行距,更透气
- 大段文字不要用双倍行距,太散
正文行间距太挤读者累,太松浪费纸,自己把握平衡。
18.8 页边距
标准A4纸默认边距:上下左右各1英寸(1440缇)就很好。
如果需要装订,可以在左边加装订线(一般300-600缇)。
18.9 标题排版
标题排版原则:
- 层级清晰:字号从大到小,字体区分
- 留白足够:标题段前比段后多留点空白
- 比如:一级标题段前18磅,段后12磅
- 对齐一致:同级标题对齐方式一致,都居中就都居中,都左对齐就都左对齐
- 不要孤行:标题不要留在页底,和正文分开,设置keepNext
章节编号
用Word自动编号:
- 好处:插入删除章节,编号自动更新
- 设置:开始 → 编号 → 定义新的多级列表,链接到标题样式
- 不要手动打编号,删改麻烦
18.10 表格排版
中文表格习惯:
- 标题行一般灰色底纹加粗
- 边框:外框粗一点,内框细一点,或者都单线也可以
- 文字单元格垂直居中好看
- 内容少的表格可以适当增加行高,不要挤在一起
18.11 目录
目录自动生成,要点:
- 标题用标题样式
- 大纲级别正确
- 插入TOC域,自动生成
- 修改文档后更新域就可以了
目录一般放在正文前面,页码用罗马数字,正文重新从1开始阿拉伯,分节设置不同页码就可以了。
18.12 页码
页码一般放页脚居中,也可以放外侧(奇偶页不同,奇数在右,偶数在左),装订成册阅读方便。
常见格式:第 5 页,共 10 页,用PAGE和NUMPAGES域自动更新。
18.13 最佳实践检查清单
写完文档可以检查一遍:
- 每个段落都应用了正确样式
- 正文首行缩进两字符(用段落设置,不是空格)
- 标点都是全角(英文数字除外)
- 中英文混排,英文数字前后加了空格
- 标题大纲级别正确,可以生成目录
- 标题设置了keepNext,不会和正文分页分开
- 行间距合适,不挤不散
- 层级清晰,标题字号逐级减小
- 没有多余手动分页,自动分页就好
- 目录自动生成,不是手敲
都检查过,就是一份符合中文排版习惯的好文档了。
本章小结
- 中文排版有自己的习惯,和英文不一样
- 首行缩进两字符用段落设置,不要用空格
- 中文用全角标点,中英文混排英文前后加空格
- 层级清晰,标题字号逐级减小,留白足够
- 用自动编号,自动目录,不要手动
- 最后按照检查清单过一遍,细节对了整体就专业了
下一章我们讲解目录与交叉引用。
第19章:目录与交叉引用
学习目标
- 掌握自动目录的正确做法
- 理解目录基于什么生成
- 学会使用交叉引用
- 掌握更新域的方法
19.1 自动目录的原理
我们之前讲过,Word自动目录基于标题样式或大纲级别生成。
工作原理:
- 你给各级标题应用对应的样式
- 每个标题样式已经设置了对应的大纲级别
- 插入TOC域
- Word更新时扫描文档,收集所有标题,按级别生成目录
- 每个目录条目自动带页码,还可以点击跳转
所以,正确设置标题样式是自动目录的前提。手敲目录,加完删改章节还要手改页码,太麻烦了。
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 更新目录
你修改了文档,增加删除了章节,页码变了,需要更新目录:
- 右键点击目录区域
- 选择“更新域“
- 选择“只更新页码“或者“更新整个目录“
- 确定
如果只是页码变了,选只更新页码,快。如果加删了标题,选更新整个目录。
19.4 自定义目录
你可以选择包含哪些级别:
- 如果你的文档只有两级标题,就
\o "1-2" - 如果有四级,就
\o "1-4"
插入目录时在对话框里设置起始级别和结束级别就可以了。
你也可以自定义目录样式,目录本身用什么格式,改目录样式就可以,所有目录自动更新。
19.5 图表目录
如果你的文档有很多图或表,可以做图表目录:
前提:
- 所有图表题注都用Word的插入题注功能插入
- 图用“图“标签,表用“表“标签
然后:
- 引用 → 插入图表目录
- 选择标签,生成
就自动生成带页码的图表目录了。原理和目录一样,也是基于题注收集。
19.6 交叉引用是什么
交叉引用就是:“详见 第3章”,那个“第3章“如果是手敲的,你把第3章挪到第4章了,这里还要手改。用交叉引用,自动更新。
使用交叉引用步骤
- 光标放在你要放引用的地方
- 引用 → 交叉引用
- 选择引用类型:标题、书签、编号、图表等
- 选择要引用的目标
- 插入
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 书签
书签是什么?书签就是给文档中某个位置打个标记,可以交叉引用跳过去。
插入书签:
- 选中位置或文字
- 插入 → 书签
- 书签名 → 添加
你可以在书签对话框跳到某个书签,交叉引用也可以引用书签。长文档善用书签,跳转很方便。
19.9 最佳实践
- 永远用自动目录,不要手敲目录
- 善用交叉引用,不要手敲章节号页码
- 修改完文档最后一定要更新所有域
- 多级列表链接到标题样式,编号自动更新
- 图表用题注,做图表目录方便
本章小结
- 自动目录基于标题样式/大纲级别,正确设置标题就可以一键生成
- 修改文档后右键更新域就可以更新目录
- 交叉引用自动引用目标,章节移动自动更新,不用手改
- 全选文档按F9可以更新所有域
- 图表用题注可以生成图表目录
下一章我们讲解样式自动化排版技巧。
第20章:样式自动化排版技巧
学习目标
- 掌握提高排版效率的技巧
- 学会使用样式集和模板
- 了解VBA宏自动化批量处理
- 养成好的排版工作流
20.1 使用模板
模板是 .dotx 文件,保存了样式和格式设置,新建文档基于模板。
为什么用模板
- 一次设置好所有样式,每次新建直接用
- 团队协作,所有人用同一个模板,格式统一
- 省去每次重复设置的麻烦
怎么做
- 新建一个空白文档
- 设置好所有需要的样式:正文、各级标题、题注等
- 文件 → 另存为 → 保存类型选择 “Word 模板 (*.dotx)”
- 以后新建文档,基于这个模板就好了
如果你经常写同类型的文档(比如论文、报告),做个模板,一了百了。
20.2 样式集
Word 支持样式集,把一套样式保存为样式集,可以套用给现有文档:
- 设计好你的样式
- 设计 → 样式集 → 保存为新样式集
- 以后换风格直接点一下样式集就换了,全文档样式自动更新
适合给文档换整体风格,很快。
20.3 格式刷的正确用法
格式刷可以复制格式:
- 点一下格式刷 → 复制一次格式
- 双击格式刷 → 可以复制给多个地方,按ESC结束
很多人不知道双击可以重复用,这个技巧节省很多时间。
20.4 查找替换格式
Word查找替换不仅可以替换文字,还可以替换格式。
例子:把所有蓝色粗体改成红色斜体:
- 查找 → 更多 → 格式 → 选蓝色粗体
- 替换为 → 格式 → 选红色斜体
- 全部替换
一下子全换完,比你一个个找快太多了。
批量改格式非常有用。
20.5 多级列表链接到标题样式
这是非常有用的技巧:把自动编号链接到标题样式,各级标题自动编号,插入删除自动更新。
设置步骤:
- 开始 → 多级列表 → 定义新的多级列表
- 级别1链接到标题1,编号格式比如 “第1章”
- 级别2链接到标题2,编号格式比如 “1.1”
- 级别3链接到标题3,编号格式比如 “1.1.1”
- 确定
之后你每次应用标题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,正文就用正文,不要乱改格式
- 插图插表:用题注,自动编号
- 引用交叉:需要引用就用交叉引用
- 最后整理:
- 更新所有域(全选 → F9)
- 检查目录页码
- 检查交叉引用
- 检查格式一致性
这样出来的文档,结构清晰,格式一致,容易修改,非常专业。
20.11 常见错误要避免
- ❌ 不用样式,所有格式手工调 → 乱,难改
- ❌ 手工打章节编号 → 插入删除要全改
- ❌ 用空格缩进首行 → 不对齐,难改
- ❌ 硬插很多手动分页 → 内容变了分页全错
- ❌ 手敲目录 → 改了内容页码不对
这些错很多人都犯,其实只要用对Word功能,这些问题都不存在。
本章小结
- 用模板,一次设置永久用
- 多级列表链接标题样式,自动编号不用管
- 查找替换可以批量改格式
- 设置样式快捷键,提高效率
- 导航窗格方便长文档导航
- 自动化做重复工作,省时间
- 遵循好的工作流,出来的文档专业好改
这就是第四排版设计实践的最后一章了。整个第四部分我们从排版原理讲到样式,讲到中文实践,讲到目录交叉引用,讲到自动化技巧,相信你现在对Word排版已经有了深入理解。
附录A:XML命名空间参考
本书常用的XML命名空间参考表:
| 前缀 | 命名空间URI | 用途 |
|---|---|---|
w | http://schemas.openxmlformats.org/wordprocessingml/2006/main | WordprocessingML主命名空间,绝大多数元素 |
r | http://schemas.openxmlformats.org/officeDocument/2006/relationships | 关系引用 |
a | http://schemas.openxmlformats.org/drawingml/2006/main | DrawingML绘图 |
wp | http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing | Word绘图 |
pic | http://schemas.openxmlformats.org/drawingml/2006/picture | 图片 |
mc | http://schemas.openxmlformats.org/markup-compatibility/2006 | 标记兼容性 |
ct | http://schemas.openxmlformats.org/package/2006/content-types | 内容类型 |
rel | http://schemas.openxmlformats.org/package/2006/relationships | 包级关系 |
cp | http://schemas.openxmlformats.org/package/2006/metadata/core-properties | 核心属性 |
dc | http://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