mirror of https://github.com/apache/poi.git
Few little short/int tweaks, and then tests to show that FormulaEvaluator plays nicely with xssf
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@642634 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b4590a5c1e
commit
0cd7ba4ad2
|
@ -20,6 +20,99 @@
|
|||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
public class Count extends NotImplementedFunction {
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.BlankEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Eval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RefEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
}
|
||||
/**
|
||||
* Counts the number of cells that contain numeric data within
|
||||
* the list of arguments.
|
||||
*
|
||||
* Excel Syntax
|
||||
* COUNT(value1,value2,...)
|
||||
* Value1, value2, ... are 1 to 30 arguments representing the values or ranges to be counted.
|
||||
*
|
||||
* TODO: Check this properly matches excel on edge cases
|
||||
* like formula cells, error cells etc
|
||||
*/
|
||||
public class Count implements Function {
|
||||
|
||||
public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
|
||||
int nArgs = args.length;
|
||||
if (nArgs < 1) {
|
||||
// too few arguments
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
if (nArgs > 30) {
|
||||
// too many arguments
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
int temp = 0;
|
||||
|
||||
for(int i=0; i<nArgs; i++) {
|
||||
temp += countArg(args[i]);
|
||||
|
||||
}
|
||||
return new NumberEval(temp);
|
||||
}
|
||||
|
||||
private static int countArg(Eval eval) {
|
||||
if (eval instanceof AreaEval) {
|
||||
AreaEval ae = (AreaEval) eval;
|
||||
return countAreaEval(ae);
|
||||
}
|
||||
if (eval instanceof RefEval) {
|
||||
RefEval refEval = (RefEval)eval;
|
||||
return countValue(refEval.getInnerValueEval());
|
||||
}
|
||||
if (eval instanceof NumberEval) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Unexpected eval type (" + eval.getClass().getName() + ")");
|
||||
}
|
||||
|
||||
private static int countAreaEval(AreaEval ae) {
|
||||
|
||||
int temp = 0;
|
||||
ValueEval[] values = ae.getValues();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
ValueEval val = values[i];
|
||||
if(val == null) {
|
||||
// seems to occur. Really we would have expected BlankEval
|
||||
continue;
|
||||
}
|
||||
temp += countValue(val);
|
||||
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
private static int countValue(ValueEval valueEval) {
|
||||
|
||||
if(valueEval == BlankEval.INSTANCE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(valueEval instanceof BlankEval) {
|
||||
// wouldn't need this if BlankEval was final
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(valueEval instanceof ErrorEval) {
|
||||
// note - error values not counted
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(valueEval instanceof NumberEval)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -120,10 +120,28 @@ public final class HSSFRow implements Comparable, Row {
|
|||
*
|
||||
* @return HSSFCell a high level representation of the created cell.
|
||||
*/
|
||||
|
||||
public HSSFCell createCell(short column)
|
||||
{
|
||||
return this.createCell(column,HSSFCell.CELL_TYPE_BLANK);
|
||||
return this.createCell(column,HSSFCell.CELL_TYPE_BLANK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to create new cells within the row and return it.
|
||||
* <p>
|
||||
* The cell that is returned is a CELL_TYPE_BLANK. The type can be changed
|
||||
* either through calling <code>setCellValue</code> or <code>setCellType</code>.
|
||||
*
|
||||
* @param column - the column number this cell represents
|
||||
*
|
||||
* @return HSSFCell a high level representation of the created cell.
|
||||
*/
|
||||
public HSSFCell createCell(int column)
|
||||
{
|
||||
short shortCellNum = (short)column;
|
||||
if(column > 0x7FFF) {
|
||||
shortCellNum = (short)(0xffff - column);
|
||||
}
|
||||
return this.createCell(shortCellNum,HSSFCell.CELL_TYPE_BLANK);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,7 +154,6 @@ public final class HSSFRow implements Comparable, Row {
|
|||
*
|
||||
* @return HSSFCell a high level representation of the created cell.
|
||||
*/
|
||||
|
||||
public HSSFCell createCell(short column, int type)
|
||||
{
|
||||
HSSFCell cell = new HSSFCell(book, sheet, getRowNum(), column, type);
|
||||
|
|
|
@ -33,9 +33,20 @@ public interface Row extends Iterable {
|
|||
*
|
||||
* @param column - the column number this cell represents
|
||||
*
|
||||
* @return HSSFCell a high level representation of the created cell.
|
||||
* @return Cell a high level representation of the created cell.
|
||||
*/
|
||||
Cell createCell(int column);
|
||||
|
||||
/**
|
||||
* Use this to create new cells within the row and return it.
|
||||
* <p>
|
||||
* The cell that is returned is a CELL_TYPE_BLANK. The type can be changed
|
||||
* either through calling <code>setCellValue</code> or <code>setCellType</code>.
|
||||
*
|
||||
* @param column - the column number this cell represents
|
||||
*
|
||||
* @return Cell a high level representation of the created cell.
|
||||
*/
|
||||
Cell createCell(short column);
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,7 +39,7 @@ public class XSSFCell implements Cell {
|
|||
private static final String TRUE_AS_STRING = "1";
|
||||
private final CTCell cell;
|
||||
private final XSSFRow row;
|
||||
private short cellNum;
|
||||
private int cellNum;
|
||||
private SharedStringSource sharedStringSource;
|
||||
private StylesSource stylesSource;
|
||||
|
||||
|
@ -91,7 +91,7 @@ public class XSSFCell implements Cell {
|
|||
}
|
||||
|
||||
public short getCellNum() {
|
||||
return this.cellNum;
|
||||
return (short)this.cellNum;
|
||||
}
|
||||
|
||||
public CellStyle getCellStyle() {
|
||||
|
@ -212,6 +212,9 @@ public class XSSFCell implements Cell {
|
|||
|
||||
}
|
||||
|
||||
public void setCellNum(int num) {
|
||||
setCellNum((short)num);
|
||||
}
|
||||
public void setCellNum(short num) {
|
||||
checkBounds(num);
|
||||
this.cellNum = num;
|
||||
|
|
|
@ -79,9 +79,12 @@ public class XSSFRow implements Row {
|
|||
return 0;
|
||||
}
|
||||
|
||||
public Cell createCell(short column) {
|
||||
public Cell createCell(int column) {
|
||||
return createCell(column, Cell.CELL_TYPE_BLANK);
|
||||
}
|
||||
public Cell createCell(short column) {
|
||||
return createCell((int)column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new empty cell to this row.
|
||||
|
@ -91,7 +94,7 @@ public class XSSFRow implements Row {
|
|||
* @param type TODO
|
||||
* @return The new cell.
|
||||
*/
|
||||
protected XSSFCell addCell(short column, int index, int type) {
|
||||
protected XSSFCell addCell(int column, int index, int type) {
|
||||
CTCell ctcell = row.insertNewC(index);
|
||||
XSSFCell xcell = new XSSFCell(this, ctcell);
|
||||
xcell.setCellNum(column);
|
||||
|
@ -102,6 +105,9 @@ public class XSSFRow implements Row {
|
|||
}
|
||||
|
||||
public Cell createCell(short column, int type) {
|
||||
return createCell((int)column, type);
|
||||
}
|
||||
public Cell createCell(int column, int type) {
|
||||
int index = 0;
|
||||
for (Cell c : this.cells) {
|
||||
if (c.getCellNum() == column) {
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/* ====================================================================
|
||||
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;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class TestXSSFFormulaEvaluation extends TestCase {
|
||||
public TestXSSFFormulaEvaluation(String name) {
|
||||
super(name);
|
||||
|
||||
// Use system out logger
|
||||
System.setProperty(
|
||||
"org.apache.poi.util.POILogger",
|
||||
"org.apache.poi.util.SystemOutLogger"
|
||||
);
|
||||
}
|
||||
|
||||
public void testSimpleArithmatic() throws Exception {
|
||||
Workbook wb = new XSSFWorkbook();
|
||||
Sheet s = wb.createSheet();
|
||||
Row r = s.createRow(0);
|
||||
|
||||
Cell c1 = r.createCell(0);
|
||||
c1.setCellFormula("1+5");
|
||||
assertTrue( Double.isNaN(c1.getNumericCellValue()) );
|
||||
|
||||
Cell c2 = r.createCell(1);
|
||||
c2.setCellFormula("10/2");
|
||||
assertTrue( Double.isNaN(c2.getNumericCellValue()) );
|
||||
|
||||
FormulaEvaluator fe = new FormulaEvaluator(s, wb);
|
||||
fe.setCurrentRow(r);
|
||||
|
||||
fe.evaluateFormulaCell(c1);
|
||||
fe.evaluateFormulaCell(c2);
|
||||
|
||||
assertEquals(6.0, c1.getNumericCellValue(), 0.0001);
|
||||
assertEquals(5.0, c2.getNumericCellValue(), 0.0001);
|
||||
}
|
||||
|
||||
public void testSumCount() throws Exception {
|
||||
Workbook wb = new XSSFWorkbook();
|
||||
Sheet s = wb.createSheet();
|
||||
Row r = s.createRow(0);
|
||||
r.createCell(0).setCellValue(2.5);
|
||||
r.createCell(1).setCellValue(1.1);
|
||||
r.createCell(2).setCellValue(3.2);
|
||||
r.createCell(4).setCellValue(10.7);
|
||||
|
||||
r = s.createRow(1);
|
||||
|
||||
Cell c1 = r.createCell(0);
|
||||
c1.setCellFormula("SUM(A1:B1)");
|
||||
assertTrue( Double.isNaN(c1.getNumericCellValue()) );
|
||||
|
||||
Cell c2 = r.createCell(1);
|
||||
c2.setCellFormula("SUM(A1:E1)");
|
||||
assertTrue( Double.isNaN(c2.getNumericCellValue()) );
|
||||
|
||||
Cell c3 = r.createCell(2);
|
||||
c3.setCellFormula("COUNT(A1:A1)");
|
||||
assertTrue( Double.isNaN(c3.getNumericCellValue()) );
|
||||
|
||||
Cell c4 = r.createCell(2);
|
||||
c4.setCellFormula("COUNTA(A1:E1)");
|
||||
assertTrue( Double.isNaN(c4.getNumericCellValue()) );
|
||||
|
||||
|
||||
// Evaluate and test
|
||||
FormulaEvaluator fe = new FormulaEvaluator(s, wb);
|
||||
fe.setCurrentRow(r);
|
||||
|
||||
fe.evaluateFormulaCell(c1);
|
||||
fe.evaluateFormulaCell(c2);
|
||||
fe.evaluateFormulaCell(c3);
|
||||
fe.evaluateFormulaCell(c4);
|
||||
|
||||
assertEquals(3.6, c1.getNumericCellValue(), 0.0001);
|
||||
assertEquals(17.5, c2.getNumericCellValue(), 0.0001);
|
||||
assertEquals(1, c3.getNumericCellValue(), 0.0001);
|
||||
assertEquals(4, c4.getNumericCellValue(), 0.0001);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue