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:
Nick Burch 2008-03-29 22:45:11 +00:00
parent b4590a5c1e
commit 0cd7ba4ad2
6 changed files with 244 additions and 10 deletions

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);
/**

View File

@ -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;

View File

@ -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) {

View File

@ -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);
}
}