more progress with support for charts in XSSF, see patch 51196
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1148642 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
59b5b941b3
commit
db284964ab
139
src/java/org/apache/poi/ss/util/SheetBuilder.java
Normal file
139
src/java/org/apache/poi/ss/util/SheetBuilder.java
Normal file
@ -0,0 +1,139 @@
|
||||
/* ====================================================================
|
||||
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 java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
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.
|
||||
*
|
||||
* @author Roman Kashitsyn
|
||||
*/
|
||||
public class SheetBuilder {
|
||||
|
||||
private Workbook workbook;
|
||||
private Object[][] cells;
|
||||
private boolean shouldCreateEmptyCells = false;
|
||||
|
||||
public SheetBuilder(Workbook workbook, Object[][] cells) {
|
||||
this.workbook = workbook;
|
||||
this.cells = cells;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if null objects should be trated as empty cells
|
||||
* false otherwise
|
||||
*/
|
||||
public boolean getCreateEmptyCells() {
|
||||
return shouldCreateEmptyCells;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shouldCreateEmptyCells true if null array elements should be
|
||||
* trated as empty cells
|
||||
* @return this
|
||||
*/
|
||||
public SheetBuilder setCreateEmptyCells(boolean shouldCreateEmptyCells) {
|
||||
this.shouldCreateEmptyCells = shouldCreateEmptyCells;
|
||||
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.
|
||||
* The conversion is performed in the following way:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Numbers become numeric cells.</li>
|
||||
* <li><code>java.util.Date</code> or <code>java.util.Calendar</code>
|
||||
* instances become date cells.</li>
|
||||
* <li>String with leading '=' char become formulas (leading '='
|
||||
* trancated).</li>
|
||||
* <li>Other objects become strings via <code>Object.toString()</code>
|
||||
* method.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return newly created sheet
|
||||
*/
|
||||
public Sheet build() {
|
||||
Sheet sheet = workbook.createSheet();
|
||||
Row currentRow = null;
|
||||
Cell currentCell = null;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cell value using object type information.
|
||||
* @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 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;
|
||||
}
|
||||
}
|
||||
|
||||
private String getFormula(Object obj) {
|
||||
return ((String) obj).substring(1);
|
||||
}
|
||||
}
|
34
src/java/org/apache/poi/ss/util/cellwalk/CellHandler.java
Normal file
34
src/java/org/apache/poi/ss/util/cellwalk/CellHandler.java
Normal file
@ -0,0 +1,34 @@
|
||||
/* ====================================================================
|
||||
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.cellwalk;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
|
||||
/**
|
||||
* Represents callback for CellWalk traverse method.
|
||||
* @author Roman Kashitsyn
|
||||
*/
|
||||
public interface CellHandler {
|
||||
|
||||
/**
|
||||
* @param cell current cell
|
||||
* @param ctx information about invokation context
|
||||
*/
|
||||
void onCell(Cell cell, CellWalkContext ctx);
|
||||
|
||||
}
|
129
src/java/org/apache/poi/ss/util/cellwalk/CellWalk.java
Normal file
129
src/java/org/apache/poi/ss/util/cellwalk/CellWalk.java
Normal file
@ -0,0 +1,129 @@
|
||||
/* ====================================================================
|
||||
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.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.
|
||||
*
|
||||
* @author Roman Kashitsyn
|
||||
*/
|
||||
public class CellWalk {
|
||||
|
||||
private Sheet sheet;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we call handler on empty (blank) cells. Default is
|
||||
* false.
|
||||
* @return true if handler should be called on empty (blank)
|
||||
* cells, false otherwise.
|
||||
*/
|
||||
public boolean isTraverseEmptyCells() {
|
||||
return traverseEmptyCells;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the traverseEmptyCells property.
|
||||
* @param traverseEmptyCells new property value
|
||||
*/
|
||||
public void setTraverseEmptyCells(boolean 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmpty(Cell cell) {
|
||||
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 getOrdinalNumber() {
|
||||
return ordinalNumber;
|
||||
}
|
||||
|
||||
public int getRowNumber() {
|
||||
return rowNumber;
|
||||
}
|
||||
|
||||
public int getColumnNumber() {
|
||||
return colNumber;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/* ====================================================================
|
||||
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.cellwalk;
|
||||
|
||||
/**
|
||||
* @author Roman Kashitsyn
|
||||
*/
|
||||
public interface CellWalkContext {
|
||||
|
||||
/**
|
||||
* Returns ordinal number of cell in range. Numeration starts
|
||||
* from top left cell and ends at bottom right cell. Here is a
|
||||
* brief example (number in cell is it's ordinal number):
|
||||
*
|
||||
* <table border="1">
|
||||
* <tbody>
|
||||
* <tr><td>1</td><td>2</td></tr>
|
||||
* <tr><td>3</td><td>4</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*
|
||||
* @return ordinal number of current cell
|
||||
*/
|
||||
long getOrdinalNumber();
|
||||
|
||||
/**
|
||||
* Returns number of current row.
|
||||
* @return number of current row
|
||||
*/
|
||||
int getRowNumber();
|
||||
|
||||
/**
|
||||
* Returns number of current column.
|
||||
* @return number of current column
|
||||
*/
|
||||
int getColumnNumber();
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/* ====================================================================
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -6,14 +6,14 @@
|
||||
(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
|
||||
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;
|
||||
|
||||
@ -53,93 +53,124 @@ import org.apache.poi.xssf.usermodel.XSSFChart;
|
||||
*/
|
||||
public class XSSFScatterChartData implements ScatterChartData {
|
||||
|
||||
/**
|
||||
* List of all data series.
|
||||
*/
|
||||
private List<Serie> series;
|
||||
|
||||
public XSSFScatterChartData() {
|
||||
series = new ArrayList<Serie>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Package private ScatterChartSerie implementation.
|
||||
*/
|
||||
static class Serie implements ScatterChartSerie {
|
||||
private int id;
|
||||
private int order;
|
||||
private boolean useCache;
|
||||
private DataMarker xMarker;
|
||||
private DataMarker yMarker;
|
||||
private XSSFNumberCache lastCaclulatedXCache;
|
||||
private XSSFNumberCache lastCalculatedYCache;
|
||||
|
||||
protected Serie(int id, int order) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.order = order;
|
||||
this.useCache = true;
|
||||
}
|
||||
|
||||
public void setXValues(DataMarker marker) {
|
||||
xMarker = marker;
|
||||
}
|
||||
|
||||
public void setYValues(DataMarker marker) {
|
||||
yMarker = marker;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of all data series.
|
||||
* @param useCache if true, cached results will be added on plot
|
||||
*/
|
||||
private List<Serie> series;
|
||||
|
||||
public XSSFScatterChartData() {
|
||||
series = new ArrayList<Serie>();
|
||||
public void setUseCache(boolean useCache) {
|
||||
this.useCache = useCache;
|
||||
}
|
||||
|
||||
public static class Serie implements ScatterChartSerie {
|
||||
private int id;
|
||||
private int order;
|
||||
private boolean useCache;
|
||||
private DataMarker xMarker;
|
||||
private DataMarker yMarker;
|
||||
|
||||
public Serie(int id, int order) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.order = order;
|
||||
this.useCache = false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
protected void addToChart(CTScatterChart ctScatterChart) {
|
||||
CTScatterSer scatterSer = ctScatterChart.addNewSer();
|
||||
scatterSer.addNewIdx().setVal(this.id);
|
||||
scatterSer.addNewOrder().setVal(this.order);
|
||||
|
||||
CTAxDataSource xVal = scatterSer.addNewXVal();
|
||||
CTNumRef numRef = xVal.addNewNumRef();
|
||||
numRef.setF(xMarker.formatAsString());
|
||||
|
||||
CTNumDataSource yVal = scatterSer.addNewYVal();
|
||||
numRef = yVal.addNewNumRef();
|
||||
numRef.setF(yMarker.formatAsString());
|
||||
}
|
||||
/**
|
||||
* Returns last calculated number cache for X axis.
|
||||
* @return last calculated number cache for X axis.
|
||||
*/
|
||||
XSSFNumberCache getLastCaculatedXCache() {
|
||||
return lastCaclulatedXCache;
|
||||
}
|
||||
|
||||
public XSSFScatterChartData.Serie 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;
|
||||
/**
|
||||
* Returns last calculated number cache for Y axis.
|
||||
* @return last calculated number cache for Y axis.
|
||||
*/
|
||||
XSSFNumberCache getLastCalculatedYCache() {
|
||||
return lastCalculatedYCache;
|
||||
}
|
||||
|
||||
public void fillChart(Chart chart, ChartAxis... axis) {
|
||||
if (!(chart instanceof XSSFChart)) {
|
||||
throw new IllegalArgumentException("Chart must be instance of XSSFChart");
|
||||
}
|
||||
protected void addToChart(CTScatterChart ctScatterChart) {
|
||||
CTScatterSer scatterSer = ctScatterChart.addNewSer();
|
||||
scatterSer.addNewIdx().setVal(this.id);
|
||||
scatterSer.addNewOrder().setVal(this.order);
|
||||
|
||||
XSSFChart xssfChart = (XSSFChart) chart;
|
||||
CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea();
|
||||
CTScatterChart scatterChart = plotArea.addNewScatterChart();
|
||||
addStyle(scatterChart);
|
||||
/* 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());
|
||||
|
||||
for (Serie s : series) {
|
||||
s.addToChart(scatterChart);
|
||||
}
|
||||
CTNumDataSource yVal = scatterSer.addNewYVal();
|
||||
CTNumRef yNumRef = yVal.addNewNumRef();
|
||||
yNumRef.setF(yMarker.formatAsString());
|
||||
|
||||
for (ChartAxis ax : axis) {
|
||||
scatterChart.addNewAxId().setVal(ax.getId());
|
||||
}
|
||||
if (useCache) {
|
||||
/* We can not store cache since markers are not immutable */
|
||||
XSSFNumberCache.buildCache(xMarker, xNumRef);
|
||||
lastCalculatedYCache = XSSFNumberCache.buildCache(yMarker, yNumRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 void fillChart(Chart chart, ChartAxis... axis) {
|
||||
if (!(chart instanceof XSSFChart)) {
|
||||
throw new IllegalArgumentException("Chart must be instance of XSSFChart");
|
||||
}
|
||||
|
||||
public List<? extends Serie> getSeries() {
|
||||
return series;
|
||||
XSSFChart xssfChart = (XSSFChart) chart;
|
||||
CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea();
|
||||
CTScatterChart scatterChart = plotArea.addNewScatterChart();
|
||||
addStyle(scatterChart);
|
||||
|
||||
for (Serie s : series) {
|
||||
s.addToChart(scatterChart);
|
||||
}
|
||||
|
||||
private void addStyle(CTScatterChart ctScatterChart) {
|
||||
CTScatterStyle scatterStyle = ctScatterChart.addNewScatterStyle();
|
||||
scatterStyle.setVal(STScatterStyle.LINE_MARKER);
|
||||
for (ChartAxis ax : axis) {
|
||||
scatterChart.addNewAxId().setVal(ax.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public List<? extends Serie> getSeries() {
|
||||
return series;
|
||||
}
|
||||
|
||||
private void addStyle(CTScatterChart ctScatterChart) {
|
||||
CTScatterStyle scatterStyle = ctScatterChart.addNewScatterStyle();
|
||||
scatterStyle.setVal(STScatterStyle.LINE_MARKER);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
/* ====================================================================
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -6,47 +6,57 @@
|
||||
(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
|
||||
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 junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.xssf.usermodel.*;
|
||||
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.charts.XSSFChartDataFactory;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
/**
|
||||
* Tests for XSSFScatterChartData.
|
||||
* @author Roman Kashitsyn
|
||||
*/
|
||||
public final class TestXSSFScatterChartData extends TestCase {
|
||||
|
||||
public void testOneSeriePlot() throws Exception {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
XSSFSheet sheet = wb.createSheet();
|
||||
XSSFDrawing drawing = sheet.createDrawingPatriarch();
|
||||
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 1, 1, 10, 30);
|
||||
XSSFChart chart = drawing.createChart(anchor);
|
||||
|
||||
ChartAxis bottomAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.BOTTOM);
|
||||
ChartAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
|
||||
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}
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
ScatterChartData scatterChartData =
|
||||
XSSFChartDataFactory.getInstance().createScatterChartData();
|
||||
ChartAxis bottomAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.BOTTOM);
|
||||
ChartAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
|
||||
|
||||
DataMarker xMarker = new DataMarker(sheet, new CellRangeAddress(0,0,1,10));
|
||||
DataMarker yMarker = new DataMarker(sheet, new CellRangeAddress(1,1,1,10));
|
||||
ScatterChartSerie serie = scatterChartData.addSerie(xMarker, yMarker);
|
||||
ScatterChartData scatterChartData =
|
||||
chart.getChartDataFactory().createScatterChartData();
|
||||
|
||||
assertEquals(scatterChartData.getSeries().size(), 1);
|
||||
DataMarker xMarker = new DataMarker(sheet, CellRangeAddress.valueOf("A1:A10"));
|
||||
DataMarker yMarker = new DataMarker(sheet, CellRangeAddress.valueOf("B1:B10"));
|
||||
ScatterChartSerie serie = scatterChartData.addSerie(xMarker, yMarker);
|
||||
|
||||
chart.plot(scatterChartData, bottomAxis, leftAxis);
|
||||
}
|
||||
assertEquals(1, scatterChartData.getSeries().size());
|
||||
|
||||
chart.plot(scatterChartData, bottomAxis, leftAxis);
|
||||
}
|
||||
|
||||
}
|
||||
|
77
src/testcases/org/apache/poi/ss/util/TestSheetBuilder.java
Normal file
77
src/testcases/org/apache/poi/ss/util/TestSheetBuilder.java
Normal file
@ -0,0 +1,77 @@
|
||||
/* ====================================================================
|
||||
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 java.util.Date;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
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"}
|
||||
};
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/* ====================================================================
|
||||
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.cellwalk;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.util.SheetBuilder;
|
||||
|
||||
public class TestCellWalk extends TestCase {
|
||||
|
||||
private static Object[][] testData = new Object[][] {
|
||||
{ 1, 2, null},
|
||||
{null, new Date(), null},
|
||||
{null, null, "str"}
|
||||
};
|
||||
|
||||
private CountCellHandler countCellHandler = new CountCellHandler();
|
||||
|
||||
public void testNotTraverseEmptyCells() {
|
||||
Workbook wb = new HSSFWorkbook();
|
||||
Sheet sheet = new SheetBuilder(wb, testData).build();
|
||||
CellRangeAddress range = CellRangeAddress.valueOf("A1:C3");
|
||||
|
||||
CellWalk cellWalk = new CellWalk(sheet, range);
|
||||
countCellHandler.reset();
|
||||
cellWalk.traverse(countCellHandler);
|
||||
|
||||
assertEquals(4, countCellHandler.getVisitedCellsNumber());
|
||||
/* 1 + 2 + 5 + 9 */
|
||||
assertEquals(17L, countCellHandler.getOrdinalNumberSum());
|
||||
}
|
||||
|
||||
|
||||
private static class CountCellHandler implements CellHandler {
|
||||
|
||||
private int cellsVisited = 0;
|
||||
private long ordinalNumberSum = 0L;
|
||||
|
||||
public void onCell(Cell cell, CellWalkContext ctx) {
|
||||
++cellsVisited;
|
||||
ordinalNumberSum += ctx.getOrdinalNumber();
|
||||
}
|
||||
|
||||
public int getVisitedCellsNumber() {
|
||||
return cellsVisited;
|
||||
}
|
||||
|
||||
public long getOrdinalNumberSum() {
|
||||
return ordinalNumberSum;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
cellsVisited = 0;
|
||||
ordinalNumberSum = 0L;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user