ASF Bugzilla – Attachment 27294 Details for
Bug 51196
[PATCH] Patch to simplify XSSFChart creation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Draft of numeric cache implementation.
numCache.patch (text/plain), 37.40 KB, created by
Roman Kashitsyn
on 2011-07-17 20:41:44 UTC
(
hide
)
Description:
Draft of numeric cache implementation.
Filename:
MIME Type:
Creator:
Roman Kashitsyn
Created:
2011-07-17 20:41:44 UTC
Size:
37.40 KB
patch
obsolete
>Index: src/java/org/apache/poi/ss/util/cellwalk/CellWalkContext.java >=================================================================== >--- src/java/org/apache/poi/ss/util/cellwalk/CellWalkContext.java (revision 0) >+++ src/java/org/apache/poi/ss/util/cellwalk/CellWalkContext.java (revision 0) >@@ -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(); >+} >\ No newline at end of file >Index: src/java/org/apache/poi/ss/util/cellwalk/CellHandler.java >=================================================================== >--- src/java/org/apache/poi/ss/util/cellwalk/CellHandler.java (revision 0) >+++ src/java/org/apache/poi/ss/util/cellwalk/CellHandler.java (revision 0) >@@ -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); >+ >+} >\ No newline at end of file >Index: src/java/org/apache/poi/ss/util/cellwalk/CellWalk.java >=================================================================== >--- src/java/org/apache/poi/ss/util/cellwalk/CellWalk.java (revision 0) >+++ src/java/org/apache/poi/ss/util/cellwalk/CellWalk.java (revision 0) >@@ -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; >+ } >+ } >+} >Index: src/java/org/apache/poi/ss/util/SheetBuilder.java >=================================================================== >--- src/java/org/apache/poi/ss/util/SheetBuilder.java (revision 0) >+++ src/java/org/apache/poi/ss/util/SheetBuilder.java (revision 0) >@@ -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); >+ } >+} >\ No newline at end of file >Index: src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFNumberCache.java >=================================================================== >--- src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFNumberCache.java (revision 0) >+++ src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFNumberCache.java (revision 0) >@@ -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; >+ } >+ >+ } >+} >Index: src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFScatterChartData.java >=================================================================== >--- src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFScatterChartData.java (revision 1147700) >+++ src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFScatterChartData.java (working copy) >@@ -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 @@ > */ > public class XSSFScatterChartData implements ScatterChartData { > >- /** >- * List of all data series. >- */ >- private List<Serie> series; >+ /** >+ * List of all data series. >+ */ >+ private List<Serie> series; > >- public XSSFScatterChartData() { >- series = new ArrayList<Serie>(); >+ 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 static class Serie implements ScatterChartSerie { >- private int id; >- private int order; >- private boolean useCache; >- private DataMarker xMarker; >- private DataMarker yMarker; >+ public void setXValues(DataMarker marker) { >+ xMarker = marker; >+ } > >- public Serie(int id, int order) { >- super(); >- this.id = id; >- this.order = order; >- this.useCache = false; >- } >+ public void setYValues(DataMarker marker) { >+ yMarker = marker; >+ } > >- public void setXValues(DataMarker marker) { >- xMarker = marker; >- } >+ /** >+ * @param useCache if true, cached results will be added on plot >+ */ >+ public void setUseCache(boolean useCache) { >+ this.useCache = useCache; >+ } > >- public void setYValues(DataMarker marker) { >- yMarker = marker; >- } >+ /** >+ * Returns last calculated number cache for X axis. >+ * @return last calculated number cache for X axis. >+ */ >+ XSSFNumberCache getLastCaculatedXCache() { >+ return lastCaclulatedXCache; >+ } > >- /** >- * @param useCache if true, cached results will be added on plot >- */ >- public void setUseCache(boolean useCache) { >- this.useCache = useCache; >- } >+ /** >+ * Returns last calculated number cache for 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); >+ 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()); >+ /* 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(); >- numRef = yVal.addNewNumRef(); >- numRef.setF(yMarker.formatAsString()); >- } >- } >+ CTNumDataSource yVal = scatterSer.addNewYVal(); >+ CTNumRef yNumRef = yVal.addNewNumRef(); >+ yNumRef.setF(yMarker.formatAsString()); > >- 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; >+ if (useCache) { >+ /* We can not store cache since markers are not immutable */ >+ XSSFNumberCache.buildCache(xMarker, xNumRef); >+ lastCalculatedYCache = XSSFNumberCache.buildCache(yMarker, yNumRef); >+ } > } >+ } > >- public void fillChart(Chart chart, ChartAxis... axis) { >- if (!(chart instanceof XSSFChart)) { >- throw new IllegalArgumentException("Chart must be instance of XSSFChart"); >- } >+ 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; >+ } > >- XSSFChart xssfChart = (XSSFChart) chart; >- CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea(); >- CTScatterChart scatterChart = plotArea.addNewScatterChart(); >- addStyle(scatterChart); >+ public void fillChart(Chart chart, ChartAxis... axis) { >+ if (!(chart instanceof XSSFChart)) { >+ throw new IllegalArgumentException("Chart must be instance of XSSFChart"); >+ } > >- for (Serie s : series) { >- s.addToChart(scatterChart); >- } >+ XSSFChart xssfChart = (XSSFChart) chart; >+ CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea(); >+ CTScatterChart scatterChart = plotArea.addNewScatterChart(); >+ addStyle(scatterChart); > >- for (ChartAxis ax : axis) { >- scatterChart.addNewAxId().setVal(ax.getId()); >- } >+ for (Serie s : series) { >+ s.addToChart(scatterChart); > } > >- public List<? extends Serie> getSeries() { >- return series; >+ for (ChartAxis ax : axis) { >+ scatterChart.addNewAxId().setVal(ax.getId()); > } >+ } > >- private void addStyle(CTScatterChart ctScatterChart) { >- CTScatterStyle scatterStyle = ctScatterChart.addNewScatterStyle(); >- scatterStyle.setVal(STScatterStyle.LINE_MARKER); >- } >+ public List<? extends Serie> getSeries() { >+ return series; >+ } >+ >+ private void addStyle(CTScatterChart ctScatterChart) { >+ CTScatterStyle scatterStyle = ctScatterChart.addNewScatterStyle(); >+ scatterStyle.setVal(STScatterStyle.LINE_MARKER); >+ } > } >Index: src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFNumberCache.java >=================================================================== >--- src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFNumberCache.java (revision 0) >+++ src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFNumberCache.java (revision 0) >@@ -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); >+ } >+ >+ >+} >\ No newline at end of file >Index: src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFScatterChartData.java >=================================================================== >--- src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFScatterChartData.java (revision 1147700) >+++ src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFScatterChartData.java (working copy) >@@ -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); >+ } >+ > } >Index: src/testcases/org/apache/poi/ss/util/TestSheetBuilder.java >=================================================================== >--- src/testcases/org/apache/poi/ss/util/TestSheetBuilder.java (revision 0) >+++ src/testcases/org/apache/poi/ss/util/TestSheetBuilder.java (revision 0) >@@ -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()); >+ } >+ >+} >\ No newline at end of file >Index: src/testcases/org/apache/poi/ss/util/cellwalk/TestCellWalk.java >=================================================================== >--- src/testcases/org/apache/poi/ss/util/cellwalk/TestCellWalk.java (revision 0) >+++ src/testcases/org/apache/poi/ss/util/cellwalk/TestCellWalk.java (revision 0) >@@ -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; >+ } >+ } >+} >\ No newline at end of file
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 51196
:
26995
|
26996
|
27004
|
27021
|
27033
|
27039
|
27077
| 27294 |
27445