Java poi-tl word表格自定义渲染

该代码示例展示了如何使用Java的XWPFTemplate库结合自定义渲染策略MyLoopRenderPolicy,从BugVO对象列表生成Word文档。方法exportWord读取模板文件,填充数据并输出到新的Word文档,自定义插件处理表格的循环渲染。
摘要由CSDN通过智能技术生成

一、最终实现目标
在这里插入图片描述
二、实现方式

public void exportWord() throws IOException
    {
        ClassPathResource resource = new ClassPathResource("word/template-report-text.docx");
        InputStream inputStream = resource.getInputStream();

        List<BugVO> bugList = new ArrayList<>();
        for (int i = 0; i < 5000; i++) {
            BugVO bugVO = new BugVO();
            bugVO.setSortIndex(i);
            bugVO.setLine(i);
            bugVO.setFilePath("E://haha//" + i);
            bugVO.setMessage("你是哈哈" + i);
            bugVO.setSourceCode("private String " + i);
            bugVO.setBugSteps("第" + i + "步");
            bugList.add(bugVO);
        }

        Configure config = Configure.builder().bind("bugList", new MyLoopRenderPolicy()).build();

        XWPFTemplate template = XWPFTemplate.compile(inputStream, config).render(
                new HashMap<String, Object>(){{
                    put("bugCatalogName", "haha");
                    put("subBugHeaderTitle", "hehe");
                    put("bugCount", "2222222");
                    put("bugDesc", "色色得瑟得瑟");
                    put("bugFix", "贝多芬的");
                    put("bugList", bugList);
                }});
        template.writeAndClose(new FileOutputStream("D:\\louddt\\workspace\\wisdom-city\\wisdom-city-business\\wisdom-city-business-gcgl\\src\\main\\resources\\word\\output.docx"));
    }
public class BugVO
{
    private int sortIndex;
    private String filePath;
    private String message;
    private String sourceCode;
    private String bugSteps;
    private int line;
    //get set
}

自定义表格渲染插件:MyLoopRenderPolicy

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.policy.RenderPolicy;
import com.deepoove.poi.render.compute.EnvModel;
import com.deepoove.poi.render.compute.RenderDataCompute;
import com.deepoove.poi.render.processor.DocumentProcessor;
import com.deepoove.poi.render.processor.EnvIterator;
import com.deepoove.poi.resolver.TemplateResolver;
import com.deepoove.poi.template.ElementTemplate;
import com.deepoove.poi.template.MetaTemplate;
import com.deepoove.poi.template.run.RunTemplate;
import com.deepoove.poi.util.ReflectionUtils;
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;

import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Vector;

public class MyLoopRenderPolicy implements RenderPolicy {

    private static final String DEFAULT_MULTIPLE_PREFIX = "$(";

    private static final String DEFAULT_MULTIPLE_SUFFIX = ")";

    private static final String DEFAULT_PREFIX = "[";

    private static final String DEFAULT_SUFFIX = "]";

    private final String multiplePrefix;

    private final String multipleSuffix;

    public MyLoopRenderPolicy() {
        this(DEFAULT_MULTIPLE_PREFIX, DEFAULT_MULTIPLE_SUFFIX, DEFAULT_PREFIX, DEFAULT_SUFFIX);
    }

    public MyLoopRenderPolicy(String multiplePrefix, String multipleSuffix, String prefix, String suffix) {
        this.multiplePrefix = multiplePrefix;
        this.multipleSuffix = multipleSuffix;
    }

    /**
     * 渲染数据 将bugList中的数据通过表格渲染到word中
     * @param eleTemplate template tag
     * @param data        render data
     * @param template    XWPFTemplate instance
     */
    @Override
    public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) {
        System.out.println("start render==================================");
        try {
            RunTemplate runTemplate = runTemplate(eleTemplate);
            XWPFRun run = runTemplate.getRun();

            checkTargetIsTable(run, "Processing [" + runTemplate.getTagName()
                    + "] failed, the target content is not a table");
            XWPFTableCell tagCell = (XWPFTableCell) ((XWPFParagraph) run.getParent()).getBody();

            final XWPFTable table = tagCell.getTableRow().getTable();

            if (data instanceof Iterable) {
                run.setText("", 0);
                TemplateResolver resolver = new TemplateResolver(template.getConfig().copy(DEFAULT_PREFIX, DEFAULT_SUFFIX));
                //读取模板所在起始行
                int position = getRowIndex(tagCell.getTableRow());
                List<XWPFTableRow> tempRows = getAllTemplateRow(table, position);
                //保存第行内容,以便后续操作中获取光标
                final XWPFTableRow firstTempRow = tempRows.get(0);
                Iterator<?> dataIt = ((Iterable<?>) data).iterator();
                boolean hasNextData = dataIt.hasNext();
                int index = 0;

                while (hasNextData) {
                    Object dt = dataIt.next();
                    hasNextData = dataIt.hasNext();

                    Iterator<XWPFTableRow> rowTempIt = tempRows.iterator();
                    boolean hasNextTempRow = rowTempIt.hasNext();
                    while (hasNextTempRow) {
                        XWPFTableRow tempRow = rowTempIt.next();
                        hasNextTempRow = rowTempIt.hasNext();

                        if (!table.addRow(tempRow, position)) {
                            throw new RenderException("create new table fail...");
                        }

                        //光标操作,移动光标到目标行,以便后续模板渲染
                        XmlCursor newCursor = firstTempRow.getCtRow().newCursor();
                        newCursor.toPrevSibling();
                        XmlObject object = newCursor.getObject();
                        XWPFTableRow newRow = new XWPFTableRow((CTRow) object, table);
                        newRow.getCtRow().set(object);
                        setTableRow(table, newRow, position);

                        List<XWPFTableCell> cells = newRow.getTableCells();
                        RenderDataCompute dataCompute = template.getConfig()
                                .getRenderDataComputeFactory()
                                .newCompute(EnvModel.of(dt, EnvIterator.makeEnv(index++, hasNextData || hasNextTempRow)));
                        cells.forEach(tableCell -> {
                            List<MetaTemplate> metaTemplates = resolver
                                    .resolveBodyElements(tableCell.getBodyElements());
                            new DocumentProcessor(template, resolver, dataCompute)
                                    .process(metaTemplates);
                        });
                        ++position;
                    }
                }

                removeTableRow(table, position, tempRows.size());
            }
        } catch (Exception e) {
            throw new RenderException("failed to render table multi-row template", e);
        }
    }

    private List<XWPFTableRow> getAllTemplateRow(XWPFTable table, int startIndex) {
        int tempRowNum = getMultipleRowNum();
        List<XWPFTableRow> rows = table.getRows();
        return new Vector<>(rows.subList(startIndex, startIndex + tempRowNum));
    }

    private void removeTableRow(XWPFTable table, int startIndex, int size) {
        for (int i = 0; i < size; ++i) {
            table.removeRow(startIndex);
        }
    }

    private RunTemplate runTemplate(MetaTemplate template) {
        if (!(template instanceof RunTemplate)) {
            throw new ClassCastException("type conversion failed, template is not of type RunTemplate");
        }
        return (RunTemplate) template;
    }

    private int getMultipleRowNum() {
        return 4;
    }

    private void checkTargetIsTable(XWPFRun run, String message) {
        if (Objects.isNull(run) || !TableTools.isInsideTable(run)) {
            throw new IllegalStateException(message);
        }
    }

    @SuppressWarnings("unchecked")
    private void setTableRow(XWPFTable table, XWPFTableRow row, int pos) {
        List<XWPFTableRow> rows = (List<XWPFTableRow>) ReflectionUtils.getValue("tableRows", table);
        rows.set(pos, row);
        table.getCTTbl().setTrArray(pos, row.getCtRow());
    }

    private int getRowIndex(XWPFTableRow row) {
        List<XWPFTableRow> rows = row.getTable().getRows();
        return rows.indexOf(row);
    }
}

三、效果

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值