使用Apache POI生成Excel折线图单数据系列图例异常问题
解决Apache POI单系列折线图图例异常问题
我之前用Apache POI生成Excel折线图时也踩过一模一样的坑,咱们来聊聊问题根源和修复方案:
问题原因
当你只保留单个数据系列时,Apache POI 4.1.1会犯一个小错误——它把**分类轴的标签(china、usa、japan)**当成了图例项,而不是用你设置的系列标题(Area)。多系列时因为有明确的多个系列区分,所以不会触发这个问题,单系列时就暴露了这个默认逻辑的bug。
修复方案
在绘制图表后,手动清除错误的图例条目,然后添加正确的系列标题作为图例项。修改后的代码如下:
public static void test() throws Exception { try (XSSFWorkbook wb = new XSSFWorkbook()) { String sheetName = "CountryLineChart"; XSSFSheet sheet = wb.createSheet(sheetName); XSSFDrawing drawing = sheet.createDrawingPatriarch(); XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 4, 7, 26); XSSFChart chart = drawing.createChart(anchor); chart.setTitleText("Area-wise Top Seven Countries"); chart.setTitleOverlay(false); XDDFChartLegend legend = chart.getOrAddLegend(); legend.setPosition(LegendPosition.TOP_RIGHT); XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); bottomAxis.setTitle("Country"); XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); leftAxis.setTitle("Area & Population"); XDDFDataSource<String> countries = XDDFDataSourcesFactory.fromArray(new String[] { "china", "usa", "japan" }); XDDFNumericalDataSource<Double> area = XDDFDataSourcesFactory.fromArray(new Double[] { 12d, 22d, 12d }); // XDDFNumericalDataSource<Double> population = XDDFDataSourcesFactory.fromArray(new Double[] { 33d, 12d, 16d }); XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis); XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(countries, area); series1.setTitle("Area", null); series1.setSmooth(false); series1.setMarkerStyle(MarkerStyle.STAR); // 注释掉第二个系列的代码 // =========================================================================== // XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(countries, population); // series2.setTitle("Population", null); // series2.setSmooth(true); // series2.setMarkerStyle(MarkerStyle.SQUARE); // =========================================================================== chart.plot(data); // ------------------------ 新增修复图例的代码 ------------------------ // 清除默认生成的错误图例条目 while (legend.getEntries().size() > 0) { legend.removeEntry(0); } // 添加正确的系列标题作为图例项 if (!data.getSeries().isEmpty()) { XDDFLineChartData.Series singleSeries = (XDDFLineChartData.Series) data.getSeries().get(0); XDDFLegendEntry legendEntry = legend.addEntry(0, LegendEntryType.SERIES); legendEntry.setText(singleSeries.getTitleText()); } // ------------------------------------------------------------------- // 写入Excel文件 String filename = "/Users/jiangxingshang/Downloads/tmp/line-chart.xlsx"; try (FileOutputStream fileOut = new FileOutputStream(filename)) { wb.write(fileOut); } } }
补充说明
- 这段修复代码会先清空所有自动生成的错误图例条目,然后从当前数据系列中获取唯一的系列标题,添加为新的图例项,确保图例显示的是你预期的系列名称。
- 如果你后续又恢复多系列,这段代码也能兼容——当有多个系列时,你可以注释掉手动修复的代码,让POI自动处理图例即可。
内容的提问来源于stack exchange,提问作者user1434702




