Easypoi_4.2.0源码修改 word模板导出 增加表格第一列非循环语句时word导出

本文记录了Easypoi 4.2.0源码修改的过程,以支持Word模板中表格第一列非循环语句的情况。通过分析`exportWord07`方法及`ParseWord07`类的`parseThisTable`方法,找到了问题所在并进行修复,实现了正确解析非首列循环语句的功能。
摘要由CSDN通过智能技术生成

Easypoi_4.2.0源码修改 word模板导出 增加表格第一列非循环语句时word导出

1. 写在前面

  之前写过easypoi修改源码的文章,写的很细,但是发现基本没什么反响。这篇文章不会太详细的介绍如何定位问题,只会简单记录,最后把修改完的代码贴出来,并实现功能。

2. 开始寻找突破口

  首先定位到问题,当word模板中存在表格的情况下,并且表格的第一列是固定,如下图中蓝框中的内容是固定,这时使用 !fe: 遍历的时候,会发现毫无效果。问题定位到了,那就一步一步来找到原因所在吧。
在这里插入图片描述

3. 解决问题

  首先找到代码入口。查看该方法exportWord07

WordExportUtil.exportWord07("班级.docx", map)

经过一系列的调试,定位到了ParseWord07类中的parseThisTable方法。源码如下:

    private void parseThisTable(XWPFTable table, Map<String, Object> map) throws Exception {
        for(int i = 0; i < table.getNumberOfRows(); ++i) {
            XWPFTableRow row = table.getRow(i);
            List<XWPFTableCell> cells = row.getTableCells();
            Object listobj = this.checkThisTableIsNeedIterator((XWPFTableCell)cells.get(0), map);
            if (listobj == null) {
                this.parseThisRow(cells, map);
            } else if (listobj instanceof ExcelListEntity) {
                (new ExcelEntityParse()).parseNextRowAndAddRow(table, i, (ExcelListEntity)listobj);
                i = i + ((ExcelListEntity)listobj).getList().size() - 1;
            } else {
                ExcelMapParse.parseNextRowAndAddRow(table, i, (List)listobj);
                i = i + ((List)listobj).size() - 1;
            }
        }

    }

  我们需要改的地方就是第五行,之后替换表格内容的代码最重要的就是listobj参数。这源代码中第五行很明显,他只是根据第一列的内容来获取listobj,而我们的模板循环语句并未在第一列上,因此导致word导出时,无法替换内容。原因讲完了,下面都是动手节了。

  首先将ParseWord07类中的parseThisTable方法 修改成以下代码。

 private void parseThisTable(XWPFTable table, Map<String, Object> map) throws Exception {
        for (int i = 0; i < table.getNumberOfRows(); ++i) {
            XWPFTableRow row = table.getRow(i);
            List<XWPFTableCell> cells = row.getTableCells();

            //此部分为修改的源代码
            //作用 用于识别word中表格非第一列的循环语法
            Object listobj = null;
            int col = 0;
            for (XWPFTableCell cell : cells) {
                listobj = this.checkThisTableIsNeedIterator(cell, map);
                if (listobj != null) {
                    break;
                }
                col++;
            }
            if (listobj == null) {
                this.parseThisRow(cells, map);
            } else if (listobj instanceof ExcelListEntity) {
                (new ExcelEntityParse()).parseNextRowAndAddRow(table, i, (ExcelListEntity) listobj);
                i = i + ((ExcelListEntity) listobj).getList().size() - 1;
            } else {
                LcExcelMapParse.parseNextRowAndAddRow(table, i, (List) listobj, col);
                i = i + ((List) listobj).size() - 1;
            }
        }

    }

  再找到ExcelMapParse类中的parseNextRowAndAddRow方法,修改成以下代码


    public static void parseNextRowAndAddRow(XWPFTable table, int index, List<Object> list, int col) throws Exception {
        XWPFTableRow currentRow = table.getRow(index);
        String[] params = parseCurrentRowGetParams(currentRow);
        String listname = params[col];
        boolean isCreate = !listname.contains("!fe:");
        listname = listname.replace("!fe:", "").replace("$fe:", "").replace("fe:", "").replace("{{", "");
        String[] keys = listname.replaceAll("\\s{1,}", " ").trim().split(" ");
        params[col] = keys[1];
        List<XWPFTableCell> tempCellList = new ArrayList();
        tempCellList.addAll(table.getRow(index).getTableCells());
//        int cellIndex = false;
        Map<String, Object> tempMap = Maps.newHashMap();
        LOGGER.debug("start for each data list :{}", list.size());
        Iterator var11 = list.iterator();

        while (var11.hasNext()) {
            Object obj = var11.next();
            currentRow = isCreate ? table.insertNewTableRow(index++) : table.getRow(index++);
            tempMap.put("t", obj);

            //如果有合并单元格情况,会导致params越界,这里需要补齐
            String[] paramsNew = (String[]) ArrayUtils.clone(params);
            if (params.length < currentRow.getTableCells().size()) {
                for (int i = 0; i < currentRow.getTableCells().size() - params.length; i++) {
                    paramsNew = (String[]) ArrayUtils.add(paramsNew, 0, "placeholderLc_" + i);
                }
            }

            String val;
            int cellIndex;
            for (cellIndex = 0; cellIndex < currentRow.getTableCells().size(); ++cellIndex) {
                val = PoiElUtil.eval(paramsNew[cellIndex], tempMap).toString();
                //源代码的bug 此方法无法删除单元格中的内容
                //currentRow.getTableCells().get(cellIndex).setText("");
                //使用此方法清空单元格内容
                if (!Strings.isNullOrEmpty(val)) {
                    currentRow.getTableCells().get(cellIndex).getParagraphs().forEach(p -> p.getRuns().forEach(r -> r.setText("", 0)));
                }
                PoiWordStyleUtil.copyCellAndSetValue(cellIndex >= tempCellList.size() ? tempCellList.get(tempCellList.size() - 1) : tempCellList.get(cellIndex)
                        , currentRow.getTableCells().get(cellIndex), val);
            }

            while (cellIndex < paramsNew.length) {
                val = PoiElUtil.eval(paramsNew[cellIndex], tempMap).toString();
                PoiWordStyleUtil.copyCellAndSetValue((XWPFTableCell) tempCellList.get(cellIndex), currentRow.createCell(), val);
                ++cellIndex;
            }
        }

        table.removeRow(index);
    }

  至此源代码全部修改完毕,这次没有解释太多,因为估计真有遇到需要修改源代码的时候,大部分人选择的是放弃使用这个第三方类库,修改源码也确实有一定难度,所以这个基本用于记录自己解决问题的整个流程,方便以后看得时候能快速想起来。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值