
使用 apache poi 在 word(.docx)中生成柱状图时,若文档无法被 microsoft word 或 libreoffice 正常打开,通常因图表系列缺少必需的标题、坐标轴配置不当或填充色缺失所致;本文提供完整可运行示例及关键修复要点。
使用 apache poi 在 word(.docx)中生成柱状图时,若文档无法被 microsoft word 或 libreoffice 正常打开,通常因图表系列缺少必需的标题、坐标轴配置不当或填充色缺失所致;本文提供完整可运行示例及关键修复要点。
在 Apache POI 中通过 XWPFChart 创建嵌入式图表看似简单,但 Word 的 OOXML 规范对图表结构有严格要求。常见错误——如文档生成后双击提示“文件已损坏”或“无法打开”——绝大多数源于 图表系列(Series)未设置标题。Word 和 LibreOffice 均将 series.setTitle(...) 视为必填项,即使传入空字符串也不可省略;原代码中该行被注释,正是导致文件无效的主因。
此外,以下配置虽非强制,但直接影响图表渲染效果与兼容性:
- ✅ 必须设置系列标题:series.setTitle("Fruit Sales", null) —— null 表示无自定义字体格式,但标题文本不可为空。
- ✅ 合理配置坐标轴交叉点:调用 valueAxis.setCrosses(AxisCrosses.AUTO_ZERO) 确保数值轴在 0 刻度处与分类轴相交,避免负值区域异常。
- ✅ 设置 AxisCrossBetween.BETWEEN:使数值轴穿过分类轴的“类别之间”,而非“类别上”,否则首尾柱形仅显示一半。
- ✅ 明确指定柱形方向:((XDDFBarChartData)data).setBarDirection(BarDirection.COL)(垂直柱状图)或 BarDirection.BAR(水平条形图),避免默认行为不一致。
- ✅ 手动设置填充色:尤其对 LibreOffice 至关重要,因其不自动应用默认色。推荐使用 solidFillSeries(...) 辅助方法:
private static void solidFillSeries(XDDFChartData.Series series, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setFillProperties(fill);
series.setShapeProperties(properties);
}
完整可运行示例(已验证兼容 Apache POI 5.2.4+):
使用tbot机器ID身份文件配合tsh CLI,通过Teleport访问控制SSH登录托管主机或执行远程命令。
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");
// 添加数据系列 —— 标题为 REQUIRED 字段!
XDDFChartData.Series series = data.addSeries(catData, valData);
series.setTitle("Findings Count", null); // ← 关键:不可省略!
// 设置填充色(提升 LibreOffice 兼容性)
solidFillSeries(series, PresetColor.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);
}
}</double></string>
⚠️ 注意事项:
- 使用 try-with-resources 确保 FileOutputStream 正确关闭(示例已优化);
- Apache POI 5.2.0+ 要求 xmlbeans 和 commons-collections4 等依赖完整,建议通过 Maven 管理;
- 若需多系列图表,请为每个 series.setTitle(...) 提供唯一标题,并分别调用 solidFillSeries(...) 设置不同颜色;
- 图表尺寸单位为 EMU(English Metric Unit),Units.EMU_PER_CENTIMETER 是可靠换算常量。
遵循以上规范,即可生成完全符合 Office Open XML 标准、能被 Word、WPS 和 LibreOffice 无缝打开的含柱状图 Word 文档。










