需求
报表引出 Excel 支持列头单元格融合,不支持内容单元格融合。
思路方案
引出 Excel 操作执行 ReportView.exportExcel() -> ReportList.exportExcel()
找到处理 Excel 类 ReportList.getExcelExporter() ,内容单元格融合在这个类就可以解决,但是源码是写死的 kd.bos.mvc.export.GridExcelExporter。
参考 GridExcelExporter 源码修改实现内容单元格融合
参考 ReportView 和 ReportList 实现引出操作功能
实现步骤
1.参考GridExcelExporter 源码编写内容单元融合功能
GridExcelExporter.createBodyColumn() 处理内容区域生成,同时单元格合并使用 SXSSFSheet.addMergedRegion(CellRangeAddress region) 。基于这两部分,在 GridExcelExporter.setCellValueAndStyle() 判断需要合并的单元格添加到待合并单元格集合中,最后在GridExcelExporter.createBodyColumn() 统一处理合并。
需要注意:苍穹报表单元格融合是列纵向融合,没有多列横向融合,这块简单写了一个类用于计算合并单元开始和结束索引。noMergeFieldKey 是实现按条件判断单元格融合,之前我写的一篇文章 https://developer.kingdee.com/article/416977219471536640?productLineId=29
public class MyMergeCell { private final String columnName; private final int columnIndex; private final LinkedList<MergeRegion> mergeRegions = new LinkedList<>(); public MyMergeCell(String columnName, int columnIndex) { this.columnName = columnName; this.columnIndex = columnIndex; } public void compare(int rowIndex, Object value, String noMergeFields) { MergeRegion lastRegion = mergeRegions.isEmpty() ? null : mergeRegions.getLast(); if (lastRegion == null) { lastRegion = new MergeRegion(this.columnName); mergeRegions.addLast(lastRegion); } if (!lastRegion.compare(rowIndex, value, noMergeFields)) { mergeRegions.addLast(new MergeRegion(this.columnName, rowIndex, value, noMergeFields)); } } public List<CellRangeAddress> createCellRanges() { List<CellRangeAddress> cellRanges = new ArrayList<>(); for (MergeRegion item : mergeRegions) { if (item.check()) { cellRanges.add(new CellRangeAddress(item.beginRow, item.endRow, columnIndex, columnIndex)); } } return cellRanges; } public static class MergeRegion { private String columnName; private String preValue; private int beginRow = -1; private int endRow = -1; public MergeRegion(String columnName) { this.columnName = columnName; } public MergeRegion(String columnName, int rowIndex, Object value, String noMergeFields) { this(columnName); compare(rowIndex, value, noMergeFields); } public boolean check() { if (beginRow > 0 && endRow > 0) { return endRow > beginRow; } return false; } public boolean compare(int rowIndex, Object value, String noMergeFields) { String stringValue = convertStringValue(value); if (this.beginRow >= 0) { if (StringUtils.isNotBlank(stringValue) && StringUtils.equals(this.preValue, stringValue)) { if (checkNoMerge(noMergeFields)) { return false; } this.endRow = rowIndex; return true; } else { if (this.endRow > 0) { return false; } } } this.preValue = stringValue; this.beginRow = rowIndex; this.endRow = -1; return true; } private boolean checkNoMerge(String noMergeFields) { if (StringUtils.isNotBlank(noMergeFields)) { if (!noMergeFields.startsWith(",")) { noMergeFields = "," + noMergeFields; } if (!noMergeFields.endsWith(",")) { noMergeFields = noMergeFields + ","; } return noMergeFields.indexOf("," + this.columnName + ",") >= 0; } return false; } private String convertStringValue(Object value) { String stringValue = value == null ? "" : String.valueOf(value); return stringValue; } } }
2.参考 ReportView 和 ReportList 实现引出操作功能
这块代码比较多,大量是ReportView 和 ReportList 代码合并起来。只是增加了获取报表列表有哪些列启用了合并。下图红框中,基于报表设置列合并,需要重写报表表单插件 setMergeColums() 。
ReportList.getColumnList() | MyCustomExportExcel.getColumnList() |
![]() | ![]() |
3.报表自定义引出操作
实现效果
Excel 内容单元格融合 | Excel 按条件内容单元格融合 (noMergeFieldKey) |
![]() | ![]() |
开发环境版本
v5.0.011
注意事项
文章内示例代码仅供参考,因为有一些对源码处理,如有需要私信我发你。
报表所见即所得引出.zip(20.74KB)
推荐阅读