
本文详解 apache poi 生成 word 柱状图时常见的“文件无法打开”问题,指出系列标题(series title)为必需项,并提供完整、健壮的代码示例,涵盖轴配置、颜色设置与兼容性优化。
本文详解 apache poi 生成 word 柱状图时常见的“文件无法打开”问题,指出系列标题(series title)为必需项,并提供完整、健壮的代码示例,涵盖轴配置、颜色设置与兼容性优化。
在使用 Apache POI(尤其是 XWPFChart)向 .docx 文件嵌入柱状图时,一个看似成功却导致文档无法被 Microsoft Word 或 LibreOffice 打开的典型错误是:未为图表系列(XDDFChartData.Series)设置标题。虽然该字段在 API 中看似可选,但实际生成的 OOXML 结构要求 <c:tx>(标题元素)必须存在,否则 Word 将拒绝加载文档并提示“文件已损坏”。
✅ 核心修复:必须设置 series title
原代码中注释掉的这行是关键:
series.setTitle("Fruit Sales", null);取消注释并传入有效标题字符串(第二个参数为 CTTextReference,通常设为 null 即可),即可满足 XML Schema 要求。
?️ 进阶配置提升兼容性与显示效果
除标题外,以下配置显著增强图表稳定性与跨平台兼容性(尤其对 LibreOffice):
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 坐标轴交叉点:调用 valueAxis.setCrosses(AxisCrosses.AUTO_ZERO),确保数值轴在 0 处与分类轴相交;
- 分类轴对齐方式:使用 valueAxis.setCrossBetween(AxisCrossBetween.BETWEEN),避免首尾柱体被截断(默认 AT 模式会使柱子中心对齐刻度线,导致边缘柱仅显示一半);
- 柱形方向:明确指定 BarDirection.COL(垂直柱状图)或 BarDirection.BAR(水平条形图),避免渲染歧义;
-
填充颜色:LibreOffice 不会自动应用默认色,需主动设置纯色填充(如蓝色):
solidFillSeries(series, PresetColor.BLUE);
其中辅助方法 solidFillSeries 构建 XDDFSolidFillProperties 并注入 ShapeProperties。
? 完整可运行示例(含关键注释)
import java.io.FileOutputStream;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xwpf.usermodel.*;
public class BarChartWordMinimal {
public static void main(String[] args) throws Exception {
XWPFDocument doc = new XWPFDocument();
// 添加文本内容(非必需,但体现文档结构完整性)
XWPFParagraph paragraph = doc.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("Bar Chart Example:");
// 创建图表(宽10cm × 高5cm)
XWPFChart chart = doc.createChart(10 * Units.EMU_PER_CENTIMETER, 5 * Units.EMU_PER_CENTIMETER);
// 数据源
String[] categories = {"Critical", "High", "Medium", "Low", "Best Practice"};
Double[] values = {1.0, 2.0, 3.0, 4.0, 5.0};
XDDFDataSource<String> catData = XDDFDataSourcesFactory.fromArray(categories);
XDDFNumericalDataSource<Double> valData = XDDFDataSourcesFactory.fromArray(values);
// 坐标轴配置
XDDFCategoryAxis categoryAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis valueAxis = chart.createValueAxis(AxisPosition.LEFT); // 推荐 LEFT 而非 TOP
valueAxis.setCrosses(AxisCrosses.AUTO_ZERO);
valueAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
// 创建柱状图数据
XDDFChartData data = chart.createData(ChartTypes.BAR, categoryAxis, valueAxis);
((XDDFBarChartData) data).setBarDirection(BarDirection.COL);
// 设置图表标题(可选)
chart.setTitleText("Security Severity Distribution");
// 添加数据系列 —— ⚠️ series.setTitle() 是强制要求!
XDDFChartData.Series series = data.addSeries(catData, valData);
series.setTitle("Severity Count", null); // 关键:不可省略!
// 设置填充色(保障 LibreOffice 正常显示)
solidFillSeries(series, PresetColor.DARK_BLUE);
// 渲染图表
chart.plot(data);
// 保存文件
try (FileOutputStream out = new FileOutputStream("bar_chart_document.docx")) {
doc.write(out);
}
System.out.println("✅ Bar chart document created successfully!");
}
private static void solidFillSeries(XDDFChartData.Series series, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFShapeProperties props = series.getShapeProperties();
if (props == null) props = new XDDFShapeProperties();
props.setFillProperties(fill);
series.setShapeProperties(props);
}
}⚠️ 注意事项与最佳实践
- 依赖版本:确保使用 Apache POI ≥ 5.2.4(推荐 5.2.5+),旧版本存在 XDDF 图表 API 不稳定问题;
-
Maven 依赖(关键):
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.5</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-full</artifactId> <version>5.2.5</version> </dependency>? poi-ooxml-full 替代了早期 ooxml-schemas,提供完整 XML Schema 支持。
- 资源释放:务必使用 try-with-resources 或显式 close(),防止文件句柄泄漏;
- 调试技巧:若仍报错,可用 ZIP 工具解压 .docx,检查 word/charts/chart1.xml 是否包含 <c:tx><c:rich><a:t>Fruit Sales</a:t></c:rich></c:tx> 节点。
遵循以上规范,即可生成完全符合 Office Open XML 标准、能在 Word 和 LibreOffice 中无缝打开并正确渲染的柱状图文档。

















