简体   繁体   English

我正在尝试更改幻灯片中折线图的值,但它无法使用POI

[英]I'm trying to change the values of a line graph in a slide but it is not working using POI

I'm using Apache POI 4.01 and trying to use a powerpoint slide with a single line chart as template and then using that to generate a new slide with some different values in the chart but I'm getting the same slide copied without any value change. 我正在使用Apache POI 4.01并试图使用带有单个折线图作为模板的powerpoint幻灯片,然后使用它来生成一个在图表中具有一些不同值的新幻灯片,但我正在复制相同的幻灯片而没有任何值更改。 Kindly help. 请帮助。

I'm trying the below code using a simple line chart in a powerpoint slide. 我正在使用powerpoint幻灯片中的简单折线图尝试以下代码。

public static void main(String[] args) throws IOException {
        // creating presentation
        XMLSlideShow ppt = new XMLSlideShow();

        File file1 = new File("MyDrive://LineSample.pptx");
        FileInputStream inputstream;
        try {
            inputstream = new FileInputStream(file1);

            XMLSlideShow template = new XMLSlideShow(inputstream);
            XMLSlideShow testReport = new XMLSlideShow();
            XSLFSlide xslfSlide = template.getSlides().get(0);

            // TODO Auto-generated method stub

            // adding slides to the slideshow

            XSLFSlide slide1 = testReport.createSlide();

            XSLFSlideLayout src_sl = xslfSlide.getSlideLayout();
            XSLFSlideMaster src_sm = xslfSlide.getSlideMaster();

            XSLFSlideLayout new_sl = slide1.getSlideLayout();
            XSLFSlideMaster new_sm = slide1.getSlideMaster();

            // copy source layout to the new layout
            new_sl.importContent(src_sl);
            // copy source master to the new master
            new_sm.importContent(src_sm);

            slide1.importContent(xslfSlide);
            XSLFSlide slide = xslfSlide;

            // find chart in the slide
            XSLFChart chart = null;
            for (POIXMLDocumentPart part : slide.getRelations()) {
                if (part instanceof XSLFChart) {
                    chart = (XSLFChart) part;
                    break;

                }
            }

            if (chart == null) {
                throw new IllegalStateException("chart not found in the template");
            } else {
                System.out.println("Chart Found");
            }
            // Series Text
            List<XDDFChartData> series = chart.getChartSeries();
            XDDFLineChartData linechart = (XDDFLineChartData) series.get(0);

            // Category
            List<String> listCategories = new ArrayList<>(3);
            listCategories.add("Test1");
            listCategories.add("Test2");
            listCategories.add("Test3");
            // Values
            List<Double> listValues = new ArrayList<>(3);
            listValues.add(10.00);
            listValues.add(20.00);
            listValues.add(30.00);

            String[] categories = listCategories.toArray(new String[listCategories.size()]);
            Double[] values = listValues.toArray(new Double[listValues.size()]);

            final int numOfPoints = categories.length;
            final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
            final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
            final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange);
            final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values,
                    valuesDataRange);

            XDDFLineChartData.Series firstSeries = (XDDFLineChartData.Series) linechart.getSeries().get(0);
            firstSeries.replaceData(categoriesData, valuesData);
            // firstSeries.setTitle("chartTitle",
            // chart.setSheetTitle("chartTitle", 0));
            firstSeries.setMarkerSize((short) 70);
            firstSeries.setMarkerStyle(MarkerStyle.DASH);
            firstSeries.setShowLeaderLines(true);
            firstSeries.setSmooth(true);
            // firstSeries.setShapeProperties(XDDFShapeProperties);

            chart.plot(linechart);

            FileOutputStream out = new FileOutputStream("MyDrive");
            testReport.write(out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

No errors but chart values remain the same, actual result needed is a line chart with different values. 没有错误,但图表值保持不变,所需的实际结果是具有不同值的折线图。

Main problem is that the data source of a PowerPoint chart is a embedded Excel worksheet. 主要问题是PowerPoint图表的数据源是嵌入式Excel工作表。 And this worksheet needs changed too additional to the cached data in the chart. 此工作表需要更改为图表中的缓存数据。 That means we need get the chart's data source which is a Excel sheet. 这意味着我们需要获取图表的数据源,这是一个Excel工作表。 And then we need set all new category data, new series titles and new data values always in that sheet as well as in the chart. 然后我们需要在该表和图表中设置所有新的类别数据,新系列标题和新数据值。

Complete example: 完整的例子:

Lets start with that LineSample.pptx template: 让我们从LineSample.pptx模板开始:

在此输入图像描述

Code: 码:

import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.CellRangeAddress;

import org.apache.poi.ooxml.POIXMLDocumentPart;

public class PowerPointCopySlideChangeChartData {

 public static void main(String[] args) throws Exception {

  String filePath = "LineSample.pptx"; // has template line chart
  String filePathNew = "LineSample_New.pptx";

  Object[][] data = new Object[][] { // new data 1 series, 4 categories
   {"", "Amount"}, // series title
   {"Jan", 123d}, // category 1
   {"Feb", 345d}, // category 2
   {"Mar", 180d}, // category 3
   {"Apr", 180d} // category 4
  };

  XMLSlideShow slideShowTemplate = new XMLSlideShow(new FileInputStream(filePath));
  XSLFSlide slideTemplate = slideShowTemplate.getSlides().get(0);
  XSLFSlideLayout slideLayoutTemplate = slideTemplate.getSlideLayout();
  XSLFSlideMaster slideMasterTemplate = slideTemplate.getSlideMaster();

  XMLSlideShow slideShowNew = new XMLSlideShow();
  XSLFSlide slideNew = slideShowNew.createSlide();
  XSLFSlideLayout slideLayoutNew = slideNew.getSlideLayout();
  XSLFSlideMaster slideMasterNew = slideNew.getSlideMaster();

  slideLayoutNew.importContent(slideLayoutTemplate);
  slideMasterNew.importContent(slideMasterTemplate);

  slideNew.importContent(slideTemplate);

  slideShowTemplate.close();

  XSLFChart chart = null;
  for (POIXMLDocumentPart part : slideNew.getRelations()) {
   if (part instanceof XSLFChart) {
    chart = (XSLFChart) part;
    break;
   }
  }
  if (chart == null) {
   throw new Exception("chart not found in the template");
  } else {
   System.out.println("Chart Found");
  }

  XSSFWorkbook chartDataWorkbook = chart.getWorkbook();
  String sheetName = chartDataWorkbook.getSheetName(0);
  XSSFSheet chartDataSheet = chartDataWorkbook.getSheet(sheetName);

  if (chart.getChartSeries().size() == 1) { // we will process only one chart data
   XDDFChartData chartData = chart.getChartSeries().get(0);
   if (chartData.getSeries().size() == 1) { // we will process exact one series

    int rMin = 1;
    int rMax = data.length - 1;

    // set new category data
    XDDFCategoryDataSource category = null;
    int c = 0;
    for (int r = rMin; r < rMax+1; r++) {
     XSSFRow row = chartDataSheet.getRow(r); if (row == null) row = chartDataSheet.createRow(r);
     XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
     cell.setCellValue((String)data[r][c]); // in sheet
    }
    category = XDDFDataSourcesFactory.fromStringCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); // in chart

    // series 1
    XDDFChartData.Series series1 = chartData.getSeries().get(0);
    c = 1;
    // set new title
    String series1Title = (String)data[0][c];
    chartDataSheet.getRow(0).getCell(c).setCellValue(series1Title); // in sheet
    series1.setTitle(series1Title, new CellReference(sheetName, 0, c, true, true)); // in chart

    // set new values
    XDDFNumericalDataSource<Double> values = null;
    for (int r = rMin; r < rMax+1; r++) {
     XSSFRow row = chartDataSheet.getRow(r); if (row == null) row = chartDataSheet.createRow(r);
     XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
     cell.setCellValue((Double)data[r][c]); // in sheet
    }
    values = XDDFDataSourcesFactory.fromNumericCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); 
    series1.replaceData(category, values);
    series1.plot(); //in chart

    series1.setShowLeaderLines(true);
    if (series1 instanceof XDDFLineChartData.Series) {
     ((XDDFLineChartData.Series)series1).setMarkerSize((short) 70);
     ((XDDFLineChartData.Series)series1).setMarkerStyle(MarkerStyle.DASH);
     ((XDDFLineChartData.Series)series1).setSmooth(true);
    }
   }
  }

  FileOutputStream out = new FileOutputStream(filePathNew); 
  slideShowNew.write(out);
  out.close();
  slideShowNew.close();
 }

}

Result: 结果:

在此输入图像描述

The question is whether the copying of the slide from the template to a new created slide show is really necessary since this leads to formatting issues as you see. 问题是,是否真的有必要将幻灯片从模板复制到新创建的幻灯片放映,因为这会导致格式问题。 In my opinion simply opening the whole template, changing the needed things and then saving that changed template as a new file will be better. 在我看来,只需打开整个模板,更改所需的东西,然后将更改的模板保存为新文件将更好。

Start with same template. 从相同的模板开始。

Code: 码:

import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.CellRangeAddress;

public class PowerPointChangeChartData {

 public static void main(String[] args) throws Exception {

  String filePath = "LineSample.pptx"; // has template line chart
  String filePathNew = "LineSample_New.pptx";

  Object[][] data = new Object[][] { // new data 1 series, 4 categories
   {"", "Amount"}, // series title
   {"Jan", 123d}, // category 1
   {"Feb", 345d}, // category 2
   {"Mar", 180d}, // category 3
   {"Apr", 180d} // category 4
  };

  XMLSlideShow slideShow = new XMLSlideShow(new FileInputStream(filePath));

  XSLFChart chart = slideShow.getCharts().get(0);

  // get chart's data source which is a Excel sheet
  XSSFWorkbook chartDataWorkbook = chart.getWorkbook();
  String sheetName = chartDataWorkbook.getSheetName(0);
  XSSFSheet chartDataSheet = chartDataWorkbook.getSheet(sheetName);

  if (chart.getChartSeries().size() == 1) { // we will process only one chart data
   XDDFChartData chartData = chart.getChartSeries().get(0);
   if (chartData.getSeries().size() == 1) { // we will process exact one series

    int rMin = 1;
    int rMax = data.length - 1;

    // set new category data
    XDDFCategoryDataSource category = null;
    int c = 0;
    for (int r = rMin; r < rMax+1; r++) {
     XSSFRow row = chartDataSheet.getRow(r); if (row == null) row = chartDataSheet.createRow(r);
     XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
     cell.setCellValue((String)data[r][c]); // in sheet
    }
    category = XDDFDataSourcesFactory.fromStringCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); // in chart

    // series 1
    XDDFChartData.Series series1 = chartData.getSeries().get(0);
    c = 1;
    // set new title
    String series1Title = (String)data[0][c];
    chartDataSheet.getRow(0).getCell(c).setCellValue(series1Title); // in sheet
    series1.setTitle(series1Title, new CellReference(sheetName, 0, c, true, true)); // in chart

    // set new values
    XDDFNumericalDataSource<Double> values = null;
    for (int r = rMin; r < rMax+1; r++) {
     XSSFRow row = chartDataSheet.getRow(r); if (row == null) row = chartDataSheet.createRow(r);
     XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
     cell.setCellValue((Double)data[r][c]); // in sheet
    }
    values = XDDFDataSourcesFactory.fromNumericCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); 
    series1.replaceData(category, values);
    series1.plot(); //in chart

    series1.setShowLeaderLines(true);
    if (series1 instanceof XDDFLineChartData.Series) {
     ((XDDFLineChartData.Series)series1).setMarkerSize((short) 70);
     ((XDDFLineChartData.Series)series1).setMarkerStyle(MarkerStyle.DASH);
     ((XDDFLineChartData.Series)series1).setSmooth(true);
    }

   }
  }

  FileOutputStream out = new FileOutputStream(filePathNew); 
  slideShow.write(out);
  out.close();
  slideShow.close();
 }

}

Result: 结果:

在此输入图像描述

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

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