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

发布于 2024-10-31 03:25:25 字数 384 浏览 7 评论 0原文

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

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

XSSFSheet sheet = xwb.getSheetAt(0);

我还可以迭代包部分来检索图表部分,但我不知道如何继续检索有关图表的任何信息?

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

Is it possible to extract chart information from an Office 2007 (xlsx / OpenXML) spreadsheet using Apache POI? I've managed to read in the spreadsheet and even get the part that refers to the chart but not sure how I can retrieve any info from this part e.g. Type of chart, chart data etc.

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

XSSFSheet sheet = xwb.getSheetAt(0);

I can also iterate through the package parts to retrieve the chart part, but I don't see how I then go on to retrieve any info about the chart?

Note, I'm not interested in creating charts using POI, just read as much chart info as is possible to do...I'm also not saving an xlsx. I simply wish to extract line colours, labels, data, chart type (pie, line, bar etc.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

秋凉 2024-11-07 03:25:25

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

对于图表表,XSSFChartSheet 将为您提供一个 CTChartsheet 对象,其中包含一些信息。

对于 XSSFChartXSSFChartSheet(常规工作表和图表工作表),您需要通过绘图来获取图表。每张带有图表的工作表都应该有一个绘图,并且图表从绘图链接,而不是工作表本身。

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

虽然这有点繁琐,所以如果您在使用 CTChart 对象方面得到了很好的解决方案,请考虑向 POI 发送补丁!

There isn't a high level representation at the moment, so you'll need to drop down into the xmlbeans level and work with the low level CT* objects.

For Chart Sheets, there's XSSFChartSheet which will give you a CTChartsheet object, which has a little bit of info.

For both XSSFChart and XSSFChartSheet (regular and chart sheets), you'll need to go via the drawings to get the charts. Each sheet with charts on it should have one Drawing, and the charts get linked from the drawing, rather than the sheet itself.

As of r1090442 (so POI 3.8 or newer), there's a method on XSSFDrawing to give you all the XSSFChart objects (which are wrappers around the /charts/chart#.xml part). If you're on a really really old version of POI, use the CTDrawing to get the details of the chart, grab the /charts/chart#.xml part that corresponts, and then have xmlbeans give you the CT objects for it. Either way that'll let you get the titles, types, data ranges etc.

It is a bit fiddly though, so do please consider sending in a patch to POI if you get something good worked out for working with the CTChart objects!

初心 2024-11-07 03:25:25

您可以使用 XSSFDrawing 以 XML 形式读取图表数据,

例如

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

将整个图表打印为 XMl 并且还

drawing.getCharts();

可以使用它添加迭代器来浏览图表

you can read chart data as XML using XSSFDrawing

like

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

will print whole chart as XMl and also using

drawing.getCharts();

you can add Iterator to it to browse chart

风柔一江水 2024-11-07 03:25:25

我不知道您问题的确切答案,但是 OpenXML SDK 2.0 附带了一个 DocumentReflector.exe 工具,该工具将向您准确显示图表的定义方式(包括 SpreadsheetML 和DrawingML 包)。 本文中提供了有关此工具的更多信息。

I don't know the exact answer to your question, but the OpenXML SDK 2.0 comes with a DocumentReflector.exe tool that will show you exactly how the chart is defined (including all relationships between the SpreadsheetML and the DrawingML packages). There is some more info on this tool in this article.

你曾走过我的故事 2024-11-07 03:25:25

是的,可以使用 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() + ",");
            }

        }
    }
}

控制台:

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

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

Yes, It is possible to read any type of chart using Apache POI. But Before reading any chart information you need to know what XML string you are receiving because this could be different based on the chart type i.e. pie, line, bar, scatter or mixed (a combination of two or more) charts, etc. Therefore you approach will be different for different type of chart.

For a simple bar chart like this:

enter image description here

Your XML will look something like this:

<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>

Now based on the above XML String we can use CT* classes and its various methods to traverse through the whole XML using Apache POI. Let's see how to read Chart Title, Labels(Employee names) and Series(Employee salaries) using 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,

Note: Here, the idea is to first read the XML String(because could be different based on your graph type) and then traverse the whole XML accordingly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文