官方教程地址:http://deepoove.com/poi-tl/

apache poi 入门示例教程:http://deepoove.com/poi-tl/apache-poi-guide.html

poi-tl模板使用方法:

1、文本标签是Word模板中最基本的标签类型,{{name}}会被数据模型中key为name的值替换,如果找不到默认会清空标签,可以配置是保留还是抛出异常。
2、图片标签以@开始,如{{@logo}}会在数据中寻找key为logo的值,然后将标签替换成图片。由于Word文档中图片不是由字符串表示(在文本型模板中,比如HTML网页图片是由字符串<img src="" />表示),所以图片标签对应的数据有一定的结构要求,这些结构都会有相应的Java类对应
3、表格标签以#开始,如{{#table}},它会被渲染成N行N列的Word表格,N的值取决于table标签的值。
4、列表标签对应Word的符号列表或者编号列表,以*开始,如{{*number}}。
5、区块对由前后两个标签组成,开始标签以?标识,结束标签以/标识,如{{?sections}}作为sections区块的起始标签,{{/sections}}为结束标签,sections是这个区块对的名称。
6、嵌套是在Word模板中引入另一个Word模板,可以理解为import、include或者word文档合并,以+标识,如{{+nested}}。

引入jar包:版本:1.8.2

<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.8.2</version>
</dependency>

1、简单文字填充替换,直接写变量即可

 2、表格不用刷色和复杂样式处理,直接填充的,用jar自带的HackLoopTableRenderPolicy来实现。

注意:第一行数据要绑定属性名称

3、表格内容复杂,比如文字刷色,背景刷色,合并内单元格等的。写自定义类来实现表格填充

下面直接上案例代码:

@ApiOperation(value="日报word导出", notes="日报word导出")
@PostMapping(value = "/dayReportExport")
public void dayReportExport(HttpServletResponse response, @RequestBody JSONObject jsonObject)
{
Map<String, Object> model = new HashMap<>();//传入word数据 //解析单变量数据
model.put("exportDate", jsonObject.getString("exportDate"));
model.put("weekDay", jsonObject.getString("weekDay"));
model.put("lunarDate",jsonObject.getString("lunarDate"));
model.put("windDir",jsonObject.getString("windDir"));
model.put("windSc",jsonObject.getString("windSc"));
model.put("tmp",jsonObject.getString("tmp"));
model.put("weatherInfo",jsonObject.getString("weatherInfo"));
model.put("preWordText",jsonObject.getString("preWordText"));
model.put("dateStr",jsonObject.getString("dateStr"));
model.put("airTable1Text",jsonObject.getString("airTable1Text"));
model.put("airTable2Text",jsonObject.getString("airTable2Text"));
model.put("waterSituationText",jsonObject.getString("waterSituationText"));
model.put("o2MonthValue",jsonObject.getString("o2MonthValue"));
model.put("o2MonthTongbi",jsonObject.getString("o2MonthTongbi"));
model.put("o2YearValue",jsonObject.getString("o2YearValue"));
model.put("o2YearTongbi",jsonObject.getString("o2YearTongbi"));
model.put("upStreamText",jsonObject.getString("upStreamText"));
model.put("waterTableText",jsonObject.getString("waterTableText"));
model.put("airForeText",jsonObject.getString("airForeText"));
model.put("waterForeText",jsonObject.getString("waterForeText"));
model.put("endingDate",jsonObject.getString("endingDate")); model.put("today",jsonObject.getString("today"));
model.put("wjjTodayO2",jsonObject.getString("wjjTodayO2"));
model.put("wjjTodayLevel",jsonObject.getString("wjjTodayLevel"));
model.put("wjjYearO2",jsonObject.getString("wjjYearO2"));
model.put("wjjYearLevel",jsonObject.getString("wjjYearLevel")); //王江泾国考断面-表格里面的单变量
//第一行
JSONArray arr=jsonObject.getJSONArray("wangjjTable");
model.put("type1",arr.getJSONObject(0).getString("type"));
model.put("o21",arr.getJSONObject(0).getString("o2"));
model.put("gmindex1",arr.getJSONObject(0).getString("gmindex"));
model.put("nh3n1",arr.getJSONObject(0).getString("nh3n"));
model.put("tp1",arr.getJSONObject(0).getString("tp"));
model.put("tn1",arr.getJSONObject(0).getString("tn"));
model.put("temp1",arr.getJSONObject(0).getString("temp"));
//第二行
model.put("type2",arr.getJSONObject(1).getString("type"));
model.put("o22",arr.getJSONObject(1).getString("o2"));
model.put("gmindex2",arr.getJSONObject(1).getString("gmindex"));
model.put("nh3n2",arr.getJSONObject(1).getString("nh3n"));
model.put("tp2",arr.getJSONObject(1).getString("tp"));
model.put("tn2",arr.getJSONObject(1).getString("tn"));
model.put("temp2",arr.getJSONObject(1).getString("temp")); //处理airTable1的数据
String airTable1_str = jsonObject.getJSONArray("airTable1").toJSONString();
List<Map<String,Object>> airTable1_list = (List<Map<String,Object>>) JSONArray.parse(airTable1_str);
model.put("airTable1",airTable1_list); //处理airTable2的数据
String airTable2_str = jsonObject.getJSONArray("airTable2").toJSONString();
List<Map<String,Object>> airTable2_list = (List<Map<String,Object>>) JSONArray.parse(airTable2_str);
model.put("airTable2",airTable2_list); //处理upStreamTable的数据--要设置表格行高,没有搞定,就直接在word中写死的
// String upStreamTable_str = jsonObject.getJSONArray("upStreamTable").toJSONString();
// List<Map<String,Object>> upStreamTable_list = (List<Map<String,Object>>) JSONArray.parse(upStreamTable_str);
// model.put("upStreamTable",upStreamTable_list); //处理waterTable的数据
String waterTable_str = jsonObject.getJSONArray("waterTable").toJSONString();
List<Map<String,Object>> waterTable_list = (List<Map<String,Object>>) JSONArray.parse(waterTable_str);
model.put("waterTable",waterTable_list); //处理waterCityTable1的数据
String waterCityTable1_str = jsonObject.getJSONArray("waterCityTable1").toJSONString();
List<Map<String,Object>> waterCityTable1_list = (List<Map<String,Object>>) JSONArray.parse(waterCityTable1_str);
model.put("waterCityTable1",waterCityTable1_list); //处理waterCityTable2的数据
String waterCityTable2_str = jsonObject.getJSONArray("waterCityTable2").toJSONString();
List<Map<String,Object>> waterCityTable2_list = (List<Map<String,Object>>) JSONArray.parse(waterCityTable2_str);
model.put("waterCityTable2",waterCityTable2_list); //jar包里面自带插件-简单行循环生成(第一行数据要绑定属性名称)-没有合并单元格和刷色
HackLoopTableRenderPolicy simpleLoopPolicy = new HackLoopTableRenderPolicy(); //配置config和插件绑定
Configure config = Configure.newBuilder()
.bind("airTable1", simpleLoopPolicy)
.bind("waterCityTable1", new waterCityTable1MethodPolicy())
.bind("waterCityTable2", simpleLoopPolicy)
.bind("airTable2", new AirTable2MethodPolicy())
.bind("waterTable", new waterTableMethodPolicy()).build(); try {
String path=new ClassPathResource("templates/dayReport.docx").getUrl().getPath();
XWPFTemplate template = XWPFTemplate.compile(path,config).render(model); response.setContentType("application/octet-stream");
response.setHeader("Content-disposition","attachment;filename=\""+"out_template.docx"+"\""); OutputStream out = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(out);
template.write(bos);
template.close();
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
waterTableMethodPolicy类代码如下:
package org.jeecg.modules.systems.wordExport;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.TextRenderData;
import com.deepoove.poi.data.style.TableStyle;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.policy.MiniTableRenderPolicy;
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.jeecg.common.util.oConvertUtils;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.util.CollectionUtils; import java.util.ArrayList;
import java.util.List;
import java.util.Map; import static java.util.stream.Collectors.groupingBy; /***
* 水质分析表格数据,注意:浓度值要刷色,第一列区域要合并单元格,背景刷色
*/
public class waterTableMethodPolicy extends DynamicTableRenderPolicy{ // 填充数据所在行数
int listsStartRow = 1; @Override
public void render(XWPFTable table, Object data) {
if (null == data) {
return;
}
//tata从List<Map<String,Object>>转成JSONArray
JSONArray arr=JSON.parseArray(JSON.toJSONString(data));
if (!CollectionUtils.isEmpty(arr))
{
table.removeRow(listsStartRow);
List<RowRenderData> dataList = new ArrayList<>();
for (int x=0;x<arr.size();x++)
{
JSONObject obj=arr.getJSONObject(x);
String o2Color=obj.getString("o2Color");
o2Color=oConvertUtils.isNotEmpty(o2Color)?o2Color:"000000";
String nh3nColor=obj.getString("nh3nColor");
nh3nColor=oConvertUtils.isNotEmpty(nh3nColor)?nh3nColor:"000000";
String gmindexColor=obj.getString("gmindexColor");
gmindexColor=oConvertUtils.isNotEmpty(gmindexColor)?gmindexColor:"000000";
String tpColor=obj.getString("tpColor");
tpColor=oConvertUtils.isNotEmpty(tpColor)?tpColor:"000000";
String rankColor=obj.getString("rankColor");
rankColor=oConvertUtils.isNotEmpty(rankColor)?rankColor:"000000";
RowRenderData renderData = RowRenderData.build(
new TextRenderData(obj.getString("area"),ZDYStyle.getStyle("000000",11,"宋体")),//字体颜色和文本内容
new TextRenderData(obj.getString("riversort"),ZDYStyle.getStyle("000000",10,"Arial")),
new TextRenderData(obj.getString("sitename"),ZDYStyle.getStyle("000000",10,"宋体")),
new TextRenderData(obj.getString("rank"),ZDYStyle.getStyle(rankColor,10,"宋体")),
new TextRenderData(obj.getString("o2"),ZDYStyle.getStyle(o2Color,10,"Arial")),
new TextRenderData(obj.getString("gmindex"),ZDYStyle.getStyle(gmindexColor,10,"Arial")),
new TextRenderData(obj.getString("nh3n"),ZDYStyle.getStyle(nh3nColor,10,"Arial")),
new TextRenderData(obj.getString("tp"),ZDYStyle.getStyle(tpColor,10,"Arial"))
);
dataList.add(renderData);
}
//table循环插入行,dataList从后到前插入
for (int i = dataList.size() - 1; i >= 0; i--)
{
XWPFTableRow insertNewTableRow = table.insertNewTableRow(listsStartRow);
for (int j = 0; j < 8; j++)//8列数据
{
insertNewTableRow.createCell();
}
// 渲染单行数据
MiniTableRenderPolicy.Helper.renderRow(table, listsStartRow, dataList.get(i));
} //获取array的分组统计信息
List<Map<String,Object>> list =(List<Map<String,Object>>) data;
Map<String, List<Map<String,Object>>> groupMap = list.stream().collect(groupingBy(p->p.get("area").toString()));
List<String> groupList = JSON.parseArray(JSON.toJSONString(groupMap.keySet()), String.class);
//table的第1列数据合并,空气站的区域合并
for (int i = 0; i < dataList.size(); i++)
{
//处理第一列机组合并
Object area = dataList.get(i).getCells().get(0).getCellText();
String area_name = String.valueOf(area);
for (int j = 0; j < groupList.size(); j++)
{
String areaName = groupList.get(j);
List<Map<String,Object>> areaNameNum= groupMap.get(areaName);
if (area_name.equals(areaName))
{
if((i + 1)<=dataList.size()&&(i + areaNameNum.size())<=dataList.size())
{
// 合并第0列的第i+2行到第i+unitSize行的单元格
TableTools.mergeCellsVertically(table, 0, i + 1, i + areaNameNum.size());
//处理垂直居中
for (int y = 0; y < 8; y++)//8列数据
{
XWPFTableCell cell = table.getRow(i + 1).getCell(y);
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); //垂直居中
}
i=i+areaNameNum.size()-1;
}
}
}
}
//处理表格row背景刷色
String old_area_name="";
String bgStr="FFFFFF";
for (int i = 0; i < dataList.size(); i++)
{
Object area = dataList.get(i).getCells().get(0).getCellText();
String area_name = String.valueOf(area);
old_area_name=oConvertUtils.isEmpty(old_area_name)?area_name:old_area_name;//old_area_name初始给一个值
//当area的名称有变化的时候,就换一种颜色
bgStr=old_area_name.equals(area_name)?bgStr:getAnotherColor(bgStr);
for (int y = 0; y < 8; y++)//8列数据
{
XWPFTableCell cell = table.getRow(i + 1).getCell(y);
cell.setColor(bgStr);
/** 设置水平居中 */
if(y!=2)
{
CTTc cttc = cell.getCTTc();
CTTcPr ctPr = cttc.addNewTcPr();
ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
cttc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
}
}
old_area_name=area_name;
}
//设置表格水平居中
TableStyle style=new TableStyle();
style.setAlign(STJc.CENTER);
TableTools.styleTable(table,style);
}
}
//用户后来说,暂时不用刷色了
public String getAnotherColor(String rgbStr)
{
if(rgbStr.equals("FFFFFF"))
{
return "FFFFFF";//"EFFDFF";
}
else
{
return "FFFFFF";
}
}
}

用poi-tl导出word报告-支持表格文字刷色、背景刷色、表格合并单元格的更多相关文章

  1. java使用freemarker模板导出word(带有合并单元格)文档

    来自:https://blog.csdn.net/qq_33195578/article/details/73790283 前言:最近要做一个导出word功能,其实网上有很多的例子,但是我需要的是合并 ...

  2. java导出标题多行且合并单元格的EXCEL

    场景:项目中遇到有需要导出Excel的需求,并且是多行标题且有合并单元格的,参考网上的文章,加上自己的理解,封装成了可自由扩展的导出工具 先上效果,再贴代码: 调用工具类进行导出: public st ...

  3. 记录一下表格用poi的导出word

    也是网上找的代码http://53873039oycg.iteye.com/blog/2152009,但是横向合并单元格没成功.只能用很蠢的办法建立了好多table public void fillT ...

  4. 使用POI创建word表格合并单元格兼容wps

    poi创建word表格合并单元格代码如下: /** * @Description: 跨列合并 */ public void mergeCellsHorizontal(XWPFTable table, ...

  5. 复杂的POI导出Excel表格(多行表头、合并单元格)

    poi导出excel有两种方式: 第一种:从无到有的创建整个excel,通过HSSFWorkbook,HSSFSheet HSSFCell, 等对象一步一步的创建出工作簿,sheet,和单元格,并添加 ...

  6. poi合并单元格同时导出excel

    poi合并单元格同时导出excel POI进行跨行需要用到对象HSSFSheet对象,现在就当我们程序已经定义了一个HSSFSheet对象sheet. 跨第1行第1个到第2个单元格的操作为 sheet ...

  7. 前端Excel表格导入导出,包括合并单元格,表格自定义样式等

    表格数据导入 读取导入Excel表格数据这里采用的是 xlsx 插件 npm i xlsx 读取excel需要通过 XLSX.read(data, {type: type}) 方法来实现,返回一个叫W ...

  8. poi导出Excel报表多表头双层表头、合并单元格

    效果图: controller层方法: /**     *      * 导出Excel报表     * @param request     * @return     *      */    @ ...

  9. poi导出excel合并单元格(包括列合并、行合并)

    1 工程所需jar包如下:commons-codec-1.5.jarcommons-logging-1.1.jarlog4j-1.2.13.jarjunit-3.8.1.jarpoi-3.9-2012 ...

  10. Qt高仿Excel表格组件-支持冻结列、冻结行、内容自适应和合并单元格

    目录 一.概述 二.效果展示 三.实现思路 1.冻结行.冻结列 2.行高自适应 3.蚂蚁线 四.测试代码 1.添加表格数据 2.设置冻结行.列 3.行高.列宽 4.单元格背景色 5.单元格文字 6.其 ...

随机推荐

  1. 【已解决】mysql8.0安装报错 error: Found option without preceding group in config file:

    D:\Program Files (x86)\mysql-8.0.13-winx64\mysql-8.0.13-winx64 在此路径下找到my.ini(在个人安装的路径下) 另存为ANSI编码:

  2. Emmet Documentation ( Abbreviations+CSS Abbreviations )

    Emmet Documentation Emmet - the essential toolkit for web-developers Abbreviations Abbreviations Syn ...

  3. #根号分治,树形dp#CF1039D You Are Given a Tree

    题目 给定一棵树,对于 \(k\in [1,n]\) 问最多可以分成多少段长度为 \(k\) 的不交路径 分析 首先考虑对于单个 \(k\) 怎么做. 设 \(dp[x]\) 表示点 \(x\) 往下 ...

  4. Jetty的https模块

    启用https模块,执行如下命令: java -jar $JETTY_HOME/start.jar --add-modules=https 命令的输出,如下: INFO : https initial ...

  5. C#中十进制转与二进制相互转换

    将十进制转换为二进制 将二进制转换为十进制

  6. C#实现文件加密、解密及文件拖拽至程序图标直接打开

    引用:https://www.cnblogs.com/longqi293/archive/2010/07/23/1783672.html 下载源码:http://files.cnblogs.com/l ...

  7. 深入了解图片Base64编码

    title: 深入了解图片Base64编码 date: 2024/4/8 10:03:22 updated: 2024/4/8 10:03:22 tags: Base64编码 图片转换 HTTP请求 ...

  8. 使用 K8S 部署 RSS 全套自托管解决方案- RssHub + Tiny Tiny Rss

    前言 什么是 RSS? RSS 是一种描述和同步网站内容的格式,是使用最广泛的 XML 应用.RSS 搭建了信息迅速传播的一个技术平台,使得每个人都成为潜在的信息提供者.发布一个 RSS 文件后,这个 ...

  9. identity4 系列————用户数据持久化篇[六]

    前言 前面的例子已经将各种情形下的例子已经介绍了一遍,那么后面就是用户数据持久化该如何处理了. 正文 例子位置: https://github.com/IdentityServer/IdentityS ...

  10. 重新点亮shell————变量[三]

    前言 简单介绍一下shell的变量. 正文 变量的定义 变量名的命名规则 字母.数字.下划线 不以数字开头 变量的赋值 在赋值的时候不能出现空格 a =123,在等号前面有一个空格,那么会报错. 这是 ...