Apache POI Word - 样式

Last Modified: 2023/11/10

概述

前面我们讲述了如何创建创建段落,在添加标题时我们并没有真正的使用样式,本篇中我们将实现一个名为“一级标题” 的样式,并将该样式应用到标题文字上。

样式的好处

使用样式可以极大的简化代码。试想一篇文章可能包含多个二级标题,而每个二级标题的样式显然都是相同的,如果不使用样式,那么需要对每个二级标题设置相同的属性,这将导致很多重复的代码。解决办法很简单,就是定义一个“二级标题”的样式,然后所有的二级标题都可以使用这个样式。

样式管理

在 POI word 中,一篇文档可以多个样式,样式通过 XWPFStyles 管理。我们可以创建一个样式对象(XWPFStyle 对象) ,然后将该样式加到 XWPFStyles 对象中。每个样式都有一个唯一的 id,之后可以通过该 id 来引用该样式。

一个样式肯定会包含 id 和样式名称,其它的则根据样式的用途而定。例如一级标题通常字体很大、加粗并且居中显示。下面我们就来定义这个样式:

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;

XWPFDocument doc = new XWPFDocument();
XWPFStyles styles = doc.createStyles();
CTStyle ctStyleHeading1 = CTStyle.Factory.newInstance();
// 样式 id
ctStyleHeading1.setStyleId("heading1");
CTString styleName = CTString.Factory.newInstance();
// 样式名称
styleName.setVal("heading 1");
ctStyleHeading1.setName(styleName);

CTRPr rPr = ctStyleHeading1.addNewRPr();
// 加粗
rPr.addNewB().setVal(true);
// 字体大小
rPr.addNewSz().setVal(new BigInteger("44"));
rPr.addNewSpacing().setVal(new BigInteger("44"));
CTFonts ctFonts = rPr.addNewRFonts();
// 字体名称
ctFonts.setCs("Calibri");
ctFonts.setAscii("Calibri");
ctFonts.setHAnsi("Calibri");
// 设置大纲级别
CTPPrGeneral pPr = ctStyleHeading1.addNewPPr();
pPr.addNewOutlineLvl().setVal(new BigInteger("0"));

// 居中
pPr.addNewJc().setVal(STJc.CENTER);

XWPFStyle heading1Style = new XWPFStyle(ctStyleHeading1);
heading1Style.setType(STStyleType.PARAGRAPH);
// 加入 XWPFStyles 中管理
styles.addStyle(heading1Style);

不得不说,定义样式的代码还是相当啰嗦的,但是一旦样式定义好了,应用样式就很简单了,只需要通过样式 id 来引用即可。

XWPFParagraph paragraph = doc.createParagraph();
// 通过 id 引用样式
paragraph.setStyle("heading1");
XWPFRun run = paragraph.createRun();
run.setText("This the title");

另外需要提醒的是,一个标题的大纲级别是很重要的,大纲级别相当于文档的目录结构和骨架。

Specifies the outline level associated with the paragraph. It is used to build the table of contents and does not affect the appearance of the text. The single attribute val can have a value of from 0 to 9, where 9 indicates that no outline level applies to the paragraph. So <w:outlineLvl w:val="0"/> indicates that the paragraph is an outline level 1.

CTxx

在上面的实现中相信你看到了不少 CT 打头的接口:CTRPr、CTFonts、CTString 和 CTStyle 等。这些接口其实对应了 Office Open XML 中定义的复杂类型(Complex Type)。创建这些接口的对象都有着相同的套路,一般都是通过 CTxx.Factory.newInstance() 来创建。

  • CTStyle.Factory.newInstance()
  • CTString.Factory.newInstance()

个人认为这些接口属于相对底层的 api,一般情况下如果 POI 没有提供高层的方法,我们也可以通过这些相对底层的 api 来实现相同的效果。

举个例子,下面的两段代码都实现了往段落中插入一段文字“hello”,但是显然第一种方法简洁很多。

XWPFParagraph paragraph = doc.createParagraph();
Run run = paragraph.createRun();
run.setText("hello");

第二种方法直接使用粗暴的方法来实现。为什么说粗暴呢?因为从这种方法实现可以依稀窥见 xml 的结构。

XWPFParagraph p = doc.createParagraph();
XWPFRun run = p.createRun();
// r tag
CTR ctr = run.getCTR();
// t tag
CTText ctText = ctr.addNewT();
// text in t tag
ctText.setStringValue("hello");

如果 POI 中已经提供了便捷的方法来实现某种操作,就没有必要绕弯路了。 这么多 xml 标签,记住是很难的,遇到不知道的,可以去查一查 WPcontentOverview。

有问题吗?点此反馈!

温馨提示:反馈需要登录