是否可以使用Apache POI从Office 2007 (xlsx OpenXML)电子表格中提取图表信息?我已经设法读取了电子表格,甚至得到了指向图表的部分,但不确定如何从这部分中获取任何信息,例如图表类型、图表数据等。
XSSFWorkbook xwb = new XSSFWorkbook("charts_lines.xlsx");
XSSFSheet sheet = xwb.getSheetAt(0);
我也可以通过迭代包的部分来检索图表部分,但我不知道如何继续检索关于图表的任何信息?
注意,我对使用POI创建图表不感兴趣,只是尽可能多的读取图表信息......我也没有保存一个xlsx。我只是想提取线的颜色、标签、数据、图表类型(饼状、线状、条状等)。
目前还没有高级别的表示方法,所以你需要下放到xmlbeans级别,并使用低级别的CT*对象。
对于图表表,有 XSSFChartSheet 这将给你一个CTChartsheet对象,它有一点信息。
对于这两个 XSSFChart 和 XSSFChartSheet (常规和图表表),你需要通过图纸来获取图表。每个有图表的工作表都应该有一个Drawing,而图表是从Drawing中获得链接的,而不是工作表本身。
从r1090442开始(所以POI 3.8或更新),在XSSFDrawing上有一个方法可以给你所有的XSSFChart对象(是chartschart#.xml部分的封装器)。如果你是在一个非常非常老的POI版本上,使用CTDrawing来获取图表的细节,抓取对应的chartschart#.xml部分,然后让xmlbeans给你它的CT对象。无论哪种方式都能让你得到标题、类型、数据范围等。
虽然这有点麻烦,所以如果你能找到一些好的CTChart对象,请考虑给POI发送一个补丁!你可以使用XML来读取图表数据。
你可以使用以下方法读取XML图表数据 XSSFDrawing
喜欢
XSSFDrawing drawing = ((XSSFSheet)sheet).createDrawingPatriarch();
System.out.println(drawing.getCTDrawing().toString());
将整个图表打印成 XMl
并使用
drawing.getCharts();
你可以在其中添加Iterator来浏览图表。
我不知道你的问题的确切答案,但是OpenXML SDK 2.0自带了一个 DocumentReflector.exe
工具,它将向您展示图表是如何定义的(包括SpreadsheetML和DrawingML包之间的所有关系)。关于这个工具的更多信息,请参见 本文.
是的,它可以通过以下方式读取任何类型的图表 Apache POI. 但是在读取任何图表信息之前,你需要知道你所接收的XML字符串,因为这可能是基于不同的图表类型,即饼状图、线状图、条状图、散点图或混合图(两个或多个图表的组合)等。因此,对于不同类型的图表,你的方法会有所不同。
对于一个简单的条形图,比如这样。
你的XML将看起来像这样。
<xml-fragment ...>
<c:title>
<c:tx>
<c:rich>
...
<a:p>
...
<a:r>
...
<a:t>Employee Salary</a:t>
</a:r>
</a:p>
</c:rich>
</c:tx>
...
</c:title>
...
<c:plotArea>
...
<c:barChart>
...
<c:ser>
...
<c:cat>
<c:strRef>
...
<c:strCache>
<c:ptCount val="5"/>
<c:pt idx="0">
<c:v>Tom</c:v>
</c:pt>
<c:pt idx="1">
<c:v>John</c:v>
</c:pt>
<c:pt idx="2">
<c:v>Harry</c:v>
</c:pt>
<c:pt idx="3">
<c:v>Sam</c:v>
</c:pt>
<c:pt idx="4">
<c:v>Richa</c:v>
</c:pt>
</c:strCache>
</c:strRef>
</c:cat>
<c:val>
<c:numRef>
...
<c:numCache>
<c:formatCode>"$"#,##0</c:formatCode>
<c:ptCount val="5"/>
<c:pt idx="0">
<c:v>1000</c:v>
</c:pt>
<c:pt idx="1">
<c:v>700</c:v>
</c:pt>
<c:pt idx="2">
<c:v>300</c:v>
</c:pt>
<c:pt idx="3">
<c:v>900</c:v>
</c:pt>
<c:pt idx="4">
<c:v>800</c:v>
</c:pt>
</c:numCache>
</c:numRef>
</c:val>
...
</c:ser>
...
</c:barChart>
...
</c:plotArea>
...
</xml-fragment>
现在基于上面的XML字符串,我们可以使用CT*类和它的各种方法来使用Apache POI遍历整个XML。让我们看看如何读取 图表标题, 标签(员工姓名) 和 系列(雇员薪金) 使用POI。
Workbook workbook = new XSSFWorkbook(new File(PATH));
Sheet sheet = workbook.getSheet("GraphSheet");
XSSFSheet xsheet = (XSSFSheet) sheet;
XSSFDrawing drawing = xsheet.getDrawingPatriarch();
if (drawing != null) {
List<XSSFChart> charts = drawing.getCharts();
for (int chartIndex = 0; charts != null && chartIndex < (charts.size()); chartIndex++) {
XSSFChart chart = charts.get(chartIndex);
CTChart chart2 = chart.getCTChart();
CTPlotArea plot = chart2.getPlotArea();
System.out.println("Chart Title :" + chart2.getTitle().getTx().getRich().getPArray(0).getRArray(0).getT());
CTBarSer[] ctScaSerList = plot.getBarChartArray(0).getSerArray();
for (CTBarSer ctLineSer : ctScaSerList) {
CTStrVal[] ctStrVals = ctLineSer.getCat().getStrRef().getStrCache().getPtArray();
for (int i = 0; i < ctStrVals.length; i++) {
System.out.print(ctStrVals[i].getV() + ",");
}
System.out.println();
CTNumVal[] ctXNumVal = ctLineSer.getVal().getNumRef().getNumCache().getPtArray();
for (int i = 0; i < ctXNumVal.length; i++) {
System.out.print(ctXNumVal[i].getV() + ",");
}
}
}
}
Console:
Chart Title :Employee Salary
Tom,John,Harry,Sam,Richa,
1000,700,300,900,800,
注:这里,我们的想法是 首先读取XML字符串(因为可能根据你的图形类型而不同)和 然后据此遍历整个XML.