使用Apache POI+Java生成PPT图表遇文件损坏修复提示求助
使用Apache POI生成PPT图表后打开需修复的问题排查
我参考相关代码用Apache POI和Java创建PPT图表,PPT文件能生成,但打开时弹出要求修复的窗口,求排查原因。
参考代码如下:
import java.io.FileOutputStream; import org.apache.poi.xslf.usermodel.*; import org.apache.poi.util.Units; import org.apache.poi.xddf.usermodel.*; import org.apache.poi.xddf.usermodel.chart.*; import java.awt.Rectangle; public class CreatePowerPointXDDFChart { public static void main(String[] args) throws Exception { try (XMLSlideShow slideShow = new XMLSlideShow()) { // create a new empty slide XSLFSlide slide = slideShow.createSlide(); // create chart XSLFChart chart = slideShow.createChart(); chart.setTitleText("Test Chart"); // set axis XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN); // define chart data for bar chart XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis); // add chart categories (x-axis data) String[] categories = new String[] { "Category 1", "Category 2", "Category 3" }; String categoryDataRange = chart.formatRange(new org.apache.poi.ss.util.CellRangeAddress(1, categories.length, 0, 0)); XDDFCategoryDataSource categoryData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0); // add chart values (y-axis data) Double[] values = new Double[] { 10.0, 20.0, 15.0 }; String valuesDataRange = chart.formatRange(new org.apache.poi.ss.util.CellRangeAddress(1, values.length, 1, 1)); XDDFNumericalDataSource<Double> valueData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange, 1); XDDFBarChartData bar = (XDDFBarChartData) data; bar.setBarDirection(BarDirection.BAR); // add series XDDFChartData.Series series = data.addSeries(categoryData, valueData); series.setTitle("Series 1", chart.setSheetTitle("Series 1", 1)); // plot chart chart.plot(data); // set chart dimensions !!Units are EMU (English Metric Units)!! Rectangle chartDimensions = new Rectangle( 100*Units.EMU_PER_POINT, 50*Units.EMU_PER_POINT, 400*Units.EMU_PER_POINT, 400*Units.EMU_PER_POINT); // add chart to slide slide.addChart(chart, chartDimensions); // Write the output to a file try (FileOutputStream fileOut = new FileOutputStream("./CreatePowerPointXDDFChart.pptx")) { slideShow.write(fileOut); } } } }
问题原因及修复方案
核心问题1:数据范围的行索引错误
代码中使用CellRangeAddress(1, categories.length, 0, 0),起始行设为1,但Apache POI处理图表关联的Excel数据时,行索引从0开始,该设置会导致数据引用超出有效范围,引发PPT结构损坏。
核心问题2:系列标题的工作表索引错误
调用chart.setSheetTitle("Series 1", 1)时,传入的工作表索引为1,但图表默认关联的工作表索引是0,引用不存在的工作表会破坏PPT内部结构。
修复后的完整代码
import java.io.FileOutputStream; import org.apache.poi.xslf.usermodel.*; import org.apache.poi.util.Units; import org.apache.poi.xddf.usermodel.*; import org.apache.poi.xddf.usermodel.chart.*; import java.awt.Rectangle; public class CreatePowerPointXDDFChart { public static void main(String[] args) throws Exception { try (XMLSlideShow slideShow = new XMLSlideShow()) { // create a new empty slide XSLFSlide slide = slideShow.createSlide(); // create chart XSLFChart chart = slideShow.createChart(); chart.setTitleText("Test Chart"); // set axis XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN); // define chart data for bar chart XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis); // add chart categories (x-axis data) String[] categories = new String[] { "Category 1", "Category 2", "Category 3" }; // 修复:行索引从0开始,对应数据的3行内容 String categoryDataRange = chart.formatRange(new org.apache.poi.ss.util.CellRangeAddress(0, categories.length-1, 0, 0)); XDDFCategoryDataSource categoryData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0); // add chart values (y-axis data) Double[] values = new Double[] { 10.0, 20.0, 15.0 }; // 修复:行索引从0开始 String valuesDataRange = chart.formatRange(new org.apache.poi.ss.util.CellRangeAddress(0, values.length-1, 1, 1)); XDDFNumericalDataSource<Double> valueData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange, 1); XDDFBarChartData bar = (XDDFBarChartData) data; bar.setBarDirection(BarDirection.BAR); // add series XDDFChartData.Series series = data.addSeries(categoryData, valueData); // 修复:使用默认工作表索引0 series.setTitle("Series 1", chart.setSheetTitle("Series 1", 0)); // plot chart chart.plot(data); // set chart dimensions !!Units are EMU (English Metric Units)!! Rectangle chartDimensions = new Rectangle( 100*Units.EMU_PER_POINT, 50*Units.EMU_PER_POINT, 400*Units.EMU_PER_POINT, 400*Units.EMU_PER_POINT); // add chart to slide slide.addChart(chart, chartDimensions); // Write the output to a file try (FileOutputStream fileOut = new FileOutputStream("./CreatePowerPointXDDFChart.pptx")) { slideShow.write(fileOut); } } } }
额外注意事项
- 确保使用Apache POI 4.1.2及以上版本,旧版本的XDDF图表模块存在较多兼容性问题,可能导致PPT结构异常。
- 若修复后仍有提示,可检查是否遗漏了图表元素的初始化(如轴标签),但上述修复已解决引发修复提示的核心问题。
内容的提问来源于stack exchange,提问作者praavi
相关产品推荐
相关产品推荐

