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
This commit is contained in:
parent
cc4a1dd8f1
commit
b1dce5c2ad
@ -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;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
ValueAxis bottomAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.BOTTOM);
|
||||
ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
|
||||
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
|
||||
|
||||
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));
|
||||
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));
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -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 <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();
|
||||
}
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
146
src/java/org/apache/poi/ss/usermodel/charts/DataSources.java
Normal file
146
src/java/org/apache/poi/ss/usermodel/charts/DataSources.java
Normal file
@ -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 <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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -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<? extends Number> ys);
|
||||
|
||||
/**
|
||||
* @return list of all series
|
||||
|
@ -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<? extends Number> getYValues();
|
||||
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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:
|
||||
*
|
||||
* <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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
if (currentCell == null) {
|
||||
continue;
|
||||
}
|
||||
if (isEmpty(currentCell) && !traverseEmptyCells) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ctx.ordinalNumber =
|
||||
(ctx.rowNumber - firstRow) * width +
|
||||
(ctx.colNumber - firstColumn + 1);
|
||||
ctx.ordinalNumber =
|
||||
(ctx.rowNumber - firstRow) * width +
|
||||
(ctx.colNumber - firstColumn + 1);
|
||||
|
||||
handler.onCell(currentCell, ctx);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -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<? 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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.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 org.apache.poi.util.Beta;
|
||||
import org.apache.poi.xssf.usermodel.XSSFChart;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 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<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;
|
||||
private int id;
|
||||
private int order;
|
||||
private ChartDataSource<?> xs;
|
||||
private ChartDataSource<? extends Number> ys;
|
||||
|
||||
protected Serie(int id, int order) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.order = order;
|
||||
this.useCache = true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
public void setXValues(DataMarker marker) {
|
||||
xMarker = marker;
|
||||
}
|
||||
/**
|
||||
* Returns data source used for X axis values.
|
||||
* @return data source used for X axis values
|
||||
*/
|
||||
public ChartDataSource<?> getXValues() {
|
||||
return xs;
|
||||
}
|
||||
|
||||
public void setYValues(DataMarker marker) {
|
||||
yMarker = marker;
|
||||
}
|
||||
/**
|
||||
* Returns data source used for Y axis values.
|
||||
* @return data source used for Y axis values
|
||||
*/
|
||||
public ChartDataSource<? extends Number> getYValues() {
|
||||
return ys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useCache if true, cached results will be added on plot
|
||||
*/
|
||||
public void setUseCache(boolean useCache) {
|
||||
this.useCache = useCache;
|
||||
}
|
||||
protected void addToChart(CTScatterChart ctScatterChart) {
|
||||
CTScatterSer scatterSer = ctScatterChart.addNewSer();
|
||||
scatterSer.addNewIdx().setVal(this.id);
|
||||
scatterSer.addNewOrder().setVal(this.order);
|
||||
|
||||
/**
|
||||
* Returns last calculated number cache for X axis.
|
||||
* @return last calculated number cache for X axis.
|
||||
*/
|
||||
XSSFNumberCache getLastCaculatedXCache() {
|
||||
return lastCaclulatedXCache;
|
||||
}
|
||||
CTAxDataSource xVal = scatterSer.addNewXVal();
|
||||
XSSFChartUtil.buildAxDataSource(xVal, xs);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
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");
|
||||
}
|
||||
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);
|
||||
XSSFChart xssfChart = (XSSFChart) chart;
|
||||
CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea();
|
||||
CTScatterChart scatterChart = plotArea.addNewScatterChart();
|
||||
addStyle(scatterChart);
|
||||
|
||||
for (Serie s : series) {
|
||||
s.addToChart(scatterChart);
|
||||
}
|
||||
for (Serie s : series) {
|
||||
s.addToChart(scatterChart);
|
||||
}
|
||||
|
||||
for (ChartAxis ax : axis) {
|
||||
scatterChart.addNewAxId().setVal(ax.getId());
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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<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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<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]);
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
Workbook wb = new HSSFWorkbook();
|
||||
Sheet sheet = new SheetBuilder(wb, testData).build();
|
||||
|
||||
assertEquals(sheet.getPhysicalNumberOfRows(), 3);
|
||||
assertEquals(sheet.getPhysicalNumberOfRows(), 3);
|
||||
|
||||
Row firstRow = sheet.getRow(0);
|
||||
Cell firstCell = firstRow.getCell(0);
|
||||
Row firstRow = sheet.getRow(0);
|
||||
Cell firstCell = firstRow.getCell(0);
|
||||
|
||||
assertEquals(firstCell.getCellType(), Cell.CELL_TYPE_NUMERIC);
|
||||
assertEquals(1.0, firstCell.getNumericCellValue(), 0.00001);
|
||||
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 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);
|
||||
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());
|
||||
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();
|
||||
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());
|
||||
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());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user