package org.apache.poi.xssf.usermodel.examples;
import java.io.FileOutputStream;
-import java.util.Date;
-
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.ss.usermodel.charts.*;
-import org.apache.poi.xssf.usermodel.*;
-import org.apache.poi.xssf.usermodel.charts.*;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
* Illustrates how to create a simple scatter chart.
+ *
+ * @author Roman Kashitsyn
*/
public class ScatterChart {
- public static void main(String[]args) throws Exception {
- Workbook wb = new XSSFWorkbook();
- CreationHelper creationHelper = wb.getCreationHelper();
- Sheet sheet = wb.createSheet("Sheet 1");
- final int NUM_OF_ROWS = 3;
- final int NUM_OF_COLUMNS = 10;
+ public static void main(String[] args) throws Exception {
+ Workbook wb = new XSSFWorkbook();
+ Sheet sheet = wb.createSheet("Sheet 1");
+ 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));
+ }
+ }
- // 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);
- 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);
- Chart chart = drawing.createChart(anchor);
- ChartLegend legend = chart.getOrCreateLegend();
- legend.setPosition(LegendPosition.TOP_RIGHT);
+ ScatterChartData data = chart.getChartDataFactory().createScatterChartData();
- ScatterChartData data = chart.getChartDataFactory().createScatterChartData();
+ ValueAxis bottomAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.BOTTOM);
+ ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
+ leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
- ValueAxis bottomAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.BOTTOM);
- ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
+ ChartDataSource<Number> xs = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
+ ChartDataSource<Number> ys1 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
+ ChartDataSource<Number> ys2 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
- DataMarker xMarker = new DataMarker(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
- DataMarker y1Marker = new DataMarker(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
- DataMarker y2Marker = new DataMarker(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
-
- data.addSerie(xMarker, y1Marker);
- data.addSerie(xMarker, y2Marker);
+ data.addSerie(xs, ys1);
+ data.addSerie(xs, ys2);
- chart.plot(data, bottomAxis, leftAxis);
+ chart.plot(data, bottomAxis, leftAxis);
- // Write the output to a file
- FileOutputStream fileOut = new FileOutputStream("ooxml-scatter-chart.xlsx");
- wb.write(fileOut);
- fileOut.close();
- }
+ // Write the output to a file
+ FileOutputStream fileOut = new FileOutputStream("ooxml-scatter-chart.xlsx");
+ wb.write(fileOut);
+ fileOut.close();
+ }
}
package org.apache.poi.ss.usermodel.charts;
+import org.apache.poi.util.Beta;
+
/**
* High level representation of chart axis.
*
* @author Roman Kashitsyn
*/
+@Beta
public interface ChartAxis {
/**
package org.apache.poi.ss.usermodel.charts;
import org.apache.poi.ss.usermodel.Chart;
+import org.apache.poi.util.Beta;
/**
* A factory for different chart axis.
*
* @author Roman Kashitsyn
*/
+@Beta
public interface ChartAxisFactory {
/**
package org.apache.poi.ss.usermodel.charts;
import org.apache.poi.ss.usermodel.Chart;
+import org.apache.poi.util.Beta;
/**
- * A base for all chart data types.
+ * A base for all charts data types.
*
* @author Roman Kashitsyn
*/
+@Beta
public interface ChartData {
/**
- * Fills a chart with data specified by implementation.
+ * Fills a charts with data specified by implementation.
*
- * @param chart a chart to fill in
- * @param axis chart axis to use
+ * @param chart a charts to fill in
+ * @param axis charts axis to use
*/
void fillChart(Chart chart, ChartAxis... axis);
}
package org.apache.poi.ss.usermodel.charts;
+import org.apache.poi.util.Beta;
+
/**
- * A factory for different chart data types.
+ * A factory for different charts data types.
*
* @author Roman Kashitsyn
*/
+@Beta
public interface ChartDataFactory {
/**
--- /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.ss.usermodel.charts;
+
+import org.apache.poi.util.Beta;
+
+/**
+ * Represents data model of the charts.
+ *
+ * @param <T> type of points the data source contents
+ * @author Roman Kashitsyn
+ */
+@Beta
+public interface ChartDataSource<T> {
+
+ /**
+ * Return number of points contained by data source.
+ *
+ * @return number of points contained by data source
+ */
+ int getPointCount();
+
+ /**
+ * Returns point value at specified index.
+ *
+ * @param index index to value from
+ * @return point value at specified index.
+ * @throws {@code IndexOutOfBoundsException} if index
+ * parameter not in range {@code 0 <= index <= pointCount}
+ */
+ T getPointAt(int index);
+
+ /**
+ * Returns {@code true} if charts data source is valid cell range.
+ *
+ * @return {@code true} if charts data source is valid cell range
+ */
+ boolean isReference();
+
+ /**
+ * Returns {@code true} if data source points should be treated as numbers.
+ *
+ * @return {@code true} if data source points should be treated as numbers
+ */
+ boolean isNumeric();
+
+ /**
+ * Returns formula representation of the data source. It is only applicable
+ * for data source that is valid cell range.
+ *
+ * @return formula representation of the data source
+ * @throws {@code UnsupportedOperationException} if the data source is not a
+ * reference.
+ */
+ String getFormulaString();
+}
package org.apache.poi.ss.usermodel.charts;
+import org.apache.poi.util.Beta;
+
/**
* High level representation of chart legend.
*
* @author Roman Kashitsyn
*/
+@Beta
public interface ChartLegend extends ManuallyPositionable {
/**
--- /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.ss.usermodel.charts;
+
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.util.Beta;
+
+/**
+ * Class {@code DataSources} is a factory for {@link ChartDataSource} instances.
+ *
+ * @author Roman Kashitsyn
+ */
+@Beta
+public class DataSources {
+
+ private DataSources() {
+ }
+
+ public static <T> ChartDataSource<T> fromArray(T[] elements) {
+ return new ArrayDataSource<T>(elements);
+ }
+
+ public static ChartDataSource<Number> fromNumericCellRange(Sheet sheet, CellRangeAddress cellRangeAddress) {
+ return new AbstractCellRangeDataSource<Number>(sheet, cellRangeAddress) {
+ public Number getPointAt(int index) {
+ CellValue cellValue = getCellValueAt(index);
+ if (cellValue != null && cellValue.getCellType() == Cell.CELL_TYPE_NUMERIC) {
+ return Double.valueOf(cellValue.getNumberValue());
+ } else {
+ return null;
+ }
+ }
+
+ public boolean isNumeric() {
+ return true;
+ }
+ };
+ }
+
+ public static ChartDataSource<String> fromStringCellRange(Sheet sheet, CellRangeAddress cellRangeAddress) {
+ return new AbstractCellRangeDataSource<String>(sheet, cellRangeAddress) {
+ public String getPointAt(int index) {
+ CellValue cellValue = getCellValueAt(index);
+ if (cellValue != null && cellValue.getCellType() == Cell.CELL_TYPE_STRING) {
+ return cellValue.getStringValue();
+ } else {
+ return null;
+ }
+ }
+
+ public boolean isNumeric() {
+ return false;
+ }
+ };
+ }
+
+ private static class ArrayDataSource<T> implements ChartDataSource<T> {
+
+ private final T[] elements;
+
+ public ArrayDataSource(T[] elements) {
+ this.elements = elements;
+ }
+
+ public int getPointCount() {
+ return elements.length;
+ }
+
+ public T getPointAt(int index) {
+ return elements[index];
+ }
+
+ public boolean isReference() {
+ return false;
+ }
+
+ public boolean isNumeric() {
+ Class<?> arrayComponentType = elements.getClass().getComponentType();
+ return (Number.class.isAssignableFrom(arrayComponentType));
+ }
+
+ public String getFormulaString() {
+ throw new UnsupportedOperationException("Literal data source can not be expressed by reference.");
+ }
+ }
+
+ private abstract static class AbstractCellRangeDataSource<T> implements ChartDataSource<T> {
+ private final Sheet sheet;
+ private final CellRangeAddress cellRangeAddress;
+ private final int numOfCells;
+ private FormulaEvaluator evaluator;
+
+ protected AbstractCellRangeDataSource(Sheet sheet, CellRangeAddress cellRangeAddress) {
+ this.sheet = sheet;
+ // Make copy since CellRangeAddress is mutable.
+ this.cellRangeAddress = cellRangeAddress.copy();
+ this.numOfCells = this.cellRangeAddress.getNumberOfCells();
+ this.evaluator = sheet.getWorkbook().getCreationHelper().createFormulaEvaluator();
+ }
+
+ public int getPointCount() {
+ return numOfCells;
+ }
+
+ public boolean isReference() {
+ return true;
+ }
+
+ public String getFormulaString() {
+ return cellRangeAddress.formatAsString(sheet.getSheetName(), true);
+ }
+
+ protected CellValue getCellValueAt(int index) {
+ if (index < 0 || index >= numOfCells) {
+ throw new IndexOutOfBoundsException("Index must be between 0 and " +
+ (numOfCells - 1) + " (inclusive), given: " + index);
+ }
+ int firstRow = cellRangeAddress.getFirstRow();
+ int firstCol = cellRangeAddress.getFirstColumn();
+ int lastCol = cellRangeAddress.getLastColumn();
+ int width = lastCol - firstCol + 1;
+ int rowIndex = firstRow + index / width;
+ int cellIndex = firstCol + index % width;
+ Row row = sheet.getRow(rowIndex);
+ return (row == null) ? null : evaluator.evaluate(row.getCell(cellIndex));
+ }
+ }
+}
\r
package org.apache.poi.ss.usermodel.charts;\r
\r
+import org.apache.poi.util.Beta;\r
+\r
/**\r
* High level representation of chart element manual layout.\r
*\r
* @author Roman Kashitsyn\r
*/\r
+@Beta\r
public interface ManualLayout {\r
\r
/**\r
\r
package org.apache.poi.ss.usermodel.charts;\r
\r
+import org.apache.poi.util.Beta;\r
+\r
/**\r
* Abstraction of chart element that can be positioned with manual\r
* layout.\r
*\r
* @author Roman Kashitsyn\r
*/\r
+@Beta\r
public interface ManuallyPositionable {\r
\r
/**\r
package org.apache.poi.ss.usermodel.charts;
import java.util.List;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.util.DataMarker;
-
/**
* @author Roman Kashitsyn
*/
public interface ScatterChartData extends ChartData {
/**
- * @param xMarker data marker to be used for X value range
- * @param yMarker data marker to be used for Y value range
- * @return a new scatter chart serie
+ * @param xs data source to be used for X axis values
+ * @param ys data source to be used for Y axis values
+ * @return a new scatter charts serie
*/
- ScatterChartSerie addSerie(DataMarker xMarker, DataMarker yMarker);
+ ScatterChartSerie addSerie(ChartDataSource<?> xs, ChartDataSource<? extends Number> ys);
/**
* @return list of all series
package org.apache.poi.ss.usermodel.charts;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.util.DataMarker;
-import org.apache.poi.ss.usermodel.charts.ChartDataFactory;
+import org.apache.poi.util.Beta;
/**
+ * Represents scatter charts serie.
+ *
* @author Roman Kashitsyn
*/
+@Beta
public interface ScatterChartSerie {
- /**
- * @param xMarker data marker to use for X values.
- */
- void setXValues(DataMarker xMarker);
+ /**
+ * @return data source used for X axis values
+ */
+ ChartDataSource<?> getXValues();
- /**'
- * @param yMarker data marker to use for Y values.
- */
- void setYValues(DataMarker yMarker);
+ /**
+ * @return data source used for Y axis values
+ */
+ ChartDataSource<? extends Number> getYValues();
}
package org.apache.poi.ss.usermodel.charts;
+import org.apache.poi.util.Beta;
+
/**
* @author Roman Kashitsyn
*/
+@Beta
public interface ValueAxis extends ChartAxis {
/**
-/*\r
- * ====================================================================\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements. See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License. You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ====================================================================\r
- */\r
-\r
-package org.apache.poi.ss.util;\r
-\r
-import org.apache.poi.ss.usermodel.Sheet;\r
-\r
-/**\r
- * Represents data marker used in charts.\r
- * @author Roman Kashitsyn\r
- */\r
-public class DataMarker {\r
- \r
- private Sheet sheet;\r
- private CellRangeAddress range;\r
-\r
- /**\r
- * @param sheet the sheet where data located.\r
- * @param range the range within that sheet.\r
- */\r
- public DataMarker(Sheet sheet, CellRangeAddress range) {\r
- this.sheet = sheet;\r
- this.range = range;\r
- }\r
-\r
- /**\r
- * Returns the sheet marker points to.\r
- * @return sheet marker points to.\r
- */\r
- public Sheet getSheet() {\r
- return sheet;\r
- }\r
-\r
- /**\r
- * Sets sheet marker points to.\r
- * @param sheet new sheet for the marker.\r
- */\r
- public void setSheet(Sheet sheet) {\r
- this.sheet = sheet;\r
- }\r
-\r
- /**\r
- * Returns range of the marker.\r
- * @return range of cells marker points to.\r
- */\r
- public CellRangeAddress getRange() {\r
- return range;\r
- }\r
-\r
- /**\r
- * Sets range of the marker.\r
- * @param range new range for the marker.\r
- */\r
- public void setRange(CellRangeAddress range) {\r
- this.range = range;\r
- }\r
-\r
- /**\r
- * Formats data marker using canonical format, for example\r
- * `SheetName!$A$1:$A$5'.\r
- * @return formatted data marker.\r
- */\r
- public String formatAsString() {\r
- String sheetName = (sheet == null) ? (null) : (sheet.getSheetName());\r
- if (range == null) {\r
- return null;\r
- } else {\r
- return range.formatAsString(sheetName, true);\r
- }\r
- }\r
-}\r
import org.apache.poi.ss.usermodel.Cell;
/**
- * Class that provides useful sheet build capabilities. It can be used
- * in test cases to improve readability or in Swing applications with
- * tables.
+ * Class {@code SheetBuilder} provides an easy way of building workbook sheets
+ * from 2D array of Objects. It can be used in test cases to improve code
+ * readability or in Swing applications with tables.
*
* @author Roman Kashitsyn
*/
public class SheetBuilder {
- private Workbook workbook;
- private Object[][] cells;
+ private final Workbook workbook;
+ private final Object[][] cells;
private boolean shouldCreateEmptyCells = false;
+ private String sheetName = null;
public SheetBuilder(Workbook workbook, Object[][] cells) {
- this.workbook = workbook;
- this.cells = cells;
+ this.workbook = workbook;
+ this.cells = cells;
}
/**
- * @return true if null objects should be trated as empty cells
- * false otherwise
+ * Returns {@code true} if null array elements should be treated as empty
+ * cells.
+ *
+ * @return {@code true} if null objects should be treated as empty cells
+ * and {@code false} otherwise
*/
public boolean getCreateEmptyCells() {
- return shouldCreateEmptyCells;
+ return shouldCreateEmptyCells;
}
/**
- * @param shouldCreateEmptyCells true if null array elements should be
- * trated as empty cells
- * @return this
+ * Specifies if null array elements should be treated as empty cells.
+ *
+ * @param shouldCreateEmptyCells {@code true} if null array elements should be
+ * treated as empty cells
+ * @return {@code this}
*/
public SheetBuilder setCreateEmptyCells(boolean shouldCreateEmptyCells) {
- this.shouldCreateEmptyCells = shouldCreateEmptyCells;
- return this;
+ this.shouldCreateEmptyCells = shouldCreateEmptyCells;
+ return this;
+ }
+
+ /**
+ * Specifies name of the sheet to build. If not specified, default name (provided by
+ * workbook) will be used instead.
+ * @param sheetName sheet name to use
+ * @return {@code this}
+ */
+ public SheetBuilder setSheetName(String sheetName) {
+ this.sheetName = sheetName;
+ return this;
}
/**
* Builds sheet from parent workbook and 2D array with cell
* values. Creates rows anyway (even if row contains only null
- * cells), creates cells only if corresponding property is true.
+ * cells), creates cells if either corresponding array value is not
+ * null or createEmptyCells property is true.
* The conversion is performed in the following way:
- *
+ * <p/>
* <ul>
* <li>Numbers become numeric cells.</li>
* <li><code>java.util.Date</code> or <code>java.util.Calendar</code>
- * instances become date cells.</li>
+ * instances become date cells.</li>
* <li>String with leading '=' char become formulas (leading '='
- * trancated).</li>
+ * will be truncated).</li>
* <li>Other objects become strings via <code>Object.toString()</code>
- * method.</li>
+ * method call.</li>
* </ul>
*
* @return newly created sheet
*/
public Sheet build() {
- Sheet sheet = workbook.createSheet();
- Row currentRow = null;
- Cell currentCell = null;
+ Sheet sheet = (sheetName == null) ? workbook.createSheet() : workbook.createSheet(sheetName);
+ Row currentRow = null;
+ Cell currentCell = null;
- for (int rowIndex = 0; rowIndex < cells.length; ++rowIndex) {
- Object[] rowArray = cells[rowIndex];
- currentRow = sheet.createRow(rowIndex);
+ for (int rowIndex = 0; rowIndex < cells.length; ++rowIndex) {
+ Object[] rowArray = cells[rowIndex];
+ currentRow = sheet.createRow(rowIndex);
- for (int cellIndex = 0; cellIndex < rowArray.length; ++cellIndex) {
- Object cellValue = rowArray[cellIndex];
- if (cellValue != null || shouldCreateEmptyCells) {
- currentCell = currentRow.createCell(cellIndex);
- setCellValue(currentCell, cellValue);
- }
- }
- }
- return sheet;
+ for (int cellIndex = 0; cellIndex < rowArray.length; ++cellIndex) {
+ Object cellValue = rowArray[cellIndex];
+ if (cellValue != null || shouldCreateEmptyCells) {
+ currentCell = currentRow.createCell(cellIndex);
+ setCellValue(currentCell, cellValue);
+ }
+ }
+ }
+ return sheet;
}
/**
* Sets the cell value using object type information.
- * @param cell cell to change
+ *
+ * @param cell cell to change
* @param value value to set
*/
- public void setCellValue(Cell cell, Object value) {
- if (value == null || cell == null) {
- return;
- } else if (value instanceof Number) {
- double doubleValue = ((Number) value).doubleValue();
- cell.setCellValue(doubleValue);
- } else if (value instanceof Date) {
- cell.setCellValue((Date) value);
- } else if (value instanceof Calendar) {
- cell.setCellValue((Calendar) value);
- } else if (isFormulaDefinition(value)) {
- cell.setCellFormula(getFormula(value));
- } else {
- cell.setCellValue(value.toString());
- }
+ private void setCellValue(Cell cell, Object value) {
+ if (value == null || cell == null) {
+ return;
+ } else if (value instanceof Number) {
+ double doubleValue = ((Number) value).doubleValue();
+ cell.setCellValue(doubleValue);
+ } else if (value instanceof Date) {
+ cell.setCellValue((Date) value);
+ } else if (value instanceof Calendar) {
+ cell.setCellValue((Calendar) value);
+ } else if (isFormulaDefinition(value)) {
+ cell.setCellFormula(getFormula(value));
+ } else {
+ cell.setCellValue(value.toString());
+ }
}
private boolean isFormulaDefinition(Object obj) {
- if (obj instanceof String) {
- String str = (String) obj;
- if (str.length() < 2) {
- return false;
- } else {
- return ((String) obj).charAt(0) == '=';
- }
- } else {
- return false;
- }
+ if (obj instanceof String) {
+ String str = (String) obj;
+ if (str.length() < 2) {
+ return false;
+ } else {
+ return ((String) obj).charAt(0) == '=';
+ }
+ } else {
+ return false;
+ }
}
private String getFormula(Object obj) {
- return ((String) obj).substring(1);
+ return ((String) obj).substring(1);
}
}
\ No newline at end of file
package org.apache.poi.ss.util.cellwalk;
-
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.DataMarker;
/**
* Traverse cell range.
private CellRangeAddress range;
private boolean traverseEmptyCells;
- public CellWalk(DataMarker dm) {
- this(dm.getSheet(), dm.getRange());
- }
public CellWalk(Sheet sheet, CellRangeAddress range) {
- this.sheet = sheet;
- this.range = range;
- this.traverseEmptyCells = false;
+ this.sheet = sheet;
+ this.range = range;
+ this.traverseEmptyCells = false;
}
/**
* Should we call handler on empty (blank) cells. Default is
* false.
+ *
* @return true if handler should be called on empty (blank)
- * cells, false otherwise.
+ * cells, false otherwise.
*/
public boolean isTraverseEmptyCells() {
- return traverseEmptyCells;
+ return traverseEmptyCells;
}
/**
* Sets the traverseEmptyCells property.
+ *
* @param traverseEmptyCells new property value
*/
public void setTraverseEmptyCells(boolean traverseEmptyCells) {
- this.traverseEmptyCells = traverseEmptyCells;
+ this.traverseEmptyCells = traverseEmptyCells;
}
/**
* Traverse cell range from top left to bottom right cell.
+ *
* @param handler handler to call on each appropriate cell
*/
public void traverse(CellHandler handler) {
- int firstRow = range.getFirstRow();
- int lastRow = range.getLastRow();
- int firstColumn = range.getFirstColumn();
- int lastColumn = range.getLastColumn();
- final int width = lastColumn - firstColumn + 1;
- SimpleCellWalkContext ctx = new SimpleCellWalkContext();
- Row currentRow = null;
- Cell currentCell = null;
-
- for (ctx.rowNumber = firstRow; ctx.rowNumber <= lastRow; ++ctx.rowNumber) {
- currentRow = sheet.getRow(ctx.rowNumber);
- if (currentRow == null) {
- continue;
- }
- for (ctx.colNumber = firstColumn; ctx.colNumber <= lastColumn; ++ctx.colNumber) {
- currentCell = currentRow.getCell(ctx.colNumber);
-
- if (currentCell == null) {
- continue;
- }
- if (isEmpty(currentCell) && !traverseEmptyCells) {
- continue;
- }
-
- ctx.ordinalNumber =
- (ctx.rowNumber - firstRow) * width +
- (ctx.colNumber - firstColumn + 1);
-
- handler.onCell(currentCell, ctx);
- }
- }
+ int firstRow = range.getFirstRow();
+ int lastRow = range.getLastRow();
+ int firstColumn = range.getFirstColumn();
+ int lastColumn = range.getLastColumn();
+ final int width = lastColumn - firstColumn + 1;
+ SimpleCellWalkContext ctx = new SimpleCellWalkContext();
+ Row currentRow = null;
+ Cell currentCell = null;
+
+ for (ctx.rowNumber = firstRow; ctx.rowNumber <= lastRow; ++ctx.rowNumber) {
+ currentRow = sheet.getRow(ctx.rowNumber);
+ if (currentRow == null) {
+ continue;
+ }
+ for (ctx.colNumber = firstColumn; ctx.colNumber <= lastColumn; ++ctx.colNumber) {
+ currentCell = currentRow.getCell(ctx.colNumber);
+
+ if (currentCell == null) {
+ continue;
+ }
+ if (isEmpty(currentCell) && !traverseEmptyCells) {
+ continue;
+ }
+
+ ctx.ordinalNumber =
+ (ctx.rowNumber - firstRow) * width +
+ (ctx.colNumber - firstColumn + 1);
+
+ handler.onCell(currentCell, ctx);
+ }
+ }
}
private boolean isEmpty(Cell cell) {
- return (cell.getCellType() == Cell.CELL_TYPE_BLANK);
+ return (cell.getCellType() == Cell.CELL_TYPE_BLANK);
}
/**
* Inner class to hold walk context.
+ *
* @author Roman Kashitsyn
*/
private class SimpleCellWalkContext implements CellWalkContext {
- public long ordinalNumber = 0;
- public int rowNumber = 0;
- public int colNumber = 0;
+ public long ordinalNumber = 0;
+ public int rowNumber = 0;
+ public int colNumber = 0;
- public long getOrdinalNumber() {
- return ordinalNumber;
- }
+ public long getOrdinalNumber() {
+ return ordinalNumber;
+ }
- public int getRowNumber() {
- return rowNumber;
- }
+ public int getRowNumber() {
+ return rowNumber;
+ }
- public int getColumnNumber() {
- return colNumber;
- }
+ public int getColumnNumber() {
+ return colNumber;
+ }
}
}
import org.apache.poi.ss.usermodel.charts.AxisPosition;
import org.apache.poi.ss.usermodel.charts.AxisOrientation;
import org.apache.poi.ss.usermodel.charts.AxisCrosses;
+import org.apache.poi.util.Beta;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxPos;
*
* @author Roman Kashitsyn
*/
+@Beta
public abstract class XSSFChartAxis implements ChartAxis {
protected XSSFChart chart;
package org.apache.poi.xssf.usermodel.charts;
import org.apache.poi.ss.usermodel.charts.*;
+import org.apache.poi.util.Beta;
/**
* @author Roman Kashitsyn
*/
+@Beta
public class XSSFChartDataFactory implements ChartDataFactory {
private static XSSFChartDataFactory instance;
}
/**
- * @return new scatter chart data instance
+ * @return new scatter charts data instance
*/
public XSSFScatterChartData createScatterChartData() {
return new XSSFScatterChartData();
package org.apache.poi.xssf.usermodel.charts;
+import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.ss.usermodel.charts.ChartLegend;
import org.apache.poi.ss.usermodel.charts.LegendPosition;
* Represents a SpreadsheetML chart legend
* @author Roman Kashitsyn
*/
+@Beta
public final class XSSFChartLegend implements ChartLegend {
/**
--- /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.xssf.usermodel.charts;
+
+import org.apache.poi.ss.usermodel.charts.ChartDataSource;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
+
+/**
+ * Package private class with utility methods.
+ *
+ * @author Roman Kashitsyn
+ */
+class XSSFChartUtil {
+
+ private XSSFChartUtil() {}
+
+ /**
+ * Builds CTAxDataSource object content from POI ChartDataSource.
+ * @param ctAxDataSource OOXML data source to build
+ * @param dataSource POI data source to use
+ */
+ public static void buildAxDataSource(CTAxDataSource ctAxDataSource, ChartDataSource<?> dataSource) {
+ if (dataSource.isNumeric()) {
+ if (dataSource.isReference()) {
+ buildNumRef(ctAxDataSource.addNewNumRef(), dataSource);
+ } else {
+ buildNumLit(ctAxDataSource.addNewNumLit(), dataSource);
+ }
+ } else {
+ if (dataSource.isReference()) {
+ buildStrRef(ctAxDataSource.addNewStrRef(), dataSource);
+ } else {
+ buildStrLit(ctAxDataSource.addNewStrLit(), dataSource);
+ }
+ }
+ }
+
+ /**
+ * Builds CTNumDataSource object content from POI ChartDataSource
+ * @param ctNumDataSource OOXML data source to build
+ * @param dataSource POI data source to use
+ */
+ public static void buildNumDataSource(CTNumDataSource ctNumDataSource,
+ ChartDataSource<? extends Number> dataSource) {
+ if (dataSource.isReference()) {
+ buildNumRef(ctNumDataSource.addNewNumRef(), dataSource);
+ } else {
+ buildNumLit(ctNumDataSource.addNewNumLit(), dataSource);
+ }
+ }
+
+ private static void buildNumRef(CTNumRef ctNumRef, ChartDataSource<?> dataSource) {
+ ctNumRef.setF(dataSource.getFormulaString());
+ CTNumData cache = ctNumRef.addNewNumCache();
+ fillNumCache(cache, dataSource);
+ }
+
+ private static void buildNumLit(CTNumData ctNumData, ChartDataSource<?> dataSource) {
+ fillNumCache(ctNumData, dataSource);
+ }
+
+ private static void buildStrRef(CTStrRef ctStrRef, ChartDataSource<?> dataSource) {
+ ctStrRef.setF(dataSource.getFormulaString());
+ CTStrData cache = ctStrRef.addNewStrCache();
+ fillStringCache(cache, dataSource);
+ }
+
+ private static void buildStrLit(CTStrData ctStrData, ChartDataSource<?> dataSource) {
+ fillStringCache(ctStrData, dataSource);
+ }
+
+ private static void fillStringCache(CTStrData cache, ChartDataSource<?> dataSource) {
+ int numOfPoints = dataSource.getPointCount();
+ cache.addNewPtCount().setVal(numOfPoints);
+ for (int i = 0; i < numOfPoints; ++i) {
+ Object value = dataSource.getPointAt(i);
+ if (value != null) {
+ CTStrVal ctStrVal = cache.addNewPt();
+ ctStrVal.setIdx(i);
+ ctStrVal.setV(value.toString());
+ }
+ }
+
+ }
+
+ private static void fillNumCache(CTNumData cache, ChartDataSource<?> dataSource) {
+ int numOfPoints = dataSource.getPointCount();
+ cache.addNewPtCount().setVal(numOfPoints);
+ for (int i = 0; i < numOfPoints; ++i) {
+ Number value = (Number) dataSource.getPointAt(i);
+ if (value != null) {
+ CTNumVal ctNumVal = cache.addNewPt();
+ ctNumVal.setIdx(i);
+ ctNumVal.setV(value.toString());
+ }
+ }
+ }
+}
\r
package org.apache.poi.xssf.usermodel.charts;\r
\r
+import org.apache.poi.util.Beta;\r
import org.apache.poi.util.Internal;\r
import org.apache.poi.ss.usermodel.charts.ManualLayout;\r
import org.apache.poi.ss.usermodel.charts.LayoutMode;\r
* Represents a SpreadsheetML manual layout.\r
* @author Roman Kashitsyn\r
*/\r
+@Beta\r
public final class XSSFManualLayout implements ManualLayout {\r
\r
/**\r
+++ /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.xssf.usermodel.charts;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.CellValue;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.NumberToTextConverter;
-import org.apache.poi.ss.util.DataMarker;
-import org.apache.poi.ss.util.cellwalk.CellWalk;
-import org.apache.poi.ss.util.cellwalk.CellHandler;
-import org.apache.poi.ss.util.cellwalk.CellWalkContext;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumRef;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumData;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumVal;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTUnsignedInt;
-
-/**
- * Package private class to fill chart's number reference with cached
- * numeric values. If a formula-typed cell referenced by data marker,
- * cell's value will be calculated and placed to cache. Numeric cells
- * will be placed to cache as is. Non-numeric cells will be ignored.
- *
- * @author Roman Kashitsyn
- */
-class XSSFNumberCache {
-
- private CTNumData ctNumData;
-
- XSSFNumberCache(CTNumData ctNumData) {
- this.ctNumData = ctNumData;
- }
-
- /**
- * Builds new numeric cache container.
- * @param marker data marker to use for cache evaluation
- * @param ctNumRef parent number reference
- * @return numeric cache instance
- */
- static XSSFNumberCache buildCache(DataMarker marker, CTNumRef ctNumRef) {
- CellRangeAddress range = marker.getRange();
- int numOfPoints = range.getNumberOfCells();
-
- if (numOfPoints == 0) {
- // Nothing to do.
- return null;
- }
-
- XSSFNumberCache cache = new XSSFNumberCache(ctNumRef.addNewNumCache());
- cache.setPointCount(numOfPoints);
-
- Workbook wb = marker.getSheet().getWorkbook();
- FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
-
- CellWalk cellWalk = new CellWalk(marker);
- NumCacheCellHandler numCacheHandler = cache.new NumCacheCellHandler(evaluator);
- cellWalk.traverse(numCacheHandler);
- return cache;
- }
-
- /**
- * Returns total count of points in cache. Some (or even all) of
- * them might be empty.
- * @return total count of points in cache
- */
- long getPointCount() {
- CTUnsignedInt pointCount = ctNumData.getPtCount();
- if (pointCount != null) {
- return pointCount.getVal();
- } else {
- return 0L;
- }
- }
-
- /**
- * Returns cache value at specified index.
- * @param index index of the point in cache
- * @return point value
- */
- double getValueAt(int index) {
- /* TODO: consider more effective algorithm. Left as is since
- * this method should be invoked mostly in tests. */
- for (CTNumVal pt : ctNumData.getPtList()) {
- if (pt.getIdx() == index) {
- return Double.valueOf(pt.getV()).doubleValue();
- }
- }
- return 0.0;
- }
-
- private void setPointCount(int numOfPoints) {
- ctNumData.addNewPtCount().setVal(numOfPoints);
- }
-
- private class NumCacheCellHandler implements CellHandler {
-
- private FormulaEvaluator evaluator;
-
- public NumCacheCellHandler(FormulaEvaluator evaluator) {
- this.evaluator = evaluator;
- }
-
- public void onCell(Cell cell, CellWalkContext ctx) {
- double pointValue = getOrEvalCellValue(cell);
- /* Silently ignore non-numeric values.
- * This is Office default behaviour. */
- if (Double.isNaN(pointValue)) {
- return;
- }
-
- CTNumVal point = ctNumData.addNewPt();
- point.setIdx(ctx.getOrdinalNumber());
- point.setV(NumberToTextConverter.toText(pointValue));
- }
-
- private double getOrEvalCellValue(Cell cell) {
- int cellType = cell.getCellType();
-
- if (cellType == Cell.CELL_TYPE_NUMERIC) {
- return cell.getNumericCellValue();
- } else if (cellType == Cell.CELL_TYPE_FORMULA) {
- CellValue value = evaluator.evaluate(cell);
- if (value.getCellType() == Cell.CELL_TYPE_NUMERIC) {
- return value.getNumberValue();
- }
- }
- return Double.NaN;
- }
-
- }
-}
package org.apache.poi.xssf.usermodel.charts;
-import java.util.List;
-import java.util.ArrayList;
-
import org.apache.poi.ss.usermodel.Chart;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.util.DataMarker;
+import org.apache.poi.ss.usermodel.charts.ChartAxis;
+import org.apache.poi.ss.usermodel.charts.ChartDataSource;
import org.apache.poi.ss.usermodel.charts.ScatterChartData;
import org.apache.poi.ss.usermodel.charts.ScatterChartSerie;
-import org.apache.poi.ss.usermodel.charts.ChartDataFactory;
-import org.apache.poi.ss.usermodel.charts.ChartAxis;
+import org.apache.poi.util.Beta;
+import org.apache.poi.xssf.usermodel.XSSFChart;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterChart;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterStyle;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterSer;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumRef;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumFmt;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx;
-import org.openxmlformats.schemas.drawingml.x2006.chart.STScatterStyle;
-import org.openxmlformats.schemas.drawingml.x2006.chart.STCrosses;
-import org.openxmlformats.schemas.drawingml.x2006.chart.STCrossBetween;
-import org.openxmlformats.schemas.drawingml.x2006.chart.STOrientation;
-import org.openxmlformats.schemas.drawingml.x2006.chart.STTickLblPos;
-import org.openxmlformats.schemas.drawingml.x2006.chart.STAxPos;
+import java.util.ArrayList;
+import java.util.List;
-import org.apache.poi.xssf.usermodel.XSSFChart;
/**
- * Represents DrawingML scatter chart.
+ * Represents DrawingML scatter charts.
*
* @author Roman Kashitsyn
*/
+@Beta
public class XSSFScatterChartData implements ScatterChartData {
/**
private List<Serie> series;
public XSSFScatterChartData() {
- series = new ArrayList<Serie>();
+ series = new ArrayList<Serie>();
}
/**
* Package private ScatterChartSerie implementation.
*/
static class Serie implements ScatterChartSerie {
- private int id;
- private int order;
- private boolean useCache;
- private DataMarker xMarker;
- private DataMarker yMarker;
- private XSSFNumberCache lastCaclulatedXCache;
- private XSSFNumberCache lastCalculatedYCache;
-
- protected Serie(int id, int order) {
- super();
- this.id = id;
- this.order = order;
- this.useCache = true;
- }
-
- public void setXValues(DataMarker marker) {
- xMarker = marker;
- }
-
- public void setYValues(DataMarker marker) {
- yMarker = marker;
- }
-
- /**
- * @param useCache if true, cached results will be added on plot
- */
- public void setUseCache(boolean useCache) {
- this.useCache = useCache;
- }
-
- /**
- * Returns last calculated number cache for X axis.
- * @return last calculated number cache for X axis.
- */
- XSSFNumberCache getLastCaculatedXCache() {
- return lastCaclulatedXCache;
- }
-
- /**
- * Returns last calculated number cache for Y axis.
- * @return last calculated number cache for Y axis.
- */
- XSSFNumberCache getLastCalculatedYCache() {
- return lastCalculatedYCache;
- }
-
- protected void addToChart(CTScatterChart ctScatterChart) {
- CTScatterSer scatterSer = ctScatterChart.addNewSer();
- scatterSer.addNewIdx().setVal(this.id);
- scatterSer.addNewOrder().setVal(this.order);
-
- /* TODO: add some logic to automatically recognize cell
- * types and choose appropriate data representation for
- * X axis.
- */
- CTAxDataSource xVal = scatterSer.addNewXVal();
- CTNumRef xNumRef = xVal.addNewNumRef();
- xNumRef.setF(xMarker.formatAsString());
-
- CTNumDataSource yVal = scatterSer.addNewYVal();
- CTNumRef yNumRef = yVal.addNewNumRef();
- yNumRef.setF(yMarker.formatAsString());
-
- if (useCache) {
- /* We can not store cache since markers are not immutable */
- XSSFNumberCache.buildCache(xMarker, xNumRef);
- lastCalculatedYCache = XSSFNumberCache.buildCache(yMarker, yNumRef);
- }
- }
+ private int id;
+ private int order;
+ private ChartDataSource<?> xs;
+ private ChartDataSource<? extends Number> ys;
+
+ protected Serie(int id, int order,
+ ChartDataSource<?> xs,
+ ChartDataSource<? extends Number> ys) {
+ super();
+ this.id = id;
+ this.order = order;
+ this.xs = xs;
+ this.ys = ys;
+ }
+
+ /**
+ * Returns data source used for X axis values.
+ * @return data source used for X axis values
+ */
+ public ChartDataSource<?> getXValues() {
+ return xs;
+ }
+
+ /**
+ * Returns data source used for Y axis values.
+ * @return data source used for Y axis values
+ */
+ public ChartDataSource<? extends Number> getYValues() {
+ return ys;
+ }
+
+ protected void addToChart(CTScatterChart ctScatterChart) {
+ CTScatterSer scatterSer = ctScatterChart.addNewSer();
+ scatterSer.addNewIdx().setVal(this.id);
+ scatterSer.addNewOrder().setVal(this.order);
+
+ CTAxDataSource xVal = scatterSer.addNewXVal();
+ XSSFChartUtil.buildAxDataSource(xVal, xs);
+
+ CTNumDataSource yVal = scatterSer.addNewYVal();
+ XSSFChartUtil.buildNumDataSource(yVal, ys);
+ }
}
- public ScatterChartSerie addSerie(DataMarker xMarker, DataMarker yMarker) {
- int numOfSeries = series.size();
- Serie newSerie = new Serie(numOfSeries, numOfSeries);
- newSerie.setXValues(xMarker);
- newSerie.setYValues(yMarker);
- series.add(newSerie);
- return newSerie;
+ public ScatterChartSerie addSerie(ChartDataSource<?> xs,
+ ChartDataSource<? extends Number> ys) {
+ if (!ys.isNumeric()) {
+ throw new IllegalArgumentException("Y axis data source must be numeric.");
+ }
+ int numOfSeries = series.size();
+ Serie newSerie = new Serie(numOfSeries, numOfSeries, xs, ys);
+ series.add(newSerie);
+ return newSerie;
}
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();
- CTScatterChart scatterChart = plotArea.addNewScatterChart();
- addStyle(scatterChart);
-
- for (Serie s : series) {
- s.addToChart(scatterChart);
- }
-
- for (ChartAxis ax : axis) {
- scatterChart.addNewAxId().setVal(ax.getId());
- }
+ if (!(chart instanceof XSSFChart)) {
+ throw new IllegalArgumentException("Chart must be instance of XSSFChart");
+ }
+
+ XSSFChart xssfChart = (XSSFChart) chart;
+ CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea();
+ CTScatterChart scatterChart = plotArea.addNewScatterChart();
+ addStyle(scatterChart);
+
+ for (Serie s : series) {
+ s.addToChart(scatterChart);
+ }
+
+ for (ChartAxis ax : axis) {
+ scatterChart.addNewAxId().setVal(ax.getId());
+ }
}
public List<? extends Serie> getSeries() {
- return series;
+ return series;
}
private void addStyle(CTScatterChart ctScatterChart) {
- CTScatterStyle scatterStyle = ctScatterChart.addNewScatterStyle();
- scatterStyle.setVal(STScatterStyle.LINE_MARKER);
+ CTScatterStyle scatterStyle = ctScatterChart.addNewScatterStyle();
+ scatterStyle.setVal(STScatterStyle.LINE_MARKER);
}
}
import org.apache.poi.ss.usermodel.charts.AxisCrossBetween;
import org.apache.poi.ss.usermodel.charts.AxisCrosses;
+import org.apache.poi.util.Beta;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxPos;
*
* @author Roman Kashitsyn
*/
+@Beta
public class XSSFValueAxis extends XSSFChartAxis implements ValueAxis {
private CTValAx ctValAx;
XSSFChartSheet sheet = (XSSFChartSheet)wb.getSheetAt(2);
for(Row row : sheet) {
- fail("Row iterator for chart sheets should return zero rows");
+ fail("Row iterator for charts sheets should return zero rows");
}
//access to a arbitrary row
assertEquals(null, sheet.getRow(1));
}
/**
- * Problems with XSSFWorkbook.removeSheetAt when workbook contains chart
+ * Problems with XSSFWorkbook.removeSheetAt when workbook contains charts
*/
public void testBug47813() {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("47813.xlsx");
+++ /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.xssf.usermodel.charts;
-
-import org.apache.poi.ss.usermodel.*;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.DataMarker;
-import org.apache.poi.ss.util.SheetBuilder;
-import org.apache.poi.ss.usermodel.charts.*;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-
-import junit.framework.TestCase;
-
-public class TestXSSFNumberCache extends TestCase {
- private static Object[][] plotData = {
- {0, 1, 2, 3, 4},
- {0, "=B1*2", "=C1*2", "=D1*2", "=E1*4"}
- };
-
- public void testFormulaCache() {
- 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().createValueAxis(AxisPosition.BOTTOM);
- ChartAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
-
- ScatterChartData scatterChartData =
- chart.getChartDataFactory().createScatterChartData();
-
- DataMarker xMarker = new DataMarker(sheet, CellRangeAddress.valueOf("A1:E1"));
- DataMarker yMarker = new DataMarker(sheet, CellRangeAddress.valueOf("A2:E2"));
- ScatterChartSerie serie = scatterChartData.addSerie(xMarker, yMarker);
-
- chart.plot(scatterChartData, bottomAxis, leftAxis);
-
- XSSFScatterChartData.Serie xssfScatterSerie =
- (XSSFScatterChartData.Serie) serie;
- XSSFNumberCache yCache = xssfScatterSerie.getLastCalculatedYCache();
-
- assertEquals(5, yCache.getPointCount());
- assertEquals(4.0, yCache.getValueAt(3), 0.00001);
- assertEquals(16.0, yCache.getValueAt(5), 0.00001);
- }
-
-
-}
\ No newline at end of file
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.DataMarker;
import org.apache.poi.ss.util.SheetBuilder;
import org.apache.poi.ss.usermodel.charts.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
* Tests for XSSFScatterChartData.
+ *
* @author Roman Kashitsyn
*/
-public final class TestXSSFScatterChartData extends TestCase {
+public final class TestXSSFScatterChartData extends TestCase {
- private static Object[][] plotData = new Object[][] {
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+ 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);
+ 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().createValueAxis(AxisPosition.BOTTOM);
- ChartAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
+ ChartAxis bottomAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.BOTTOM);
+ ChartAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
- ScatterChartData scatterChartData =
- chart.getChartDataFactory().createScatterChartData();
+ ScatterChartData scatterChartData =
+ chart.getChartDataFactory().createScatterChartData();
- DataMarker xMarker = new DataMarker(sheet, CellRangeAddress.valueOf("A1:A10"));
- DataMarker yMarker = new DataMarker(sheet, CellRangeAddress.valueOf("B1:B10"));
- ScatterChartSerie serie = scatterChartData.addSerie(xMarker, yMarker);
+ ChartDataSource<String> xs = DataSources.fromStringCellRange(sheet, CellRangeAddress.valueOf("A1:J1"));
+ ChartDataSource<Number> ys = DataSources.fromNumericCellRange(sheet, CellRangeAddress.valueOf("A2:J2"));
+ ScatterChartSerie serie = scatterChartData.addSerie(xs, ys);
- assertEquals(1, scatterChartData.getSeries().size());
+ assertNotNull(serie);
+ assertEquals(1, scatterChartData.getSeries().size());
+ assertTrue(scatterChartData.getSeries().contains(serie));
- chart.plot(scatterChartData, bottomAxis, leftAxis);
+ chart.plot(scatterChartData, bottomAxis, leftAxis);
}
-
}
--- /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.ss.usermodel.charts;
+
+import junit.framework.TestCase;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.SheetBuilder;
+
+/**
+ * Tests for {@link org.apache.poi.ss.usermodel.charts.DataSources}.
+ *
+ * @author Roman Kashitsyn
+ */
+public class TestDataSources extends TestCase {
+
+ private static final Object[][] numericCells = {
+ {0.0, 1.0, 2.0, 3.0, 4.0},
+ {0.0, "=B1*2", "=C1*2", "=D1*2", "=E1*2"}
+ };
+
+ private static final Object[][] stringCells = {
+ { 1, 2, 3, 4, 5},
+ {"A", "B", "C", "D", "E"}
+ };
+
+ private static final Object[][] mixedCells = {
+ {1.0, "2.0", 3.0, "4.0", 5.0, "6.0"}
+ };
+
+ public void testNumericArrayDataSource() {
+ Double[] doubles = new Double[]{1.0, 2.0, 3.0, 4.0, 5.0};
+ ChartDataSource<Double> doubleDataSource = DataSources.fromArray(doubles);
+ assertTrue(doubleDataSource.isNumeric());
+ assertFalse(doubleDataSource.isReference());
+ assertDataSourceIsEqualToArray(doubleDataSource, doubles);
+ }
+
+ public void testStringArrayDataSource() {
+ String[] strings = new String[]{"one", "two", "three", "four", "five"};
+ ChartDataSource<String> stringDataSource = DataSources.fromArray(strings);
+ assertFalse(stringDataSource.isNumeric());
+ assertFalse(stringDataSource.isReference());
+ assertDataSourceIsEqualToArray(stringDataSource, strings);
+ }
+
+ public void testNumericCellDataSource() {
+ Workbook wb = new HSSFWorkbook();
+ Sheet sheet = new SheetBuilder(wb, numericCells).build();
+ CellRangeAddress numCellRange = CellRangeAddress.valueOf("A2:E2");
+ ChartDataSource<Number> numDataSource = DataSources.fromNumericCellRange(sheet, numCellRange);
+ assertTrue(numDataSource.isReference());
+ assertTrue(numDataSource.isNumeric());
+ assertEquals(numericCells[0].length, numDataSource.getPointCount());
+ for (int i = 0; i < numericCells[0].length; ++i) {
+ assertEquals(((Number) numericCells[0][i]).doubleValue() * 2,
+ numDataSource.getPointAt(i).doubleValue(), 0.00001);
+ }
+ }
+
+ public void testStringCellDataSource() {
+ Workbook wb = new HSSFWorkbook();
+ Sheet sheet = new SheetBuilder(wb, stringCells).build();
+ CellRangeAddress numCellRange = CellRangeAddress.valueOf("A2:E2");
+ ChartDataSource<String> numDataSource = DataSources.fromStringCellRange(sheet, numCellRange);
+ assertTrue(numDataSource.isReference());
+ assertFalse(numDataSource.isNumeric());
+ assertEquals(numericCells[0].length, numDataSource.getPointCount());
+ for (int i = 0; i < stringCells[1].length; ++i) {
+ assertEquals(stringCells[1][i], numDataSource.getPointAt(i));
+ }
+ }
+
+ public void testMixedCellDataSource() {
+ Workbook wb = new HSSFWorkbook();
+ Sheet sheet = new SheetBuilder(wb, mixedCells).build();
+ CellRangeAddress mixedCellRange = CellRangeAddress.valueOf("A1:F1");
+ ChartDataSource<String> strDataSource = DataSources.fromStringCellRange(sheet, mixedCellRange);
+ ChartDataSource<Number> numDataSource = DataSources.fromNumericCellRange(sheet, mixedCellRange);
+ for (int i = 0; i < mixedCells[0].length; ++i) {
+ if (i % 2 == 0) {
+ assertNull(strDataSource.getPointAt(i));
+ assertEquals(((Number) mixedCells[0][i]).doubleValue(),
+ numDataSource.getPointAt(i).doubleValue(), 0.00001);
+ } else {
+ assertNull(numDataSource.getPointAt(i));
+ assertEquals(mixedCells[0][i], strDataSource.getPointAt(i));
+ }
+ }
+ }
+
+ public void testIOBExceptionOnInvalidIndex() {
+ Workbook wb = new HSSFWorkbook();
+ Sheet sheet = new SheetBuilder(wb, numericCells).build();
+ CellRangeAddress rangeAddress = CellRangeAddress.valueOf("A2:E2");
+ ChartDataSource<Number> numDataSource = DataSources.fromNumericCellRange(sheet, rangeAddress);
+ IndexOutOfBoundsException exception = null;
+ try {
+ numDataSource.getPointAt(-1);
+ } catch (IndexOutOfBoundsException e) {
+ exception = e;
+ }
+ assertNotNull(exception);
+
+ exception = null;
+ try {
+ numDataSource.getPointAt(numDataSource.getPointCount());
+ } catch (IndexOutOfBoundsException e) {
+ exception = e;
+ }
+ assertNotNull(exception);
+ }
+
+ private <T> void assertDataSourceIsEqualToArray(ChartDataSource<T> ds, T[] array) {
+ assertEquals(ds.getPointCount(), array.length);
+ for (int i = 0; i < array.length; ++i) {
+ assertEquals(ds.getPointAt(i), array[i]);
+ }
+ }
+}
/**
* Tests SheetBuilder.
+ *
* @see org.apache.poi.ss.util.SheetBuilder
*/
public final class TestSheetBuilder extends TestCase {
-
- private static Object[][] testData = new Object[][] {
- { 1, 2, 3},
- {new Date(), null, null},
- { "one", "two", "=A1+B2"}
+
+ private static Object[][] testData = new Object[][]{
+ {1, 2, 3},
+ {new Date(), null, null},
+ {"one", "two", "=A1+B2"}
};
public void testNotCreateEmptyCells() {
- Workbook wb = new HSSFWorkbook();
- Sheet sheet = new SheetBuilder(wb, testData).build();
-
- assertEquals(sheet.getPhysicalNumberOfRows(), 3);
-
- Row firstRow = sheet.getRow(0);
- Cell firstCell = firstRow.getCell(0);
-
- assertEquals(firstCell.getCellType(), Cell.CELL_TYPE_NUMERIC);
- assertEquals(1.0, firstCell.getNumericCellValue(), 0.00001);
-
-
- Row secondRow = sheet.getRow(1);
- assertNotNull(secondRow.getCell(0));
- assertNull(secondRow.getCell(2));
-
- Row thirdRow = sheet.getRow(2);
- assertEquals(Cell.CELL_TYPE_STRING, thirdRow.getCell(0).getCellType());
- String cellValue = thirdRow.getCell(0).getStringCellValue();
- assertEquals(testData[2][0].toString(), cellValue);
-
- assertEquals(Cell.CELL_TYPE_FORMULA, thirdRow.getCell(2).getCellType());
- assertEquals("A1+B2", thirdRow.getCell(2).getCellFormula());
+ Workbook wb = new HSSFWorkbook();
+ Sheet sheet = new SheetBuilder(wb, testData).build();
+
+ assertEquals(sheet.getPhysicalNumberOfRows(), 3);
+
+ Row firstRow = sheet.getRow(0);
+ Cell firstCell = firstRow.getCell(0);
+
+ assertEquals(firstCell.getCellType(), Cell.CELL_TYPE_NUMERIC);
+ assertEquals(1.0, firstCell.getNumericCellValue(), 0.00001);
+
+
+ Row secondRow = sheet.getRow(1);
+ assertNotNull(secondRow.getCell(0));
+ assertNull(secondRow.getCell(2));
+
+ Row thirdRow = sheet.getRow(2);
+ assertEquals(Cell.CELL_TYPE_STRING, thirdRow.getCell(0).getCellType());
+ String cellValue = thirdRow.getCell(0).getStringCellValue();
+ assertEquals(testData[2][0].toString(), cellValue);
+
+ assertEquals(Cell.CELL_TYPE_FORMULA, thirdRow.getCell(2).getCellType());
+ assertEquals("A1+B2", thirdRow.getCell(2).getCellFormula());
}
public void testEmptyCells() {
- Workbook wb = new HSSFWorkbook();
- Sheet sheet = new SheetBuilder(wb, testData).setCreateEmptyCells(true).build();
-
- Cell emptyCell = sheet.getRow(1).getCell(1);
- assertNotNull(emptyCell);
- assertEquals(Cell.CELL_TYPE_BLANK, emptyCell.getCellType());
+ Workbook wb = new HSSFWorkbook();
+ Sheet sheet = new SheetBuilder(wb, testData).setCreateEmptyCells(true).build();
+
+ Cell emptyCell = sheet.getRow(1).getCell(1);
+ assertNotNull(emptyCell);
+ assertEquals(Cell.CELL_TYPE_BLANK, emptyCell.getCellType());
}
+ public void testSheetName() {
+ final String sheetName = "TEST SHEET NAME";
+ Workbook wb = new HSSFWorkbook();
+ Sheet sheet = new SheetBuilder(wb, testData).setSheetName(sheetName).build();
+ assertEquals(sheetName, sheet.getSheetName());
+ }
}
\ No newline at end of file