Docx4j开发手册-7|Docx4j的页码

一、创建文档或者读取文档

1
2
3
4
5
6
7
public static void main(String[] args) throws Docx4JException {
WordprocessingMLPackage wmp = WordprocessingMLPackage.createPackage();
// 生成页码
setPageNum(wmp);
// 保存文档到指定路径
wmp.save(new File("/xxxx/xx.docx"));
}

二、生成页码相关逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static void setPageNum(WordprocessingMLPackage wmp) throws InvalidFormatException {
// 创建页脚部分
FooterPart footerPart = new FooterPart();
footerPart.setPackage(wmp);

// 生成并设置页码,对齐方式为左对齐
Ftr ftr = pageNumGenerator(JcEnumeration.LEFT);
footerPart.setJaxbElement(ftr);

// 添加页脚部分到文档,并创建页脚的引用关系
Relationship footerRelationship = wmp.getMainDocumentPart().addTargetPart(footerPart);

// 创建页脚引用
createFooterReference(wmp, footerRelationship);
}

三、生成一个包含页码的脚注

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* 生成一个包含页码的脚注
*
* @param alignMode 页码的对齐方式
* @return 返回一个设置好页码的脚注对象
*/
private static Ftr pageNumGenerator(JcEnumeration alignMode) {
// 创建一个脚注对象、创建一个段落对象
Ftr ftr = FACTORY.createFtr();
P paragraph = FACTORY.createP();

// 获取段落属性
PPr pPr = paragraph.getPPr();
// 如果段落属性不存在,则创建并设置段落属性,包括页码对齐方式
if (pPr == null) {
pPr = FACTORY.createPPr();
Jc jc = FACTORY.createJc();
// 设置对齐模式
jc.setVal(alignMode);
pPr.setJc(jc);
paragraph.setPPr(pPr);
}

// 在段落中添加页码字段的开始、页码字段本身和结束标记
addFieldBegin(paragraph);
addPageNumberField(paragraph);
addFieldEnd(paragraph);

// 将含有页码字段的段落添加到脚注内容中
ftr.getContent().add(paragraph);
// 返回包含页码的脚注对象
return ftr;
}

四、创建页脚引用关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 创建页脚引用关系
*
* @param wmp DOCX文档对象
* @param relationship 文档中页脚与主体部分的关系对象
*/
private static void createFooterReference(WordprocessingMLPackage wmp, Relationship relationship) {
// 获取文档中的所有节
List<SectionWrapper> sections = wmp.getDocumentModel().getSections();

// 获取最后一个节的节属性
SectPr sectionProperties = sections.get(sections.size() - 1).getSectPr();

// 如果节属性不存在,则创建一个新的节属性并添加到文档中
if (sectionProperties == null) {
sectionProperties = FACTORY.createSectPr();
wmp.getMainDocumentPart().addObject(sectionProperties);
sections.get(sections.size() - 1).setSectPr(sectionProperties);
}

// 创建页脚引用,并设置其关系ID和类型
FooterReference footerReference = FACTORY.createFooterReference();
footerReference.setId(relationship.getId());
footerReference.setType(HdrFtrRef.DEFAULT);

// 将页脚引用添加到节属性中
sectionProperties.getEGHdrFtrReferences().add(footerReference);
}

五、相关辅助方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* 一个用于将对象包装在R类型中
*
* @param o
* @return
*/
private static R rWrapper(Object o) {
// 使用工厂模式创建一个R类型的实例
R r = FACTORY.createR();
// 将传入的对象添加到R实例的内容中
r.getContent().add(o);
return r;
}

/**
* 为给定的段落添加一个字段开始的分隔符
* 这个方法主要用于文档编辑中,插入一个表示字段开始的特殊字符
*
* @param paragraph 段落对象
*/
private static void addFieldBegin(P paragraph) {
// 创建一个表示字段开始的分隔符对象
FldChar beginFldChar = FACTORY.createFldChar();
beginFldChar.setFldCharType(STFldCharType.BEGIN);

// 将字段开始分隔符包装成一个 JAXBElement,以便于插入段落内容中
JAXBElement<FldChar> beginR = FACTORY.createRFldChar(beginFldChar);

// 调用 rWrapper 方法,将 JAXBElement 包装成 R 对象,方便处理
R r = rWrapper(beginR);

// 将包装好的 R 对象添加到段落的内容中
paragraph.getContent().add(r);
}

/**
* 向指定段落中添加页码字段
*
* @param paragraph 段落对象
*/
private static void addPageNumberField(P paragraph) {
// 创建一个文本对象,设置保留空格,并设置其值为"PAGE"。
Text txt = new Text();
txt.setSpace("preserve");
txt.setValue("PAGE");
// 使用创建的文本对象,构建一个RT元素。
JAXBElement<Text> rt = FACTORY.createRT(txt);
// 封装RT元素到R元素中。
R r = rWrapper(rt);
// 将R元素添加到段落内容中,从而实现页码字段的添加。
paragraph.getContent().add(r);
}

/**
* 为给定的段落添加字段结束符
* 此方法用于在段落中的实际字段后插入一个字段结束符,以标记字段的结束
*
* @param paragraph 段落对象
*/
private static void addFieldEnd(P paragraph) {
// 创建一个字段结束符对象
FldChar endFldChar = FACTORY.createFldChar();
// 设置字段结束符的类型
endFldChar.setFldCharType(STFldCharType.END);
// 将字段结束符包装成一个 JAXBElement
JAXBElement<FldChar> endR = FACTORY.createRFldChar(endFldChar);
// 调用 rWrapper 方法,将 JAXBElement 包装成 R 对象
R r = rWrapper(endR);
// 将包装后的 R 对象添加到段落的内容中
paragraph.getContent().add(r);
}