问题描述
我正在使用Apache POI Java库(v4.1.1)创建包括Excel图表在内的精彩Word文档.对于Excel图表,我使用Excel模板,并且通过Apache POI库通过
I am using the Apache POI Java library (v4.1.1) to create wonderfull Word documents including Excel Charts. For the Excel Charts I use an Excel template and via the Apache POI library access the charts in the Word document via
List<XWPFChart> chartList = wordDoc.getCharts();
这对于条形图/列形图/线形图等工作正常.但是,通过这种方法我无法获得瀑布图.因此,我想知道是否有人对此有解决方案?我看到一些选择;
This is working fine for Bar / Column / Line etc. I can't get, however, the Waterfall chart via this method. So, I am wondering if anybody has got a solution for this? I see some options;
- 等待直到Apache POI支持
- 创建另一个图表类型作为模板,通过getCharts方法访问该图表并以编程方式更改该图表类型
- 创建我自己的代码以生成瀑布图
我希望有人已经对第二种甚至第三种选择有经验吗?
I am hoping somebody already has experience with the second or even third option?
推荐答案
XWPFChart
的类型为 application/vnd.openxmlformats-officedocument.drawingml.chart + xml
图表的类型为 application/vnd.ms-office.chartex + xml
.这是因为瀑布图是扩展的图表类型,在 apache poi
提供的 Office Open XML
版本中不可用.我不相信 apache poi
在不久的将来会提供这种扩展的图表,因为它甚至不提供类型为 application/vnd.openxmlformats-officedocument.drawingml.chart + xml 的所有本机图表.代码>到现在为止.
XWPFChart
is of type application/vnd.openxmlformats-officedocument.drawingml.chart+xml
while waterfall chart is of type application/vnd.ms-office.chartex+xml
. This is because the waterfall chart is an extended chart type which is not available in versions of Office Open XML
which apache poi
provides. I don't believe apache poi
will provide such extended charts in near future since it not even provides all native charts of type application/vnd.openxmlformats-officedocument.drawingml.chart+xml
until now.
因此,到目前为止,只能通过直接更改XML在非常低的级别上处理那些图表类型的选项.我已经在此处,并在此处.
So until now there only is the option to work on those chart types on very low level by changing the XML directly. I have shown this for a sunburst chart here How to change the graphical attributes of a point in an Excel sunburst chart through Apache POI and here How to set the text attributes of the individual data labels in an Excel Sunburst Chart through Apache POI?.
以下工作草案提供了一个非常基本的类 XWPFChartEx
,到目前为止,该类仅提供了方法 getChartExXmlObject
,该方法返回扩展图表的普通 XML
作为 XmlObject
.可以使用低级 XML
方法以编程方式更改此 XML
.因为 XWPFChartEx
扩展了 POIXMLDocumentPart
,所以它的 commit
方法会将更改写入新的 Word
文档中,而同时document.write(out)
.并且它提供了 getWorkbookPart
,它返回包含图表数据的 XSSFWorkbook
的 PackagePart
.如果存在,此工作簿的内容也将被更改.
Following working draft provides a very basic class XWPFChartEx
which up to now only provides method getChartExXmlObject
which returns the plain XML
of the extended chart as a XmlObject
. This XML
could be programmatically changed using low level XML
methods. Because XWPFChartEx
extends POIXMLDocumentPart
, it's commit
method will write that changes into the new Word
document then while document.write(out)
. And it provides getWorkbookPart
which returns the PackagePart
of the XSSFWorkbook
containing the chart's data. This workbook content also would mus be changed, if present.
文件 Waterfall_Chart.docx
必须至少具有一个瀑布图.
The file Waterfall_Chart.docx
must have at least one waterfall chart.
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);
}
}
}
这篇关于使用Apache POI更新瀑布图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!