官方教程地址: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. .net 发邮件的小工具,包含json,环境变量,命令行参数三种配置方式

    一.业务需求 在工作中遇到一个场景,软件bug或功能发布之后,会通知测试进行测试,要求写一个小工具能自动发送邮件,功能包含发送和抄送支持多个,因为只是通知没有写进附件功能,这个其他博客都有搜一下就可以 ...

  2. #dp,概率期望#AT4513 [AGC030D] Inversion Sum

    题目 分析 考虑每次交换最多影响到\(2n\)个点对的逆序对判断 不妨设\(dp[i][j]\)表示\(a[i]>a[j]\)的概率,一开始按照\(a\)求出初始的\(dp\) 之后每次交换或不 ...

  3. JDK 14的新特性:文本块Text Blocks

    目录 举个例子 Indentation编排 Escaping转义 formatted格式化 总结 说起来,Text Blocks是在JDK13中以第一次预览版本引入的.现在在JDK14中是第二次预览版 ...

  4. HDC2021技术分论坛:HarmonyOS内核技术大揭秘!

    作者:jikecheng,miaoxie,HarmonyOS内核技术专家 HarmonyOS整体框架分为四个层级,如图1所示.从上到下,依次为:第一层是应用层,主要涵盖系统应用.Launcher.设置 ...

  5. 在windows电脑中安装redis

    1,github下载地址:https://github.com/MSOpenTech/redis/tags 2,下载完成后,解压到对应文件夹 3,打开redis.windows.conf,在#requ ...

  6. HashMap面试必问的数据结构相关知识总结

    1:HashMap 的数据结构? A:哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点.当链表长度超过 8 时,链表转换为红黑树.transient Node<K,V>[] t ...

  7. 利用navicat 完成两台服务器之间的数据库迁移,安全可靠

    首先,准备工作先做好 1. 工具,navicat,我这里用的是navicat12+ 2. 建立两台服务器的链接,即新建链接,mysql,同时,需要在迁移目标服务器上面实现建立好对应的数据库,即如果有1 ...

  8. 什么是token,为什么需要token

    1.为什么需要token 随着互联网的发展,为了更安全,以及更好的用户体验,逐渐产生了token这个技术方案 之所以使用token是因为http/https协议本身是无状态的,不能进行信息的存储 (c ...

  9. 优化搜索排序结果从而“ 提升CTR、CVR业务指标”

    简介: 搭建搜索功能不难,难的是如何提高搜索质量,帮助用户快速找到心中所想的内容或商品,那么搜索结果的相关性排序则是影响用户体验最关键的一环,本文通过阿里云开放搜索电商行业解决方案和大家聊一聊如何优化 ...

  10. Apache Flink 在实时金融数据湖的应用

    简介: 本文由京东搜索算法架构团队分享,主要介绍 Apache Flink 在京东商品搜索排序在线学习中的应用实践 一.背景 在京东的商品搜索排序中,经常会遇到搜索结果多样性不足导致系统非最优解的问题 ...