目录
1、段落标签
在 WordML 中,段落由 <w:p>
标签定义。
每个段落都有属性标签:<w:pPr>
。其中包含一些属性标签,比如段落的对其方式:<w:jc>
;段落的边框:<w:pBdr>
。
一般情况下:段落的内容就是一个或多个 <w:r>
标签构成。
2、引入 docx4j
2.1 引入 docx4j 的 maven 依赖
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-JAXB-Internal</artifactId>
<version>8.3.4</version>
</dependency>
2.2 加载文档
public static void main(String[] args) throws Exception {
String filePath = "p/1.docx";//将要操作的 word 文档
String destPath = "p/dest/1.docx";
WordprocessingMLPackage wPackage = WordprocessingMLPackage.load(new FileInputStream(filePath));//打开一个 word 文档
Parts parts = wPackage.getParts();//获取 word 文档的各个部分
System.out.println(parts);
//保存文档
wPackage.save(new File(destPath));
}
上面这段代码我们通过 WordprocessingMLPackage.load()
方法打开一个 word 文档,并获取了它的所有 Part
。
文档的 Part 就是我们之前在 初识 word 文档 中介绍的 zip 包结构中的内容:
2.3 获取段落中的文本
我们将通过 docx4j 提供的 API 来获取上述文档中段落的内容。
这里的 <w:bookmarkStart> 与 <w:bookmarkEnd> 标签大家可以忽略,这两个是 WPS 软件添加的书签,用于记录上次修改的地方。
通过前面这个 document.xml 的内容我们可以看出,段落标签是当前文档的第一个标签。存放我们文本内容的标签的 <w:p>
标签下第一个子标签 <w:r>
。<w:pPr>
是段落的属性标签不算作段落的内容。
接下来就按照顺序一个一个的把这些标签拿到,就可以获取段落中的文本内容。
public static void main(String[] args) throws Exception{
String filePath = "p/2.docx";
String destPath = "p/dest/2.docx";
WordprocessingMLPackage wPackage = WordprocessingMLPackage.load(new FileInputStream(filePath));
MainDocumentPart document = wPackage.getMainDocumentPart();
//获取文档中的标签
List<Object> content = document.getContent();
P p = (P)content.get(0);
//获取 p 标签的内容,即它的孩子标签
List<Object> pContent = p.getContent();
R r = (R)pContent.get(0);
//获取 <w:r> 标签下的 <w:t> 标签
List<Object> rContent = r.getContent();
Text t = (Text)((JAXBElement)rContent.get(0)).getValue();
System.out.println(t.getValue());
}
运行结果:
通过 Text 类的 setValue() 方法可以设置 <w:t> 标签的文本内容:
Text t = (Text)((JAXBElement)rContent.get(0)).getValue();
System.out.println(t.getValue());
t.setValue("新设置的文本内容");
//设置后需要保存文档
wPackage.save(new File(destPath));
3、<w:r> 的属性
<w:r> 标签中的 <W:rPr> 用于记录 <w:r> 标签的文本内容的样式。比如文本是否加粗、是否斜体、是否高亮等。
//设置 <w:r> 的属性
public static void setRunPPR () throws Exception{
String filePath = "p/2.docx";
String destPath = "p/dest/3.docx";
WordprocessingMLPackage wPackage = WordprocessingMLPackage.load(new FileInputStream(filePath));
MainDocumentPart document = wPackage.getMainDocumentPart();
//获取文档中的标签
List<Object> content = document.getContent();
P p = (P)content.get(0);
//获取 p 标签的内容,即它的孩子标签
List<Object> pContent = p.getContent();
R r = (R)pContent.get(0);
//获取 r 的属性
RPr rPr = r.getRPr();
//加粗
rPr.setB(new BooleanDefaultTrue());
//黄色高亮
Highlight highlight = new Highlight();
//设置高亮的颜色,WordML只支持 16 种常用的颜色,不支持自定义颜色
highlight.setVal("yellow");
rPr.setHighlight(highlight);
//斜体
rPr.setI(new BooleanDefaultTrue());
wPackage.save(new File(destPath));
}
运行结果:
我们再来看一下 document.xml 中的内容:
4、设置文本字体与大小
4.1 设置字体大小
字体大小 由 <w:sz w:val=""/>
标签控制。
public static void setRunFont () throws Exception{
String filePath = "p/2.docx";
String destPath = "p/dest/3.docx";
WordprocessingMLPackage wPackage = WordprocessingMLPackage.load(new FileInputStream(filePath));
MainDocumentPart document = wPackage.getMainDocumentPart();
//获取文档中的标签
List<Object> content = document.getContent();
P p = (P)content.get(0);
//获取 p 标签的内容,即它的孩子标签
List<Object> pContent = p.getContent();
R r = (R)pContent.get(0);
//获取 r 的属性
RPr rPr = r.getRPr();
//设置字体大小
HpsMeasure hpsMeasure = new HpsMeasure();
hpsMeasure.setVal( BigInteger.valueOf(144));
rPr.setSz(hpsMeasure);
wPackage.save(new File(destPath));
}
这是修改字体大小前:
修改后:
可以看到字体变大了。
【注意单位】:hpsMeasure.setVal( BigInteger.valueOf(144));
我们在设置字体大小的时候,其实是设置半个点(half-point
)的大小,所以在 WPS 中显示的字体大小为 72。
WordML 的文档说明:
4.2 设置字体
字体由 <w:rFonts w:ascii="黑体" w:hAnsi="新宋体" w:eastAsia="楷体"/>
标签控制。
w:ascii 定义 ascii 码的字体类型;w:eastAsia 定义中文、日文等文字的字体类型; w:cs 定义复杂文字的字体类型,如阿拉伯文等;w:hAnsi 定义前三者以外的字体类型。
//设置字体
RFonts rFonts = new RFonts();
rFonts.setEastAsia("楷体");
rFonts.setAscii("黑体");
rFonts.setHAnsi("新宋体");
rFonts.setCs("Arial Unicode MS");
rPr.setRFonts(rFonts);
这段代码表示,在当前的 <w:r> 标签中的文本的字体类型,如果是中文就用楷体、如果是阿拉伯文就用 Arial Unicode MS 字体。
设置前:
设置后:
中文和日文由原来的宋体变成现在的楷体,英文算 ascii ,也变成现在的 Times New Roman 字体了。Å(acsii 码表的197,输入方式:alt+197) 的字体也发生了变化。后面的阿拉伯文应该也是变化了的,只是我们看不出来效果。
【注意】我在测试的时候,这一段文本是在一个 <w:r> 标签中的。如果你在测试的时候,发现字体没有变化,可能是这段文本被分成了多个 <w:r> 标签,你可以单独给每个 run 设置不同的字体,也可以像我这样把所有文本放在一个 run 中,给这一个 run 设置不同文本的字体,由系统去选择哪种文本用什么字体。
5、复杂文本
设置复杂文本的加粗、斜体时,不能通过 rpr.setB(new BooleanDefaultTrue());
来完成了,需要先申明这段文本是复杂文本,再设置加粗、斜体等:
RPr rPr = r.getRPr();
//文本为复杂文本,若该 run 标签中还有非复杂文本,那么这些非复杂文本将乱码显示。
rPr.setCs(new BooleanDefaultTrue());
//加粗
rPr.setBCs(new BooleanDefaultTrue());
//斜体
rPr.setICs(new BooleanDefaultTrue());
HpsMeasure hpsMeasure = new HpsMeasure();
hpsMeasure.setVal(BigInteger.valueOf(144));
rPr.setSzCs(hpsMeasure);
示例源码:https://gitee.com/li_liankun/docx4j-demo
本文源码:com.llk.p.Test03.java。