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

官方教程地址: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";
        }
    }
}

 

posted @ 2023-03-03 16:52  JackGIS  阅读(2844)  评论(0编辑  收藏  举报