如何使用Apache POI从Excel电子表格中获取图表信息?

时间:2011-04-08 18:28:45

标签: apache excel charts openxml apache-poi

是否可以使用Apache POI从Office 2007(xlsx / OpenXML)电子表格中提取图表信息?我已经成功阅读了电子表格,甚至获得了引用图表的部分,但不确定如何从此部分检索任何信息,例如图表类型,图表数据等。

XSSFWorkbook xwb = new XSSFWorkbook("charts_lines.xlsx");

XSSFSheet sheet = xwb.getSheetAt(0);

我也可以遍历包裹部分来检索图表部分,但是我不知道如何继续检索有关图表的任何信息?

注意,我对使用POI创建图表不感兴趣,只读取尽可能多的图表信息...我也没有保存xlsx。我只想提取线条颜色,标签,数据,图表类型(饼图,线条,条形图等)

4 个答案:

答案 0 :(得分:6)

目前没有高级别的表示,因此您需要下载到xmlbeans级别并使用低级CT *对象。

对于图表表格,有 XSSFChartSheet ,它会为您提供一个CTChartsheet对象,它有一些信息。

对于 XSSFChart XSSFChartSheet (常规和图表),您需要通过图纸来获取图表。每张带有图表的图表都应该有一个图纸,图表会从图纸而不是图纸本身链接。

从r1090442开始(所以POI 3.8或更新版本),XSSFDrawing上有一个方法可以为您提供所有XSSFChart对象(它们是/charts/chart#.xml部分的包装器)。如果您使用的是非常旧版本的POI,请使用CTDrawing获取图表的详细信息,获取对应的/charts/chart#.xml部分,然后让xmlbeans为您提供CT对象。无论哪种方式,都可以让你获得标题,类型,数据范围等。

虽然这有点繁琐,但如果你得到了一些有关CTChart对象的好处,请考虑向POI发送补丁!

答案 1 :(得分:4)

您可以使用XSSFDrawing

将图表数据读取为XML

喜欢

 XSSFDrawing drawing = ((XSSFSheet)sheet).createDrawingPatriarch();
        System.out.println(drawing.getCTDrawing().toString());

将整个图表打印为XMl并使用

drawing.getCharts();

您可以添加Iterator来浏览图表

答案 2 :(得分:2)

我不知道您问题的确切答案,但OpenXML SDK 2.0附带了DocumentReflector.exe工具,可以准确显示图表的定义方式(包括SpreadsheetML和DrawingML包之间的所有关系) )。 this article中有关于此工具的更多信息。

答案 3 :(得分:0)

是的,可以使用this library读取任何类型的图表。但是,在读取任何图表信息之前,您需要知道接收的XML字符串,因为根据图表类型(饼形图,折线图,条形图,散点图或混合(两个或多个)的图表)的不同,该字符串可能有所不同。因此,您对于不同类型的图表,方法会有所不同。

对于像这样的简单条形图:

Apache POI

您的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() + ",");
            }

        }
    }
}

控制台:

Chart Title :Employee Salary
Tom,John,Harry,Sam,Richa,
1000,700,300,900,800,

注意:这里的想法是首先读取XML字符串(因为根据您的图形类型可能会有所不同),然后然后遍历整个XML 。< / p>