java word导出表格_Java实现word导出(表格带图片)
一、 关键词
POI:Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能
POI-TL:基于Apache POI的Word模板引擎,通过插件机制使其具有高度扩展性
word格式:
1. doc:POI组件HWPF组件支持对doc文件的操作
2. docx:POI组件XWPF组件支持对docx文件的操作
3. POI-TL使用的是XWPF组件,所以更好的支持docx文件的操作。
二、 简单用法示例
1. 依赖
org.apache.poi
poi
4.1.0
org.apache.poi
poi-ooxml
4.1.0
com.deepoove
poi-tl
1.5.0
2. word模板
3. 初始化数据
public Map initWordData() throws Exception {
Map renderData = new HashMap<>();
// 文本标题
TextRenderData title = new TextRenderData("这是一个标题");
renderData.put("title", title);
// 文本副标题
TextRenderData subTitle = new TextRenderData("这是一个副标题");
renderData.put("sub_title", subTitle);
// 文本内容
StringBuilder contentValue = new StringBuilder()
.append("内容一")
.append(System.lineSeparator())
.append("内容二")
.append(System.lineSeparator())
.append("内容三")
.append(System.lineSeparator())
.append("内容四")
.append(System.lineSeparator())
.append("......");
TextRenderData content = new TextRenderData("00C1FF" ,contentValue.toString());
renderData.put("content", content);
// 作者信息
Map author = new HashMap<>();
author.put("name", "作者");
author.put("email", new HyperLinkTextRenderData("xxx@xxx.xxx","https://www.baidu.com"));
PictureRenderData avatar = new PictureRenderData(100, 100, ".jpg", BytePictureUtils.getUrlBufferedImage("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1566878817&di=ecc0bc000703c669f5d660ca9bb70f17&src=http://img11.photophoto.cn/20090505/0035035789118626_s.jpg"));
author.put("avatar", avatar);
renderData.put("author", author);
// 表格1 (使用表格模板)
RowRenderData header = RowRenderData.build("单元格1", "单元格2");
RowRenderData row1 = RowRenderData.build("测试11", "测试12");
RowRenderData row2 = RowRenderData.build("测试21", "测试22");
List table1RenderData = new ArrayList<>();
table1RenderData.add(row1);
table1RenderData.add(row2);
MiniTableRenderData miniTableRenderData = new MiniTableRenderData(header, table1RenderData, MiniTableRenderData.WIDTH_A4_MEDIUM_FULL);
renderData.put("table1", miniTableRenderData);
// 表格2 (需要添加填充表信息策略)
List table2RenderData = new ArrayList<>();
table2RenderData.add(RowRenderData.build("张三","地址xxx"));
table2RenderData.add(RowRenderData.build("李四","地址xxx"));
renderData.put("table2", table2RenderData);
return renderData;
}
4. 定义现有表格填充数据策略
// 自定义表格填充策略
public class DetailTablePolicy extends DynamicTableRenderPolicy {
// 填充的起始行,
// 注意:行号从0开始
private int row = 1;// 默认从第一行开始
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public DetailTablePolicy() {
}
public DetailTablePolicy(int row) {
this.row = row;
}
@Override
public void render(XWPFTable table, Object data) {
if (null == data) return;
// 对应渲染的表格数据
List table2RenderData = (List) data;
// 删除当前起始行
table.removeRow(row);
// 插入每一行
for (int i = 0,len = table2RenderData.size(); i < len; i++) {
XWPFTableRow insertNewTableRow = table.insertNewTableRow(row+i);
RowRenderData rowRenderData = table2RenderData.get(i);
for (int j = 0,len2 = rowRenderData.size(); j < len2; j++) insertNewTableRow.createCell();
// 渲染每一行数据
MiniTableRenderPolicy.Helper.renderRow(table, row + i, rowRenderData);
}
}
}
5. 导出word
public void exportWord() {
OutputStream os = null;
XWPFTemplate template = null;
try {
Map renderData = initWordData();
Configure.ConfigureBuilder builder = Configure.newBuilder();
// 使用自定义表格填充策略
builder.customPolicy("table2", new DetailTablePolicy(1));
Configure configure = builder.build();
// 模板文件
String templatePath = "D:\\Desktop\\SimpleTemplate.docx";
InputStream is = new FileInputStream(new File(templatePath));
// 输出位置
String outPath = "D:\\Desktop\\test.docx";
os = new FileOutputStream(new File(outPath));
// 编译,导入策略插件,并渲染数据
template = XWPFTemplate.compile(is, configure).render(renderData);
// 输出
template.write(os);
os.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (os != null) {
os.close();
}
if (template != null) {
template.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
6. 运行结果
7. 注意:
当word中有表格需要渲染时(无论是{{#table}}或者是自定义的表格),都需要加入poi-ooxml依赖,否则会报错
如图:(模板中存在table1和table2)
注释poi-ooxml
运行时会报错:
三、 自定义策略
1. 导出表格(带图片)
1.1. 依赖
同简单示例
1.2. 模板
1.3. 初始化数据
1.3.1. 注意:
● RowRenderData中存放的数据是String或TextRenderData,因此需要将PictureRenderData转为String类型
● 然后渲染数据时,再将String转为PictureRenderData类型
● PictureRenderData没有无参构造函数,无法使用com.fasterxml.jackson.databind.ObjectMapper进行相互转换。因此需要自定义一个类来实现PictureRenderData与String之间的转换
● 具体实现如下:
○ 将PictureRenderData转换为PicRenderDataConvert对象,然后将PicRenderDataConvert对象转为String类型写入RowRenderData中
PictureRenderData avatar = new PictureRenderData(100, 100, ".jpg", BytePictureUtils.getUrlBufferedImage("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1566878817&di=ecc0bc000703c669f5d660ca9bb70f17&src=http://img11.photophoto.cn/20090505/0035035789118626_s.jpg"));
PicRenderDataConvert picRenderDataConvert = new PicRenderDataConvert(avatar);
List picRenderData = new ArrayList<>();
RowRenderData picRow = RowRenderData.build("张三", mapper.writeValueAsString(picRenderDataConvert));
○ 在渲染数据时,再获取PictureRenderData对象
PicRenderDataConvert picRenderDataConvert = mapper.readValue(text, PicRenderDataConvert.class);
// 转换图片
PictureRenderData pictureRenderData = picRenderDataConvert.convert();
if (pictureRenderData != null) {
com.deepoove.poi.policy.PictureRenderPolicy.Helper.renderPicture(par.createRun(), pictureRenderData);
}
1.3.2. 自定义PictureRenderData转换类
public class PicRenderDataConvert {
// 字段与PictureRenderData相同
private int width;
private int height;
private String path;
private transient byte[] data;
private String altMeta;
// 无参构造
public PicRenderDataConvert() {
}
public PicRenderDataConvert(PictureRenderData pictureRenderData) {
this.width = pictureRenderData.getWidth();
this.height = pictureRenderData.getHeight();
this.path = pictureRenderData.getPath();
this.altMeta = pictureRenderData.getAltMeta();
this.data = pictureRenderData.getData();
}
// 转换方法,获取PictureRenderData对象
public PictureRenderData convert() {
if (data == null && StringUtils.isEmpty(path)) {
return null;
}
PictureRenderData pictureRenderData = new PictureRenderData(width, height, path, data);
return pictureRenderData;
}
}
1.3.3. 初始化数据
public Map initWordData() throws Exception {
Map renderData = new HashMap<>();
PictureRenderData avatar = new PictureRenderData(100, 100, ".jpg", BytePictureUtils.getUrlBufferedImage("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1566878817&di=ecc0bc000703c669f5d660ca9bb70f17&src=http://img11.photophoto.cn/20090505/0035035789118626_s.jpg"));
// 渲染表格(包含图片)
List picRenderData = new ArrayList<>();
PicRenderDataConvert picRenderDataConvert = new PicRenderDataConvert(avatar);
RowRenderData picRow = RowRenderData.build("张三", mapper.writeValueAsString(picRenderDataConvert));
picRenderData.addAll(Arrays.asList(picRow, picRow));
renderData.put("pic_table", picRenderData);
return renderData;
}
1.4. 定义图片表格策略
public class DetailPicTablePolicy extends DynamicTableRenderPolicy {
// 填充数据其实行
// 注意:行号从0开始
private int row = 1;
ObjectMapper mapper = new ObjectMapper();
public DetailPicTablePolicy() {
}
public DetailPicTablePolicy(int row) {
this.row = row;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
@Override
public void render(XWPFTable xwpfTable, Object data) {
if (null == data) return;
List renderData = (List) data;
if (null != renderData) {
xwpfTable.removeRow(row);
// 循环插入行
for (int i = 0, len = renderData.size(); i < len; i++) {
XWPFTableRow insertNewTableRow = xwpfTable.insertNewTableRow(row + i);
RowRenderData rowRenderData = renderData.get(i);
// 插入每一个单元格
for (int j = 0, len2 = rowRenderData.getCellDatas().size(); j < len2; j++)
insertNewTableRow.createCell();
// 自定义渲染表格(包括图片)
renderCellPic(xwpfTable, row + i, rowRenderData);
}
}
}
private void renderCellPic(XWPFTable table, int row, RowRenderData rowData) {
if (null != rowData && rowData.size() > 0) {
XWPFTableRow tableRow = table.getRow(row);
ObjectUtils.requireNonNull(tableRow, "Row " + row + " do not exist in the table");
TableStyle rowStyle = rowData.getRowStyle();
List cellList = rowData.getCellDatas();
XWPFTableCell cell = null;
for (int i = 0; i < cellList.size(); ++i) {
cell = tableRow.getCell(i);
if (null == cell) {
RenderPolicy.logger.warn("Extra cell data at row {}, but no extra cell: col {}", row, cell);
break;
}
renderCell(cell, (CellRenderData) cellList.get(i), rowStyle);
}
}
}
public void renderCell(XWPFTableCell cell, CellRenderData cellData, TableStyle rowStyle) {
TableStyle cellStyle = null == cellData.getCellStyle() ? rowStyle : cellData.getCellStyle();
if (null != cellStyle && null != cellStyle.getBackgroundColor()) {
cell.setColor(cellStyle.getBackgroundColor());
}
TextRenderData renderData = cellData.getRenderData();
String cellText = renderData.getText();
if (!StringUtils.isBlank(cellText)) {
CTTc ctTc = cell.getCTTc();
CTP ctP = ctTc.sizeOfPArray() == 0 ? ctTc.addNewP() : ctTc.getPArray(0);
XWPFParagraph par = new XWPFParagraph(ctP, cell);
StyleUtils.styleTableParagraph(par, cellStyle);
String text = renderData.getText();
String[] fragment = text.split("\\n", -1);
if (fragment.length <= 1) {
try {
PicRenderDataConvert picRenderDataConvert = mapper.readValue(text, PicRenderDataConvert.class);
// 渲染图片
PictureRenderData pictureRenderData = picRenderDataConvert.convert();
if (pictureRenderData != null) {
com.deepoove.poi.policy.PictureRenderPolicy.Helper.renderPicture(par.createRun(), pictureRenderData);
}
} catch (Exception e) {
// 渲染文本
com.deepoove.poi.policy.TextRenderPolicy.Helper.renderTextRun(par.createRun(), renderData);
}
} else {
for (int j = 0; j < fragment.length; ++j) {
if (0 != j) {
par = cell.addParagraph();
StyleUtils.styleTableParagraph(par, cellStyle);
}
XWPFRun run = par.createRun();
StyleUtils.styleRun(run, renderData.getStyle());
run.setText(fragment[j]);
}
}
}
}
}
1.5. 浏览器导出word
public void exportWord(HttpServletRequest request,
HttpServletResponse response) throws Exception {
Map renderData = initWordData();
Configure.ConfigureBuilder builder = Configure.newBuilder();
// 表格(含图片)渲染策略
builder.customPolicy("pic_table", new DetailPicTablePolicy(1));
Configure configure = builder.build();
String fileName = "测试文档";
String templatePath = "D:\\Desktop\\PicTableTemplate.docx";
renderWord(request, response, fileName, templatePath, renderData, configure);
}
public void renderWord(HttpServletRequest request,
HttpServletResponse response,
String fileName,
String templatePath,
Map renderData,
Configure configure) {
String codedFileName = "临时文档.docx";
ServletOutputStream out = null;
XWPFTemplate template = null;
try {
if (!StringUtils.isEmpty(fileName)) {
codedFileName = fileName + ".docx";
}
if (request.getHeader("USER-AGENT").toLowerCase().indexOf("msie") > 0 || request.getHeader("USER-AGENT").toLowerCase().indexOf("rv:11.0") > 0 || request.getHeader("USER-AGENT").toLowerCase().indexOf("edge") > 0) {
codedFileName = URLEncoder.encode(codedFileName, "UTF8");
} else {
codedFileName = new String(codedFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
}
response.setHeader("content-disposition", "attachment;filename=" + codedFileName);
InputStream is = new FileInputStream(new File(templatePath));
if (configure == null) {
template = XWPFTemplate.compile(is).render(renderData);
} else {
template = XWPFTemplate.compile(is, configure).render(renderData);
}
out = response.getOutputStream();
template.write(out);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (template != null) {
template.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.6. 运行结果
四、 总结
1. 依赖完整
必须存在
依赖,否则无法进行word中的表格渲染
2. 插件机制实现可扩展的word导出
3. POI-TL支持
文件操作
4. 参考文档
java word导出表格_Java实现word导出(表格带图片)相关推荐
- java调用word模板文件_Java使用模板导出word文档
Java使用模板导出word文档 需要导入freemark的jar包 使用word模板,在需要填值的地方使用字符串代替,是因为word转换为xml文件时查找不到要填入内容的位置.尽量不要在写字符串的时 ...
- java word表格_java操作word的表格
java操作word的表格 最近项目中需要把提交的页面表单的数据动态写在word模板中,简单的写了个工具类.里面有怎眼操作word 中表格的内容,可以在word中已有的表格后面添加行并且可以增加内容. ...
- java怎么导出有模板的表格_java用模板导出数据表格-Go语言中文社区
1.创建表格: 2.编写导出的controller; @PostMapping("/cust/report/customer/export") public void export ...
- java循环导出word文档_Java使用freemarker导出word文档
通过freemarker,以及JAVA,导出word文档. 共分为三步: 第一步:创建模板文件 第二步:通过JAVA创建返回值. 第三步:执行 分别介绍如下: 第一步: 首先创建word文档,按照想要 ...
- java word文本框_Java 读取Word文本框中的文本、图片、表格
Word可插入文本框,文本框中可嵌入文本.图片.表格等内容.对文档中的已有文本框,也可以读取其中的内容.本文以Java程序代码来展示如何读取文本框,包括读取文本框中的文本.图片以及表格等. [程序环境 ...
- java word创建表格_Java 在Word中创建表格
import com.spire.doc.*;import com.spire.doc.documents.*;importcom.spire.doc.fields.TextRange;import ...
- java io导出excel表格_Java IO 导入导出Excel表格
1.将excel导入到内存 1. 调用工作簿Workbook的静态方法getWorkbook(),获得工作簿Workbook对象 InputStream in = new FileInputStrea ...
- java word转成表格_java将Word/Excel/PDF文件转换成HTML整理
项目开发过程中,需求涉及到了各种文档转换为HTML或者网页易显示格式,现在将实现方式整理如下: 一.使用Jacob转换Word,Excel为HTML "JACOB一个Java-COM中间件. ...
- java导出复杂excel表格_java使用freemarker导出复杂的excel表格
正常导出excel表格使用的poi,但是导出复杂的excel有点困难,但是可以使用freemaker模板来导出复杂的excel. 都是先生成一个Excel表格的模板,最好是增加一行数据.具体看图里面的 ...
- java word表格_Java 添加Word表格行或列
import com.spire.doc.*; import com.spire.doc.documents.BorderStyle; import java.awt.*; public class ...
最新文章
- 2012年度IT博客大赛50强报道:高俊峰
- mybatis mysql rownum_MyBatis怎样实现MySQL动态分页?
- ubuntu-11.10-server-i386学习笔记-SVN版本服务器安装
- Java中的引用类型(强引用、弱引用)和垃圾回收
- 程序员如何坚持写作? 1
- 【纸牌识别】基于matlab形态学扑克牌识别【含Matlab源码 1352期】
- angular.injector()
- 读书笔记:普林斯顿微积分读本
- The Elements of Style 4ed ---英文写作指南(一)
- emmagee测试汇总
- python 去除文本空行
- 整合阿里云域名 + 腾讯云 CDN + 又拍云存储的使用流程
- FastDFS作者余庆谈真正的开源精神
- jmeter压力测试并发
- RTSP实时音视频传输介绍
- 计算机的发展史英语作文,选择一种计算机英语作文:求一篇关于计算机发展史的英语作文...
- 尝试用bert做文本聚类
- CPLD/FPGA四位七段数码管动态扫描
- asp php微信支付,Asp微信支付接口代码 微信中生成订单后可以直接调出微信钱包直接付款_随便下源码网...
- Qt 解决程序全屏运行弹窗引发任务栏显示
热门文章
- java创建一个自己的类库_建立并使用自己的类库
- mPaaS 月度小报|魔方卡片(Cube)公测,十个卡片模板任意使用
- 5G无线关键技术 — 大规模天线技术
- ILSVRC竞赛详细介绍(ImageNet Large Scale Visual Recognition Challenge)
- 最好用的七大顶级 API 接口测试工具
- 计算机PS个人规划目标,这里有一份PS个人陈述写作规划
- python写接口程序_利用Python开发PCAN程序接口
- MD5介绍以及如何破解MD5算法
- JAVA代码实现MD5加密算法
- 求助:安装windows server 2003的时候报错:用 Windows NT 4.0 创建基本卷