poi-tl中,表格在word中动态生成且合并单元格

param.setColumns(Arrays.asList("征集稿详情", "意见单位", "修改建议", "修改理由", "是否采纳", "意见小结"));
File file = new File(path);
// 获取模板文件流
InputStream resourceAsStream = new FileInputStream(file);

//poi-tl 配置
ConfigureBuilder builder = Configure.builder();
builder.useSpringEL(false);
Map<String, Object> map = new HashMap<>();
//创建表格并动态写入表头
RowRenderData row0 = new RowRenderData();
for (int g = 0; g < param.getColumns().size(); g++) {
    CellRenderData cell_1 = Cells.of(new TextRenderData(param.getColumns().get(g))).create();
    row0.addCell(cell_1);
}
Tables.TableBuilder tableBuilder = Tables.of(row0);


//给表格装载数据
ServerTableData serverTableData = getServerTableData(param);
List<RowRenderData> serverDataList = serverTableData.getServerDataList();
List<Map<String, Object>> groupDataList = serverTableData.getGroupDataList();
Integer mergeColumn = serverTableData.getMergeColumn(); //合并第几列,一般是0列
for (RowRenderData qiankuan : serverTableData.getServerDataList()) {
    RowRenderData row = qiankuan;
    tableBuilder.addRow(row);
}

MergeCellRule.MergeCellRuleBuilder rule = MergeCellRule.builder();

//待需要合并的行的集合
Map<MergeCellRule.Grid, MergeCellRule.Grid> mergeMap = new HashMap<>();
// 处理合并---开始
for (int i = 0; i < serverDataList.size(); i++) {
    // 获取要合并的名称那一列数据 mergeColumn代表要合并的列,从0开始
    String typeNameData = serverDataList.get(i).getCells().get(0).getParagraphs().get(0).getContents().get(0).toString();
    for (int j = 0; j < groupDataList.size(); j++) {
        String typeNameTemplate = String.valueOf(groupDataList.get(j).get("typeName"));
        int listSize = Integer.parseInt(String.valueOf(groupDataList.get(j).get("listSize")));

        //合并征集稿对象合并
        if (typeNameTemplate.equals(typeNameData) && listSize > 1) {
            mergeMap.put(MergeCellRule.Grid.of(i + 1, 0), MergeCellRule.Grid.of(i + listSize, 0));
            groupDataList.remove(j);
            break;
        }
    }
}

//将需要的合并行集合放到map中
for (Map.Entry<MergeCellRule.Grid, MergeCellRule.Grid> entry : mergeMap.entrySet()) {
    MergeCellRule.Grid mapKey = entry.getKey();
    MergeCellRule.Grid mapValue = entry.getValue();
    rule.map(mapKey, mapValue);
}
// 处理合并---结束

 tableBuilder.mergeRule(rule.build());//开始合并
    map.put("oneTable", tableBuilder.create());
    XWPFTemplate template = XWPFTemplate.compile(Objects.requireNonNull(resourceAsStream), builder.build()).render(map);
    //输出网络流
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/octet-stream");
    response.setHeader("Content-disposition", "attachment;fileName=" + URLEncoder.encode(param.getDraftTitle() +"."+ param.getType(), "utf-8"));
    // HttpServletResponse response
    OutputStream out = response.getOutputStream();
    BufferedOutputStream bos = new BufferedOutputStream(out);
    template.write(bos);
    bos.flush();
    out.flush();
    PoitlIOUtils.closeQuietlyMulti(template, bos, out);



private ServerTableData getServerTableData(ExportParam param) {
    ServerTableData serverTableData = new ServerTableData();
    List<RowRenderData> serverDataList = new ArrayList<>();
    
    for (int a = 0; a < param.getResult().size(); a++) {
        List<OpinionResultVo> listVos = param.getResult().get(a).getData();
        listVos.stream().forEach(x -> {
            RowRenderData serverData = new RowRenderData();
            param.getColumns().stream().forEach(e -> {

             CellRenderData cell_1 = Cells.of(new TextRenderData(columnName(e,                     x))).center().create();
            serverData.addCell(cell_1);

            });
            serverDataList.add(serverData);
        });

    }

    serverTableData.setServerDataList(serverDataList);

    List<Map<String, Object>> groupDataList = new ArrayList<>();
    for (int b = 0; b < param.getResult().size(); b++) {
        ExportExcelVo exportExcelVo = param.getResult().get(b);
        Map<String, Object> groupData1 = new HashMap<>();
        groupData1.put("typeName", exportExcelVo.getRule());
        groupData1.put("listSize", exportExcelVo.getData().size());
        groupDataList.add(groupData1);
    }
    serverTableData.setGroupDataList(groupDataList);
    serverTableData.setMergeColumn(0);
    serverTableData.setColumns(param.getColumns());
    return serverTableData;
}



word模板例子:

### 使用 poi-tl 合并 Word 表格 在使用 `poi-tl` 库时,可以通过定义合并规则来处理复杂的表格数据。以下是具体方法和示例代码: #### 1. 定义合并规则 通过 `MergeCellRule.builder()` 方法创建一个合并规则对象,并指定需要合并的列索引以及对应的值判断逻辑。 ```java import cn.afterturn.easypoi.word.template.merge.cell.MergeCellRule; public class MergeTableExample { public static void main(String[] args) { // 创建合并规则构建器 MergeCellRule.MergeCellRuleBuilder mergeCellRuleBuilder = MergeCellRule.builder(); // 添加需要合并的列及其对应条件 (假设第0列为姓名列) mergeCellRuleBuilder.addSameRowMerge(0); // 如果同一列相邻单元内容相同,则合并 // 构建最终的合并规则 MergeCellRule mergeCellRule = mergeCellRuleBuilder.build(); } } ``` 此部分代码用于配置哪些列应该被检查是否有重复项,并决定是否要执行跨行或单行内的单元合并操作[^4]。 #### 2. 配置模板参数 当准备好了上述合并策略之后,在实际调用 POI-TL 的 API 来渲染 DOCX 文件之前,还需要将这些规则传递给工具类以便其应用到目标区域上。 ```java import cn.afterturn.easypoi.word.WordExportUtil; import org.apache.poi.xwpf.usermodel.XWPFDocument; import java.io.FileOutputStream; import java.util.HashMap; import java.util.Map; public class ExportWordWithMerge { public static void export() throws Exception{ Map<String, Object> dataMap = new HashMap<>(); // 假设这里有一些业务逻辑填充dataMap... XWPFDocument doc = WordExportUtil.exportWord("template.docx", dataMap); FileOutputStream fos = null; try { fos = new FileOutputStream("output.docx"); doc.write(fos); System.out.println("成功生成带有合并单元Word文档!"); } finally { if (fos != null){ fos.close(); } if (doc != null){ doc.close(); } } } public static void main(String[] args)throws Exception{ export(); } } ``` 在这个例子中,虽然未直接展示如何传入自定义的 `mergeCellRule` 对象至 `exportWord` 函数内部,但实际上该功能已被集成到了 EasyPoi 工具包里,默认会自动识别并应用任何预设定好的样式调整指令集,包括但不限于单元边框颜色修改、字体大小变更等高级特性支持[^3]。 以上就是利用 Java 编程语言配合第三方开源库——POI-TL 实现自动化批量生产含有多层次结构化信息呈现效果(特别是针对复杂型态下的 Excel Sheet 或者 Docx Page Layout Design 方面)的一个典型应用场景介绍[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值