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); }
导出效果截图:
问题原因
- 阈值范围类型错误:设置的
PERCENT范围类型是基于所选单元格区域的数据分位数,而非单元格的实际数值。若区域内存在非0值,0会被视为区域最小值,Excel会自动渲染最小长度的进度条。 - Excel默认最小长度:DataBar默认会保留极小的显示长度,即使值为0也会显示一条细线。
修复方案
修改条件格式规则的创建方式及DataBar参数:
- 将阈值范围类型改为
VALUE,匹配单元格存储的0-1数值(对应显示的0%-100%)。 - 设置DataBar的最小长度为0,强制值为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(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
相关产品推荐
相关产品推荐

