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

使用Apache POI生成含BAR图表的DOCX无法在Word 365打开

问题描述
  • 使用Apache POI生成DOCX文件已有数月,此前所有版本Microsoft Word均可正常打开;近期发现包含ChartTypes.BAR类型图表的文件无法在Word 365中打开,仅提示文件无法打开
  • 已完成OOXML验证,未发现任何验证错误
  • 可通过Apache POI官方示例或以下JUnit测试代码复现问题
复现代码
@Test
public void barChartTest() throws FileNotFoundException, IOException {

    String chartTitle = "10 languages with most speakers as first language";
    String[] series = { "countries", "speakers", "language" };

    // Category Axis Data
    List<String> listLanguages = new ArrayList<>(3);

    // Values
    List<Double> listCountries = new ArrayList<>(3);
    List<Double> listSpeakers = new ArrayList<>(3);

    listCountries.add(2d);
    listCountries.add(4d);
    listCountries.add(6d);
    listSpeakers.add(10d);
    listSpeakers.add(12d);
    listSpeakers.add(14d);
    listLanguages.add("A");
    listLanguages.add("B");
    listLanguages.add("C");

    String[] categories = listLanguages.toArray(new String[0]);
    Double[] values1 = listCountries.toArray(new Double[0]);
    Double[] values2 = listSpeakers.toArray(new Double[0]);

    int columnLanguages = 0;
    int columnCountries = 1;
    int columnSpeakers = 2;

    try (XWPFDocument doc = new XWPFDocument()) {
        XWPFChart chart = doc.createChart(6000000, 5000000);

        XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        bottomAxis.setTitle(series[2]);
        XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
        leftAxis.setTitle(series[0] + "," + series[1]);
        leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        leftAxis.setMajorTickMark(AxisTickMark.OUT);
        leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

        final int numOfPoints = categories.length;
        final String categoryDataRange = chart
                .formatRange(new CellRangeAddress(1, numOfPoints, columnLanguages, columnLanguages));
        final String valuesDataRange = chart
                .formatRange(new CellRangeAddress(1, numOfPoints, columnCountries, columnCountries));
        final String valuesDataRange2 = chart
                .formatRange(new CellRangeAddress(1, numOfPoints, columnSpeakers, columnSpeakers));
        final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange,
                columnLanguages);
        final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1,
                valuesDataRange, columnCountries);
        valuesData.setFormatCode("General");
//          values1[6] = 16.0; // if you ever want to change the underlying data, it has to be done before
//                              // building the data source
        final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2,
                valuesDataRange2, columnSpeakers);
        valuesData2.setFormatCode("General");

        XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
        bar.setBarGrouping(BarGrouping.CLUSTERED);

        XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData);
        series1.setTitle(series[0], chart.setSheetTitle(series[0], columnCountries));

        XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2);
        series2.setTitle(series[1], chart.setSheetTitle(series[1], columnSpeakers));

        bar.setVaryColors(true);
        bar.setBarDirection(BarDirection.COL);
        chart.plot(bar);

        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.LEFT);
        legend.setOverlay(false);

        chart.setTitleText(chartTitle);
        chart.setTitleOverlay(false);
        chart.setAutoTitleDeleted(false);

        try (FileOutputStream out = new FileOutputStream("output/chart.docx")) {
            doc.write(out);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }

}
解决方案建议
  • 升级Apache POI版本:Word 365对OOXML格式的兼容性要求更严格,建议升级到最新稳定版(如5.2.5及以上),新版本通常会修复针对Office 365的兼容性问题
  • 调整图表方向设置:尝试移除bar.setBarDirection(BarDirection.COL)代码,或改为BarDirection.BAR,部分场景下Word 365对垂直柱状图的XML结构解析存在异常
  • 禁用自动颜色变化:注释掉bar.setVaryColors(true),部分版本中该设置生成的XML属性可能触发Word 365的解析错误
  • 手动修正OOXML结构:解压DOCX文件,找到word/charts/chart1.xml,检查<barDir>标签值,确保其符合Word 365预期(如bar),重新打包后测试
  • 临时替代图表类型:若上述方法无效,可暂时使用ChartTypes.LINE生成图表,验证是否为柱状图特有的兼容性问题,同时等待Apache POI官方修复

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 09:02:09