]> source.dussan.org Git - poi.git/commitdiff
[github-98] write data in respective Column in case of XDDFChart. Thanks to Sandeep...
authorPJ Fanning <fanningpj@apache.org>
Tue, 27 Feb 2018 23:12:53 +0000 (23:12 +0000)
committerPJ Fanning <fanningpj@apache.org>
Tue, 27 Feb 2018 23:12:53 +0000 (23:12 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1825521 13f79535-47bb-0310-9956-ffa450edef68

src/examples/src/org/apache/poi/xwpf/usermodel/examples/BarChartExampleDOCX.java [new file with mode: 0644]
src/examples/src/org/apache/poi/xwpf/usermodel/examples/bar-chart-data.txt [new file with mode: 0644]
src/examples/src/org/apache/poi/xwpf/usermodel/examples/bar-chart-template.docx [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java
src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFDataSource.java
src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFDataSourcesFactory.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java

diff --git a/src/examples/src/org/apache/poi/xwpf/usermodel/examples/BarChartExampleDOCX.java b/src/examples/src/org/apache/poi/xwpf/usermodel/examples/BarChartExampleDOCX.java
new file mode 100644 (file)
index 0000000..efc5a70
--- /dev/null
@@ -0,0 +1,129 @@
+
+/*
+ *  ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one or more
+ *    contributor license agreements.  See the NOTICE file distributed with
+ *    this work for additional information regarding copyright ownership.
+ *    The ASF licenses this file to You under the Apache License, Version 2.0
+ *    (the "License"); you may not use this file except in compliance with
+ *    the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ * ====================================================================
+ */
+
+package org.apache.poi.xwpf.usermodel.examples;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.POIXMLDocumentPart;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xddf.usermodel.chart.AxisOrientation;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.BarDirection;
+import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xwpf.usermodel.XWPFChart;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+
+/**
+ * Build a bar chart from a template docx
+ */
+public class BarChartExampleDOCX {
+    private static void usage(){
+        System.out.println("Usage: BarChartDemo <bar-chart-template.docx> <bar-chart-data.txt>");
+        System.out.println("    bar-chart-template.docx     template with a bar chart");
+        System.out.println("    bar-chart-data.txt          the model to set. First line is chart title, " +
+                "then go pairs {axis-label value}");
+    }
+
+    public static void main(String[] args) throws Exception {
+        if(args.length < 2) {
+            usage();
+            return;
+        }
+
+        try (FileInputStream argIS = new FileInputStream(args[0]);
+                BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) {
+
+            String chartTitle = modelReader.readLine();  // first line is chart title
+
+            // Category Axis Data
+            List<String> listCategories = new ArrayList<String>(3);
+
+            // Values
+            List<Double> listValues = new ArrayList<Double>(3);
+
+            // set model
+            String ln;
+            while((ln = modelReader.readLine()) != null){
+                String[] vals = ln.split("\\s+");
+                listCategories.add(vals[0]);
+                listValues.add(Double.valueOf(vals[1]));
+            }
+            String[] categories = listCategories.toArray(new String[listCategories.size()]);
+            Double[] values = listValues.toArray(new Double[listValues.size()]);
+
+            try (XWPFDocument doc = new XWPFDocument(argIS)) {
+                XWPFChart chart = doc.getCharts().get(0);
+                setBarData(chart, chartTitle, categories, values);
+                chart = doc.getCharts().get(1);
+                setColumnData(chart, "Column variant");
+
+                // save the result
+                try (OutputStream out = new FileOutputStream("bar-chart-demo-output.docx")) {
+                    doc.write(out);
+                }
+            }
+        }
+        System.out.println("Done");
+    }
+
+    private static void setBarData(XWPFChart chart, String chartTitle, String[] categories, Double[] values) {
+        final List<XDDFChartData> series = chart.getChartSeries();
+        final XDDFBarChartData bar = (XDDFBarChartData) series.get(0);
+
+        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 String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
+        final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
+        final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange, 1);
+        values[2] = 10.0;
+        final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values, valuesDataRange2, 2);
+        bar.getSeries().get(0).replaceData(categoriesData, valuesData);
+        bar.addSeries(categoriesData, valuesData2);
+        bar.getSeries().get(0).setTitle(chartTitle, chart.setSheetTitle(chartTitle));
+        chart.plot(bar);
+    }
+
+    private static void setColumnData(XWPFChart chart, String chartTitle) {
+        // Series Text
+        List<XDDFChartData> series = chart.getChartSeries();
+        XDDFBarChartData bar = (XDDFBarChartData) series.get(0);
+        bar.getSeries().get(0).setTitle(chartTitle, chart.setSheetTitle(chartTitle));
+
+        // in order to transform a bar chart into a column chart, you just need to change the bar direction
+        bar.setBarDirection(BarDirection.COL);
+
+        // additionally, you can adjust the axes
+        bar.getCategoryAxis().setOrientation(AxisOrientation.MAX_MIN);
+        bar.getValueAxes().get(0).setPosition(AxisPosition.TOP);
+    }
+}
+
diff --git a/src/examples/src/org/apache/poi/xwpf/usermodel/examples/bar-chart-data.txt b/src/examples/src/org/apache/poi/xwpf/usermodel/examples/bar-chart-data.txt
new file mode 100644 (file)
index 0000000..7f9c271
--- /dev/null
@@ -0,0 +1,4 @@
+My Bar or Column Chart\r
+First 1.0\r
+Second 3.0\r
+Third 4.0
\ No newline at end of file
diff --git a/src/examples/src/org/apache/poi/xwpf/usermodel/examples/bar-chart-template.docx b/src/examples/src/org/apache/poi/xwpf/usermodel/examples/bar-chart-template.docx
new file mode 100644 (file)
index 0000000..ddd57ef
Binary files /dev/null and b/src/examples/src/org/apache/poi/xwpf/usermodel/examples/bar-chart-template.docx differ
index 99a117fd36a98d7764a06afb3bea56eadf89af58..b39419bfca8ca53a124b8ffac839a79369042b72 100644 (file)
@@ -21,6 +21,8 @@ package org.apache.poi.xddf.usermodel.chart;
 
 import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
@@ -41,11 +43,14 @@ import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.openxml4j.exceptions.NotOfficeXmlFileException;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
+import org.apache.poi.util.TempFile;
 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
+import org.apache.poi.xssf.usermodel.XSSFCell;
 import org.apache.poi.xssf.usermodel.XSSFRow;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
@@ -67,6 +72,9 @@ import org.openxmlformats.schemas.drawingml.x2006.chart.CTSurface;
 import org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx;
 import org.openxmlformats.schemas.drawingml.x2006.chart.ChartSpaceDocument;
 import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumns;
 
 @Beta
 public abstract class XDDFChart extends POIXMLDocumentPart {
@@ -78,6 +86,8 @@ public abstract class XDDFChart extends POIXMLDocumentPart {
 
     private int chartIndex = 0;
 
+    private POIXMLDocumentPart documentPart = null;
+
     protected List<XDDFChartAxis> axes = new ArrayList<>();
 
     /**
@@ -412,8 +422,7 @@ public abstract class XDDFChart extends POIXMLDocumentPart {
      * @since POI 4.0.0
      */
     public PackageRelationship createRelationshipInChart(POIXMLRelation chartRelation, POIXMLFactory chartFactory, int chartIndex) {
-        POIXMLDocumentPart documentPart = createRelationship(chartRelation, chartFactory, chartIndex, true).getDocumentPart();
-        documentPart.setCommited(true);
+        documentPart = createRelationship(chartRelation, chartFactory, chartIndex, true).getDocumentPart();
         return this.addRelation(null, chartRelation, documentPart).getRelationship();
     }
 
@@ -442,7 +451,7 @@ public abstract class XDDFChart extends POIXMLDocumentPart {
      * @since POI 4.0.0
      */
     public void saveWorkbook(XSSFWorkbook workbook) throws IOException, InvalidFormatException {
-        PackagePart worksheetPart = getWorksheetPart(true);
+        PackagePart worksheetPart = getWorksheetPart();
         if (worksheetPart == null) {
             POIXMLRelation chartRelation = getChartRelation();
             POIXMLRelation chartWorkbookRelation = getChartWorkbookRelation();
@@ -454,6 +463,7 @@ public abstract class XDDFChart extends POIXMLDocumentPart {
             }
         }
         try (OutputStream xlsOut = worksheetPart.getOutputStream()) {
+            setWorksheetPartCommitted();
             workbook.write(xlsOut);
         }
     }
@@ -490,9 +500,43 @@ public abstract class XDDFChart extends POIXMLDocumentPart {
     protected void fillSheet(XSSFSheet sheet, XDDFDataSource<?> categoryData, XDDFNumericalDataSource<?> valuesData) {
         int numOfPoints = categoryData.getPointCount();
         for (int i = 0; i < numOfPoints; i++) {
-            XSSFRow row = sheet.createRow(i + 1); // first row is for title
-            row.createCell(0).setCellValue(categoryData.getPointAt(i).toString());
-            row.createCell(1).setCellValue(valuesData.getPointAt(i).doubleValue());
+            XSSFRow row = this.getRow(sheet, i + 1); // first row is for title
+            this.getCell(row, categoryData.getColIndex()).setCellValue(categoryData.getPointAt(i).toString());
+            this.getCell(row, valuesData.getColIndex()).setCellValue(valuesData.getPointAt(i).doubleValue());
+        }
+    }
+
+    /**
+     * this method return row on given index
+     * if row is null then create new row
+     *
+     * @param sheet current sheet object
+     * @param index index of current row
+     * @return this method return sheet row on given index
+     * @since POI 4.0.0
+     */
+    private XSSFRow getRow(XSSFSheet sheet,int index){
+        if (sheet.getRow(index) != null) {
+            return sheet.getRow(index);
+        } else {
+            return sheet.createRow(index);
+        }
+    }
+
+    /**
+     * this method return cell on given index
+     * if cell is null then create new cell
+     *
+     * @param row current row object
+     * @param index index of current cell
+     * @return this method return sheet cell on given index
+     * @since POI 4.0.0
+     */
+    private XSSFCell getCell(XSSFRow row,int index){
+        if (row.getCell(index) != null) {
+            return row.getCell(index);
+        } else {
+            return row.createCell(index);
         }
     }
 
@@ -537,10 +581,33 @@ public abstract class XDDFChart extends POIXMLDocumentPart {
      */
     public CellReference setSheetTitle(String title) {
         XSSFSheet sheet = getSheet();
-        sheet.createRow(0).createCell(1).setCellValue(title);
+        XSSFRow row = this.getRow(sheet, 0);
+        XSSFCell cell = this.getCell(row, 1);
+        cell.setCellValue(title);
+        this.updateSheetTable(sheet.getTables().get(0).getCTTable(), title, 1);
         return new CellReference(sheet.getSheetName(), 0, 1, true, true);
     }
 
+    /**
+     * this method update column header of sheet into table
+     *
+     * @param ctTable xssf table object
+     * @param title title of column
+     * @param index index of column
+     */
+    private void updateSheetTable(CTTable ctTable, String title, int index) {
+        CTTableColumns tableColumnList = ctTable.getTableColumns();
+        CTTableColumn column = null;
+        if(tableColumnList.getCount() >= index) {
+            column = tableColumnList.getTableColumnArray(index);
+        }
+        else {
+            column =  tableColumnList.addNewTableColumn();
+            column.setId(index);
+        }
+        column.setName(title);
+    }
+
     /**
      * @param range
      * @return
@@ -566,17 +633,6 @@ public abstract class XDDFChart extends POIXMLDocumentPart {
         return sheet;
     }
 
-    /**
-     * default method for worksheet part
-     *
-     * @return return embedded worksheet part
-     * @throws InvalidFormatException
-     * @since POI 4.0.0
-     */
-    private PackagePart getWorksheetPart() throws InvalidFormatException {
-        return getWorksheetPart(false);
-    }
-
     /**
      * this method is used to get worksheet part
      * if call is from saveworkbook method then check isCommitted
@@ -587,18 +643,24 @@ public abstract class XDDFChart extends POIXMLDocumentPart {
      * @throws InvalidFormatException
      * @since POI 4.0.0
      */
-    private PackagePart getWorksheetPart(boolean isCommitted) throws InvalidFormatException {
+    private PackagePart getWorksheetPart() throws InvalidFormatException {
         for (RelationPart part : getRelationParts()) {
             if (POIXMLDocument.PACK_OBJECT_REL_TYPE.equals(part.getRelationship().getRelationshipType())) {
-                if (isCommitted) {
-                    part.getDocumentPart().setCommited(true);
-                }
                 return getTargetPart(part.getRelationship());
             }
         }
         return null;
     }
 
+    private void setWorksheetPartCommitted() throws InvalidFormatException {
+        for (RelationPart part : getRelationParts()) {
+            if (POIXMLDocument.PACK_OBJECT_REL_TYPE.equals(part.getRelationship().getRelationshipType())) {
+                part.getDocumentPart().setCommited(true);
+                break;
+            }
+        }
+    }
+
     /**
      * @return returns the workbook object of embedded excel file
      * @throws IOException
@@ -631,7 +693,19 @@ public abstract class XDDFChart extends POIXMLDocumentPart {
      * @since POI 4.0.0
      */
     public void setWorkbook(XSSFWorkbook workbook) {
-        this.workbook = workbook;
+        File file;
+        FileOutputStream fos;
+        try {
+            file = TempFile.createTempFile("TempEmbedded",".xlsx");
+            fos = new FileOutputStream(file);
+            workbook.write(fos);
+            fos.close();
+            this.workbook = new XSSFWorkbook(file);
+        } catch (IOException e) {
+           
+        } catch (InvalidFormatException e) {
+
+        }
     }
 
     /**
index f6c19a1d1d821477cc71e57b9b3aa575937e9c9c..1ab617571dcf31111793d66e278e531c9c8a9a35 100644 (file)
@@ -31,5 +31,7 @@ public interface XDDFDataSource<T> {
 
     boolean isNumeric();
 
+    int getColIndex();
+
     String getDataRangeReference();
 }
index a740d92f4fba6c699e23950e156ec9a7df378761..be8a34ad23bf52b917c6cd20f494a9feb535bebe 100644 (file)
@@ -68,6 +68,11 @@ public class XDDFDataSourcesFactory {
             public String getDataRangeReference() {
                 return categoryDS.getStrRef().getF();
             }
+
+            @Override
+            public int getColIndex() {
+                return 0;
+            }
         };
     }
 
@@ -110,6 +115,11 @@ public class XDDFDataSourcesFactory {
             public String getDataRangeReference() {
                 return valuesDS.getNumRef().getF();
             }
+
+            @Override
+            public int getColIndex() {
+                return 0;
+            }
         };
     }
 
@@ -121,6 +131,14 @@ public class XDDFDataSourcesFactory {
         return new StringArrayDataSource(elements, dataRange);
     }
 
+    public static <T extends Number> XDDFNumericalDataSource<T> fromArray(T[] elements, String dataRange, int col) {
+        return new NumericalArrayDataSource<T>(elements, dataRange, col);
+    }
+
+    public static XDDFCategoryDataSource fromArray(String[] elements, String dataRange, int col) {
+        return new StringArrayDataSource(elements, dataRange, col);
+    }
+
     public static XDDFNumericalDataSource<Double> fromNumericCellRange(XSSFSheet sheet,
             CellRangeAddress cellRangeAddress) {
         return new NumericalCellRangeDataSource(sheet, cellRangeAddress);
@@ -133,12 +151,19 @@ public class XDDFDataSourcesFactory {
     private abstract static class AbstractArrayDataSource<T> implements XDDFDataSource<T> {
         private final T[] elements;
         private final String dataRange;
+        private int col = 0;
 
         public AbstractArrayDataSource(T[] elements, String dataRange) {
             this.elements = elements.clone();
             this.dataRange = dataRange;
         }
 
+        public AbstractArrayDataSource(T[] elements, String dataRange, int col) {
+            this.elements = elements.clone();
+            this.dataRange = dataRange;
+            this.col = col;
+        }
+
         @Override
         public int getPointCount() {
             return elements.length;
@@ -168,6 +193,11 @@ public class XDDFDataSourcesFactory {
                 return dataRange;
             }
         }
+
+        @Override
+        public int getColIndex() {
+            return col;
+        }
     }
 
     private static class NumericalArrayDataSource<T extends Number> extends AbstractArrayDataSource<T>
@@ -178,6 +208,10 @@ public class XDDFDataSourcesFactory {
             super(elements, dataRange);
         }
 
+        public NumericalArrayDataSource(T[] elements, String dataRange, int col) {
+            super(elements, dataRange, col);
+        }
+
         @Override
         public String getFormatCode() {
             return formatCode;
@@ -194,6 +228,10 @@ public class XDDFDataSourcesFactory {
         public StringArrayDataSource(String[] elements, String dataRange) {
             super(elements, dataRange);
         }
+
+        public StringArrayDataSource(String[] elements, String dataRange, int col) {
+            super(elements, dataRange, col);
+        }
     }
 
     private abstract static class AbstractCellRangeDataSource<T> implements XDDFDataSource<T> {
@@ -220,6 +258,11 @@ public class XDDFDataSourcesFactory {
             return true;
         }
 
+        @Override
+        public int getColIndex() {
+            return cellRangeAddress.getFirstColumn();
+        }
+
         @Override
         public String getDataRangeReference() {
             return cellRangeAddress.formatAsString(sheet.getSheetName(), true);
@@ -262,7 +305,7 @@ public class XDDFDataSourcesFactory {
         @Override
         public Double getPointAt(int index) {
             CellValue cellValue = getCellValueAt(index);
-            if (cellValue != null && cellValue.getCellTypeEnum() == CellType.NUMERIC) {
+            if (cellValue != null && cellValue.getCellType() == CellType.NUMERIC) {
                 return Double.valueOf(cellValue.getNumberValue());
             } else {
                 return null;
@@ -284,7 +327,7 @@ public class XDDFDataSourcesFactory {
         @Override
         public String getPointAt(int index) {
             CellValue cellValue = getCellValueAt(index);
-            if (cellValue != null && cellValue.getCellTypeEnum() == CellType.STRING) {
+            if (cellValue != null && cellValue.getCellType() == CellType.STRING) {
                 return cellValue.getStringValue();
             } else {
                 return null;
index b2cf29e43b4d993bb224d2d87d3b27468a18f987..35da6bf558cbc84e4b8bbc1eb5ad310a6952fb71 100644 (file)
@@ -189,7 +189,7 @@ public class XSLFGraphicFrame extends XSLFShape implements GraphicalFrame<XSLFSh
                 XSLFChart srcChart = (XSLFChart) src.getRelationById(id);
                 XSLFChart chartCopy = slide.getSlideShow().createChart(slide);
                 chartCopy.importContent(srcChart);
-                chartCopy.saveWorkbook(srcChart.getWorkbook());
+                chartCopy.setWorkbook(srcChart.getWorkbook());
                 c.setAttributeText(idQualifiedName, slide.getRelationId(chartCopy));
             } catch (InvalidFormatException e) {
                 throw new POIXMLException(e);