POI-TL使用及工具类

maven依赖

<!-- poi-tl -->
		<!-- http://deepoove.com/poi-tl/ -->
		<dependency>
			<groupId>com.deepoove</groupId>
			<artifactId>poi-tl</artifactId>
			<version>1.7.1</version>
		</dependency>
		  <!-- excel工具 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
        </dependency>

工具类所需目录结构:
在这里插入图片描述
核心工具类:

package com.ruoyi.common.utils.poi;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.*;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.data.style.TableStyle;
import com.ruoyi.common.utils.poi.custom.CustomListRenderPolicyWP;
import com.ruoyi.common.utils.poi.custom.CustomTableRenderPolicyWP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * description: PoiTlUtils <br>
 * date: 2020/2/10 14:26 <br>
 * author: <br>
 * version: 1.0 <br>
 */
public class PoiTlUtils {

    public static void main(String[] args){
        Map<String,Object> map = new HashMap<>();
        ArrayList<String[]> strings = new ArrayList<>();
        String[] heard = new String[]{"t1","t2"};
        String[] row1 = new String[]{"r1","r2"};
        String[] row2 = new String[]{"s1","s2"};
        strings.add(row1);
        strings.add(row2);
        MiniTableRenderData miniTableRenderData = list2Table(heard, strings);
        map.put("test",miniTableRenderData);
        try {
            CustomTableRenderPolicy customTableRenderPolicy = new CustomTableRenderPolicy();
            ITableToolsMCImpl tableToolsMC = new ITableToolsMCImpl();
            customTableRenderPolicy.setMergeCells(true);
            customTableRenderPolicy.setiTableToolsMC(tableToolsMC);
            createDocByTemplateName("test.docx","D:\\ruoyi\\resultPath\\test.docx",map,customTableRenderPolicy);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    /** 功能描述: 根据指定的模板和数据生成docx文件到指定的路径
     * @param templateName
     * @param docPath
     * @param data
    * @return: void
    * @Author: 
    * @Date: 2020/2/20 14:31
    */
    public static void createDocByTemplateName(String templateName,
                                           String docPath,
                                           Object data) throws Exception{
        String docTemplatePath = PoiTlUtils.class.getClassLoader()
                .getResource("docTemplates/" + templateName).getPath(); // 模板文件的路径
        createDocByTemplate(docTemplatePath,docPath,data,null);
    }

    public static void createDocByTemplateName(String templateName,String docPath,
                                           Object data,CustomTableRenderPolicy customTableRenderPolicy) throws Exception{
        String docTemplatePath = PoiTlUtils.class.getClassLoader()
                .getResource("docTemplates/" + templateName).getPath(); // 模板文件的路径
        createDocByTemplate(docTemplatePath,docPath,data,customTableRenderPolicy);
    }

    public static void createDocByTemplate(String docTemplatePath,
                                           String docPath,
                                           Object data,CustomTableRenderPolicy customTableRenderPolicy) throws Exception{
        if(customTableRenderPolicy == null){
            customTableRenderPolicy = new CustomTableRenderPolicy();
            customTableRenderPolicy.setMergeCells(false);
        }

        // 自定义表格控件覆盖原有控件
        Configure config = Configure.newBuilder()
                .addPlugin('#', customTableRenderPolicy)
                .addPlugin('+', new CustomTableRenderPolicyWP()) // zidingyibaioghhe
                .addPlugin('>', new CustomListRenderPolicyWP())  // 自定义列表
                .build();

        // 生成报告doc文件
        XWPFTemplate template = XWPFTemplate
                .compile(docTemplatePath,config)
                .render(data);
        FileOutputStream out = new FileOutputStream(docPath);
        template.write(out);
        out.flush();
        out.close();
        template.close();
    }


    public static MiniTableRenderData list2Table(
            String[] headerArr,
            List<String[]> datas){
        // 通用样式
        TableStyle tableStyle = new TableStyle();
        tableStyle.setAlign(STJc.Enum.forInt(2));

        RowRenderData header = null;
        if(headerArr != null){
            List<TextRenderData> headerDatas = new ArrayList();
            for (String headerText: headerArr){
                headerDatas.add(new TextRenderData(headerText));
            }
             header = new RowRenderData(headerDatas,"eeeeee"); // 表头
        }


        List<RowRenderData> rows = new ArrayList<>();
        for (String[] dataRow: datas){
            List<TextRenderData> rowData = new ArrayList();
            for (String cellData: dataRow){
                rowData.add(new TextRenderData( cellData)); // 每行
            }
            RowRenderData row = new RowRenderData(rowData,null); // 行数据
            rows.add(row);
        }


        MiniTableRenderData tableRenderData = new MiniTableRenderData(header,rows,MiniTableRenderData.WIDTH_A4_MEDIUM_FULL);

        return tableRenderData;
    }


    public static MiniTableRenderData list2Table4Pcr2(
            String[] headerArr,
            List<String[]> datas){
        // 通用样式
        TableStyle tableStyle = new TableStyle();
        tableStyle.setAlign(STJc.Enum.forInt(2));

                RowRenderData header = null;
        if(headerArr != null){
            List<TextRenderData> headerDatas = new ArrayList();
            for (String headerText: headerArr){
                headerDatas.add(new TextRenderData(headerText));
            }
             header = new RowRenderData(headerDatas,"d3dce9"); // 表头
        }

        String backgroundColor = "ffffff";
        List<RowRenderData> rows = new ArrayList<>();
        for (int i = 0; i < datas.size(); i++) {
            String[] dataRow = datas.get(i);
            List<TextRenderData> rowData = new ArrayList();
            for (String cellData: dataRow){
                rowData.add(new TextRenderData( cellData)); // 每行
            }
            if (i == datas.size() - 1) backgroundColor = "d3dce9";
            RowRenderData row = new RowRenderData(rowData,backgroundColor); // 行数据
            rows.add(row);
        }
        MiniTableRenderData tableRenderData = new MiniTableRenderData(header,rows,MiniTableRenderData.WIDTH_A4_FULL);
        return tableRenderData;
    }


    /** 功能描述: map 列表转表格
     * @param headerArr
     * @param cellKeyArr
     * @param mapLists
    * @return: com.deepoove.poi.data.MiniTableRenderData
    * @Author: 
    * @Date: 2020/2/16 16:21
    */
    public static MiniTableRenderData listMap2Table(
            String[] headerArr, String[] cellKeyArr,
            List<Map<String,String>>... mapLists){

        List<Map<String,String>> mapList = new ArrayList<>();
        for (List<Map<String,String>> list: mapLists){
            mapList.addAll(list);
        }

        // 表头单元格样式
        Style style = new Style();
        style.setBold(true); // 加粗

        // 表头样式
        TableStyle headerStyle = new TableStyle();
        headerStyle.setAlign(STJc.Enum.forInt(2)); // 文字居中
        headerStyle.setBackgroundColor("eeeeee");


        // 内容样式
        TableStyle contentStyle = new TableStyle();
        contentStyle.setAlign(STJc.Enum.forInt(2)); // 文字居中


        CellRenderData cellRenderData = new CellRenderData();
        List<TextRenderData> headerDatas = new ArrayList();
        for (String headerText: headerArr){
            TextRenderData textRenderData = new TextRenderData(headerText,style);
            headerDatas.add(new TextRenderData(headerText,style));
        }
        RowRenderData header = new RowRenderData(headerDatas,"eeeeee"); // 表头
        header.setRowStyle(headerStyle);


        List<RowRenderData> rows = new ArrayList<>();
        for (Map<String,String> map: mapList){
            List<TextRenderData> rowData = new ArrayList();
            for (String cellKey: cellKeyArr){
                rowData.add(new TextRenderData(map.get(cellKey))); // 每行
            }
            RowRenderData row = new RowRenderData(rowData,null); // 行数据
            row.setRowStyle(contentStyle);
            rows.add(row);
        }


        MiniTableRenderData tableRenderData = new MiniTableRenderData(header,rows,MiniTableRenderData.WIDTH_A4_MEDIUM_FULL);
        tableRenderData.setNoDatadesc("无");

        return tableRenderData;
    }



    /* 功能描述: String 列表转带序号的表格
     * @param headerArr 必须是偶数个 [序号 , 名字 ,  序号 , 名字]
     * @param strList
    * @return: com.deepoove.poi.data.MiniTableRenderData
    * @Author: 
    * @Date: 2020/2/15 17:51
    *
    * 例子:  序号  名字   序号  名字
    *         1   张三   3    李四
    *         2   王五   4    赵柳
    */
    public static MiniTableRenderData listStr2TableWithNum(
            String[] headerArr,
            List<String> strList){

        Style style = new Style();
        style.setBold(true); // 加粗

        // 表头
        List<TextRenderData> headerDatas = new ArrayList();
        for (String headerText: headerArr){
            headerDatas.add(new TextRenderData(headerText,style));
        }
        RowRenderData header = new RowRenderData(headerDatas,"eeeeee"); // 表头


        // 内容
        // 算出来除去序号多少列
        int leiCount = headerArr.length / 2;
        if (strList.size() < leiCount){
            leiCount = strList.size();
        }

        // 算出来应该占多少行
        int hangCount = strList.size()%leiCount==0?strList.size() / leiCount:strList.size() / leiCount +1;

        List<RowRenderData> rows = new ArrayList<>();

        for (int hangNum = 1; hangNum <= hangCount; hangNum++) {
            int num = hangNum;
            List<TextRenderData> rowData = new ArrayList();
            for (int lieNum = 1; lieNum <= leiCount; lieNum++) {
                if (strList.size() >= num){
                    rowData.add(new TextRenderData(String.valueOf(num))); // 每行
                    rowData.add(new TextRenderData(strList.get(num - 1))); // 每行
                }else {
                    rowData.add(new TextRenderData("")); // 每行
                    rowData.add(new TextRenderData("")); // 每行
                }

                num += hangCount;
            }
            RowRenderData row = new RowRenderData(rowData, null); // 行数据
            rows.add(row);
        }


        MiniTableRenderData tableRenderData =
                new MiniTableRenderData(header,rows,MiniTableRenderData.WIDTH_A4_MEDIUM_FULL); // 列宽

        return tableRenderData;
    }




    /* 功能描述: 文本列表  转 doc列表  带字体颜色
     * @param textList
     * @param color  "FFFFFF"
     * @param fontSize  9 - 小五
    * @return: com.deepoove.poi.data.NumbericRenderData
    * @Author: 
    * @Date: 2020/2/13 20:40
    */
    public static NumbericRenderData list2DocList(List<String> textList,Style style){
        List<TextRenderData> list = new ArrayList<TextRenderData>();
        for (String text: textList){
            TextRenderData data = new TextRenderData(text);
            if (style != null){
                data.setStyle(style);
            }
            list.add(data);
        }
        return new NumbericRenderData(NumbericRenderData.FMT_DECIMAL,list);  // NumbericRenderData.FMT_DECIMAL 数字列表
    }

    public static NumbericRenderData list2DocList(List<String> textList,
                                                  String color,
                                                  int fontSize){
        Style style = new Style();
        style.setColor(color);
        style.setFontSize(fontSize);
        return list2DocList(textList,style);
    }

    public static NumbericRenderData list2DocList(List<String> textList){
        return list2DocList(textList,null);
    }



    public static Style createStyle(String fontFamily, int fontSize, String color){
        Style style = new Style();
        if (fontSize != 0) style.setFontSize(fontSize);
        if (fontFamily != null) style.setFontFamily(fontFamily);
        style.setColor(color);
        return style;
    }

}

自定义poi-tl模板插件
CustomTableRenderPolicy:

package com.ruoyi.common.utils.poi;

import com.deepoove.poi.data.CellRenderData;
import com.deepoove.poi.data.MiniTableRenderData;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.util.TableTools;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import com.ruoyi.common.utils.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

/** 自定义word表格   -- 自定义poi-tl模板插件
 * description: CustomTableRenderPolicy <br>
 * date: 2020/2/28 13:47 <br>
 * author: <br>
 * version: 1.0 <br>
 */
public class CustomTableRenderPolicy extends AbstractRenderPolicy<MiniTableRenderData> {

    private boolean isMergeCells;

    private ITableToolsMC iTableToolsMC;

    public ITableToolsMC getiTableToolsMC() {
        return iTableToolsMC;
    }

    public void setiTableToolsMC(ITableToolsMC iTableToolsMC) {
        this.iTableToolsMC = iTableToolsMC;
    }

    public boolean isMergeCells() {
        return isMergeCells;
    }

    public void setMergeCells(boolean mergeCells) {
        isMergeCells = mergeCells;
    }

    @Override
    protected void afterRender(RenderContext<MiniTableRenderData> context) {
        // 清空模板标签
        clearPlaceholder(context, true);
    }

    @Override
    public void doRender(RenderContext<MiniTableRenderData> context)
            throws Exception {

        NiceXWPFDocument doc = context.getXWPFDocument();
        XWPFRun run = context.getRun();
        Object data = context.getData();
        MiniTableRenderData miniTableRenderData = (MiniTableRenderData) data;


        // 当前位置的容器
        BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);


        List<CellRenderData> headerCellList = miniTableRenderData.getHeader().getCells();
        List<RowRenderData> rowsDataList = miniTableRenderData.getRows();

        // 定义行列
        int colCount = headerCellList.size(),
                rowCount = rowsDataList.size() == 0?rowsDataList.size() + 2:rowsDataList.size() + 1;
        // 定义列宽
//        String[] colWidthArr = new String[]{"1960","7670","5820","1640","1700"};


        // 创建表格
        // 当前位置插入表格
        XWPFTable table = bodyContainer.insertNewTable(run, rowCount, colCount);

//        setTableWidth(table,"18790");


        // 设置表头
        XWPFTableRow headerRow = table.getRow(0);
        setRowHeight(headerRow,"400");
        for (int colNum = 0;colNum < colCount; colNum++){
            XWPFTableCell cell = headerRow.getCell(colNum);
//            cell = cellCenterY(cell);
            setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
            if (miniTableRenderData.getHeader().getRowStyle() != null){
                cell.setColor(miniTableRenderData.getHeader().getRowStyle().getBackgroundColor());
            }
            cell.setText(headerCellList.get(colNum).getCellText().getText());
        }

        // 向表格添加数据
        for (int rowNum = 1;rowNum < rowCount;rowNum++){
            XWPFTableRow row = table.getRow(rowNum);
            if (rowsDataList.size() > 0){
                List<CellRenderData> cellDataList = rowsDataList.get(rowNum -1).getCells();
                for (int colNum = 0;colNum < colCount; colNum++){
                    XWPFTableCell cell = row.getCell(colNum);
                    setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
                    cell.setText(cellDataList.get(colNum).getCellText().getText());
                    if (rowsDataList.get(rowNum -1).getRowStyle() != null){
                        cell.setColor(rowsDataList.get(rowNum -1).getRowStyle().getBackgroundColor());
                    }
                }
            }else {
                XWPFTableCell cell = row.getCell(0);
                setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
                cell.setText("无数据");
                TableTools.mergeCellsHorizonal(table, rowNum, 0, colCount - 1); // 水平合并
            }
        }

        // 定义表格宽度、边框和样式
        TableTools.widthTable(table, MiniTableRenderData.WIDTH_A4_MEDIUM_FULL, colCount);
        TableTools.borderTable(table, 4);

        // TODO 调用XWPFTable API操作表格:data对象可以包含任意你想要的数据,包括图片文本等
        // TODO 调用MiniTableRenderPolicy.Helper.renderRow方法快速方便的渲染一行数据
        // TODO 调用TableTools类方法操作表格,比如合并单元格
        // ......
//        TableTools.mergeCellsHorizonal(table, 0, 0, 7); // 水平合并
        // 合并第0列的第2行到第4行的单元格
//        TableTools.mergeCellsVertically(table, 0, 2, 4);
        if(isMergeCells){
            iTableToolsMC.mergeCells(table);
        }

    }

    private void setTableWidth(XWPFTable table, String width) {
        // 定义表格宽度
        CTTblPr tblPr = table.getCTTbl().getTblPr();
        tblPr.getTblW().setType(STTblWidth.DXA);
        tblPr.getTblW().setW(new BigInteger(width));
    }


    // 设置列宽和水平垂直居中
    public void setCellWidthAndXYAlign(XWPFTableCell cell, STVerticalJc.Enum typeEnum, STJc.Enum vAlign, String width) {
        CTTc cttc = cell.getCTTc();
        CTTcPr cellPr = cttc.addNewTcPr();
        cellPr.addNewVAlign().setVal(typeEnum);
        cttc.getPList().get(0).addNewPPr().addNewJc().setVal(vAlign);
        if(!StringUtils.isEmpty(width)){
            CTTblWidth tblWidth = cellPr.isSetTcW() ? cellPr.getTcW() : cellPr.addNewTcW();
            tblWidth.setType(STTblWidth.DXA);
            tblWidth.setW(new BigInteger(width));
        }
    }

    // 设置表格样式
    public void setCellStyle(XWPFTableCell cell,boolean bold) {
        XWPFParagraph p = cell.addParagraph();
        XWPFRun headRun = p.createRun();
        headRun.setBold(bold);// 是否粗体
    }



    private void setRowHeight(XWPFTableRow row, String height){
            CTTrPr trPr = row.getCtRow().addNewTrPr();
            CTHeight ht = trPr.addNewTrHeight();
            ht.setVal(new BigInteger(height));
    }


    private List<String[]> getList (){
        List<String[]> list = new ArrayList<>();
        String[] arr1 = new String[]{"1.1","1.2","1.3","1.4","1.5"};
        String[] arr2 = new String[]{"2.1","2.2","2.3","2.4","2.5"};
        String[] arr3 = new String[]{"3.1","3.2","3.3","3.4","3.5"};
        String[] arr4 = new String[]{"4.1","4.2","4.3","4.4","4.5"};
        String[] arr5 = new String[]{"5.1","5.2","5.3","5.4","5.5"};
        list.add(arr1);
        list.add(arr2);
        list.add(arr3);
        list.add(arr4);
        list.add(arr5);

        return list;
    }
}

CustomListRenderPolicyWP:

package com.ruoyi.common.utils.poi.custom;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.TextRenderData;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.policy.MiniTableRenderPolicy;
import com.deepoove.poi.policy.RenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.template.ElementTemplate;
import com.deepoove.poi.template.run.RunTemplate;
import com.deepoove.poi.util.TableTools;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;

import java.math.BigInteger;
import java.util.List;

/** 自定义word表格   -- 自定义poi-tl模板插件
 * description: CustomTableRenderPolicy <br>
 * date: 2020/2/28 13:47 <br>
 * author: <br>
 * version: 1.0 <br>
 */
public class CustomListRenderPolicyWP extends AbstractRenderPolicy<MyListDataWP> {

    @Override
    protected void afterRender(RenderContext<MyListDataWP> context) {
        // 清空模板标签
        clearPlaceholder(context, true);
    }

    @Override
    public void doRender(RenderContext<MyListDataWP> context) throws Exception {
        XWPFRun run = context.getRun();
        BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);
        XWPFParagraph paragraph = bodyContainer.insertNewParagraph(run);
        MyListDataWP data = context.getData();

        paragraphList(paragraph,bodyContainer,data);//
    }



    /** 功能描述: 在当前位置插入多个段落组成的列表
     * @param paragraph
     * @param bodyContainer
     * @param dataWP
    * @return: void
    * @Author: 
    * @Date: 2020/3/25 14:02
    */
    private void paragraphList(XWPFParagraph paragraph,
                               BodyContainer bodyContainer,
                               MyListDataWP dataWP){
        List<TextRenderData> textList = dataWP.getTextList();

        int firstLineIndent = dataWP.getFirstLineIndent() * 200;

        paragraph.setFirstLineIndent(firstLineIndent); // 首行缩进  具体怎么换算的不清楚
        XWPFRun pRun = paragraph.createRun();
//		p.setAlignment(ParagraphAlignment.CENTER); // 居中
//		p.setSpacingBefore(1000); // 段前

        for (int i = 0; i < textList.size() - 1; i++) {
            TextRenderData text = textList.get(i);
            XWPFParagraph p = bodyContainer.insertNewParagraph(pRun);
            paragraph.setFirstLineIndent(firstLineIndent); // 首行缩进  具体怎么换算的不清楚

            XWPFRun r = p.createRun();
            r.setText(text.getText());
            setRunStyle(r,text.getStyle());
        }

        TextRenderData text = textList.get(textList.size() - 1);
        pRun.setText(text.getText());
        setRunStyle(pRun,text.getStyle());
    }


    /* 功能描述: 为 run设置style
     * @param run
     * @param style
    * @return: void
    * @Author: 
    * @Date: 2020/3/25 14:03
    */
    private void setRunStyle(XWPFRun run,Style style){
        if (style != null){
            run.setColor(style.getColor());
            run.setFontFamily(style.getFontFamily());
            if (style.getFontSize() != 0){
                run.setFontSize(style.getFontSize());
            }
        }
    }
}

CustomTableRenderPolicyWP:

package com.ruoyi.common.utils.poi.custom;

import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.policy.MiniTableRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.util.TableTools;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import com.ruoyi.common.utils.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.math.BigInteger;
import java.util.List;

/** 自定义word表格   -- 自定义poi-tl模板插件
 * description: CustomTableRenderPolicy <br>
 * date: 2020/2/28 13:47 <br>
 * author: <br>
 * version: 1.0 <br>
 */
public class CustomTableRenderPolicyWP extends DynamicTableRenderPolicy {

    @Override
    public void render(XWPFTable table, Object data) {

        if (null == data) return;
        MiniTableDataWP tableDataWP = (MiniTableDataWP) data;

        int dataStartRowNum = tableDataWP.getDataStartRowNum(); // 数据从第几行开始填充
        int colCount = tableDataWP.getColCount(); // 总列数

        List<RowRenderData> rowDataList = tableDataWP.getRowDataList();
        if (null != rowDataList && rowDataList.size() > 0) {
            table.removeRow(dataStartRowNum);
            // 循环插入行
            for (int i = 0; i < rowDataList.size(); i++) {
                XWPFTableRow insertNewTableRow = table.insertNewTableRow(dataStartRowNum);
                for (int j = 0; j < colCount; j++) { // 循环初始化每列的单元格
                    setCellXYAlign(insertNewTableRow.createCell(),STVerticalJc.CENTER,STJc.CENTER); // 内容水平垂直剧中
                }
                // 合并单元格
//                TableTools.mergeCellsHorizonal(table, dataStartRowNum, 0, 3);
                MiniTableRenderPolicy.Helper.renderRow(table, dataStartRowNum, rowDataList.get(i));
                dataStartRowNum ++;
            }


            // 垂直合并
            // TableTools.mergeCellsVertically(table,0,4,5); // 合并  第0列 的 4~5行
            if (tableDataWP.getMergeCellsVerticallyDataList() != null
                    && tableDataWP.getMergeCellsVerticallyDataList().size() > 0){
                for (MergeCellsVerticallydata mergeCellsVerticallydata: tableDataWP.getMergeCellsVerticallyDataList()){
                    TableTools.mergeCellsVertically(table,
                            mergeCellsVerticallydata.getCellNum(),
                            mergeCellsVerticallydata.getStartRowNum(),
                            mergeCellsVerticallydata.getEndRowNum()); // 垂直合并
                }
            }
        }else {
            table.removeRow(dataStartRowNum);
            XWPFTableRow insertNewTableRow = table.insertNewTableRow(dataStartRowNum);
            for (int j = 0; j < colCount; j++) { // 循环初始化每列的单元格
                XWPFTableCell cell = insertNewTableRow.createCell();
                cell.setText("/");
                setCellXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER); // 内容水平垂直剧中
            }
        }
    }



    // 设置单元格 水平垂直居中
    public void setCellXYAlign(XWPFTableCell cell, STVerticalJc.Enum typeEnum, STJc.Enum vAlign) {
        CTTc cttc = cell.getCTTc();
        CTTcPr cellPr = cttc.addNewTcPr();
        cellPr.addNewVAlign().setVal(typeEnum);
        cttc.getPList().get(0).addNewPPr().addNewJc().setVal(vAlign);
    }
}

自定义样式相关:
MergeCellsVerticallydata:

package com.ruoyi.common.utils.poi.custom;

import lombok.Data;

/** 垂直合并
 * description: mergeCellsVerticallydata <br>
 * date: 2020/3/11 10:50 <br>
 * author: <br>
 * version: 1.0 <br>
 */
@Data
public class MergeCellsVerticallydata {

    private int cellNum; // 第几列

    private int startRowNum; // 开始行

    private int endRowNum; // 结束行

    public MergeCellsVerticallydata(int cellNum,int startRowNum,int endRowNum){
        this.cellNum = cellNum;
        this.startRowNum = startRowNum;
        this.endRowNum = endRowNum;
    }

}

MiniTableDataWP:

package com.ruoyi.common.utils.poi.custom;

import com.deepoove.poi.data.RowRenderData;
import lombok.Data;

import java.util.List;

/** 针对自定义poi-tl插件封装的word表格实体
 * description: CustomTableWP <br>
 * date: 2020/3/10 15:15 <br>
 * author:  <br>
 * version: 1.0 <br>
 */
@Data
public class MiniTableDataWP {
    private int colCount; // 总列数
    private int dataStartRowNum; // 从第几行开始填充数据

    List<RowRenderData> rowDataList; // 数据

    List<MergeCellsVerticallydata> mergeCellsVerticallyDataList; // 需要合并行的数据

    public MiniTableDataWP(int dataStartRowNum, int colCount, List<RowRenderData> rowDataList){
        this.colCount = colCount;
        this.dataStartRowNum = dataStartRowNum;
        this.rowDataList = rowDataList;
    }
}

MyListDataWP:

package com.ruoyi.common.utils.poi.custom;

import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.TextRenderData;
import lombok.Data;

import java.util.List;

/* 功能描述: 针对自定义poi-tl插件封装的word列表实体
 * @param null
* @return:
* @Author: 
* @Date: 2020/3/25 13:05
*/
@Data
public class MyListDataWP {
    List<TextRenderData> textList;

    int firstLineIndent; // 首行缩进


    public MyListDataWP(List<TextRenderData> textList,int firstLineIndent){
        this.textList = textList;
        this.firstLineIndent = firstLineIndent;
    }
}

使用例子1:

//这是要输出到word中的数据集map
 Map<String,Object> templateMap = Maps.newHashMap();
                templateMap.put("age","1");
//这是生成word的模版路径
String templateFileName = "pcr/PCR_REPORT_TEMPLATE_8.docx";
 ArrayList<String[]> strings = new ArrayList<>();//这是word中表格行数据集
                    List<GeneraResultsItem> generaResultsItemList = genera.getGeneraResults().getGeneraResultsItemList();//业务代码,查询出要绑定的数据源
                    if(generaResultsItemList != null && !generaResultsItemList.isEmpty()){
                        int len = generaResultsItemList.size() -1;
                        for (int i = 0; i < len; i++) {
                            GeneraResultsItem generaResultsItem = generaResultsItemList.get(i);
                            GeneraResultsItem generaResultsItem1 = generaResultsItemList.get(i+1);
                            GeneraResultsItem generaResultsItem2 = generaResultsItemList.get(i+2);
                            String[] row = new String[]{generaResultsItem.getItemName()+"("+generaResultsItem.getGeneraItemResults()+")"
                                    ,generaResultsItem1.getItemName()+"("+generaResultsItem1.getGeneraItemResults()+")"
                                    ,generaResultsItem2.getItemName()+"("+generaResultsItem2.getGeneraItemResults()+")"};//这是一行数据
                            strings.add(row);//放到数组中

                            i += 2;
                        }
                    }
                    List<RowRenderData> rows = PoiTlUtils.list2Table(new String[]{"", "", ""}, strings).getRows();//获取所有的表格数据,第一个参数为表格表头数组
					//创建自定义插件表格数据源对象
                    MiniTableDataWP miniTableDataWP = new MiniTableDataWP(0,3,rows);
					//存放到map中
                    templateMap.put("tables",miniTableDataWP);

例子1模版中使用方法:
普通字段绑定:
在这里插入图片描述
表格部分绑定:
在这里插入图片描述
例子2:

templateFileName = "pcr/PCR_REPORT_TEMPLATE_6.docx";//模版路径
                    templateMap.put("age","1");
                    //表格的表头
                    String[] heard = new String[]{"项目","数据(CT)","结果","项目","数据(CT)","结果"};
                    //表的行数据源
                    ArrayList<String[]> strings = new ArrayList<>();
                    List<GeneraResultsItem> generaResultsItemList = genera.getGeneraResults().getGeneraResultsItemList();
                    if(generaResultsItemList != null && !generaResultsItemList.isEmpty()){
                        int size = generaResultsItemList.size();
                        int len = size /2 ;
                        for (int i = 0; i < len; i++) {
                            GeneraResultsItem generaResultsItem = generaResultsItemList.get(i);
                            GeneraResultsItem generaResultsItem1 = generaResultsItemList.get(i+len);
                            String[] row = new String[]{generaResultsItem.getItemName(),"No Ct",generaResultsItem.getGeneraItemResults()
                                    ,generaResultsItem1.getItemName(),"No Ct",generaResultsItem1.getGeneraItemResults()};
                            strings.add(row);
                        }

                    }
                    templateMap.put("tables",PoiTlUtils.list2Table(heard,strings));

例子2模版中使用方法:
普通字段绑定:
在这里插入图片描述
表格绑定:
在这里插入图片描述

20200702补充基础类:


import com.deepoove.poi.data.CellRenderData;
import com.deepoove.poi.data.MiniTableRenderData;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.util.TableTools;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import com.ruoyi.common.utils.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

/** 自定义word表格   -- 自定义poi-tl模板插件
 * description: CustomTableRenderPolicy <br>
 * version: 1.0 <br>
 */
public class CustomTableRenderPolicy extends AbstractRenderPolicy<MiniTableRenderData> {

    private boolean isMergeCells;

    private ITableToolsMC iTableToolsMC;

    public ITableToolsMC getiTableToolsMC() {
        return iTableToolsMC;
    }

    public void setiTableToolsMC(ITableToolsMC iTableToolsMC) {
        this.iTableToolsMC = iTableToolsMC;
    }

    public boolean isMergeCells() {
        return isMergeCells;
    }

    public void setMergeCells(boolean mergeCells) {
        isMergeCells = mergeCells;
    }

    @Override
    protected void afterRender(RenderContext<MiniTableRenderData> context) {
        // 清空模板标签
        clearPlaceholder(context, true);
    }

    @Override
    public void doRender(RenderContext<MiniTableRenderData> context)
            throws Exception {

        NiceXWPFDocument doc = context.getXWPFDocument();
        XWPFRun run = context.getRun();
        Object data = context.getData();
        MiniTableRenderData miniTableRenderData = (MiniTableRenderData) data;


        // 当前位置的容器
        BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);


        List<CellRenderData> headerCellList = miniTableRenderData.getHeader().getCells();
        List<RowRenderData> rowsDataList = miniTableRenderData.getRows();

        // 定义行列
        int colCount = headerCellList.size(),
                rowCount = rowsDataList.size() == 0?rowsDataList.size() + 2:rowsDataList.size() + 1;
        // 定义列宽
//        String[] colWidthArr = new String[]{"1960","7670","5820","1640","1700"};


        // 创建表格
        // 当前位置插入表格
        XWPFTable table = bodyContainer.insertNewTable(run, rowCount, colCount);

//        setTableWidth(table,"18790");


        // 设置表头
        XWPFTableRow headerRow = table.getRow(0);
        setRowHeight(headerRow,"400");
        for (int colNum = 0;colNum < colCount; colNum++){
            XWPFTableCell cell = headerRow.getCell(colNum);
//            cell = cellCenterY(cell);
            setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
            if (miniTableRenderData.getHeader().getRowStyle() != null){
                cell.setColor(miniTableRenderData.getHeader().getRowStyle().getBackgroundColor());
            }
            cell.setText(headerCellList.get(colNum).getCellText().getText());
        }

        // 向表格添加数据
        for (int rowNum = 1;rowNum < rowCount;rowNum++){
            XWPFTableRow row = table.getRow(rowNum);
            if (rowsDataList.size() > 0){
                List<CellRenderData> cellDataList = rowsDataList.get(rowNum -1).getCells();
                for (int colNum = 0;colNum < colCount; colNum++){
                    XWPFTableCell cell = row.getCell(colNum);
                    setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
                    cell.setText(cellDataList.get(colNum).getCellText().getText());
                    if (rowsDataList.get(rowNum -1).getRowStyle() != null){
                        cell.setColor(rowsDataList.get(rowNum -1).getRowStyle().getBackgroundColor());
                    }
                }
            }else {
                XWPFTableCell cell = row.getCell(0);
                setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
                cell.setText("无数据");
                TableTools.mergeCellsHorizonal(table, rowNum, 0, colCount - 1); // 水平合并
            }
        }

        // 定义表格宽度、边框和样式
        TableTools.widthTable(table, MiniTableRenderData.WIDTH_A4_MEDIUM_FULL, colCount);
        TableTools.borderTable(table, 4);

        // TODO 调用XWPFTable API操作表格:data对象可以包含任意你想要的数据,包括图片文本等
        // TODO 调用MiniTableRenderPolicy.Helper.renderRow方法快速方便的渲染一行数据
        // TODO 调用TableTools类方法操作表格,比如合并单元格
        // ......
//        TableTools.mergeCellsHorizonal(table, 0, 0, 7); // 水平合并
        // 合并第0列的第2行到第4行的单元格
//        TableTools.mergeCellsVertically(table, 0, 2, 4);
        if(isMergeCells){
            iTableToolsMC.mergeCells(table);
        }

    }

    private void setTableWidth(XWPFTable table, String width) {
        // 定义表格宽度
        CTTblPr tblPr = table.getCTTbl().getTblPr();
        tblPr.getTblW().setType(STTblWidth.DXA);
        tblPr.getTblW().setW(new BigInteger(width));
    }


    // 设置列宽和水平垂直居中
    public void setCellWidthAndXYAlign(XWPFTableCell cell, STVerticalJc.Enum typeEnum, STJc.Enum vAlign, String width) {
        CTTc cttc = cell.getCTTc();
        CTTcPr cellPr = cttc.addNewTcPr();
        cellPr.addNewVAlign().setVal(typeEnum);
        cttc.getPList().get(0).addNewPPr().addNewJc().setVal(vAlign);
        if(!StringUtils.isEmpty(width)){
            CTTblWidth tblWidth = cellPr.isSetTcW() ? cellPr.getTcW() : cellPr.addNewTcW();
            tblWidth.setType(STTblWidth.DXA);
            tblWidth.setW(new BigInteger(width));
        }
    }

    // 设置表格样式
    public void setCellStyle(XWPFTableCell cell,boolean bold) {
        XWPFParagraph p = cell.addParagraph();
        XWPFRun headRun = p.createRun();
        headRun.setBold(bold);// 是否粗体
    }



    private void setRowHeight(XWPFTableRow row, String height){
            CTTrPr trPr = row.getCtRow().addNewTrPr();
            CTHeight ht = trPr.addNewTrHeight();
            ht.setVal(new BigInteger(height));
    }


    private List<String[]> getList (){
        List<String[]> list = new ArrayList<>();
        String[] arr1 = new String[]{"1.1","1.2","1.3","1.4","1.5"};
        String[] arr2 = new String[]{"2.1","2.2","2.3","2.4","2.5"};
        String[] arr3 = new String[]{"3.1","3.2","3.3","3.4","3.5"};
        String[] arr4 = new String[]{"4.1","4.2","4.3","4.4","4.5"};
        String[] arr5 = new String[]{"5.1","5.2","5.3","5.4","5.5"};
        list.add(arr1);
        list.add(arr2);
        list.add(arr3);
        list.add(arr4);
        list.add(arr5);

        return list;
    }
}
public interface ITableToolsMC {
    void mergeCells(XWPFTable table);
}
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.XWPFTable;



public class ITableToolsMCImpl implements ITableToolsMC {
    @Override
    public void mergeCells( XWPFTable table) {
        // 合并第0列的第0行到第1行的单元格
        TableTools.mergeCellsVertically(table, 0, 0, 1);
    }
}

如有不足请留言补充


版权声明:本文为qq_33333654原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。