Created attachment 34014 [details] CTBarChar use ooxml-schemas-1.1.jar Exception in thread "main" org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException: Rule M2.4 exception : this error should NEVER happen! Please raise a bug at https://bz.apache.org/bugzilla/enter_bug.cgi?product=POI and attach a file that triggers it, thanks! at org.apache.poi.openxml4j.opc.internal.ContentTypeManager.getContentType(ContentTypeManager.java:343) at org.apache.poi.openxml4j.opc.internal.ContentTypeManager.removeContentType(ContentTypeManager.java:256) at org.apache.poi.openxml4j.opc.OPCPackage.removePart(OPCPackage.java:958) at org.apache.poi.openxml4j.opc.PackagePart.getOutputStream(PackagePart.java:522) at ExcelWritingbug.updateBarChartTemplate(ExcelWritingbug.java:131) at ExcelWritingbug.main(ExcelWritingbug.java:36) //////////////////////////////////////////// program import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XSLFChart; import org.apache.poi.xslf.usermodel.XSLFSlide; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.openxmlformats.schemas.drawingml.x2006.chart.*; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; public class ExcelWritingbug { public static void main(String[] args) { String inputPath = "e:\\excel_writing_bug.pptx"; String outputPath = "e:\\excel_writing_bug_output.pptx"; int slideNumber = 1; String templateChartTitle = "Title"; String newChartTitle = "Title updated"; Map<String, Double> chartValues = new HashMap<String, Double>(); chartValues.put("Windows", 5d); chartValues.put("Solaris", 2d); chartValues.put("Unix", 8d); chartValues.put("Linux", 5d); try { updateBarChartTemplate(inputPath, outputPath, slideNumber, templateChartTitle, newChartTitle, chartValues); } catch (IOException e) { e.printStackTrace(); } } public static void updateBarChartTemplate(String inputPath, String outputPath, int slideNumber, String templateChartTitle, String newChartTitle, Map<String, Double> chartValues) throws IllegalStateException, IOException{ XMLSlideShow pptx = null; try { pptx = new XMLSlideShow(new FileInputStream(inputPath)); //获取第一个ppt页面 // XSLFSlide slide = pptx.getSlides().get(0); //pptx = new XMLSlideShow(new FileInputStream(inputPath)); //遍历第一页元素找到图表 /* XSLFChart chart = null; for(POIXMLDocumentPart part : slide.getRelations()){ if(part instanceof XSLFChart){ chart = (XSLFChart) part; break; } } if (chart == null) { return "no chart"; } POIXMLDocumentPart xlsPart = chart.getRelations().get(0); */ XSLFChart chart = getChartFromTitle(inputPath, slideNumber, templateChartTitle); if (chart == null) throw new IllegalStateException("chart not found in the template"); // embedded Excel workbook that holds the chart data POIXMLDocumentPart xlsPart = chart.getRelations().get(0); XSSFWorkbook wb = new XSSFWorkbook(); OutputStream xlsOut = null; try { XSSFSheet sheet = wb.createSheet(); CTChart ctChart = chart.getCTChart(); CTPlotArea plotArea = ctChart.getPlotArea(); CTBarChart barChart = plotArea.getBarChartArray(0); //Bar Chart Series CTBarSer ser = barChart.getSerArray(0); // Series Text CTSerTx tx = ser.getTx(); tx.getStrRef().getStrCache().getPtArray(0).setV(newChartTitle); sheet.createRow(0).createCell(1).setCellValue(newChartTitle); String titleRef = new CellReference(sheet.getSheetName(), 0, 1, true, true).formatAsString(); tx.getStrRef().setF(titleRef); // Category Axis Data CTAxDataSource cat = ser.getCat(); CTStrData strData = cat.getStrRef().getStrCache(); // Values CTNumDataSource val = ser.getVal(); CTNumData numData = val.getNumRef().getNumCache(); strData.setPtArray(null); // unset old axis text numData.setPtArray(null); // unset old values // set model int idx = 0; int rownum = 1; for (Map.Entry<String, Double> entry : chartValues.entrySet()) { String key = entry.getKey(); String value = String.valueOf(entry.getValue()); CTNumVal numVal = numData.addNewPt(); numVal.setIdx(idx); numVal.setV(value); CTStrVal sVal = strData.addNewPt(); sVal.setIdx(idx); sVal.setV(key); idx++; XSSFRow row = sheet.createRow(rownum++); row.createCell(0).setCellValue(key); row.createCell(1).setCellValue(Double.valueOf(value)); } numData.getPtCount().setVal(idx); strData.getPtCount().setVal(idx); String numDataRange = new CellRangeAddress(1, rownum - 1, 1, 1).formatAsString(sheet.getSheetName(), true); val.getNumRef().setF(numDataRange); String axisDataRange = new CellRangeAddress(1, rownum - 1, 0, 0).formatAsString(sheet.getSheetName(), true); cat.getStrRef().setF(axisDataRange); // updated the embedded workbook with the data xlsOut = xlsPart.getPackagePart().getOutputStream(); try { wb.write(xlsOut); } finally { xlsOut.close(); } FileOutputStream fos = new FileOutputStream(outputPath); try { pptx.write(fos); } finally { fos.close(); } } finally { wb.close(); } } finally { if (pptx != null) pptx.close(); } } public static XSLFChart getChartFromTitle(String inputPath, int slideNumber, String templateChartTitle) throws IOException { XMLSlideShow pptx = null; try { pptx = new XMLSlideShow(new FileInputStream(inputPath)); XSLFSlide slide = pptx.getSlides().get(slideNumber - 1); // find chart in the slide XSLFChart chart = null; for (POIXMLDocumentPart part : slide.getRelations()) { if (part instanceof XSLFChart) { chart = (XSLFChart) part; CTChart ctChart = chart.getCTChart(); CTTitle ctTitle = ctChart.getTitle(); CTTx titleTx = ctTitle.getTx(); CTTextBody body = titleTx.getRich(); CTTextParagraph paragraph = body.getPArray(0); String chartTitle = paragraph.getRArray(0).getT(); if (chartTitle.equalsIgnoreCase(templateChartTitle)) { break; } else { chart = null; } } } return chart; } finally { if (pptx != null) pptx.close(); } } }
What version of POI are you using? Could you try this again with ooxml-schemas-1.3, making sure to delete any duplicate ooxml-schemas and poi-ooxml-schemas on your classpath? https://poi.apache.org/faq.html#faq-N10025
Created attachment 34015 [details] simplified unit test I cut your example down to the attached unit test. The source of the problem is in getChartFromTitle. You're opening the slideshow, creating an XSLFChart object, and closing the slideshow. Then you're passing the XSLFChart object that belongs to the closed slideshow back to updateBarChartTemplate. Naturally, once you've closed a resource, any subsequent operations performed on that resource are likely to fail. Perhaps we could give a more informative error message here, like "could not access package part output stream because the underlying document has been closed.
Created attachment 34016 [details] simplified unit test
Set to enhancement as original problem is explained by closing the Slideshow too early and only some improved error reporting is remaining to be done.
*** This bug has been marked as a duplicate of bug 60102 ***