--- /dev/null
+
+/*
+ * ====================================================================
+ * 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);
+ }
+}
+
--- /dev/null
+My Bar or Column Chart\r
+First 1.0\r
+Second 3.0\r
+Third 4.0
\ No newline at end of file
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;
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;
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 {
private int chartIndex = 0;
+ private POIXMLDocumentPart documentPart = null;
+
protected List<XDDFChartAxis> axes = new ArrayList<>();
/**
* @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();
}
* @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();
}
}
try (OutputStream xlsOut = worksheetPart.getOutputStream()) {
+ setWorksheetPartCommitted();
workbook.write(xlsOut);
}
}
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);
}
}
*/
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
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
* @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
* @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) {
+
+ }
}
/**
boolean isNumeric();
+ int getColIndex();
+
String getDataRangeReference();
}
public String getDataRangeReference() {
return categoryDS.getStrRef().getF();
}
+
+ @Override
+ public int getColIndex() {
+ return 0;
+ }
};
}
public String getDataRangeReference() {
return valuesDS.getNumRef().getF();
}
+
+ @Override
+ public int getColIndex() {
+ return 0;
+ }
};
}
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);
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;
return dataRange;
}
}
+
+ @Override
+ public int getColIndex() {
+ return col;
+ }
}
private static class NumericalArrayDataSource<T extends Number> extends AbstractArrayDataSource<T>
super(elements, dataRange);
}
+ public NumericalArrayDataSource(T[] elements, String dataRange, int col) {
+ super(elements, dataRange, col);
+ }
+
@Override
public String getFormatCode() {
return formatCode;
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> {
return true;
}
+ @Override
+ public int getColIndex() {
+ return cellRangeAddress.getFirstColumn();
+ }
+
@Override
public String getDataRangeReference() {
return cellRangeAddress.formatAsString(sheet.getSheetName(), true);
@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;
@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;
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);