Я пытаюсь изменить значения линейного графика на слайде, но он не работает с помощью POI - PullRequest
0 голосов
/ 17 июня 2019

Я использую 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();
        }

    }

Нет ошибок, но значения диаграммы остаются прежними, фактический результат - линиядиаграмма с разными значениями.

1 Ответ

0 голосов
/ 18 июня 2019

Основная проблема заключается в том, что источником данных для диаграммы PowerPoint является встроенная рабочая таблица Excel.И этот рабочий лист нужно изменить слишком дополнительно к кэшированным данным в диаграмме.Это означает, что нам нужно получить источник данных диаграммы, который представляет собой лист Excel.И затем нам нужно установить все новые данные категорий, новые названия серий и новые значения данных всегда на этом листе, а также на диаграмме.

Полный пример:

Давайте начнем с этого LineSample.pptxшаблон:

enter image description here

Код:

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

}

Результат:

enter image description here

Вопрос в том, действительно ли необходимо копировать слайд из шаблона в новое созданное слайд-шоу, поскольку это приводит к проблемам с форматированием, как вы видите.На мой взгляд, лучше просто открыть весь шаблон, изменить необходимые элементы и затем сохранить этот измененный шаблон как новый файл.

Начните с того же шаблона.

Код:

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

}

Результат:

enter image description here

...