港Strive 2022-09-28 22:20 采纳率: 0%
浏览 1288
已结题

EasyExcel合并单元格导出慢,并消耗CPU

问题遇到的现象和发生背景

使用 EasyExcel 自定义策略合并单元格时,2k条数据需要耗时10s。且cpu使用率过高

用代码块功能插入代码,请勿粘贴截图
public class CellMergeStrategy implements CellWriteHandler {

    /**
     * 合并字段的下标
     */
    private int[] mergeColumnIndex;
    /**
     * 合并几行
     */
    private int mergeRowIndex;

    public CellMergeStrategy() {
    }

    public CellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<WriteCellData<?>> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
        //当前行
        int curRowIndex = cell.getRowIndex();
        //当前列
        int curColIndex = cell.getColumnIndex();

        if (curRowIndex > mergeRowIndex) {
            for (int columnIndex : mergeColumnIndex) {
                if (curColIndex == columnIndex) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }
    }
    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        //获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
        Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() :
                cell.getNumericCellValue();
        Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
        Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :
                preCell.getNumericCellValue();

        // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
        Cell groupIdCell = cell.getSheet().getRow(curRowIndex).getCell(0);
        Object groupData = groupIdCell.getCellTypeEnum() == CellType.STRING ? groupIdCell.getStringCellValue() :
                groupIdCell.getNumericCellValue();
        Cell groupIdPreCell = cell.getSheet().getRow(curRowIndex - 1).getCell(0);
        Object groupPreData = groupIdPreCell.getCellTypeEnum() == CellType.STRING ? groupIdPreCell.getStringCellValue() :
                groupIdPreCell.getNumericCellValue();
        if (curData.equals(preData)&& Objects.equals(groupData,groupPreData)) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
                    sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastRow(curRowIndex);
                    sheet.addMergedRegionUnsafe(cellRangeAddr);
                    isMerged = true;
                }
            }
            // 若上一个单元格未被合并,则新增合并单元
            if (!isMerged) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,
                        curColIndex);
                sheet.addMergedRegionUnsafe(cellRangeAddress);
            }
        }
    }
}
运行结果及报错内容

导出时间过久,cpu到达峰值.

我的解答思路和尝试过的方法

导出结束后,cpu4核cpu依旧保持100%的使用率.
查看线程占用发现有个自定义策略中有个addMergedRegion导致。
下面是线程异常图.

img

img

我想要达到的结果

3秒内可导出2000条数据,并降低cpu的使用率. 如有问题easyExcel相关解决方案,或者有高效率的合并单元格解决技术方案.请广大网友指教一二. 采纳后可以请您喝杯咖啡以表感谢. 谢谢大家.

  • 写回答

2条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2022-09-28 23:18
    关注
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 10月24日
  • 创建了问题 9月28日

悬赏问题

  • ¥15 系统 24h2 专业工作站版,浏览文件夹的图库,视频,图片之类的怎样删除?
  • ¥15 怎么把512还原为520格式
  • ¥15 MATLAB的动态模态分解出现错误,以CFX非定常模拟结果为快照
  • ¥15 求高通平台Softsim调试经验
  • ¥15 canal如何实现将mysql多张表(月表)采集入库到目标表中(一张表)?
  • ¥15 wpf ScrollViewer实现冻结左侧宽度w范围内的视图
  • ¥15 栅极驱动低侧烧毁MOSFET
  • ¥30 写segy数据时出错3
  • ¥100 linux下qt运行QCefView demo报错
  • ¥50 F1C100S下的红外解码IR_RX驱动问题