提问者:小点点

使用ApachePOI更新瀑布图


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

List<XWPFChart> chartList = wordDoc.getCharts();  

这适用于条形图/柱形图/折线图等。但是,我无法通过这种方法获得瀑布图。所以,我想知道是否有人对此有解决方案?我看到了一些选项;

  1. 等待直到ApachePOI支持它
  2. 创建另一种图表类型作为模板,通过getCharts方法访问该图表并以编程方式更改图表类型
  3. 创建我自己的代码来生成瀑布图

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


共1个答案

匿名用户

XWPFChart的类型是application/vnd. openxmlforms-officedocument.绘图ml.图表xml,而瀑布图的类型是application/vnd.ms-office.chartex xml。这是因为瀑布图是扩展的图表类型,在apache poi提供的Office OpenXML版本中不可用。我不相信apache poi会在不久的将来提供这样的扩展图表,因为它甚至还没有提供application/vnd.openxmlforms-officedocument.绘图ml.图表xml类型的所有本地图表。

因此,到目前为止,只有通过直接更改XML在非常低的级别上处理这些图表类型的选项。我在这里展示了太阳爆发图表如何通过Apache更改Excel太阳爆发图表中点的图形属性POI以及如何通过ApachePOI设置Excel太阳爆发图表中单个数据标签的文本属性?。

以下工作草案提供了一个非常基本的类XWPFChartEx,到目前为止,它只提供方法getChartExXmlObject,它将扩展图表的纯XML返回为XmlObject。这个XML可以使用低级XML方法以编程方式更改。因为XWPFChartEx扩展了POIXMLDocumentPart,它的提交方法将更改写入新的Word文档,然后文档. write(out)。它提供了getWorkbookPart,它返回包含图表数据的XSSFWorkbookPackagePart。如果存在,此工作簿内容也将被更改。

Waterfall_Chart. 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);
  }
 }
}