diff --git src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java new file mode 100644 index 0000000..606e12a --- /dev/null +++ src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java @@ -0,0 +1,77 @@ +package org.apache.poi.xssf.usermodel.examples; + +import java.io.FileOutputStream; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Chart; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.charts.AxisCrosses; +import org.apache.poi.ss.usermodel.charts.AxisPosition; +import org.apache.poi.ss.usermodel.charts.ChartAxis; +import org.apache.poi.ss.usermodel.charts.ChartDataSource; +import org.apache.poi.ss.usermodel.charts.ChartLegend; +import org.apache.poi.ss.usermodel.charts.DataSources; +import org.apache.poi.ss.usermodel.charts.LegendPosition; +import org.apache.poi.ss.usermodel.charts.LineChartData; +import org.apache.poi.ss.usermodel.charts.ValueAxis; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +/** + * Line chart example. + * + * @author Martin Andersson + */ +public class LineChart { + + public static void main(String[] args) throws Exception { + Workbook wb = new XSSFWorkbook(); + Sheet sheet = wb.createSheet("linechart"); + final int NUM_OF_ROWS = 3; + final int NUM_OF_COLUMNS = 10; + + // Create a row and put some cells in it. Rows are 0 based. + Row row; + Cell cell; + for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) { + row = sheet.createRow((short) rowIndex); + for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) { + cell = row.createCell((short) colIndex); + cell.setCellValue(colIndex * (rowIndex + 1)); + } + } + + Drawing drawing = sheet.createDrawingPatriarch(); + ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15); + + Chart chart = drawing.createChart(anchor); + ChartLegend legend = chart.getOrCreateLegend(); + legend.setPosition(LegendPosition.TOP_RIGHT); + + LineChartData data = chart.getChartDataFactory().createLineChartData(); + + // Use a category axis for the bottom axis. + ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM); + ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT); + leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); + + ChartDataSource xs = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1)); + ChartDataSource ys1 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1)); + ChartDataSource ys2 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1)); + + + data.addSerie(xs, ys1); + data.addSerie(xs, ys2); + + chart.plot(data, bottomAxis, leftAxis); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx"); + wb.write(fileOut); + fileOut.close(); + } +} diff --git src/java/org/apache/poi/ss/usermodel/charts/ChartDataFactory.java src/java/org/apache/poi/ss/usermodel/charts/ChartDataFactory.java index f75e663..675322d 100644 --- src/java/org/apache/poi/ss/usermodel/charts/ChartDataFactory.java +++ src/java/org/apache/poi/ss/usermodel/charts/ChartDataFactory.java @@ -22,14 +22,19 @@ import org.apache.poi.util.Beta; /** * A factory for different charts data types. * - * @author Roman Kashitsyn + * @author Roman Kashitsyn, Martin Andersson */ @Beta public interface ChartDataFactory { - + /** * @return an appropriate ScatterChartData instance */ ScatterChartData createScatterChartData(); + /** + * @return a LineChartData instance + */ + LineChartData createLineChartData(); + } diff --git src/java/org/apache/poi/ss/usermodel/charts/LineChartData.java src/java/org/apache/poi/ss/usermodel/charts/LineChartData.java new file mode 100644 index 0000000..64633d4 --- /dev/null +++ src/java/org/apache/poi/ss/usermodel/charts/LineChartData.java @@ -0,0 +1,42 @@ +/* ==================================================================== + 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.ss.usermodel.charts; + +import java.util.List; + +import org.apache.poi.util.Beta; + +/** + * + * @author Martin Andersson + */ +@Beta +public interface LineChartData extends ChartData { + + /** + * @param categories data source for categories. + * @param values data source for values. + * @return a new line chart serie. + */ + LineChartSerie addSerie(ChartDataSource categories, ChartDataSource values); + + /** + * @return list of all series. + */ + List getSeries(); +} diff --git src/java/org/apache/poi/ss/usermodel/charts/LineChartSerie.java src/java/org/apache/poi/ss/usermodel/charts/LineChartSerie.java new file mode 100644 index 0000000..7d34e4e --- /dev/null +++ src/java/org/apache/poi/ss/usermodel/charts/LineChartSerie.java @@ -0,0 +1,41 @@ +/* ==================================================================== + 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.ss.usermodel.charts; + +import org.apache.poi.util.Beta; + +/** + * + * Represents a line chart serie. + * + * @author Martin Andersson + */ +@Beta +public interface LineChartSerie { + + /** + * @return data source used for category axis data. + */ + ChartDataSource getCategoryAxisData(); + + /** + * @return data source used for value axis. + */ + ChartDataSource getValues(); + +} diff --git src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartDataFactory.java src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartDataFactory.java index 57b826a..8bde83a 100644 --- src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartDataFactory.java +++ src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartDataFactory.java @@ -40,6 +40,13 @@ public class XSSFChartDataFactory implements ChartDataFactory { } /** + * @return new line charts data instance + */ + public XSSFLineChartData createLineChartData() { + return new XSSFLineChartData(); + } + + /** * @return factory instance */ public static XSSFChartDataFactory getInstance() { diff --git src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFLineChartData.java src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFLineChartData.java new file mode 100644 index 0000000..1fb8b56 --- /dev/null +++ src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFLineChartData.java @@ -0,0 +1,123 @@ +/* ==================================================================== + 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.xssf.usermodel.charts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ss.usermodel.Chart; +import org.apache.poi.ss.usermodel.charts.ChartAxis; +import org.apache.poi.ss.usermodel.charts.ChartDataSource; +import org.apache.poi.ss.usermodel.charts.LineChartData; +import org.apache.poi.ss.usermodel.charts.LineChartSerie; +import org.apache.poi.util.Beta; +import org.apache.poi.xssf.usermodel.XSSFChart; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineChart; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineSer; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea; +import org.openxmlformats.schemas.drawingml.x2006.chart.STMarkerStyle; + +/** + * + * @author Martin Andersson + */ +@Beta +public class XSSFLineChartData implements LineChartData { + + /** + * List of all data series. + */ + private List series; + + public XSSFLineChartData() { + series = new ArrayList(); + } + + static class Serie implements LineChartSerie { + private int id; + private int order; + private ChartDataSource categories; + private ChartDataSource values; + + protected Serie(int id, int order, + ChartDataSource categories, + ChartDataSource values) { + this.id = id; + this.order = order; + this.categories = categories; + this.values = values; + } + + public ChartDataSource getCategoryAxisData() { + return categories; + } + + public ChartDataSource getValues() { + return values; + } + + protected void addToChart(CTLineChart ctLineChart) { + CTLineSer ctLineSer = ctLineChart.addNewSer(); + ctLineSer.addNewIdx().setVal(id); + ctLineSer.addNewOrder().setVal(order); + + // No marker symbol on the chart line. + ctLineSer.addNewMarker().addNewSymbol().setVal(STMarkerStyle.NONE); + + CTAxDataSource catDS = ctLineSer.addNewCat(); + XSSFChartUtil.buildAxDataSource(catDS, categories); + CTNumDataSource valueDS = ctLineSer.addNewVal(); + XSSFChartUtil.buildNumDataSource(valueDS, values); + } + } + + public LineChartSerie addSerie(ChartDataSource categoryAxisData, ChartDataSource values) { + if (!values.isNumeric()) { + throw new IllegalArgumentException("Value data source must be numeric."); + } + int numOfSeries = series.size(); + Serie newSerie = new Serie(numOfSeries, numOfSeries, categoryAxisData, values); + series.add(newSerie); + return newSerie; + } + + public List getSeries() { + return series; + } + + public void fillChart(Chart chart, ChartAxis... axis) { + if (!(chart instanceof XSSFChart)) { + throw new IllegalArgumentException("Chart must be instance of XSSFChart"); + } + + XSSFChart xssfChart = (XSSFChart) chart; + CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea(); + CTLineChart lineChart = plotArea.addNewLineChart(); + lineChart.addNewVaryColors().setVal(false); + + for (Serie s : series) { + s.addToChart(lineChart); + } + + for (ChartAxis ax : axis) { + lineChart.addNewAxId().setVal(ax.getId()); + } + } +} diff --git src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFLineChartData.java src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFLineChartData.java new file mode 100644 index 0000000..8a24bd5 --- /dev/null +++ src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFLineChartData.java @@ -0,0 +1,54 @@ +package org.apache.poi.xssf.usermodel.charts; + +import junit.framework.TestCase; + +import org.apache.poi.ss.usermodel.Chart; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.charts.AxisPosition; +import org.apache.poi.ss.usermodel.charts.ChartAxis; +import org.apache.poi.ss.usermodel.charts.ChartDataSource; +import org.apache.poi.ss.usermodel.charts.DataSources; +import org.apache.poi.ss.usermodel.charts.LineChartData; +import org.apache.poi.ss.usermodel.charts.LineChartSerie; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.SheetBuilder; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +/** + * + * @author Martin Andersson + */ +public class TestXSSFLineChartData extends TestCase { + + private static final Object[][] plotData = { + {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"}, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + }; + + public void testOneSeriePlot() throws Exception { + Workbook wb = new XSSFWorkbook(); + Sheet sheet = new SheetBuilder(wb, plotData).build(); + Drawing drawing = sheet.createDrawingPatriarch(); + ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 1, 1, 10, 30); + Chart chart = drawing.createChart(anchor); + + ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM); + ChartAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT); + + LineChartData lineChartData = + chart.getChartDataFactory().createLineChartData(); + + ChartDataSource xs = DataSources.fromStringCellRange(sheet, CellRangeAddress.valueOf("A1:J1")); + ChartDataSource ys = DataSources.fromNumericCellRange(sheet, CellRangeAddress.valueOf("A2:J2")); + LineChartSerie serie = lineChartData.addSerie(xs, ys); + + assertNotNull(serie); + assertEquals(1, lineChartData.getSeries().size()); + assertTrue(lineChartData.getSeries().contains(serie)); + + chart.plot(lineChartData, bottomAxis, leftAxis); + } +}