0

我正在尝试使用 PowerPoint 文件作为模板来生成另一个替换购物车数据的 powerpoint。为了使模板的外观尽可能相似,我只是尝试替换我需要替换的数据,从CT*Ser图表的第一个复制所有其他数据。当绘图区域内只有一个图表时,大多数图表(目前我对饼图、条形图和折线图感兴趣)都可以正常工作。

当绘图区域有多个图表时(在我的例子中,一个有多个系列的 BarChart 和一个只有一个的 LineChart),看起来有问题,Microsoft PowerPoint 无法打开文件或其中的一部分,因为它似乎是被管理的。

为此,我为每个图表和图表类型执行以下代码(图表是我用来在模板文件中保留引用的对象)。

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);
    }
}

总结:

  1. 克隆第一个 CT*Ser;
  2. 替换idx、order和tx;
  3. 如果 CT*Ser 具有内部带有 DLbl 标记的 DLbl,我将删除 DLbl,然后将它们添加,并将 delete 设置为 true;
  4. 修改猫;
    1. 如果类别都是数值,我使用 NumRefs,否则使用 StrRefs;
  5. 修改值;
  6. 删除以前的系列

我也更改了支持 Excel 资源,仅使用构建图表的数据(绘图区域中每个图表一张)。我也检查了对单元格和单元格范围的引用,它们没问题。

我使用以下软件检查了生成的文件,并报告了结果:

  • Libre Office(按我的预期工作)
  • Onlyoffice(有效,但似乎不支持每个绘图区域的多个图表?)
  • Microsoft Powerpoint 桌面(打开文件时出错,尝试恢复,但失败并且不会从错误的幻灯片上加载幻灯片内容)
  • Microsoft Powerpoint online(不打开文件)

是否有一种相对简单的方法来验证 powerpoint 文件并找到阻止文件与 Powerpoint 一起使用的错误?有什么方法可以可靠地诊断这些问题吗?在Linux上工作?

模板文件已使用 Powerpoint 创建。如果我不报告软件版本,我很抱歉,但我不记得它们(Powerpoint 不在我的电脑上)。

请帮助我了解问题所在,因为我实际上开始感到愚蠢。任何建议将不胜感激。太感谢了。

4

1 回答 1

0

我终于发现了问题所在(或者至少看起来是这样):就像在发布的代码中一样,对于每个图形,我将渐进式 ID 设置为 idx 并为元素设置顺序,但是对于绘图区域中的每个图形,我都是从 0 开始的。为每个绘图区域内的元素保持这些 idx 和 order 唯一,它起作用了。

希望这可以帮助将来的人。

于 2018-04-15T12:24:26.747 回答