You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

POI导出Excel进度条异常:值为0%时仍显示进度条求助

解决POI导出Excel时0%值仍显示进度条的问题

我在使用POI将数据导出为进度条格式时遇到异常:当单元格值为0%时,仍会显示进度条。以下是我的实现源码:

private void createProgressShape(Map<Integer, Double> map, Workbook workbook, Sheet sheet) {
    CellStyle cellStyle = workbook.createCellStyle();
    cellStyle.setBorderTop(BorderStyle.THIN);
    cellStyle.setBorderBottom(BorderStyle.THIN);
    cellStyle.setBorderLeft(BorderStyle.THIN);
    cellStyle.setBorderRight(BorderStyle.THIN);
    cellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
    cellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
    cellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
    cellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());

    DataFormat percent = workbook.createDataFormat();
    cellStyle.setDataFormat(percent.getFormat("0.00%"));

    List<Integer> list = new ArrayList<>();
    for (Integer rowNum : map.keySet()) {
        Row row = sheet.getRow(rowNum);
        Cell cell = row.getCell(1);
        cell.setCellValue(map.get(rowNum));
        cell.setCellStyle(cellStyle);
        list.add(rowNum);
    }
    List<Integer> segmentEndpoints = getSegmentEndpoints(list);
    CellRangeAddress cra[] = {
            new CellRangeAddress(segmentEndpoints.get(0), segmentEndpoints.get(1), 1, 1),
            new CellRangeAddress(segmentEndpoints.get(2), segmentEndpoints.get(3), 1, 1)
    };
    XSSFColor color = new XSSFColor(new byte[]{(byte) 0xFF, 0x00, 0x00, (byte) 0xFF});
    SheetConditionalFormatting cf = sheet.getSheetConditionalFormatting();
    ConditionalFormattingRule cfRule = cf.createConditionalFormattingRule(color);
    cf.addConditionalFormatting(cra, cfRule);
    DataBarFormatting format = cfRule.getDataBarFormatting();
    format.getMinThreshold().setRangeType(ConditionalFormattingThreshold.RangeType.PERCENT);
    format.getMinThreshold().setValue(0d);
    format.getMaxThreshold().setRangeType(ConditionalFormattingThreshold.RangeType.PERCENT);
    format.getMaxThreshold().setValue(100d);
}

导出效果截图:
导出的进度条效果截图


问题原因

  1. 阈值范围类型错误:设置的PERCENT范围类型是基于所选单元格区域的数据分位数,而非单元格的实际数值。若区域内存在非0值,0会被视为区域最小值,Excel会自动渲染最小长度的进度条。
  2. Excel默认最小长度:DataBar默认会保留极小的显示长度,即使值为0也会显示一条细线。

修复方案

修改条件格式规则的创建方式及DataBar参数:

  1. 将阈值范围类型改为VALUE,匹配单元格存储的0-1数值(对应显示的0%-100%)。
  2. 设置DataBar的最小长度为0,强制值为0时不显示进度条。
  3. 修正条件规则创建逻辑,避免同时应用单元格填充格式。

修改后的完整代码

private void createProgressShape(Map<Integer, Double> map, Workbook workbook, Sheet sheet) {
    CellStyle cellStyle = workbook.createCellStyle();
    cellStyle.setBorderTop(BorderStyle.THIN);
    cellStyle.setBorderBottom(BorderStyle.THIN);
    cellStyle.setBorderLeft(BorderStyle.THIN);
    cellStyle.setBorderRight(BorderStyle.THIN);
    cellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
    cellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
    cellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
    cellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());

    DataFormat percent = workbook.createDataFormat();
    cellStyle.setDataFormat(percent.getFormat("0.00%"));

    List<Integer> list = new ArrayList<>();
    for (Integer rowNum : map.keySet()) {
        Row row = sheet.getRow(rowNum);
        Cell cell = row.getCell(1);
        cell.setCellValue(map.get(rowNum));
        cell.setCellStyle(cellStyle);
        list.add(rowNum);
    }
    List<Integer> segmentEndpoints = getSegmentEndpoints(list);
    CellRangeAddress cra[] = {
            new CellRangeAddress(segmentEndpoints.get(0), segmentEndpoints.get(1), 1, 1),
            new CellRangeAddress(segmentEndpoints.get(2), segmentEndpoints.get(3), 1, 1)
    };
    XSSFColor color = new XSSFColor(new byte[]{(byte) 0xFF, 0x00, 0x00, (byte) 0xFF});
    SheetConditionalFormatting cf = sheet.getSheetConditionalFormatting();
    
    // 改为创建非空条件规则,避免自动添加单元格填充
    ConditionalFormattingRule cfRule = cf.createConditionalFormattingRule(ComparisonOperator.NO_BLANK, null, null);
    cf.addConditionalFormatting(cra, cfRule);
    
    DataBarFormatting format = cfRule.getDataBarFormatting();
    // 设置DataBar颜色
    format.setColor(color);
    // 设置阈值为VALUE类型,对应单元格实际存储的0-1数值
    format.getMinThreshold().setRangeType(ConditionalFormattingThreshold.RangeType.VALUE);
    format.getMinThreshold().setValue(0d);
    format.getMaxThreshold().setRangeType(ConditionalFormattingThreshold.RangeType.VALUE);
    format.getMaxThreshold().setValue(1d);
    // 设置最小长度为0,确保0值时无进度条显示
    format.setMinLength(0);
    format.setMaxLength(100);
    // 可选:若不需要显示单元格百分比数值,取消注释下面一行
    // format.setShowValue(false);
}

关键修改点说明

  • 阈值类型调整:VALUE类型直接匹配单元格的实际数值(你存储的是0到1的小数,对应显示的0%-100%),0对应完全无进度条,1对应满进度条。
  • 最小长度设置:format.setMinLength(0)覆盖Excel默认的最小进度条长度,彻底隐藏0值的进度条。
  • 规则创建修正:使用NO_BLANK规则创建条件格式,避免原代码中基于颜色的规则同时添加单元格填充样式,确保仅应用DataBar效果。

内容的提问来源于stack exchange,提问作者user27725313

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 11:04:52