【问题标题】:How to get chart info from an Excel spreadsheet using Apache POI?如何使用 Apache POI 从 Excel 电子表格中获取图表信息?
【发布时间】:2011-04-08 18:28:44
【问题描述】:

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

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

XSSFSheet sheet = xwb.getSheetAt(0);

我还可以遍历包部分以检索图表部分,但我不明白我如何继续检索有关图表的任何信息?

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

【问题讨论】:

    标签: apache excel charts openxml apache-poi


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 从 r1090442 开始,您应该能够从 XSSFSheet 的 XSSFDrawing 轻松获取所有图表,希望对您有所帮助!
    • 谢谢。只是想知道,我已经下载了 3.8 beta 1 并且 XSSFSheet 中似乎没有 XSSFDrawing 成员?
    • 你想要的方法是poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/…。您可能还需要一个夜间 svn 构建,用于从绘图中获取图表的新方法。
    • 感谢@Gagravarr 我从 SVN 获得了最新消息。现在的问题是弄清楚如何提取系列值等。非常感谢:)
    • @KevinL getDrawingPatriarch() 可能会更好——这样可以避免在没有空绘图时创建新的空绘图
    【解决方案2】:

    您可以使用XSSFDrawing将图表数据读取为XML

    喜欢

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

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

    drawing.getCharts();
    

    你可以添加Iterator来浏览图表

    【讨论】:

      【解决方案3】:

      我不知道您的问题的确切答案,但 OpenXML SDK 2.0 带有一个 DocumentReflector.exe 工具,它将准确地向您展示图表是如何定义的(包括 SpreadsheetML 和 DrawingML 包之间的所有关系)。 this article 有更多关于这个工具的信息。

      【讨论】:

        【解决方案4】:

        是的,使用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

        【讨论】:

        • 我如何获得图表的位置和使用的颜色?
        • 取决于你有什么类型的图表,只是你的方法应该是,首先在某个地方打印XML,仔细分析那个XML,你肯定会在图表中找到一个共同的模式(从中你可以得到位置),您可能还会发现图表的颜色(关于颜色我不是 100% 确定)。获取所有信息后,使用 CT* 类获取这些属性的值。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-18
        • 1970-01-01
        相关资源
        最近更新 更多