From: Yegor Kozlov Date: Sat, 10 Sep 2011 19:00:47 +0000 (+0000) Subject: more progress with xssf chart api, see Bug 51196 X-Git-Tag: REL_3_8_BETA5~178 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=e4b2a66d0915c6487a95d87a3e082847d8557107;p=poi.git more progress with xssf chart api, see Bug 51196 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1167579 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/ScatterChart.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/ScatterChart.java index 3df1d90acf..f0a94777f0 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/ScatterChart.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/ScatterChart.java @@ -20,63 +20,61 @@ 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 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)); - 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(); + } } diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ChartAxis.java b/src/java/org/apache/poi/ss/usermodel/charts/ChartAxis.java index 6542f991bf..e4ccdb5db8 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ChartAxis.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ChartAxis.java @@ -17,11 +17,14 @@ 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 { /** diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ChartAxisFactory.java b/src/java/org/apache/poi/ss/usermodel/charts/ChartAxisFactory.java index 9c1e09dcbc..bd037f500f 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ChartAxisFactory.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ChartAxisFactory.java @@ -18,12 +18,14 @@ 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 { /** diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ChartData.java b/src/java/org/apache/poi/ss/usermodel/charts/ChartData.java index f2acc6fd0d..7a4aec5f0b 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ChartData.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ChartData.java @@ -18,19 +18,21 @@ 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); } diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ChartDataFactory.java b/src/java/org/apache/poi/ss/usermodel/charts/ChartDataFactory.java index 3914fcd4a0..f75e66307d 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ChartDataFactory.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ChartDataFactory.java @@ -17,11 +17,14 @@ 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 { /** diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ChartDataSource.java b/src/java/org/apache/poi/ss/usermodel/charts/ChartDataSource.java new file mode 100644 index 0000000000..d843cac9b8 --- /dev/null +++ b/src/java/org/apache/poi/ss/usermodel/charts/ChartDataSource.java @@ -0,0 +1,72 @@ +/* + * ==================================================================== + * 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 type of points the data source contents + * @author Roman Kashitsyn + */ +@Beta +public interface ChartDataSource { + + /** + * 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(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ChartLegend.java b/src/java/org/apache/poi/ss/usermodel/charts/ChartLegend.java index b870a773ec..f40664f9c0 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ChartLegend.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ChartLegend.java @@ -17,11 +17,14 @@ 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 { /** diff --git a/src/java/org/apache/poi/ss/usermodel/charts/DataSources.java b/src/java/org/apache/poi/ss/usermodel/charts/DataSources.java new file mode 100644 index 0000000000..bd78672340 --- /dev/null +++ b/src/java/org/apache/poi/ss/usermodel/charts/DataSources.java @@ -0,0 +1,146 @@ +/* + * ==================================================================== + * 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 ChartDataSource fromArray(T[] elements) { + return new ArrayDataSource(elements); + } + + public static ChartDataSource fromNumericCellRange(Sheet sheet, CellRangeAddress cellRangeAddress) { + return new AbstractCellRangeDataSource(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 fromStringCellRange(Sheet sheet, CellRangeAddress cellRangeAddress) { + return new AbstractCellRangeDataSource(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 implements ChartDataSource { + + 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 implements ChartDataSource { + 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)); + } + } +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ManualLayout.java b/src/java/org/apache/poi/ss/usermodel/charts/ManualLayout.java index 993ab3dafd..2d8bfbd96f 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ManualLayout.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ManualLayout.java @@ -17,11 +17,14 @@ package org.apache.poi.ss.usermodel.charts; +import org.apache.poi.util.Beta; + /** * High level representation of chart element manual layout. * * @author Roman Kashitsyn */ +@Beta public interface ManualLayout { /** diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ManuallyPositionable.java b/src/java/org/apache/poi/ss/usermodel/charts/ManuallyPositionable.java index 03a85a4bce..0d749fb4b9 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ManuallyPositionable.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ManuallyPositionable.java @@ -17,12 +17,15 @@ package org.apache.poi.ss.usermodel.charts; +import org.apache.poi.util.Beta; + /** * Abstraction of chart element that can be positioned with manual * layout. * * @author Roman Kashitsyn */ +@Beta public interface ManuallyPositionable { /** diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ScatterChartData.java b/src/java/org/apache/poi/ss/usermodel/charts/ScatterChartData.java index 09e10048ef..81917473b0 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ScatterChartData.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ScatterChartData.java @@ -18,20 +18,17 @@ 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 ys); /** * @return list of all series diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ScatterChartSerie.java b/src/java/org/apache/poi/ss/usermodel/charts/ScatterChartSerie.java index 16cef9c5fa..c968f79698 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ScatterChartSerie.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ScatterChartSerie.java @@ -17,23 +17,24 @@ 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 getYValues(); } diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ValueAxis.java b/src/java/org/apache/poi/ss/usermodel/charts/ValueAxis.java index 56132573ab..f6673dae47 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ValueAxis.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ValueAxis.java @@ -17,9 +17,12 @@ package org.apache.poi.ss.usermodel.charts; +import org.apache.poi.util.Beta; + /** * @author Roman Kashitsyn */ +@Beta public interface ValueAxis extends ChartAxis { /** diff --git a/src/java/org/apache/poi/ss/util/DataMarker.java b/src/java/org/apache/poi/ss/util/DataMarker.java index 628a975aaa..e69de29bb2 100644 --- a/src/java/org/apache/poi/ss/util/DataMarker.java +++ b/src/java/org/apache/poi/ss/util/DataMarker.java @@ -1,87 +0,0 @@ -/* - * ==================================================================== - * 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.util; - -import org.apache.poi.ss.usermodel.Sheet; - -/** - * Represents data marker used in charts. - * @author Roman Kashitsyn - */ -public class DataMarker { - - private Sheet sheet; - private CellRangeAddress range; - - /** - * @param sheet the sheet where data located. - * @param range the range within that sheet. - */ - public DataMarker(Sheet sheet, CellRangeAddress range) { - this.sheet = sheet; - this.range = range; - } - - /** - * Returns the sheet marker points to. - * @return sheet marker points to. - */ - public Sheet getSheet() { - return sheet; - } - - /** - * Sets sheet marker points to. - * @param sheet new sheet for the marker. - */ - public void setSheet(Sheet sheet) { - this.sheet = sheet; - } - - /** - * Returns range of the marker. - * @return range of cells marker points to. - */ - public CellRangeAddress getRange() { - return range; - } - - /** - * Sets range of the marker. - * @param range new range for the marker. - */ - public void setRange(CellRangeAddress range) { - this.range = range; - } - - /** - * Formats data marker using canonical format, for example - * `SheetName!$A$1:$A$5'. - * @return formatted data marker. - */ - public String formatAsString() { - String sheetName = (sheet == null) ? (null) : (sheet.getSheetName()); - if (range == null) { - return null; - } else { - return range.formatAsString(sheetName, true); - } - } -} diff --git a/src/java/org/apache/poi/ss/util/SheetBuilder.java b/src/java/org/apache/poi/ss/util/SheetBuilder.java index 31609001fd..960d2d6ca2 100644 --- a/src/java/org/apache/poi/ss/util/SheetBuilder.java +++ b/src/java/org/apache/poi/ss/util/SheetBuilder.java @@ -25,115 +25,134 @@ import org.apache.poi.ss.usermodel.Row; 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: - * + *

*

    *
  • Numbers become numeric cells.
  • *
  • java.util.Date or java.util.Calendar - * instances become date cells.
  • + * instances become date cells. *
  • String with leading '=' char become formulas (leading '=' - * trancated).
  • + * will be truncated). *
  • Other objects become strings via Object.toString() - * method.
  • + * method call. *
* * @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 diff --git a/src/java/org/apache/poi/ss/util/cellwalk/CellWalk.java b/src/java/org/apache/poi/ss/util/cellwalk/CellWalk.java index 53e21640cf..4efd80d60c 100644 --- a/src/java/org/apache/poi/ss/util/cellwalk/CellWalk.java +++ b/src/java/org/apache/poi/ss/util/cellwalk/CellWalk.java @@ -17,12 +17,10 @@ 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. @@ -35,95 +33,96 @@ public class CellWalk { 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; + } } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartAxis.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartAxis.java index 95467c6b18..d2162d0531 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartAxis.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartAxis.java @@ -21,6 +21,7 @@ import org.apache.poi.ss.usermodel.charts.ChartAxis; 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; @@ -38,6 +39,7 @@ import org.openxmlformats.schemas.drawingml.x2006.chart.STCrosses; * * @author Roman Kashitsyn */ +@Beta public abstract class XSSFChartAxis implements ChartAxis { protected XSSFChart chart; diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartDataFactory.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartDataFactory.java index b36f917875..57b826a186 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartDataFactory.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartDataFactory.java @@ -18,10 +18,12 @@ 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; @@ -31,7 +33,7 @@ public class XSSFChartDataFactory implements ChartDataFactory { } /** - * @return new scatter chart data instance + * @return new scatter charts data instance */ public XSSFScatterChartData createScatterChartData() { return new XSSFScatterChartData(); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartLegend.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartLegend.java index 1123573491..896e6dff22 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartLegend.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartLegend.java @@ -17,6 +17,7 @@ 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; @@ -30,6 +31,7 @@ import org.openxmlformats.schemas.drawingml.x2006.chart.STLegendPos; * Represents a SpreadsheetML chart legend * @author Roman Kashitsyn */ +@Beta public final class XSSFChartLegend implements ChartLegend { /** diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartUtil.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartUtil.java new file mode 100644 index 0000000000..d0a13b41c6 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFChartUtil.java @@ -0,0 +1,115 @@ +/* + * ==================================================================== + * 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 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()); + } + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFManualLayout.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFManualLayout.java index 81bf55a06a..087dfb553d 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFManualLayout.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFManualLayout.java @@ -17,6 +17,7 @@ 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.ManualLayout; import org.apache.poi.ss.usermodel.charts.LayoutMode; @@ -35,6 +36,7 @@ import org.openxmlformats.schemas.drawingml.x2006.chart.STLayoutTarget; * Represents a SpreadsheetML manual layout. * @author Roman Kashitsyn */ +@Beta public final class XSSFManualLayout implements ManualLayout { /** diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFNumberCache.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFNumberCache.java deleted file mode 100644 index 04902049e3..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFNumberCache.java +++ /dev/null @@ -1,150 +0,0 @@ -/* ==================================================================== - 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; - } - - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFScatterChartData.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFScatterChartData.java index 36959b2d4d..23876272ee 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFScatterChartData.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFScatterChartData.java @@ -17,40 +17,25 @@ 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 { /** @@ -59,118 +44,93 @@ public class XSSFScatterChartData implements ScatterChartData { private List series; public XSSFScatterChartData() { - series = new ArrayList(); + series = new ArrayList(); } /** * 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 ys; + + protected Serie(int id, int order, + ChartDataSource xs, + ChartDataSource 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 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 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 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); } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFValueAxis.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFValueAxis.java index 1646db593c..3f701f04b9 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFValueAxis.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFValueAxis.java @@ -24,6 +24,7 @@ import org.apache.poi.ss.usermodel.charts.AxisOrientation; 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; @@ -39,6 +40,7 @@ import org.openxmlformats.schemas.drawingml.x2006.chart.STTickLblPos; * * @author Roman Kashitsyn */ +@Beta public class XSSFValueAxis extends XSSFChartAxis implements ValueAxis { private CTValAx ctValAx; diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFChartSheet.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFChartSheet.java index a5de464e5f..3ca9263940 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFChartSheet.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFChartSheet.java @@ -40,7 +40,7 @@ public final class TestXSSFChartSheet extends TestCase { 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)); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java index 526ab9224a..e0cfcc0336 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java @@ -332,7 +332,7 @@ public final class TestXSSFWorkbook extends BaseTestWorkbook { } /** - * 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"); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFNumberCache.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFNumberCache.java deleted file mode 100644 index 94621de825..0000000000 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFNumberCache.java +++ /dev/null @@ -1,64 +0,0 @@ -/* ==================================================================== - 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 diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFScatterChartData.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFScatterChartData.java index 4a3b9c0f43..87f8ea7b12 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFScatterChartData.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFScatterChartData.java @@ -21,42 +21,43 @@ import junit.framework.TestCase; 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 xs = DataSources.fromStringCellRange(sheet, CellRangeAddress.valueOf("A1:J1")); + ChartDataSource 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); } - } diff --git a/src/testcases/org/apache/poi/ss/usermodel/charts/TestDataSources.java b/src/testcases/org/apache/poi/ss/usermodel/charts/TestDataSources.java new file mode 100644 index 0000000000..6bf3551286 --- /dev/null +++ b/src/testcases/org/apache/poi/ss/usermodel/charts/TestDataSources.java @@ -0,0 +1,136 @@ +/* ==================================================================== + 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 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 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 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 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 strDataSource = DataSources.fromStringCellRange(sheet, mixedCellRange); + ChartDataSource 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 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 void assertDataSourceIsEqualToArray(ChartDataSource ds, T[] array) { + assertEquals(ds.getPointCount(), array.length); + for (int i = 0; i < array.length; ++i) { + assertEquals(ds.getPointAt(i), array[i]); + } + } +} diff --git a/src/testcases/org/apache/poi/ss/util/TestSheetBuilder.java b/src/testcases/org/apache/poi/ss/util/TestSheetBuilder.java index edb3df9355..ee90ee6c5a 100644 --- a/src/testcases/org/apache/poi/ss/util/TestSheetBuilder.java +++ b/src/testcases/org/apache/poi/ss/util/TestSheetBuilder.java @@ -29,49 +29,56 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook; /** * 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