5

How do we create a chart in a ppt in java using apache poi. Which POI API do we use. Below is code I am using to create a text box

XSLFSlide slide = pptx.createSlide();
XSLFTextShape textShape = slide.createTextBox();
textShape.setText(data);

The slide object doesnt contain any api for creating a chart.

Any solution to this?

Thanks in advance

user3247376
  • 205
  • 1
  • 4
  • 13

2 Answers2

13

There is nothing like a XSLFChartShape usable in a powerpoint slide in apache poi until now.

But of course if one knows the internal structure of the *.pptx ZIP archive and the XML therein, then it is possible creating this from scratch using the apache poi OPCPackage classes and the low level CT* classes from org.openxmlformats.schemas.drawingml.x2006.* and org.openxmlformats.schemas.presentationml.x2006.*.

Following code is doing this and creates a slide having a pie chart and a bar chart.

This is a draft only to show the approach.

import java.io.*;

import org.apache.poi.*;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.util.*;
import org.apache.poi.openxml4j.opc.*;
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;

import org.apache.xmlbeans.*;

import org.openxmlformats.schemas.drawingml.x2006.chart.*;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
import org.openxmlformats.schemas.presentationml.x2006.main.*;

import javax.xml.namespace.QName;

import java.util.regex.Pattern;

import java.awt.geom.Rectangle2D;
import java.awt.Rectangle;

public class CreatePPTXCharts {

 public CreatePPTXCharts() throws Exception {
  XMLSlideShow slideShow = new XMLSlideShow();
  XSLFSlide slide = slideShow.createSlide();

  MyXSLFChartShape myXSLFChartShape = createXSLFChart(slide);
  myXSLFChartShape.setAnchor(new Rectangle(50,100,300,300));

  drawPieChart(myXSLFChartShape);

  myXSLFChartShape = createXSLFChart(slide);
  myXSLFChartShape.setAnchor(new Rectangle(370,100,300,300));

  drawBarChart(myXSLFChartShape);


  FileOutputStream out = new FileOutputStream("CreatePPTXCharts.pptx");
  slideShow.write(out);
  out.close();
 }

 //a method for creating the chart XML document /ppt/charts/chart*.xml in the *.pptx ZIP archive
 //and creating a MyXSLFChartShape as slide shape  
 public MyXSLFChartShape createXSLFChart(XSLFSlide slide) throws Exception {

  OPCPackage oPCPackage = slide.getSlideShow().getPackage();
  int chartCount = oPCPackage.getPartsByName(Pattern.compile("/ppt/charts/chart.*")).size() + 1;
  PackagePartName partName = PackagingURIHelper.createPartName("/ppt/charts/chart" + chartCount + ".xml");
  PackagePart part = oPCPackage.createPart(partName, "application/vnd.openxmlformats-officedocument.drawingml.chart+xml");

  MyXSLFChart myXSLFChart = new MyXSLFChart(part);
  MyXSLFChartShape myXSLFChartShape = new MyXSLFChartShape(slide, myXSLFChart);

  return myXSLFChartShape;

 }

 public void drawPieChart(MyXSLFChartShape myXSLFChartShape) {

  CTChartSpace chartSpace = myXSLFChartShape.getMyXSLFChart().getChartSpace();
  CTPieChart cTPieChart = chartSpace.addNewChart().addNewPlotArea().addNewPieChart();
  cTPieChart.addNewVaryColors().setVal(true);
  CTPieSer cTPieSer = cTPieChart.addNewSer();
  cTPieSer.addNewIdx().setVal(0);
  CTStrRef cTStrRef = cTPieSer.addNewTx().addNewStrRef();
  cTStrRef.setF("Label 0");
  cTStrRef.addNewStrCache().addNewPtCount().setVal(1);
  CTStrVal cTStrVal = cTStrRef.getStrCache().addNewPt();
  cTStrVal.setIdx(0);
  cTStrVal.setV("Val");

  cTStrRef = cTPieSer.addNewCat().addNewStrRef();
  cTStrRef.setF("Categories");
  
  cTStrRef.addNewStrCache().addNewPtCount().setVal(3);
  for (int r = 1; r < 4; r++) { 
   cTStrVal = cTStrRef.getStrCache().addNewPt();
   cTStrVal.setIdx(r-1);
   cTStrVal.setV("Cat" + r);
  }

  CTNumRef cTNumRef = cTPieSer.addNewVal().addNewNumRef();
  cTNumRef.setF("0");

  cTNumRef.addNewNumCache().addNewPtCount().setVal(3);
  for (int r = 1; r < 4; r++) { 
   CTNumVal cTNumVal = cTNumRef.getNumCache().addNewPt();
   cTNumVal.setIdx(r-1);
   cTNumVal.setV("" + (10*r));
  }

 }

 public void drawBarChart(MyXSLFChartShape myXSLFChartShape) {

  CTChartSpace chartSpace = myXSLFChartShape.getMyXSLFChart().getChartSpace();
  CTChart cTChart = chartSpace.addNewChart();
  CTPlotArea cTPlotArea = cTChart.addNewPlotArea();
  CTBarChart cTBarChart = cTPlotArea.addNewBarChart();
  cTBarChart.addNewVaryColors().setVal(true);
  cTBarChart.addNewBarDir().setVal(STBarDir.COL);

  for (int r = 1; r < 5; r++) {
   CTBarSer cTBarSer = cTBarChart.addNewSer();
   CTStrRef cTStrRef = cTBarSer.addNewTx().addNewStrRef();
   cTStrRef.setF("Label " + r);
   cTStrRef.addNewStrCache().addNewPtCount().setVal(1);
   CTStrVal cTStrVal = cTStrRef.getStrCache().addNewPt();
   cTStrVal.setIdx(0);
   cTStrVal.setV("Val" + r);

   cTBarSer.addNewIdx().setVal(r-1);  
   cTStrRef = cTBarSer.addNewCat().addNewStrRef();
   cTStrRef.setF("Categories");
   cTStrRef.addNewStrCache().addNewPtCount().setVal(3);
   for (int c = 1; c < 4; c++) { 
    cTStrVal = cTStrRef.getStrCache().addNewPt();
    cTStrVal.setIdx(c-1);
    cTStrVal.setV("Cat" + c);
   }

   CTNumRef cTNumRef = cTBarSer.addNewVal().addNewNumRef();
   cTNumRef.setF("" + r);
   cTNumRef.addNewNumCache().addNewPtCount().setVal(3);
   for (int c = 1; c < 4; c++) { 
    CTNumVal cTNumVal = cTNumRef.getNumCache().addNewPt();
    cTNumVal.setIdx(c-1);
    cTNumVal.setV("" + ((10+r)*c));
   }
  } 

  //telling the BarChart that it has axes and giving them Ids
  cTBarChart.addNewAxId().setVal(123456);
  cTBarChart.addNewAxId().setVal(123457);

  //cat axis
  CTCatAx cTCatAx = cTPlotArea.addNewCatAx(); 
  cTCatAx.addNewAxId().setVal(123456); //id of the cat axis
  CTScaling cTScaling = cTCatAx.addNewScaling();
  cTScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
  cTCatAx.addNewDelete().setVal(false);
  cTCatAx.addNewAxPos().setVal(STAxPos.B);
  cTCatAx.addNewCrossAx().setVal(123457); //id of the val axis
  cTCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

  //val axis
  CTValAx cTValAx = cTPlotArea.addNewValAx(); 
  cTValAx.addNewAxId().setVal(123457); //id of the val axis
  cTScaling = cTValAx.addNewScaling();
  cTScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
  cTValAx.addNewDelete().setVal(false);
  cTValAx.addNewAxPos().setVal(STAxPos.L);
  cTValAx.addNewCrossAx().setVal(123456); //id of the cat axis
  cTValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

  //legend
  CTLegend cTLegend = cTChart.addNewLegend();
  cTLegend.addNewLegendPos().setVal(STLegendPos.B);
  cTLegend.addNewOverlay().setVal(false);

 }

 public static void main(String[] args) throws Exception {
  CreatePPTXCharts createPPTXCharts = new CreatePPTXCharts();
 }

//________________________________________________________________________


 //a class for providing a MyXSLFChartShape
 private class MyXSLFChartShape {
  private CTGraphicalObjectFrame _graphicalObjectFrame;
  private XSLFSlide slide;
  private MyXSLFChart myXSLFChart;

  MyXSLFChartShape(XSLFSlide slide, MyXSLFChart myXSLFChart) throws Exception {

   String rId = "rId" + (slide.getRelationParts().size()+1);
   slide.addRelation(rId, XSLFRelation.CHART, myXSLFChart);

   long cNvPrId = 1;
   String cNvPrName = "MyChart";
   int cNvPrNameCount = 1;
   for (CTGraphicalObjectFrame currGraphicalObjectFrame : slide.getXmlObject().getCSld().getSpTree().getGraphicFrameList()) {
    if (currGraphicalObjectFrame.getNvGraphicFramePr() != null) {
     if (currGraphicalObjectFrame.getNvGraphicFramePr().getCNvPr() != null) {
      cNvPrId++;
      if (currGraphicalObjectFrame.getNvGraphicFramePr().getCNvPr().getName().startsWith(cNvPrName)) {
       cNvPrNameCount++;
      }
     }
    }
   }

   CTGraphicalObjectFrame graphicalObjectFrame = slide.getXmlObject().getCSld().getSpTree().addNewGraphicFrame();
   CTGraphicalObjectFrameNonVisual cTGraphicalObjectFrameNonVisual = graphicalObjectFrame.addNewNvGraphicFramePr();
   cTGraphicalObjectFrameNonVisual.addNewCNvGraphicFramePr();
   cTGraphicalObjectFrameNonVisual.addNewNvPr();

   CTNonVisualDrawingProps cTNonVisualDrawingProps = cTGraphicalObjectFrameNonVisual.addNewCNvPr();
   cTNonVisualDrawingProps.setId(cNvPrId);
   cTNonVisualDrawingProps.setName("MyChart" + cNvPrNameCount);

   CTGraphicalObject graphicalObject = graphicalObjectFrame.addNewGraphic();
   CTGraphicalObjectData graphicalObjectData = CTGraphicalObjectData.Factory.parse(
     "<c:chart xmlns:c=\"http://schemas.openxmlformats.org/drawingml/2006/chart\" "
    +"xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" "
    +"r:id=\"" + rId + "\"/>"
   );
   graphicalObjectData.setUri("http://schemas.openxmlformats.org/drawingml/2006/chart");
   graphicalObject.setGraphicData(graphicalObjectData);

   _graphicalObjectFrame = graphicalObjectFrame;
   this.slide = slide;
   this.myXSLFChart = myXSLFChart;

   this.setAnchor(new Rectangle());
  }

  private void setAnchor(Rectangle2D anchor) {
   CTTransform2D xfrm = (_graphicalObjectFrame.getXfrm() != null) ? _graphicalObjectFrame.getXfrm() : _graphicalObjectFrame.addNewXfrm();
   CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
   long x = Units.toEMU(anchor.getX());
   long y = Units.toEMU(anchor.getY());
   off.setX(x);
   off.setY(y);
   CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt();
   long cx = Units.toEMU(anchor.getWidth());
   long cy = Units.toEMU(anchor.getHeight());
   ext.setCx(cx);
   ext.setCy(cy);
  }

  private MyXSLFChart getMyXSLFChart() {
   return myXSLFChart;
  }

 }

 //a wrapper class for the ChartSpaceDocument /ppt/charts/chart*.xml in the *.pptx ZIP archive  
 private class MyXSLFChart extends POIXMLDocumentPart {

  private CTChartSpace chartSpace;

  private MyXSLFChart(PackagePart part) throws Exception {
   super(part);
   chartSpace = ChartSpaceDocument.Factory.newInstance().addNewChartSpace();
  }

  private CTChartSpace getChartSpace() {
   return chartSpace;
  }

  @Override
  protected void commit() throws IOException {
   XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
   xmlOptions.setSaveSyntheticDocumentElement(new QName(CTChartSpace.type.getName().getNamespaceURI(), "chartSpace", "c"));
   PackagePart part = getPackagePart();
   OutputStream out = part.getOutputStream();
   chartSpace.save(out, xmlOptions);
   out.close();
  }

 }

}

Code which is producing the same but having XSSFWorkbooks as data tables.

import java.io.*;

import org.apache.poi.*;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.util.*;
import org.apache.poi.openxml4j.opc.*;
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;

import org.apache.xmlbeans.*;

import org.openxmlformats.schemas.drawingml.x2006.chart.*;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
import org.openxmlformats.schemas.presentationml.x2006.main.*;

import javax.xml.namespace.QName;

import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.regex.Pattern;

import java.awt.geom.Rectangle2D;
import java.awt.Rectangle;

public class CreatePPTXChartsXSSFWb {

 public CreatePPTXChartsXSSFWb() throws Exception {
  XMLSlideShow slideShow = new XMLSlideShow();
  XSLFSlide slide = slideShow.createSlide();

  MyXSLFChartShape myXSLFChartShape = createXSLFChart(slide);
  myXSLFChartShape.setAnchor(new Rectangle(50,100,300,300));

  drawPieChart(myXSLFChartShape);

  myXSLFChartShape = createXSLFChart(slide);
  myXSLFChartShape.setAnchor(new Rectangle(370,100,300,300));

  drawBarChart(myXSLFChartShape);

  FileOutputStream out = new FileOutputStream("CreatePPTXChartsXSSFWb.pptx");
  slideShow.write(out);
  out.close();
 }

 //a method for creating the chart XML document /ppt/charts/chart*.xml in the *.pptx ZIP archive
 //and creating a MyXSLFChartShape as slide shape  
 public MyXSLFChartShape createXSLFChart(XSLFSlide slide) throws Exception {

  OPCPackage oPCPackage = slide.getSlideShow().getPackage();
  int chartCount = oPCPackage.getPartsByName(Pattern.compile("/ppt/charts/chart.*")).size() + 1;
  PackagePartName partName = PackagingURIHelper.createPartName("/ppt/charts/chart" + chartCount + ".xml");
  PackagePart part = oPCPackage.createPart(partName, "application/vnd.openxmlformats-officedocument.drawingml.chart+xml");

  MyXSLFChart myXSLFChart = new MyXSLFChart(part);
  MyXSLFChartShape myXSLFChartShape = new MyXSLFChartShape(slide, myXSLFChart);

  return myXSLFChartShape;
 }

 public void drawPieChart(MyXSLFChartShape myXSLFChartShape) {

  XSSFWorkbook workbook = myXSLFChartShape.getMyXSLFChart().getXSLFXSSFWorkbook().getXSSFWorkbook();
  XSSFSheet sheet = workbook.getSheetAt(0);
  sheet.createRow(0).createCell(0).setCellValue("Cat");
  sheet.getRow(0).createCell(1).setCellValue("Val");
  for (int r = 1; r < 4; r++) {
   sheet.createRow(r).createCell(0).setCellValue("Cat" + r);
   sheet.getRow(r).createCell(1).setCellValue(10*r);
  }

  CTChartSpace chartSpace = myXSLFChartShape.getMyXSLFChart().getChartSpace();
  CTPieChart cTPieChart = chartSpace.addNewChart().addNewPlotArea().addNewPieChart();
  cTPieChart.addNewVaryColors().setVal(true);
  CTPieSer cTPieSer = cTPieChart.addNewSer();
  cTPieSer.addNewIdx().setVal(0);
  CTStrRef cTStrRef = cTPieSer.addNewTx().addNewStrRef();
  cTStrRef.setF("Sheet0!$B$1");
  cTStrRef.addNewStrCache().addNewPtCount().setVal(1);
  CTStrVal cTStrVal = cTStrRef.getStrCache().addNewPt();
  cTStrVal.setIdx(0);
  cTStrVal.setV("Val");

  cTStrRef = cTPieSer.addNewCat().addNewStrRef();
  cTStrRef.setF("Sheet0!$A$2:$A$4");
  
  cTStrRef.addNewStrCache().addNewPtCount().setVal(3);
  for (int r = 1; r < 4; r++) { 
   cTStrVal = cTStrRef.getStrCache().addNewPt();
   cTStrVal.setIdx(r-1);
   cTStrVal.setV("Cat" + r);
  }

  CTNumRef cTNumRef = cTPieSer.addNewVal().addNewNumRef();
  cTNumRef.setF("Sheet0!$B$2:$B$4");

  cTNumRef.addNewNumCache().addNewPtCount().setVal(3);
  for (int r = 1; r < 4; r++) { 
   CTNumVal cTNumVal = cTNumRef.getNumCache().addNewPt();
   cTNumVal.setIdx(r-1);
   cTNumVal.setV("" + (10*r));
  }
 }

 public void drawBarChart(MyXSLFChartShape myXSLFChartShape) {

  XSSFWorkbook workbook = myXSLFChartShape.getMyXSLFChart().getXSLFXSSFWorkbook().getXSSFWorkbook();
  XSSFSheet sheet = workbook.getSheetAt(0);
  sheet.createRow(0);
  for (int c = 1; c < 4; c++) { 
   sheet.getRow(0).createCell(c).setCellValue("Cat" + c);
  }
  for (int r = 1; r < 5; r++) {
   sheet.createRow(r).createCell(0).setCellValue("Val" + r);
   for (int c = 1; c < 4; c++) { 
    sheet.getRow(r).createCell(c).setCellValue((10+r)*c);
   }
  }

  CTChartSpace chartSpace = myXSLFChartShape.getMyXSLFChart().getChartSpace();
  CTChart cTChart = chartSpace.addNewChart();
  CTPlotArea cTPlotArea = cTChart.addNewPlotArea();
  CTBarChart cTBarChart = cTPlotArea.addNewBarChart();
  cTBarChart.addNewVaryColors().setVal(true);
  cTBarChart.addNewBarDir().setVal(STBarDir.COL);

  for (int r = 1; r < 5; r++) {
   CTBarSer cTBarSer = cTBarChart.addNewSer();
   CTStrRef cTStrRef = cTBarSer.addNewTx().addNewStrRef();
   cTStrRef.setF("Sheet0!$A$" + (r+1));
   cTStrRef.addNewStrCache().addNewPtCount().setVal(1);
   CTStrVal cTStrVal = cTStrRef.getStrCache().addNewPt();
   cTStrVal.setIdx(0);
   cTStrVal.setV("Val" + r);
   cTBarSer.addNewIdx().setVal(r-1);

   CTAxDataSource cttAxDataSource = cTBarSer.addNewCat();
   cTStrRef = cttAxDataSource.addNewStrRef();
   cTStrRef.setF("Sheet0!$B$1:$D$1");   
   cTStrRef.addNewStrCache().addNewPtCount().setVal(3);
   for (int c = 1; c < 4; c++) { 
    cTStrVal = cTStrRef.getStrCache().addNewPt();
    cTStrVal.setIdx(c-1);
    cTStrVal.setV("Cat" + c);
   }

   CTNumDataSource ctNumDataSource = cTBarSer.addNewVal();
   CTNumRef cTNumRef = ctNumDataSource.addNewNumRef();
   cTNumRef.setF("Sheet0!$B$" + (r+1) + ":$D$" + (r+1));
   cTNumRef.addNewNumCache().addNewPtCount().setVal(3);
   for (int c = 1; c < 4; c++) { 
    CTNumVal cTNumVal = cTNumRef.getNumCache().addNewPt();
    cTNumVal.setIdx(c-1);
    cTNumVal.setV("" + ((10+r)*c));
   }
  } 

  //telling the BarChart that it has axes and giving them Ids
  cTBarChart.addNewAxId().setVal(123456);
  cTBarChart.addNewAxId().setVal(123457);

  //cat axis
  CTCatAx cTCatAx = cTPlotArea.addNewCatAx(); 
  cTCatAx.addNewAxId().setVal(123456); //id of the cat axis
  CTScaling cTScaling = cTCatAx.addNewScaling();
  cTScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
  cTCatAx.addNewDelete().setVal(false);
  cTCatAx.addNewAxPos().setVal(STAxPos.B);
  cTCatAx.addNewCrossAx().setVal(123457); //id of the val axis
  cTCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

  //val axis
  CTValAx cTValAx = cTPlotArea.addNewValAx(); 
  cTValAx.addNewAxId().setVal(123457); //id of the val axis
  cTScaling = cTValAx.addNewScaling();
  cTScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
  cTValAx.addNewDelete().setVal(false);
  cTValAx.addNewAxPos().setVal(STAxPos.L);
  cTValAx.addNewCrossAx().setVal(123456); //id of the cat axis
  cTValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

  //legend
  CTLegend cTLegend = cTChart.addNewLegend();
  cTLegend.addNewLegendPos().setVal(STLegendPos.B);
  cTLegend.addNewOverlay().setVal(false);

 }


 public static void main(String[] args) throws Exception {
  CreatePPTXChartsXSSFWb createPPTXCharts = new CreatePPTXChartsXSSFWb();
 }

 //a class for providing a MyXSLFChartShape
 private class MyXSLFChartShape {
  private CTGraphicalObjectFrame _graphicalObjectFrame;
  private XSLFSlide slide;
  private MyXSLFChart myXSLFChart;

  MyXSLFChartShape(XSLFSlide slide, MyXSLFChart myXSLFChart) throws Exception {

   String rId = "rId" + (slide.getRelationParts().size()+1);
   slide.addRelation(rId, XSLFRelation.CHART, myXSLFChart);

   long cNvPrId = 1;
   String cNvPrName = "MyChart";
   int cNvPrNameCount = 1;
   for (CTGraphicalObjectFrame currGraphicalObjectFrame : slide.getXmlObject().getCSld().getSpTree().getGraphicFrameList()) {
    if (currGraphicalObjectFrame.getNvGraphicFramePr() != null) {
     if (currGraphicalObjectFrame.getNvGraphicFramePr().getCNvPr() != null) {
      cNvPrId++;
      if (currGraphicalObjectFrame.getNvGraphicFramePr().getCNvPr().getName().startsWith(cNvPrName)) {
       cNvPrNameCount++;
      }
     }
    }
   }

   CTGraphicalObjectFrame graphicalObjectFrame = slide.getXmlObject().getCSld().getSpTree().addNewGraphicFrame();
   CTGraphicalObjectFrameNonVisual cTGraphicalObjectFrameNonVisual = graphicalObjectFrame.addNewNvGraphicFramePr();
   cTGraphicalObjectFrameNonVisual.addNewCNvGraphicFramePr();
   cTGraphicalObjectFrameNonVisual.addNewNvPr();

   CTNonVisualDrawingProps cTNonVisualDrawingProps = cTGraphicalObjectFrameNonVisual.addNewCNvPr();
   cTNonVisualDrawingProps.setId(cNvPrId);
   cTNonVisualDrawingProps.setName("MyChart" + cNvPrNameCount);

   CTGraphicalObject graphicalObject = graphicalObjectFrame.addNewGraphic();
   CTGraphicalObjectData graphicalObjectData = CTGraphicalObjectData.Factory.parse(
     "<c:chart xmlns:c=\"http://schemas.openxmlformats.org/drawingml/2006/chart\" "
    +"xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" "
    +"r:id=\"" + rId + "\"/>"
   );
   graphicalObjectData.setUri("http://schemas.openxmlformats.org/drawingml/2006/chart");
   graphicalObject.setGraphicData(graphicalObjectData);

   _graphicalObjectFrame = graphicalObjectFrame;
   this.slide = slide;
   this.myXSLFChart = myXSLFChart;

   this.setAnchor(new Rectangle());
  }

  private void setAnchor(Rectangle2D anchor) {
   CTTransform2D xfrm = (_graphicalObjectFrame.getXfrm() != null) ? _graphicalObjectFrame.getXfrm() : _graphicalObjectFrame.addNewXfrm();
   CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
   long x = Units.toEMU(anchor.getX());
   long y = Units.toEMU(anchor.getY());
   off.setX(x);
   off.setY(y);
   CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt();
   long cx = Units.toEMU(anchor.getWidth());
   long cy = Units.toEMU(anchor.getHeight());
   ext.setCx(cx);
   ext.setCy(cy);
  }

  private MyXSLFChart getMyXSLFChart() {
   return myXSLFChart;
  }
 }

 //a wrapper class for the ChartSpaceDocument /ppt/charts/chart*.xml in the *.pptx ZIP archive  
 private class MyXSLFChart extends POIXMLDocumentPart {

  private CTChartSpace chartSpace;
  private MyXSLFXSSFWorkbook myXSLFXSSFWorkbook;

  private MyXSLFChart(PackagePart part) throws Exception {
   super(part);

   OPCPackage oPCPackage = part.getPackage();
   int chartCount = oPCPackage.getPartsByName(Pattern.compile("/ppt/embeddings/.*.xlsx")).size() + 1;
   PackagePartName partName = PackagingURIHelper.createPartName("/ppt/embeddings/Microsoft_Excel_Worksheet" + chartCount + ".xlsx");
   PackagePart xlsxpart = oPCPackage.createPart(partName, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

   myXSLFXSSFWorkbook = new MyXSLFXSSFWorkbook(xlsxpart);
 
   String rId = "rId" + (this.getRelationParts().size()+1);
   XSLFXSSFRelation xSLFXSSFRelationPACKAGE = new XSLFXSSFRelation(
    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package");

   this.addRelation(rId, xSLFXSSFRelationPACKAGE, myXSLFXSSFWorkbook);

   chartSpace = ChartSpaceDocument.Factory.newInstance().addNewChartSpace();
   CTExternalData cTExternalData = chartSpace.addNewExternalData();
   cTExternalData.setId(rId);
   //cTExternalData.addNewAutoUpdate().setVal(true);
  }

  private CTChartSpace getChartSpace() {
   return chartSpace;
  }

  private MyXSLFXSSFWorkbook getXSLFXSSFWorkbook() {
   return myXSLFXSSFWorkbook;
  }

  @Override
  protected void commit() throws IOException {
   XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
   xmlOptions.setSaveSyntheticDocumentElement(new QName(CTChartSpace.type.getName().getNamespaceURI(), "chartSpace", "c"));
   PackagePart part = getPackagePart();
   OutputStream out = part.getOutputStream();
   chartSpace.save(out, xmlOptions);
   out.close();
  }

 }

 //a wrapper class for the XSSFWorkbook /ppt/embeddings/Microsoft_Excel_Worksheet*.xlsx in the *.pptx ZIP archive  
 private class MyXSLFXSSFWorkbook extends POIXMLDocumentPart {

  private XSSFWorkbook workbook;

  private MyXSLFXSSFWorkbook(PackagePart part) throws Exception {
   super(part);
   workbook = new XSSFWorkbook();
   XSSFSheet sheet = workbook.createSheet();
  }

  private XSSFWorkbook getXSSFWorkbook() {
   return workbook;
  }

  @Override
  protected void commit() throws IOException {
   PackagePart part = getPackagePart();
   OutputStream out = part.getOutputStream();
   workbook.write(out);
   workbook.close();
   out.close();
  }
 }

 //a class to note the relations
 private class XSLFXSSFRelation extends POIXMLRelation {
  private XSLFXSSFRelation(String rel) {
   super(null, rel, null);
  }
 }
} 

Edit January 29 2019:

Above code was working using apache poi 3.16 up to apache poi 3.17. To make it work using current apache poi 4.0.1 the only need is changing the imports a little bit:

...
import org.apache.poi.openxml4j.opc.*;
//import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import org.apache.poi.ooxml.*;

import org.apache.xmlbeans.*;
...

This is because the Office Open XML stuff now is in org.apache.poi.ooxml.*and not more in org.apache.poi.*.


Edit August 2023:

Current Apache POI versions (since Apache POI 4.1.0) provide XDDF for charts. Using this it is much simpler to create charts for PowerPoint.

Example:

import java.io.FileOutputStream;

import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;

import java.awt.Rectangle;

public class CreatePowerPointXDDFChart {
    
 public static void main(String[] args) throws Exception {
  try (XMLSlideShow slideShow = new XMLSlideShow()) {
   
   // create a new empty slide
   XSLFSlide slide = slideShow.createSlide();
   
   // create chart
   XSLFChart chart = slideShow.createChart();
   chart.setTitleText("Test Chart");
   
   // set axis
   XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
   XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
   leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
   leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

   // define chart data for bar chart
   XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);

   // add chart categories (x-axis data)
   String[] categories = new String[] { "Category 1", "Category 2", "Category 3" };
   String categoryDataRange = chart.formatRange(new org.apache.poi.ss.util.CellRangeAddress(1, categories.length, 0, 0));
   XDDFCategoryDataSource categoryData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);

   // add chart values (y-axis data)
   Double[] values = new Double[] { 10.0, 20.0, 15.0 };
   String valuesDataRange = chart.formatRange(new org.apache.poi.ss.util.CellRangeAddress(1, values.length, 1, 1));
   XDDFNumericalDataSource<Double> valueData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange, 1);
   XDDFBarChartData bar = (XDDFBarChartData) data;
   bar.setBarDirection(BarDirection.BAR);

   // add series
   XDDFChartData.Series series = data.addSeries(categoryData, valueData);
   series.setTitle("Series 1", chart.setSheetTitle("Series 1", 1));
   
   // plot chart
   chart.plot(data);

   // set chart dimensions !!Units are EMU (English Metric Units)!!
   Rectangle chartDimensions = new Rectangle(
    100*Units.EMU_PER_POINT, 
    50*Units.EMU_PER_POINT, 
    400*Units.EMU_PER_POINT, 
    400*Units.EMU_PER_POINT);
   // add chart to slide
   slide.addChart(chart, chartDimensions);

   // Write the output to a file
   try (FileOutputStream fileOut = new FileOutputStream("./CreatePowerPointXDDFChart.pptx")) {
    slideShow.write(fileOut);
   }
  }
 }

}
Axel Richter
  • 56,077
  • 6
  • 60
  • 87
  • Thanks a ton!!. This does work and allows you to create a chart from scratch. No forum had a working code like this. Also can you let me know if its possible to embed a pdf in a slide similary. Any reference you have for the same? Thankyou once again Also any documentation that helpos us to understand the low level structure of pptx? – user3247376 Jul 31 '17 at 10:20
  • For the above code for the generated charts I am not able to link/edit the excel to it when I double click it. @Axel Richter any pointers on how to we see the attach the excel to the chart data – user3247376 Aug 01 '17 at 10:28
  • @user3247376: The code provides only the cached values for the chart. But `PowerPoint 2016` as well as `Libreoffice Impress` is able to create a data table if `Edit Data` is clicked. But of course `PowerPoint 2007` will not do this. But providing a embedded `XSSFWorkbook` as data table is also possible. See my supplement. – Axel Richter Aug 01 '17 at 13:30
  • Thanks Axel, I will look into the code and try it out. Meanwhile can you let me know if its possible to embed a pdf inside a slide while generating it? – user3247376 Aug 02 '17 at 05:47
  • @user3247376: Embedding a `PDF` will be done using [OLE](https://en.wikipedia.org/wiki/Object_Linking_and_Embedding). For this in Office OpenXML there in the \ppt\embeddings\ will be a `oleObject1.bin` which contains both, the data of the `PDF` and the system call to open the `PDF`. I don't know how to create this binary file. So no, I don't know how to embed a `PDF`. – Axel Richter Aug 02 '17 at 06:08
  • Perfect solution. So happy to see that the work we did to create bar-line combination charts in XL can be ported as-is to PPT ! Great solution Axel – dipan66 Oct 24 '17 at 12:52
  • Which version of poi are you using for this example? – BMH Jan 29 '19 at 09:13
  • 1
    @BMH: Must had been version 3.16 according to the date of the answer. Will try this evening (Germany) whether it runs in current version 4.0.1 too and probably update my answer if not. – Axel Richter Jan 29 '19 at 09:20
  • 1
    @BMH: done. Changing the imports a little bit makes it work using current `apache poi 4.0.1`. – Axel Richter Jan 29 '19 at 16:35
0

What about the org.apache.poi.xslf.usermodel.XSLFChart Object ? I am unable to find a direct createChart method in this Object.

But I am sure there must be something with this Object. Not much content available on stackoverflow on this.

Has anyone created a chart using org.apache.poi.xslf.usermodel.XSLFChart in a pptx ? Grateful for the response.

Mahaveer Jangir
  • 597
  • 7
  • 15