根据模板导出word文件

前言

最近项目上有个需求,需要将记录导出成word文档形式,word文档里是一个表格,类似于评分表之类的,之前导出做的基本都是excel,这是首次碰到需要导出word文档形式的,下面记录下如何导出

过程

一般excel导出用的基本都是apache的poi相关的,这次的word也是,首先引入依赖

1
2
3
4
5
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>

其中用到的几个类

1
2
3
4
XWPFDocument //doc文档
XWPFTable //表格
XWPFTableRow //表格中的行
XWPFRun //段落中的文本相关

首先读取doc文档,因为我的是按照模板导出,所以首先读取doc文档

1
XWPFDocument doc = new XWPFDocument(FileUtil.getInputStream(configProperties.getTemplatePath()));

我的模板中只有一个table表格,所以获取第一个表格

1
XWPFTable table = doc.getTables().get(0);

如果是修改表格中的某一行的话,直接获取某一行即可,比如获取第一行,代码如下

1
table.getRow(0)

如果是添加一行的话,代码如下

1
table.insertNewTableRow(2) //  2代表新行要插入的索引位置,从0开始

然后就是往表格里写文字,首先了解下XWPFParagraph段落,如果是新添加的行,则设置某个单元格的文字

1
2
3
4
XWPFRun run = TableUtil.getOrCreateCell(xwpfTableRow, index).addParagraph().createRun(); // 创建段落和文字, xwpfTableRow是你新添加的行,index就是第index个单元格
run.setFontSize(10); //设置文字大小
run.setFontFamily("楷体"); //设置字体
run.setText(content); //设置内容

上面的TableUtil用的是hutool里的工具类,getOrCreateCell方式是获取一个cell(存在直接获取,不存在创建一个)

如果要设置行高

1
xwpfTableRow.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(height));

设置对其方式

1
2
3
4
5
List<XWPFTableCell> cells = xwpfTableRow.getTableCells();//获取到这行所有单元格,然后遍历设置
for (XWPFTableCell tableCell : cells) {
CTTcPr cttcpr = tableCell.getCTTc().addNewTcPr();
cttcpr.addNewVAlign().setVal(STVerticalJc.CENTER);
}

最后修改完成后保存到新的文件里

1
2
3
4
5
OutputStream outputStream = Files.newOutputStream(Paths.get(fileName));
doc.write(outputStream);
outputStream.flush();
outputStream.close();
doc.close();

至此导出完成,我的需求是压缩成zip文件,返回二进制流给前端,代码如下

1
2
3
4
5
response.setContentType("application/zip");//response是HttpServletResponse
response.addHeader("Content-Disposition", "attachment;fileName=" + URLUtil.encode(zipFile.getName(), CharsetUtil.CHARSET_UTF_8));
InputStream inputStream = Files.newInputStream(Paths.get(zipFile.getPath()));
IoUtil.copy(inputStream, response.getOutputStream());
response.flushBuffer();
注意

如果要修改模板表格中的某行文字,不能直接XWPFTableCell.setText("323")这样的,这样话追加到原有的文字后面,不是直接替换,所以代码如下

1
TableUtil.getOrCreateCell(table.getRow(0), 0).getParagraphs().get(0).getRuns().get(0).setText("设备间位置:" + location, 0);

getParagraphs是获取到该cell的所有段落,是个列表,因为这个cell可能有多个段落,需要debug调试看下,比如我的只有一个,则直接get(0),然后getRuns是获取其中的文本,同样也是个列表,需要debug查看你要替换的文字在那个位置,然后get(index)到之后再执行setText方法