背景:通过java代码,往docx文档中写入标题和段落。
依赖的maven包:
XML
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
创建标题,网上很多文章说使用如下代码可以实现:
java
// 创建一个标题
XWPFParagraph titleParagraph = document.createParagraph();
titleParagraph.setStyle("heading 1");
XWPFRun titleRun = titleParagraph.createRun();
titleRun.setText("标题测试");
titleRun.setBold(true);
titleRun.setFontSize(20);
但是打开word后发现标题并没有生效。
这是因为需要自己编写标题的样式信息,参考如下代码中的addCustomHeadingStyle方法。
完整的代码参考如下:
java
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
/**
* word文档工具类
*/
public class DocxUtil {
/**
* 增加自定义标题样式
* @param docxDocument 目标文档
* @param strStyleId 样式名称
* @param headingLevel 样式级别
*/
private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) {
CTStyle ctStyle = CTStyle.Factory.newInstance();
ctStyle.setStyleId(strStyleId);
CTString styleName = CTString.Factory.newInstance();
styleName.setVal(strStyleId);
ctStyle.setName(styleName);
CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
indentNumber.setVal(BigInteger.valueOf(headingLevel));
// lower number > style is more prominent in the formats bar
ctStyle.setUiPriority(indentNumber);
CTOnOff onoffnull = CTOnOff.Factory.newInstance();
ctStyle.setUnhideWhenUsed(onoffnull);
// style shows up in the formats bar
ctStyle.setQFormat(onoffnull);
// style defines a heading of the given level
CTPPrGeneral ppr = CTPPrGeneral.Factory.newInstance();
ppr.setOutlineLvl(indentNumber);
ctStyle.setPPr(ppr);
XWPFStyle style = new XWPFStyle(ctStyle);
// is a null op if already defined
XWPFStyles styles = docxDocument.createStyles();
style.setType(STStyleType.PARAGRAPH);
styles.addStyle(style);
}
/**
* 生成一个标题 + 一个段落格式的docx文档
* @param title 标题
* @param content 正文
* @param filePath docx地址
*/
public static void generateDocxFile(String title, String content, String filePath){
try {
// 创建一个新的空白docx文档
XWPFDocument document = new XWPFDocument();
addCustomHeadingStyle(document, "heading 1", 1);
// 创建一个标题
XWPFParagraph titleParagraph = document.createParagraph();
titleParagraph.setStyle("heading 1");
XWPFRun titleRun = titleParagraph.createRun();
titleRun.setText(title);
titleRun.setBold(true);
titleRun.setFontSize(20);
// 获取段落的CTPPr对象
CTPPr pPr = titleParagraph.getCTP().getPPr();
// 如果pPr为null,说明还没有属性,需要创建
if (pPr == null) {
pPr = titleParagraph.getCTP().addNewPPr();
}
// 设置文本居中对齐
CTJc jc = pPr.isSetJc() ? pPr.getJc() : pPr.addNewJc();
jc.setVal(STJc.CENTER); // 居中对齐
// 创建一个段落
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText(content);
// 写入数据到文档
FileOutputStream out = new FileOutputStream(new File(filePath));
document.write(out);
out.close();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 生成N个标题 + N个段落格式的docx文档
* @param titleList
* @param contentList
* @param filePath
* @throws Exception
*/
public static void generateDocxFile(List<String> titleList, List<String> contentList, String filePath){
if(titleList.size() != contentList.size()){
System.out.println("title和content数量不匹配!");
}
// 创建一个新的空白docx文档
XWPFDocument document = new XWPFDocument();
addCustomHeadingStyle(document, "heading 1", 1);
for(int i = 0; i < titleList.size(); i++){
/* -------------创建一个标题 ---------------*/
XWPFParagraph titleParagraph = document.createParagraph();
titleParagraph.setStyle("heading 1");
XWPFRun titleRun = titleParagraph.createRun();
titleRun.setText(titleList.get(i));
titleRun.setBold(true);
titleRun.setFontSize(20);
// 获取段落的CTPPr对象
CTPPr pPr = titleParagraph.getCTP().getPPr();
// 如果pPr为null,说明还没有属性,需要创建
if (pPr == null) {
pPr = titleParagraph.getCTP().addNewPPr();
}
// 设置文本居中对齐
CTJc jc = pPr.isSetJc() ? pPr.getJc() : pPr.addNewJc();
jc.setVal(STJc.CENTER); // 居中对齐
/* -------------创建一个段落 ---------------*/
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText(contentList.get(i));
}
// 写入数据到文档
FileOutputStream out = null;
try {
out = new FileOutputStream(new File(filePath));
document.write(out);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
List<String> titleList = Arrays.asList("洗车标题2", "保养标题2");
List<String> contentList = Arrays.asList("洗车的操作事项:\n1)好好洗;2)洗干净", "保养的操作事项:\n1)好好保养;2)保养干净");
DocxUtil.generateDocxFile(titleList, contentList, "D:\\temp\\example3.docx");
}
}
效果如下,标题的属性确实是"标题1"。