官方教程地址: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. #轻重链剖分,线段树#洛谷 3703 [SDOI2017]树点涂色

    题目传送门 分析 可以发现相同的颜色一定组成一个连通块. 那么操作2就相当于 \(f_x+f_y-2*f_{lca}+1\) 操作3就相当于询问 \(f\) 的最大值. 最关键的就是操作1,考虑往上跳 ...

  2. #线段树,树状数组#CodeChef Merciless Chef

    MLCHEF 分析 首先按照dfs序将子树转换为区间,其实就是区间减和区间维护最小值判断是否大于0 因为大于0一定最多只有 \(n\) 个,所以直接将一个数记录被删除并设为正无穷. 代码 #inclu ...

  3. #线段树,矩阵乘法#LOJ 3264「ROIR 2020 Day 2」海报

    题目 分析 设\(dp[i][0/1/2/3]\)表示以\(i\)结尾1的长度为0/1/2/3的最大值, 那么 \[\begin{cases}dp[i][0]=\max\{dp[i-1][\dots] ...

  4. 使用OHOS SDK构建libsamplerate

    参照OHOS IDE和SDK的安装方法配置好开发环境. 从github下载源码. 执行如下命令: git clone --depth=1 https://github.com/libsndfile/l ...

  5. OpenHarmony父子组件单项同步使用:@Prop装饰器

      @Prop装饰的变量可以和父组件建立单向的同步关系.@Prop装饰的变量是可变的,但是变化不会同步回其父组件. 说明: 从API version 9开始,该装饰器支持在ArkTS卡片中使用. 概述 ...

  6. Docker学习路线1:介绍

    Docker是什么? Docker是一个开源平台,通过将应用程序隔离到轻量级.可移植的容器中,自动化应用程序的部署.扩展和管理.容器是独立的可执行单元,封装了运行应用程序所需的所有必要依赖项.库和配置 ...

  7. 抓包整理————wireshark DNS 演练[三]

    前言 简单整理一些wireshark dns 演练. 正文 简单介绍一下什么是dns. 这个其实可以百度一下哈,其实就是将域名转换为ip. 然后查询过程是这样的: 根域名服务器 权威服务器 dns 被 ...

  8. 如何基于香橙派AIpro对视频/图像数据进行预处理

    本文分享自华为云社区<如何基于香橙派AIpro对视频/图像数据进行预处理>,作者: 昇腾CANN. 受网络结构和训练方式等因素的影响,绝大多数神经网络模型对输入数据都有格式上的限制.在计算 ...

  9. el-tree选中子级时默认选中父级(角色授权)

    问题1:选中子级时默认选中父级 <el-tree :data="menuData" show-checkbox default-expand-all node-key=&qu ...

  10. 力扣414(java)-第三大的数(简单)

    题目: 给你一个非空数组,返回此数组中 第三大的数 .如果不存在,则返回数组中最大的数. 示例 1: 输入:[3, 2, 1]输出:1解释:第三大的数是 1 .示例 2: 输入:[1, 2]输出:2解 ...