项目代码
maven依赖
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.10.5</version>
</dependency>
controller
@GetMapping("/word")
public ResponseEntity<byte[]> getImageAsByteArray() throws IOException {
byte[] bytes = reportService.exportWord();
HttpHeaders headers = new HttpHeaders();
String filename = "导出报告.docx";
String encodedFilename = new String(filename.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
headers.set("Content-Disposition", "attachment;filename=\""+encodedFilename +"\"");
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}
service
@Override
public byte[] exportWord() throws IOException {
// 构造数据
Map<String, Object> dataMap = Maps.newHashMap();
// 描述
dataMap.put("generalDescription", "这是报告生成的总体概述。请详情描述总体概述!");
List<ReportTable> tableList = Lists.newArrayListWithCapacity(6);
// 表格
tableList.add(ReportTable.builder().no("1").category("一类").product("手机1").build());
tableList.add(ReportTable.builder().no("2").category("二类").product("手机2").build());
tableList.add(ReportTable.builder().no("3").category("三类").product("手机3").build());
tableList.add(ReportTable.builder().no("4").category("四类").product("手机4").build());
tableList.add(ReportTable.builder().no("5").category("五类").product("手机5").build());
tableList.add(ReportTable.builder().no("6").category("六类").product("手机6").build());
dataMap.put("table", tableList);
// 图片
try (InputStream inputStreamPicture = ReportServiceImpl.class.getClassLoader().getResourceAsStream("static/1.jpg");){
dataMap.put("picture", Pictures.ofStream(inputStreamPicture).size(400, 400).create());
} catch (Exception e) {
throw new RuntimeException(e);
}
// 绑定 render渲染表格等
Configure config = Configure.builder().bind("table", new ReportTableRender()).build();
// 文件写出
byte[] bytes;
FileOutputStream fos = null;
FileInputStream fis = null;
XWPFTemplate template = null;
try (InputStream inputStream = ReportServiceImpl.class.getClassLoader().getResourceAsStream("templates/wordExportTemplate.docx")) {
template = XWPFTemplate.compile(inputStream, config).render(dataMap);
String tempDir = System.getProperty("java.io.tmpdir");
File tempFile = File.createTempFile("temp", ".word", new File(tempDir));
fos = new FileOutputStream(tempFile);
template.writeAndClose(fos);
fis = new FileInputStream(tempFile);
bytes = new byte[Math.toIntExact(tempFile.length())];
fis.read(bytes);
fis.close();
tempFile.delete();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
fos.close();
fis.close();
template.close();
}
return bytes;
}
word模板

导出效果

导出不同样式代码
-
文本:在标题模板中 使用{{字段key}} 然后在生成的时候放到数据map中
// 构造数据
Map<String, Object> dataMap = Maps.newHashMap();
// 描述
dataMap.put("generalDescription", "这是报告生成的总体概述。请详情描述总体概述!");
-
表格:首先是模板绑定也是{{字段key}} 然后放入数据map中,但是表格需要编写一个表格代理类去继承AbstractRenderPolicy。并且在渲染的时候绑定到template里面。如果有多个render可以bind多个
// 表格
tableList.add(ReportTable.builder().no("1").category("一类").product("手机1").build());
tableList.add(ReportTable.builder().no("2").category("二类").product("手机2").build());
tableList.add(ReportTable.builder().no("3").category("三类").product("手机3").build());
tableList.add(ReportTable.builder().no("4").category("四类").product("手机4").build());
tableList.add(ReportTable.builder().no("5").category("五类").product("手机5").build());
tableList.add(ReportTable.builder().no("6").category("六类").product("手机6").build());
dataMap.put("table", tableList);
// 绑定 render渲染表格等
Configure config = Configure.builder().bind("table", new ReportTableRender()).build();
// 渲染时要绑定
template = XWPFTemplate.compile(inputStream, config).render(dataMap);
表格代理类
package com.example.boot.report.render;
import cn.hutool.core.collection.CollUtil;
import com.deepoove.poi.data.style.BorderStyle;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.util.TableTools;
import com.deepoove.poi.util.UnitUtils;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import com.example.boot.report.model.ReportTable;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ReportTableRender extends AbstractRenderPolicy<List<ReportTable>> {
private static final int COL_NUM = 3;
private static final float TABLE_WIDTH = 14.49f;
private static final String[] COL_TITLE = {"序号", "类别", "产品"};
@Override
protected void afterRender(RenderContext<List<ReportTable>> context) {
// 清空标签
clearPlaceholder(context, true);
}
@Override
public void doRender(RenderContext<List<ReportTable>> context) throws Exception {
XWPFRun run = context.getRun();
List<ReportTable> thing = context.getThing();
BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);
if (CollUtil.isEmpty(thing)) {
return;
}
insertTable(run, bodyContainer, thing);
}
private static void insertTable(XWPFRun run, BodyContainer bodyContainer, List<ReportTable> dto) {
int row = dto.size() + 1;
// 插入表格
XWPFTable table = bodyContainer.insertNewTable(run, row, COL_NUM);
// 表格宽度
TableTools.setWidth(table, UnitUtils.cm2Twips(TABLE_WIDTH) + "", null);
// 边框和样式
TableTools.borderTable(table, BorderStyle.DEFAULT);
// 列标题编辑
XWPFTableRow firstRow = table.getRow(0);
firstRow.setHeight(0);
List<XWPFTableCell> firstRowTableCells = firstRow.getTableCells();
for (int i = 0; i < firstRowTableCells.size(); i++) {
XWPFTableCell cell = firstRowTableCells.get(i);
if (i == 0) {
cell.setWidth("20%");
}
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
cell.setColor("D9D9D9");
XWPFParagraph paragraph = cell.getParagraphs().get(0);
paragraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun paraRun = paragraph.createRun();
paraRun.setText(COL_TITLE[i]);
paraRun.setFontSize(10);
paraRun.setBold(true);
}
// 数据区域赋值
List<XWPFTableRow> rows = table.getRows();
for (int i = 0; i < dto.size(); i++) {
ReportTable tableDto = dto.get(i);
XWPFTableRow tableRow = rows.get(i + 1);
// 第一列
XWPFTableCell cell = tableRow.getCell(0);
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
XWPFParagraph paragraph = cell.getParagraphs().get(0);
paragraph.setAlignment(ParagraphAlignment.CENTER);
paragraph.createRun().setText(tableDto.getNo());
// 第二列
cell = tableRow.getCell(1);
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
paragraph = cell.getParagraphs().get(0);
paragraph.setAlignment(ParagraphAlignment.CENTER);
paragraph.createRun().setText(tableDto.getCategory());
// 第三列
cell = tableRow.getCell(2);
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
paragraph = cell.getParagraphs().get(0);
paragraph.setAlignment(ParagraphAlignment.CENTER);
paragraph.createRun().setText(tableDto.getProduct());
}
}
}
-
图片:需要加@符号 {{@picture}} 可以用图片流,url等
try (InputStream inputStreamPicture = ReportServiceImpl.class.getClassLoader().getResourceAsStream("static/1.2.jpg");){
dataMap.put("picture", Pictures.ofStream(inputStreamPicture).size(400, 400).create());
} catch (Exception e) {
throw new RuntimeException(e);
}
官方文档
官方文档 有各种标签的解释 特殊场景可以参考官网
官方文档链接
