Java 使用ApachePOI更新瀑布图

Java 使用ApachePOI更新瀑布图,java,excel,apache-poi,Java,Excel,Apache Poi,我正在使用ApachePOIJava库(v4.1.1)创建wonderfull Word文档,包括Excel图表。对于Excel图表,我使用Excel模板,并通过ApachePOI库访问Word文档中的图表 List<XWPFChart> chartList = wordDoc.getCharts(); List chartList=wordDoc.getCharts(); 这对于条/列/线等来说效果很好。但是,我无法通过这种方法获得瀑布图。所以,我想知道是否有人能解决这个问

我正在使用ApachePOIJava库(v4.1.1)创建wonderfull Word文档,包括Excel图表。对于Excel图表,我使用Excel模板,并通过ApachePOI库访问Word文档中的图表

List<XWPFChart> chartList = wordDoc.getCharts();  
List chartList=wordDoc.getCharts();
这对于条/列/线等来说效果很好。但是,我无法通过这种方法获得瀑布图。所以,我想知道是否有人能解决这个问题?我看到了一些选择

  • 等待Apache POI支持它
  • 创建另一个图表类型作为模板,通过getCharts方法访问该图表,并以编程方式更改图表类型
  • 创建自己的代码以生成瀑布图

  • 我希望有人已经有了第二个甚至第三个选项的经验?

    XWPFChart
    application/vnd.openxmlformats of icedocument.drawingml.chart+xml
    类型,而瀑布图是
    application/vnd.ms office.chartex+xml
    类型。这是因为瀑布图是一种扩展的图表类型,在
    officeopenxml
    版本中不可用,而
    apachepoi
    提供了这种类型的图表。我不相信在不久的将来,
    ApachePOI
    会提供这样的扩展图表,因为直到现在,它还没有提供所有类型为
    application/vnd.openxmlformats of cedocument.drawingml.chart+xml
    的本地图表


    因此,到目前为止,只有通过直接更改XML,才能在非常低的级别上处理这些图表类型。我在这里和这里展示了一张太阳暴流图

    下面的工作草案提供了一个非常基本的类
    XWPFChartEx
    ,到目前为止,它只提供了方法
    getChartExXmlObject
    ,该方法将扩展图表的普通
    XML
    作为
    XmlObject
    返回。此
    XML
    可以使用低级
    XML
    方法以编程方式更改。由于
    XWPFChartEx
    扩展了
    poimmldocumentpart
    ,因此
    commit
    方法将在
    document.write(out)
    时写入新的
    Word
    文档。它还提供了
    getWorkbookPart
    ,返回包含图表数据的
    xssf工作簿的
    PackagePart
    。此工作簿内容也将更改(如果存在)

    文件
    瀑布图.docx
    必须至少有一个瀑布图

    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.FileOutputStream;
    import java.io.FileInputStream;
    
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFRelation;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import org.apache.poi.ss.usermodel.*;
    
    import org.apache.poi.ooxml.POIXMLDocumentPart;
    import org.apache.poi.ooxml.POIXMLRelation;
    import org.apache.poi.openxml4j.opc.PackagePart;
    
    import org.apache.xmlbeans.XmlObject;
    
    public class WordGetWaterfallChart {
    
     static XWPFChartEx getFirstXWPFChartEx(XWPFDocument document) throws Exception {
      XWPFChartEx xwpfChartEx = null;
      for (POIXMLDocumentPart dpart : document.getRelations()) {
       PackagePart ppart = dpart.getPackagePart();
       if ("application/vnd.ms-office.chartex+xml".equals(ppart.getContentType())) {
        xwpfChartEx = new XWPFChartEx(dpart);
        String rId = document.getRelationId(dpart);
        document.addRelation(
         rId, 
         new XSSFChartExRelation(
          "application/vnd.ms-office.chartex+xml",
          "http://schemas.microsoft.com/office/2014/relationships/chartEx",
          "/word/charts/chartEx#.xml"),
          xwpfChartEx
        );
        return xwpfChartEx;
       }
      }
      return xwpfChartEx;
     }
    
     public static void main(String[] args) throws Exception {
    
      XWPFDocument document = new XWPFDocument(new FileInputStream("Waterfall_Chart.docx"));
    
      XWPFChartEx waterfallChart = getFirstXWPFChartEx(document);
      System.out.println(waterfallChart.getChartExXmlObject());
      //TODO: change the XML
    
      System.out.println(waterfallChart.getWorkbookPart());
      if (waterfallChart.getWorkbookPart() != null) {
       XSSFWorkbook workbook = new XSSFWorkbook(waterfallChart.getWorkbookPart().getInputStream());
       for (Sheet sheet : workbook) {
        for (Row row : sheet) {
         for (Cell cell : row) {
          System.out.println(cell);
          //TODO: change the cell contents
         }
        }
       }
       OutputStream wbOut = waterfallChart.getWorkbookPart().getOutputStream();
       workbook.write(wbOut);
       wbOut.close();
       workbook.close();
      }
    
      FileOutputStream out = new FileOutputStream("Waterfall_Chart_Changed.docx");
      document.write(out);
      out.close();
      document.close();
     }
    
     private static class XWPFChartEx extends POIXMLDocumentPart {
    
      private XmlObject chartExXmlObject;
      private PackagePart workbookPart;
    
      private XWPFChartEx(POIXMLDocumentPart dpart) throws Exception {
       super(dpart.getPackagePart());
       this.chartExXmlObject = XmlObject.Factory.parse(dpart.getPackagePart().getInputStream());
       for (POIXMLDocumentPart.RelationPart rpart : dpart.getRelationParts()) {
        if ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
             .equals(rpart.getDocumentPart().getPackagePart().getContentType())) {
         this.addRelation(
          rpart.getRelationship().getId(), 
          XWPFRelation.getInstance(rpart.getRelationship().getRelationshipType()),
          rpart.getDocumentPart()
         );
         this.workbookPart = rpart.getDocumentPart().getPackagePart();
        }
       }
      }
    
      private XmlObject getChartExXmlObject() {
       return this.chartExXmlObject;
      }
    
      private PackagePart getWorkbookPart() {
       return this.workbookPart;
      }
    
      @Override
      protected void commit() throws IOException {
       PackagePart part = getPackagePart();
       OutputStream out = part.getOutputStream();
       chartExXmlObject.save(out);
       out.close();
      }
     }
    
     private static class XSSFChartExRelation extends POIXMLRelation {
      private XSSFChartExRelation(String type, String rel, String defaultName) {
       super(type, rel, defaultName);
      }
     }
    }
    

    XWPFChart
    类型为
    application/vnd.openxmlformats of icedocument.drawingml.chart+xml
    ,而瀑布图类型为
    application/vnd.ms office.chartex+xml
    。这是因为瀑布图是一种扩展的图表类型,在
    officeopenxml
    版本中不可用,而
    apachepoi
    提供了这种类型的图表。我不相信在不久的将来,
    apachepoi
    会提供这样的扩展图表,因为到目前为止,它甚至还没有提供所有的本地图表。因此,到目前为止,只有通过直接更改
    XML
    来在非常低的级别上处理这些图表类型的选项。我在这里和这里展示了一张太阳暴流图。嗨,阿克塞尔,谢谢你的快速回复。我看了你关于sunburst Excel图表的答案。我的问题稍有不同,我用的是Word。在Word中,由于您的原因,我目前无法访问瀑布图或您提到的
    vnd.ms office.chartex+xml类型的图表。棘手的部分是我现在没有一个模板图表可以开始改变,就像你和sunburst图表分享的例子一样。通过scatch的模板在Word中生成此类图表的最佳方式是什么?嗨,Axel,再次感谢您的回复。实际上,我已经在另一个方向上访问不受支持图表的Excel工作表。这是可以做到的,数据也可以修改。我发现令人伤心的是,即使基础数据发生了更改,图表也不会直接刷新。。。单击“编辑数据”将刷新图表,但这将是一种烦人的用户体验。你有解决办法吗?如果是这样,我将坚持这一方针。如果没有,我将尝试实现您刚才发布的答案。@Ivo Sturm:要更改图表数据,必须始终更改
    /word/charts/chartEx*.XML的
    XML
    ,以及
    /word/embeddings/*.xlsx
    中的
    Excel
    数据。请参见我的代码示例中的
    //TODO
    。如果仅更改了两者中的一个,则
    Word
    不会显示更新的图表。