0

我正在使用 Apache POI 4.01 并尝试使用带有单个折线图作为模板的 powerpoint 幻灯片,然后使用它来生成图表中包含一些不同值的新幻灯片,但我得到的是相同的幻灯片复制而没有任何值更改. 请帮忙。

我正在使用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();
        }

    }

没有错误但图表值保持不变,实际需要的结果是具有不同值的折线图。

4

1 回答 1

0

主要问题是PowerPoint图表的数据源是嵌入式Excel工作表。并且此工作表需要更改为图表中缓存数据的额外内容。这意味着我们需要获取图表的数据源,即 Excel 表格。然后我们需要始终在该表和图表中设置所有新类别数据、新系列标题和新数据值。

完整示例:

让我们从该LineSample.pptx模板开始:

在此处输入图像描述

代码:

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

}

结果:

在此处输入图像描述

问题是是否真的有必要将幻灯片从模板复制到新创建的幻灯片,因为这会导致格式问题,如您所见。在我看来,只需打开整个模板,更改所需的内容,然后将更改后的模板保存为新文件会更好。

从相同的模板开始。

代码:

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

}

结果:

在此处输入图像描述

于 2019-06-18T15:21:25.313 回答