简体   繁体   English

java-具有多个图表的Apache POI绘图区域

[英]java - Apache POI plot area with multiple charts

I'm trying to use a PowerPoint file as template to produce another powerpoint replacing carts data. 我正在尝试使用PowerPoint文件作为模板来生成另一个替换购物车数据的PowerPoint。 To keep the look as similar as possible with the template, I'm just trying to replace data I need to replace, replicating all other data from the first CT*Ser of the chart. 为了使外观与模板尽可能相似,我只是尝试替换需要替换的数据,从图表的第一个CT*Ser复制所有其他数据。 Everything works fine with most kind of charts (at the moment I'm interested in pie charts, bar charts and line charts) when plot areas have only one chart inside. 当绘图区域内部仅包含一个图表时,所有类型的图表都可以正常工作(目前我对饼图,条形图和折线图感兴趣)。

When plot areas have more than one chart (in my case a BarChart with several series and a LineChart with just one ), something looks to be wrong and Microsoft PowerPoint can't open the file or part of it because it seems to be managed. 当绘图区域有多个图表时(在我的情况下为具有多个系列的BarChart,而仅有一个为LineChart ),则看起来有些错误,并且Microsoft PowerPoint无法打开文件或文件的一部分,因为它似乎是受管理的。

To accomplish this, I'm executing the following code for every chart, and chart type (graph is an object I use to keep references in template file). 为此,我对每个图表和图表类型执行以下代码(graph是我用来在模板文件中保留引用的对象)。

if (graph.getType().equals(CTArea3DChart.class.getName())) {
    CTArea3DChart c = plot.getArea3DChartArray()[graph.getIndex()];
    int removeSeries = c.getSerArray().length;
    for (int s = 0; s < graph.getSeries().size(); s++) {
        CTAreaSer ser = (CTAreaSer) c.getSerArray(0).copy();
        ser.getIdx().setVal(s);
        ser.getOrder().setVal(s);
        //ser.unsetSpPr();
        Serie serie = graph.getSeries().get(s);
        boolean delete = ser.isSetDLbls() && ser.getDLbls().getDLblArray().length > 0;
        if (delete) {
            int cntDlbls = ser.getDLbls().getDLblArray().length;
            for (int d = 0; d < cntDlbls; d++) {
                ser.getDLbls().removeDLbl(0);
            }
        }
        ser.unsetTx();
        CTStrRef serTitle = ser.addNewTx().addNewStrRef();
        serTitle.setF(graph.getSheetName() + "!$" + (char) ('B' + s) + "$1");
        CTStrData serTitleData = serTitle.addNewStrCache();
        serTitleData.addNewPtCount().setVal(1);
        CTStrVal serTitleDataVal = serTitleData.addNewPt();
        serTitleDataVal.setIdx(0);
        serTitleDataVal.setV(serie.getTitle());
        // Cat
        CTAxDataSource cat = ser.getCat();
        if (cat.isSetNumRef()) {
            cat.unsetNumRef();
        }
        if (cat.isSetStrRef()) {
            cat.unsetStrRef();
        }
        if (serie.isNumericCategories()) {
            CTNumRef numRef = cat.addNewNumRef();
            numRef.setF(graph.getSheetName() + "!$A$2:$A$" + (serie.getCategories().size() + 1));
            CTNumData data = numRef.addNewNumCache();
            data.setFormatCode("General");
            CTUnsignedInt cnt = data.addNewPtCount();
            cnt.setVal(serie.getCategories().size());
            int r = 0;
            for (String v : serie.getCategories()) {
                CTNumVal pt = data.addNewPt();
                pt.setIdx(r++);
                pt.setV(StringUtils.isBlank(v) ? "0" : v);
                if (delete) {
                    CTDLbl dlbl = ser.getDLbls().addNewDLbl();
                    dlbl.addNewIdx().setVal(r - 1);
                    dlbl.addNewDelete().setVal(true);
                }
            }
        }
        else {
            CTStrRef strRef = cat.addNewStrRef();
            strRef.setF(graph.getSheetName() + "!$A$2:$A$" + (serie.getCategories().size() + 1));
            CTStrData data = strRef.addNewStrCache();
            CTUnsignedInt cnt = data.addNewPtCount();
            cnt.setVal(serie.getCategories().size());
            int r = 0;
            for (String v : serie.getCategories()) {
                CTStrVal pt = data.addNewPt();
                pt.setIdx(r++);
                pt.setV(v);
                if (delete) {
                    CTDLbl dlbl = ser.getDLbls().addNewDLbl();
                    dlbl.addNewIdx().setVal(r - 1);
                    dlbl.addNewDelete().setVal(true);
                }
            }
        }
        // Values
        CTNumDataSource val = ser.getVal();
        val.unsetNumRef();
        CTNumRef numRef = val.addNewNumRef();
        char letter = (char) ('B' + s);
        numRef.setF(graph.getSheetName() + "!$" + letter + "$2:$" + letter + "$" + (serie.getValues().size() + 1));
        CTNumData data = numRef.addNewNumCache();
        data.setFormatCode("General");
        CTUnsignedInt cnt = data.addNewPtCount();
        cnt.setVal(serie.getValues().size());
        int r = 0;
        for (String v : serie.getValues()) {
            CTNumVal pt = data.addNewPt();
            pt.setIdx(r++);
            pt.setV(StringUtils.isBlank(v) ? "0" : v);
        }
        c.addNewSer().set(ser);
    }
    for (int s = 0; s < removeSeries; s++) {
        c.removeSer(0);
    }
}

Summarizing: 总结:

  1. Cloning the first CT*Ser; 克隆第一个CT * Ser;
  2. Replacing idx, order and tx; 替换idx,order和tx;
  3. If the CT*Ser has DLbls with DLbl tags inside, I remove the DLbl and then add them with delete set to true; 如果CT * Ser中包含带有blbl标签的DLbl,则删除DLbl,然后将delete设置为true来添加它们。
  4. Modify Cat; 修改猫;
    1. If categories are all numeric values, I use NumRefs, else StrRefs; 如果类别都是数字值,则使用NumRefs,否则使用StrRefs;
  5. Modify Val; 修改Val;
  6. Remove previous series 删除以前的系列

I change the backing Excel resource too, with just the data to build the graph (with one sheet per graph in the plot area). 我也更改了Excel支持资源,仅更改了用于构建图形的数据(在绘图区域中每个图形有一张图纸)。 I checked references to cells and cell ranges too and they are ok. 我也检查了对单元格和单元格范围的引用,它们还可以。

I checked the produced file with the following software, with reported results: 我使用以下软件检查了产生的文件,并报告了结果:

  • Libre Office (works as I expect) Libre Office(按预期工作)
  • Onlyoffice (works, but it seems not to support multiple charts per plot area?) Onlyoffice(有效,但似乎每个区域不支持多个图表吗?)
  • Microsoft Powerpoint desktop (errors opening the file, tries to restore, but fails and does not load slides contents from the wrong slide on) Microsoft Powerpoint桌面(打开文件时出错,尝试还原,但失败,并且不会从错误的幻灯片上加载幻灯片内容)
  • Microsoft Powerpoint online (does not open the file) Microsoft Powerpoint在线(不会打开文件)

Is there a relatively simple way to validate powerpoint files and find the errors preventing the file to work with Powerpoint? 有没有相对简单的方法来验证Powerpoint文件并查找导致文件无法与Powerpoint一起使用的错误? Is there any way to reliably diagnose those problems? 有什么方法可以可靠地诊断这些问题? Working on linux? 在Linux上工作?

The template file has been created with Powerpoint. 模板文件已使用Powerpoint创建。 I'm sorry if I don't report software versions, but I don't remember them (Powerpoint is not on my PC). 如果我没有报告软件版本,但我不记得他们(Powerpoint不在我的PC上),我很抱歉。

Please help me to understand what is wrong, because I'm actually starting to feel stupid. 请帮助我了解问题所在,因为我实际上开始感到愚蠢。 Any suggestion will be absolutely appreciated. 任何建议将不胜感激。 Thank you so much. 非常感谢。

I finally found what is wrong (or at least it seems to be): as in posted code, for every graph I set a progressive ID as idx and order for the element, but I started from 0 for every graph in the plot area. 我终于找到了问题所在(或至少看起来是这样):如在发布的代码中一样,对于每个图,我都将一个渐进ID设置为idx并为该元素设置顺序,但是对于绘图区域中的每个图,我都从0开始。 Keeping those idx and order unique for elements inside each plot area, it worked. 对于每个绘图区域内的元素,使这些idx和order保持唯一,它起作用了。

Hope this can help someone in the future. 希望这可以在将来对某人有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM