failures = failureMessages.iterator() ;
+ while( failures.hasNext() ) {
+ log( failures.next(), Project.MSG_ERR ) ;
+ }
+ }
+ }
+ }
+
+ public boolean didTestPass() {
+
+ return passed ;
+ }
+ }
diff --git a/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntUserDefinedFunction.java b/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntUserDefinedFunction.java
new file mode 100755
index 0000000000..f69e9b6366
--- /dev/null
+++ b/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntUserDefinedFunction.java
@@ -0,0 +1,55 @@
+/* ====================================================================
+ 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.excelant;
+
+import org.apache.tools.ant.taskdefs.Typedef;
+
+/**
+ * This class encapsulates the Strings necessary to create the User Defined
+ * Function instances that will be passed to POI's Evaluator instance.
+ *
+ * @author Jon Svede ( jon [at] loquatic [dot] com )
+ * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
+ *
+ */
+public class ExcelAntUserDefinedFunction extends Typedef {
+
+
+ public String functionAlias ;
+
+ public String className ;
+
+
+ public ExcelAntUserDefinedFunction() {}
+
+ protected String getFunctionAlias() {
+ return functionAlias;
+ }
+
+ public void setFunctionAlias(String functionAlias) {
+ this.functionAlias = functionAlias;
+ }
+
+ protected String getClassName() {
+ return className;
+ }
+
+ public void setClassName(String className) {
+ this.className = className;
+ }
+}
diff --git a/src/excelant/java/org/apache/poi/ss/excelant/IExcelAntWorkbookHandler.java b/src/excelant/java/org/apache/poi/ss/excelant/IExcelAntWorkbookHandler.java
new file mode 100755
index 0000000000..3cd477abc8
--- /dev/null
+++ b/src/excelant/java/org/apache/poi/ss/excelant/IExcelAntWorkbookHandler.java
@@ -0,0 +1,46 @@
+/* ====================================================================
+ 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.excelant;
+
+import org.apache.poi.ss.usermodel.Workbook;
+
+
+/**
+ * In Excel there are many ways to handle manipulating a workbook based
+ * on some arbitrary user action (onChange, etc). You use this interface
+ * to create classes that will handle the workbook in whatever manner is needed
+ * that cannot be handled by POI.
+ *
+ * For example, suppose that in Excel when you update a cell the workbook
+ * does some calculations and updates other cells based on that change. In
+ * ExcelAnt you would set the value of the cell then write your own handler
+ * then call that from your Ant task after the set task.
+ *
+ * @author Jon Svede ( jon [at] loquatic [dot] com )
+ * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
+ *
+ */
+public interface IExcelAntWorkbookHandler {
+
+
+ public void setWorkbook( Workbook workbook ) ;
+
+ public void execute() ;
+
+
+}
diff --git a/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntEvaluationResult.java b/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntEvaluationResult.java
new file mode 100755
index 0000000000..6633357157
--- /dev/null
+++ b/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntEvaluationResult.java
@@ -0,0 +1,114 @@
+/* ====================================================================
+ 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.excelant.util;
+
+/**
+ * A simple class that encapsulates information about a cell evaluation
+ * from POI.
+ *
+ * @author Jon Svede ( jon [at] loquatic [dot] com )
+ * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
+ *
+ */
+public class ExcelAntEvaluationResult {
+
+ /**
+ * This boolean flag is used to determine if the evaluation completed
+ * without error. This alone doesn't ensure that the evaluation was
+ * sucessful.
+ */
+ private boolean evaluationCompletedWithError ;
+
+ /**
+ * This boolean flag is used to determine if the result was within
+ * the specified precision.
+ */
+ private boolean didPass ;
+
+ /**
+ * This is the actual value returned from the evaluation.
+ */
+ private double returnValue ;
+
+ /**
+ * Any error message String values that need to be returned.
+ */
+ private String errorMessage ;
+
+ /**
+ * Stores the absolute value of the delta for this evaluation.
+ */
+ private double actualDelta ;
+
+ /**
+ * This stores the fully qualified cell name (sheetName!cellId).
+ */
+ private String cellName ;
+
+
+
+ public ExcelAntEvaluationResult( boolean completedWithError,
+ boolean passed,
+ double retValue,
+ String errMessage,
+ double delta,
+ String cellId ) {
+
+ evaluationCompletedWithError = completedWithError;
+ didPass = passed;
+ returnValue = retValue;
+ errorMessage = errMessage;
+ actualDelta = delta ;
+ cellName = cellId ;
+ }
+
+ public double getReturnValue() {
+ return returnValue;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public boolean didTestPass() {
+ return didPass ;
+ }
+
+ public boolean evaluationCompleteWithError() {
+ return evaluationCompletedWithError ;
+ }
+
+ public double getDelta() {
+ return actualDelta ;
+ }
+
+ public String getCellName() {
+ return cellName ;
+ }
+
+ @Override
+ public String toString() {
+ return "ExcelAntEvaluationResult [evaluationCompletedWithError="
+ + evaluationCompletedWithError + ", didPass=" + didPass
+ + ", returnValue=" + returnValue + ", errorMessage="
+ + errorMessage + ", actualDelta=" + actualDelta + ", cellName="
+ + cellName + "]";
+ }
+
+
+}
diff --git a/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtil.java b/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtil.java
new file mode 100755
index 0000000000..af23d69c0c
--- /dev/null
+++ b/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtil.java
@@ -0,0 +1,384 @@
+/* ====================================================================
+ 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.excelant.util;
+
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+import org.apache.poi.ss.formula.udf.AggregatingUDFFinder;
+import org.apache.poi.ss.formula.udf.DefaultUDFFinder;
+import org.apache.poi.ss.formula.udf.UDFFinder;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Typedef;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * A general utility class that abstracts the POI details of loading the
+ * workbook, accessing and updating cells.
+ *
+ * @author Jon Svede ( jon [at] loquatic [dot] com )
+ * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
+ *
+ */
+public class ExcelAntWorkbookUtil extends Typedef {
+
+ private String excelFileName;
+
+ private Workbook workbook;
+
+ private HashMap xlsMacroList;
+
+ /**
+ * Constructs an instance using a String that contains the fully qualified
+ * path of the Excel file. This constructor initializes a Workbook instance
+ * based on that file name.
+ *
+ * @param fName
+ */
+ protected ExcelAntWorkbookUtil(String fName) {
+ excelFileName = fName;
+ xlsMacroList = new HashMap() ;
+ loadWorkbook();
+
+ }
+
+ /**
+ * Constructs an instance based on a Workbook instance.
+ *
+ * @param wb
+ */
+ protected ExcelAntWorkbookUtil(Workbook wb) {
+ workbook = wb;
+ xlsMacroList = new HashMap() ;
+ }
+
+ /**
+ * Loads the member variable workbook based on the fileName variable.
+ * @return
+ */
+ private Workbook loadWorkbook() {
+
+ File workbookFile = new File(excelFileName);
+ try {
+ FileInputStream fis = new FileInputStream(workbookFile);
+ workbook = WorkbookFactory.create(fis);
+ } catch(Exception e) {
+ throw new BuildException("Cannot load file " + excelFileName
+ + ". Make sure the path and file permissions are correct.", e);
+ }
+
+ return workbook ;
+ }
+
+ /**
+ * Used to add a UDF to the evaluator.
+ * @param name
+ * @param clazzName
+ * @throws ClassNotFoundException
+ * @throws InstantiationException
+ * @throws IllegalAccessException
+ */
+ public void addFunction( String name, String clazzName ) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ Class clazzInst = Class.forName( clazzName ) ;
+ Object newInst = clazzInst.newInstance() ;
+ if( newInst instanceof FreeRefFunction ) {
+ addFunction( name, (FreeRefFunction)newInst ) ;
+ }
+
+ }
+
+ /**
+ * Updates the internal HashMap of functions with instance and alias passed
+ * in.
+ *
+ * @param name
+ * @param func
+ */
+ protected void addFunction(String name, FreeRefFunction func) {
+ xlsMacroList.put(name, func);
+ }
+
+ /**
+ * returns a UDFFinder that contains all of the functions added.
+ *
+ * @return
+ */
+ protected UDFFinder getFunctions() {
+
+ String[] names = new String[xlsMacroList.size()];
+ FreeRefFunction[] functions = new FreeRefFunction[xlsMacroList.size()];
+
+ Iterator keysIt = xlsMacroList.keySet().iterator();
+ int x = 0;
+ while (keysIt.hasNext()) {
+ String name = keysIt.next();
+ FreeRefFunction function = xlsMacroList.get(name);
+ names[x] = name;
+ functions[x] = function;
+ }
+
+ UDFFinder udff1 = new DefaultUDFFinder(names, functions);
+ UDFFinder udff = new AggregatingUDFFinder(udff1);
+
+ return udff;
+
+ }
+
+ /**
+ * Returns a formula evaluator that is loaded with the functions that
+ * have been supplied.
+ *
+ * @param excelFileName
+ * @return
+ */
+ protected FormulaEvaluator getEvaluator( String excelFileName ) {
+ FormulaEvaluator evaluator ;
+ if (excelFileName.endsWith(".xlsx")) {
+ if( xlsMacroList != null && xlsMacroList.size() > 0 ) {
+ evaluator = XSSFFormulaEvaluator.create( (XSSFWorkbook) workbook,
+ null,
+ getFunctions() ) ;
+ }
+ evaluator = new XSSFFormulaEvaluator((XSSFWorkbook) workbook);
+ } else {
+ if( xlsMacroList != null && xlsMacroList.size() > 0 ) {
+ evaluator = HSSFFormulaEvaluator.create( (HSSFWorkbook)workbook,
+ null,
+ getFunctions() ) ;
+ }
+
+ evaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
+ }
+
+ return evaluator ;
+
+ }
+
+ /**
+ * Returns the Workbook instance associated with this WorkbookUtil.
+ *
+ * @return
+ */
+ public Workbook getWorkbook() {
+ return workbook;
+ }
+
+ /**
+ * Returns the fileName that was used to initialize this instance. May
+ * return null if the instance was constructed from a Workbook object.
+ *
+ * @return
+ */
+ public String getFileName() {
+ return excelFileName;
+ }
+
+ /**
+ * Returns the list of sheet names.
+ *
+ * @return
+ */
+ public ArrayList getSheets() {
+ ArrayList sheets = new ArrayList() ;
+
+ int sheetCount = workbook.getNumberOfSheets() ;
+
+ for( int x=0; x precision) {
+ evalResults = new ExcelAntEvaluationResult(false, false,
+ resultOfEval.getNumberValue(),
+ "Results was out of range based on precision " + " of "
+ + precision + ". Delta was actually " + delta, delta, cellName );
+ } else {
+ evalResults = new ExcelAntEvaluationResult(false, true,
+ resultOfEval.getNumberValue(),
+ "Evaluation passed without error within in range.", delta, cellName );
+ }
+ } else {
+ String errorMeaning = null ;
+ try {
+ errorMeaning = ErrorConstants.getText( resultOfEval
+ .getErrorValue() ) ;
+ } catch( IllegalArgumentException iae ) {
+ errorMeaning = "unknown error code: " +
+ Byte.toString( resultOfEval.getErrorValue() ) ;
+ }
+
+ evalResults = new ExcelAntEvaluationResult(false, false,
+ resultOfEval.getNumberValue(),
+ "Evaluation failed due to an evaluation error of "
+ + resultOfEval.getErrorValue()
+ + " which is "
+ + errorMeaning, 0, cellName );
+ }
+
+ return evalResults;
+ }
+
+ /**
+ * Returns a Cell as a String value.
+ *
+ * @param cellName
+ * @return
+ */
+ public String getCellAsString( String cellName ) {
+ Cell cell = getCell( cellName ) ;
+ if( cell != null ) {
+ return cell.getStringCellValue() ;
+ }
+ return "" ;
+ }
+
+
+ /**
+ * Returns the value of the Cell as a double.
+ *
+ * @param cellName
+ * @return
+ */
+ public double getCellAsDouble( String cellName ) {
+ Cell cell = getCell( cellName ) ;
+ if( cell != null ) {
+ return cell.getNumericCellValue() ;
+ }
+ return 0.0 ;
+ }
+ /**
+ * Returns a cell reference based on a String in standard Excel format
+ * (SheetName!CellId). This method will create a new cell if the
+ * requested cell isn't initialized yet.
+ *
+ * @param cellName
+ * @return
+ */
+ private Cell getCell(String cellName) {
+
+ CellReference cellRef = new CellReference(cellName);
+ String sheetName = cellRef.getSheetName();
+ Sheet sheet = workbook.getSheet(sheetName);
+ if(sheet == null) {
+ throw new BuildException("Sheet not found: " + sheetName);
+ }
+
+ int rowIdx = cellRef.getRow();
+ int colIdx = cellRef.getCol();
+ Row row = sheet.getRow(rowIdx);
+
+ if( row == null ) {
+ row = sheet.createRow( rowIdx ) ;
+ }
+
+ Cell cell = row.getCell(colIdx);
+
+ if( cell == null ) {
+ cell = row.createCell( colIdx ) ;
+ }
+
+ return cell;
+ }
+
+}
diff --git a/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtilFactory.java b/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtilFactory.java
new file mode 100755
index 0000000000..6c29eeba74
--- /dev/null
+++ b/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtilFactory.java
@@ -0,0 +1,63 @@
+/* ====================================================================
+ 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.excelant.util;
+
+import java.util.HashMap;
+
+
+/**
+ * This is a factory class maps file names to WorkbookUtil instances. This
+ * helps ExcelAnt be more efficient when being run many times in an Ant build.
+ *
+ * @author Jon Svede ( jon [at] loquatic [dot] com )
+ * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
+ *
+ */
+public class ExcelAntWorkbookUtilFactory {
+
+ private static HashMap workbookUtilMap ;
+
+ private static ExcelAntWorkbookUtilFactory factory ;
+
+ private ExcelAntWorkbookUtilFactory() {
+ workbookUtilMap = new HashMap() ;
+ }
+
+ /**
+ * Using the fileName, check the internal map to see if an instance
+ * of the WorkbookUtil exists. If not, then add an instance to the map.
+ *
+ * @param fileName
+ * @return
+ */
+ public static ExcelAntWorkbookUtil getInstance( String fileName ) {
+
+ if( factory == null ) {
+ factory = new ExcelAntWorkbookUtilFactory() ;
+ }
+ if( workbookUtilMap != null &&
+ workbookUtilMap.containsKey( fileName ) ) {
+ return workbookUtilMap.get( fileName ) ;
+ } else {
+ ExcelAntWorkbookUtil wbu = new ExcelAntWorkbookUtil( fileName ) ;
+ workbookUtilMap.put( fileName, wbu ) ;
+ return wbu ;
+ }
+ }
+
+}
diff --git a/src/excelant/resources/org/apache/poi/ss/excelant/antlib.xml b/src/excelant/resources/org/apache/poi/ss/excelant/antlib.xml
new file mode 100755
index 0000000000..31dadfaf60
--- /dev/null
+++ b/src/excelant/resources/org/apache/poi/ss/excelant/antlib.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/excelant/testcases/org/apache/poi/ss/examples/formula/CalculateMortgage.java b/src/excelant/testcases/org/apache/poi/ss/examples/formula/CalculateMortgage.java
new file mode 100755
index 0000000000..4b9a325cdf
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/examples/formula/CalculateMortgage.java
@@ -0,0 +1,93 @@
+/* ====================================================================
+ 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.examples.formula;
+
+import org.apache.poi.ss.formula.OperationEvaluationContext ;
+import org.apache.poi.ss.formula.eval.ErrorEval ;
+import org.apache.poi.ss.formula.eval.EvaluationException ;
+import org.apache.poi.ss.formula.eval.NumberEval ;
+import org.apache.poi.ss.formula.eval.OperandResolver ;
+import org.apache.poi.ss.formula.eval.ValueEval ;
+import org.apache.poi.ss.formula.functions.FreeRefFunction ;
+
+/**
+ * A simple user-defined function to calculate principal and interest.
+ *
+ * @author Jon Svede ( jon [at] loquatic [dot] com )
+ * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
+ *
+ */
+public class CalculateMortgage implements FreeRefFunction {
+
+ public ValueEval evaluate( ValueEval[] args, OperationEvaluationContext ec ) {
+
+ // verify that we have enough data
+ if (args.length != 3) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+ // declare doubles for values
+ double principal, rate, years, result;
+ try {
+ // extract values as ValueEval
+ ValueEval v1 = OperandResolver.getSingleValue( args[0],
+ ec.getRowIndex(),
+ ec.getColumnIndex() ) ;
+ ValueEval v2 = OperandResolver.getSingleValue( args[1],
+ ec.getRowIndex(),
+ ec.getColumnIndex() ) ;
+ ValueEval v3 = OperandResolver.getSingleValue( args[2],
+ ec.getRowIndex(),
+ ec.getColumnIndex() ) ;
+
+ // get data as doubles
+ principal = OperandResolver.coerceValueToDouble( v1 ) ;
+ rate = OperandResolver.coerceValueToDouble( v2 ) ;
+ years = OperandResolver.coerceValueToDouble( v3 ) ;
+
+ result = calculateMortgagePayment( principal, rate, years ) ;
+ System.out.println( "Result = " + result ) ;
+
+ checkValue(result);
+
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+
+ return new NumberEval( result ) ;
+ }
+
+ public double calculateMortgagePayment( double p, double r, double y ) {
+ double i = r / 12 ;
+ double n = y * 12 ;
+
+ double principalAndInterest =
+ p * (( i * Math.pow((1 + i),n ) ) / ( Math.pow((1 + i),n) - 1)) ;
+
+ return principalAndInterest ;
+ }
+ /**
+ * Excel does not support infinities and NaNs, rather, it gives a #NUM! error in these cases
+ *
+ * @throws EvaluationException (#NUM!) if result is NaN> or Infinity
+ */
+ private void checkValue(double result) throws EvaluationException {
+ if (Double.isNaN(result) || Double.isInfinite(result)) {
+ throw new EvaluationException(ErrorEval.NUM_ERROR);
+ }
+ }
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/examples/formula/ExcelAntUserDefinedFunctionTestHelper.java b/src/excelant/testcases/org/apache/poi/ss/examples/formula/ExcelAntUserDefinedFunctionTestHelper.java
new file mode 100755
index 0000000000..68e4b6957f
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/examples/formula/ExcelAntUserDefinedFunctionTestHelper.java
@@ -0,0 +1,36 @@
+/* ====================================================================
+ 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.examples.formula;
+
+import org.apache.poi.ss.excelant.ExcelAntUserDefinedFunction;
+
+public class ExcelAntUserDefinedFunctionTestHelper extends
+ ExcelAntUserDefinedFunction {
+
+ @Override
+ protected String getFunctionAlias() {
+ // TODO Auto-generated method stub
+ return super.getFunctionAlias();
+ }
+
+ @Override
+ protected String getClassName() {
+ // TODO Auto-generated method stub
+ return super.getClassName();
+ }
+
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/examples/formula/TestExcelAntUserDefinedFunction.java b/src/excelant/testcases/org/apache/poi/ss/examples/formula/TestExcelAntUserDefinedFunction.java
new file mode 100755
index 0000000000..ad9851ae8f
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/examples/formula/TestExcelAntUserDefinedFunction.java
@@ -0,0 +1,51 @@
+/* ====================================================================
+ 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.examples.formula;
+
+import junit.framework.TestCase;
+
+public class TestExcelAntUserDefinedFunction extends TestCase {
+
+ private ExcelAntUserDefinedFunctionTestHelper fixture ;
+
+ @Override
+ public void setUp() {
+ fixture = new ExcelAntUserDefinedFunctionTestHelper() ;
+ }
+
+ public void testSetClassName() {
+ String className = "simple.class.name" ;
+
+ fixture.setClassName( className ) ;
+ String value = fixture.getClassName() ;
+
+ assertNotNull( value ) ;
+ assertEquals( className, value ) ;
+ }
+
+ public void testSetFunction() {
+ String functionAlias = "alias" ;
+
+ fixture.setFunctionAlias( functionAlias ) ;
+
+ String alias = fixture.getFunctionAlias() ;
+
+ assertNotNull( alias ) ;
+ assertEquals( functionAlias, alias ) ;
+ }
+
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/BuildFileTest.java b/src/excelant/testcases/org/apache/poi/ss/excelant/BuildFileTest.java
new file mode 100755
index 0000000000..5a30744cd0
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/excelant/BuildFileTest.java
@@ -0,0 +1,583 @@
+/*
+ * 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.excelant;
+
+import junit.framework.TestCase;
+import org.apache.tools.ant.*;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.net.URL;
+
+/**
+ * A BuildFileTest is a TestCase which executes targets from an Ant buildfile
+ * for testing.
+ *
+ * This class provides a number of utility methods for particular build file
+ * tests which extend this class.
+ *
+ * @see
+ * http://svn.apache.org/repos/asf/ant/core/trunk/src/tests/junit/org/apache/tools/ant/BuildFileTest.java
+ */
+public abstract class BuildFileTest extends TestCase {
+
+ protected Project project;
+
+ private StringBuffer logBuffer;
+ private StringBuffer fullLogBuffer;
+ private StringBuffer outBuffer;
+ private StringBuffer errBuffer;
+ private BuildException buildException;
+
+ /**
+ * Default constructor for the BuildFileTest object.
+ */
+ public BuildFileTest() {
+ super();
+ }
+
+ /**
+ * Constructor for the BuildFileTest object.
+ *
+ * @param name string to pass up to TestCase constructor
+ */
+ public BuildFileTest(String name) {
+ super(name);
+ }
+
+ /**
+ * Automatically calls the target called "tearDown"
+ * from the build file tested if it exits.
+ *
+ * This allows to use Ant tasks directly in the build file
+ * to clean up after each test. Note that no "setUp" target
+ * is automatically called, since it's trivial to have a
+ * test target depend on it.
+ */
+ protected void tearDown() throws Exception {
+ if (project == null) {
+ /*
+ * Maybe the BuildFileTest was subclassed and there is
+ * no initialized project. So we could avoid getting a
+ * NPE.
+ * If there is an initialized project getTargets() does
+ * not return null as it is initialized by an empty
+ * HashSet.
+ */
+ return;
+ }
+ final String tearDown = "tearDown";
+ if (project.getTargets().containsKey(tearDown)) {
+ project.executeTarget(tearDown);
+ }
+ }
+
+ /**
+ * run a target, expect for any build exception
+ *
+ * @param target target to run
+ * @param cause information string to reader of report
+ */
+ public void expectBuildException(String target, String cause) {
+ expectSpecificBuildException(target, cause, null);
+ }
+
+ /**
+ * Assert that only the given message has been logged with a
+ * priority <= INFO when running the given target.
+ */
+ public void expectLog(String target, String log) {
+ executeTarget(target);
+ String realLog = getLog();
+ assertEquals(log, realLog);
+ }
+
+ /**
+ * Assert that the given substring is in the log messages.
+ */
+ public void assertLogContaining(String substring) {
+ String realLog = getLog();
+ assertTrue("expecting log to contain \"" + substring + "\" log was \""
+ + realLog + "\"",
+ realLog.indexOf(substring) >= 0);
+ }
+
+ /**
+ * Assert that the given substring is not in the log messages.
+ */
+ public void assertLogNotContaining(String substring) {
+ String realLog = getLog();
+ assertFalse("didn't expect log to contain \"" + substring + "\" log was \""
+ + realLog + "\"",
+ realLog.indexOf(substring) >= 0);
+ }
+
+ /**
+ * Assert that the given substring is in the output messages.
+ *
+ * @since Ant1.7
+ */
+ public void assertOutputContaining(String substring) {
+ assertOutputContaining(null, substring);
+ }
+
+ /**
+ * Assert that the given substring is in the output messages.
+ *
+ * @param message Print this message if the test fails. Defaults to
+ * a meaningful text if null is passed.
+ * @since Ant1.7
+ */
+ public void assertOutputContaining(String message, String substring) {
+ String realOutput = getOutput();
+ String realMessage = (message != null)
+ ? message
+ : "expecting output to contain \"" + substring + "\" output was \"" + realOutput + "\"";
+ assertTrue(realMessage, realOutput.indexOf(substring) >= 0);
+ }
+
+ /**
+ * Assert that the given substring is not in the output messages.
+ *
+ * @param message Print this message if the test fails. Defaults to
+ * a meaningful text if null is passed.
+ * @since Ant1.7
+ */
+ public void assertOutputNotContaining(String message, String substring) {
+ String realOutput = getOutput();
+ String realMessage = (message != null)
+ ? message
+ : "expecting output to not contain \"" + substring + "\" output was \"" + realOutput + "\"";
+ assertFalse(realMessage, realOutput.indexOf(substring) >= 0);
+ }
+
+ /**
+ * Assert that the given message has been logged with a priority <= INFO when running the
+ * given target.
+ */
+ public void expectLogContaining(String target, String log) {
+ executeTarget(target);
+ assertLogContaining(log);
+ }
+
+ /**
+ * Assert that the given message has not been logged with a
+ * priority <= INFO when running the given target.
+ */
+ public void expectLogNotContaining(String target, String log) {
+ executeTarget(target);
+ assertLogNotContaining(log);
+ }
+
+ /**
+ * Gets the log the BuildFileTest object.
+ * Only valid if configureProject() has been called.
+ *
+ * @return The log value
+ * @pre logBuffer!=null
+ */
+ public String getLog() {
+ return logBuffer.toString();
+ }
+
+ /**
+ * Assert that the given message has been logged with a priority
+ * >= VERBOSE when running the given target.
+ */
+ public void expectDebuglog(String target, String log) {
+ executeTarget(target);
+ String realLog = getFullLog();
+ assertEquals(log, realLog);
+ }
+
+ /**
+ * Assert that the given substring is in the log messages.
+ */
+ public void assertDebuglogContaining(String substring) {
+ String realLog = getFullLog();
+ assertTrue("expecting debug log to contain \"" + substring
+ + "\" log was \""
+ + realLog + "\"",
+ realLog.indexOf(substring) >= 0);
+ }
+
+ /**
+ * Gets the log the BuildFileTest object.
+ *
+ * Only valid if configureProject() has been called.
+ *
+ * @return The log value
+ * @pre fullLogBuffer!=null
+ */
+ public String getFullLog() {
+ return fullLogBuffer.toString();
+ }
+
+ /**
+ * execute the target, verify output matches expectations
+ *
+ * @param target target to execute
+ * @param output output to look for
+ */
+ public void expectOutput(String target, String output) {
+ executeTarget(target);
+ String realOutput = getOutput();
+ assertEquals(output, realOutput.trim());
+ }
+
+ /**
+ * Executes the target, verify output matches expectations
+ * and that we got the named error at the end
+ *
+ * @param target target to execute
+ * @param output output to look for
+ * @param error Description of Parameter
+ */
+ public void expectOutputAndError(String target, String output, String error) {
+ executeTarget(target);
+ String realOutput = getOutput();
+ assertEquals(output, realOutput);
+ String realError = getError();
+ assertEquals(error, realError);
+ }
+
+ public String getOutput() {
+ return cleanBuffer(outBuffer);
+ }
+
+ public String getError() {
+ return cleanBuffer(errBuffer);
+ }
+
+ public BuildException getBuildException() {
+ return buildException;
+ }
+
+ private String cleanBuffer(StringBuffer buffer) {
+ StringBuffer cleanedBuffer = new StringBuffer();
+ for (int i = 0; i < buffer.length(); i++) {
+ char ch = buffer.charAt(i);
+ if (ch != '\r') {
+ cleanedBuffer.append(ch);
+ }
+ }
+ return cleanedBuffer.toString();
+ }
+
+ /**
+ * Sets up to run the named project
+ *
+ * @param filename name of project file to run
+ */
+ public void configureProject(String filename) throws BuildException {
+ configureProject(filename, Project.MSG_DEBUG);
+ }
+
+ /**
+ * Sets up to run the named project
+ *
+ * @param filename name of project file to run
+ */
+ public void configureProject(String filename, int logLevel)
+ throws BuildException {
+ logBuffer = new StringBuffer();
+ fullLogBuffer = new StringBuffer();
+ project = new Project();
+ project.init();
+ File antFile = new File(System.getProperty("root"), filename);
+ project.setUserProperty("ant.file", antFile.getAbsolutePath());
+ project.addBuildListener(new AntTestListener(logLevel));
+ ProjectHelper.configureProject(project, antFile);
+ }
+
+ /**
+ * Executes a target we have set up
+ *
+ * @param targetName target to run
+ * @pre configureProject has been called
+ */
+ public void executeTarget(String targetName) {
+ PrintStream sysOut = System.out;
+ PrintStream sysErr = System.err;
+ try {
+ sysOut.flush();
+ sysErr.flush();
+ outBuffer = new StringBuffer();
+ PrintStream out = new PrintStream(new AntOutputStream(outBuffer));
+ System.setOut(out);
+ errBuffer = new StringBuffer();
+ PrintStream err = new PrintStream(new AntOutputStream(errBuffer));
+ System.setErr(err);
+ logBuffer = new StringBuffer();
+ fullLogBuffer = new StringBuffer();
+ buildException = null;
+ project.executeTarget(targetName);
+ } finally {
+ System.setOut(sysOut);
+ System.setErr(sysErr);
+ }
+
+ }
+
+ /**
+ * Get the project which has been configured for a test.
+ *
+ * @return the Project instance for this test.
+ */
+ public Project getProject() {
+ return project;
+ }
+
+ /**
+ * Gets the directory of the project.
+ *
+ * @return the base dir of the project
+ */
+ public File getProjectDir() {
+ return project.getBaseDir();
+ }
+
+ /**
+ * Runs a target, wait for a build exception.
+ *
+ * @param target target to run
+ * @param cause information string to reader of report
+ * @param msg the message value of the build exception we are waiting
+ * for set to null for any build exception to be valid
+ */
+ public void expectSpecificBuildException(String target, String cause, String msg) {
+ try {
+ executeTarget(target);
+ } catch (org.apache.tools.ant.BuildException ex) {
+ buildException = ex;
+ if ((null != msg) && (!ex.getMessage().equals(msg))) {
+ fail("Should throw BuildException because '" + cause
+ + "' with message '" + msg
+ + "' (actual message '" + ex.getMessage() + "' instead)");
+ }
+ return;
+ }
+ fail("Should throw BuildException because: " + cause);
+ }
+
+ /**
+ * run a target, expect an exception string
+ * containing the substring we look for (case sensitive match)
+ *
+ * @param target target to run
+ * @param cause information string to reader of report
+ * @param contains substring of the build exception to look for
+ */
+ public void expectBuildExceptionContaining(String target, String cause, String contains) {
+ try {
+ executeTarget(target);
+ } catch (org.apache.tools.ant.BuildException ex) {
+ buildException = ex;
+ if ((null != contains) && (ex.getMessage().indexOf(contains) == -1)) {
+ fail("Should throw BuildException because '" + cause + "' with message containing '" + contains + "' (actual message '" + ex.getMessage() + "' instead)");
+ }
+ return;
+ }
+ fail("Should throw BuildException because: " + cause);
+ }
+
+ /**
+ * call a target, verify property is as expected
+ *
+ * @param target build file target
+ * @param property property name
+ * @param value expected value
+ */
+ public void expectPropertySet(String target, String property, String value) {
+ executeTarget(target);
+ assertPropertyEquals(property, value);
+ }
+
+ /**
+ * assert that a property equals a value; comparison is case sensitive.
+ *
+ * @param property property name
+ * @param value expected value
+ */
+ public void assertPropertyEquals(String property, String value) {
+ String result = project.getProperty(property);
+ assertEquals("property " + property, value, result);
+ }
+
+ /**
+ * assert that a property equals "true".
+ *
+ * @param property property name
+ */
+ public void assertPropertySet(String property) {
+ assertPropertyEquals(property, "true");
+ }
+
+ /**
+ * assert that a property is null.
+ *
+ * @param property property name
+ */
+ public void assertPropertyUnset(String property) {
+ String result = project.getProperty(property);
+ if (result != null) {
+ fail("Expected property " + property
+ + " to be unset, but it is set to the value: " + result);
+ }
+ }
+
+ /**
+ * call a target, verify named property is "true".
+ *
+ * @param target build file target
+ * @param property property name
+ */
+ public void expectPropertySet(String target, String property) {
+ expectPropertySet(target, property, "true");
+ }
+
+ /**
+ * Call a target, verify property is null.
+ *
+ * @param target build file target
+ * @param property property name
+ */
+ public void expectPropertyUnset(String target, String property) {
+ expectPropertySet(target, property, null);
+ }
+
+ /**
+ * Retrieve a resource from the caller classloader to avoid
+ * assuming a vm working directory. The resource path must be
+ * relative to the package name or absolute from the root path.
+ *
+ * @param resource the resource to retrieve its url.
+ * @throws junit.framework.AssertionFailedError
+ * if the resource is not found.
+ */
+ public URL getResource(String resource) {
+ URL url = getClass().getResource(resource);
+ assertNotNull("Could not find resource :" + resource, url);
+ return url;
+ }
+
+ /**
+ * an output stream which saves stuff to our buffer.
+ */
+ protected static class AntOutputStream extends java.io.OutputStream {
+ private StringBuffer buffer;
+
+ public AntOutputStream(StringBuffer buffer) {
+ this.buffer = buffer;
+ }
+
+ public void write(int b) {
+ buffer.append((char) b);
+ }
+ }
+
+ /**
+ * Our own personal build listener.
+ */
+ private class AntTestListener implements BuildListener {
+ private int logLevel;
+
+ /**
+ * Constructs a test listener which will ignore log events
+ * above the given level.
+ */
+ public AntTestListener(int logLevel) {
+ this.logLevel = logLevel;
+ }
+
+ /**
+ * Fired before any targets are started.
+ */
+ public void buildStarted(BuildEvent event) {
+ }
+
+ /**
+ * Fired after the last target has finished. This event
+ * will still be thrown if an error occurred during the build.
+ *
+ * @see BuildEvent#getException()
+ */
+ public void buildFinished(BuildEvent event) {
+ }
+
+ /**
+ * Fired when a target is started.
+ *
+ * @see BuildEvent#getTarget()
+ */
+ public void targetStarted(BuildEvent event) {
+ //System.out.println("targetStarted " + event.getTarget().getName());
+ }
+
+ /**
+ * Fired when a target has finished. This event will
+ * still be thrown if an error occurred during the build.
+ *
+ * @see BuildEvent#getException()
+ */
+ public void targetFinished(BuildEvent event) {
+ //System.out.println("targetFinished " + event.getTarget().getName());
+ }
+
+ /**
+ * Fired when a task is started.
+ *
+ * @see BuildEvent#getTask()
+ */
+ public void taskStarted(BuildEvent event) {
+ //System.out.println("taskStarted " + event.getTask().getTaskName());
+ }
+
+ /**
+ * Fired when a task has finished. This event will still
+ * be throw if an error occurred during the build.
+ *
+ * @see BuildEvent#getException()
+ */
+ public void taskFinished(BuildEvent event) {
+ //System.out.println("taskFinished " + event.getTask().getTaskName());
+ }
+
+ /**
+ * Fired whenever a message is logged.
+ *
+ * @see BuildEvent#getMessage()
+ * @see BuildEvent#getPriority()
+ */
+ public void messageLogged(BuildEvent event) {
+ if (event.getPriority() > logLevel) {
+ // ignore event
+ return;
+ }
+
+ if (event.getPriority() == Project.MSG_INFO ||
+ event.getPriority() == Project.MSG_WARN ||
+ event.getPriority() == Project.MSG_ERR) {
+ logBuffer.append(event.getMessage());
+ }
+ fullLogBuffer.append(event.getMessage());
+ }
+ }
+
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/TestBuildFile.java b/src/excelant/testcases/org/apache/poi/ss/excelant/TestBuildFile.java
new file mode 100644
index 0000000000..4d8f0d5a81
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/excelant/TestBuildFile.java
@@ -0,0 +1,74 @@
+/*
+ * 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.excelant;
+
+/**
+ * JUnit test for the ExcelAnt tasks.
+ * Leverages Ant's test framework.
+ *
+ * @see
+ * http://svn.apache.org/repos/asf/ant/core/trunk/src/tests/junit/org/apache/tools/ant/BuildFileTest.java
+ */
+public class TestBuildFile extends BuildFileTest {
+
+ public void setUp() {
+ configureProject("src/excelant/testcases/org/apache/poi/ss/excelant/tests.xml");
+ }
+
+ public void testMissingFilename() {
+ expectSpecificBuildException("test-nofile", "required argument not specified",
+ "fileName attribute must be set!");
+ }
+
+ public void testFileNotFound() {
+ expectSpecificBuildException("test-filenotfound", "required argument not specified",
+ "Cannot load file invalid.xls. Make sure the path and file permissions are correct.");
+ }
+
+ public void testEvaluate() {
+ executeTarget("test-evaluate");
+ assertLogContaining("Using input file: test-data/spreadsheet/excelant.xls");
+ assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4.");
+ }
+
+ public void testPrecision() {
+ executeTarget("test-precision");
+
+ assertLogContaining("Using input file: test-data/spreadsheet/excelant.xls");
+ assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4. " +
+ "It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-4");
+ assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4. " +
+ "It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-5");
+ assertLogContaining("Failed to evaluate cell 'MortgageCalculator'!$B$4. " +
+ "It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-10 was expected.");
+ assertLogContaining("2/3 tests passed");
+ }
+
+ public void testPassOnError() {
+ executeTarget("test-passonerror");
+ }
+
+ public void testFailOnError() {
+ expectBuildException("test-failonerror", "fail on error");
+ }
+
+ public void testUdf() {
+ executeTarget("test-udf");
+ assertLogContaining("1/1 tests passed");
+ }
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/TestExcelAntPrecision.java b/src/excelant/testcases/org/apache/poi/ss/excelant/TestExcelAntPrecision.java
new file mode 100755
index 0000000000..0c6f9cbf83
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/excelant/TestExcelAntPrecision.java
@@ -0,0 +1,48 @@
+/* ====================================================================
+ 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.excelant;
+
+import junit.framework.TestCase;
+
+public class TestExcelAntPrecision extends TestCase {
+
+ private ExcelAntPrecision fixture ;
+
+ @Override
+ public void setUp() {
+ fixture = new ExcelAntPrecision() ;
+ }
+
+ @Override
+ public void tearDown() {
+ fixture = null ;
+ }
+
+ public void testVerifyPrecision() {
+
+ double value = 1.0E-1 ;
+
+ fixture.setValue( value ) ;
+
+ double result = fixture.getValue() ;
+
+ assertTrue( result > 0 ) ;
+
+ assertEquals( value, result, 0.0 ) ;
+ }
+
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/TestExcelAntSet.java b/src/excelant/testcases/org/apache/poi/ss/excelant/TestExcelAntSet.java
new file mode 100755
index 0000000000..cfba01b585
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/excelant/TestExcelAntSet.java
@@ -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.ss.excelant;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.excelant.util.ExcelAntWorkbookUtil;
+import org.apache.poi.ss.excelant.util.ExcelAntWorkbookUtilFactory;
+
+public class TestExcelAntSet extends TestCase {
+
+
+ // This is abstract in nature, so we'll use a
+ // concrete instance to test the set methods.
+ private ExcelAntSet fixture ;
+
+ private final String mortgageCalculatorFileName =
+ "test-data/spreadsheet/mortgage-calculation.xls" ;
+
+
+ @Override
+ public void setUp() {
+ fixture = new ExcelAntSetDoubleCell() ;
+ }
+
+ @Override
+ public void tearDown() {
+ fixture = null ;
+ }
+
+ public void testSetter() {
+ String cell = "simpleCellRef!$F$1" ;
+
+ fixture.setCell( cell ) ;
+
+ String cellStr = fixture.getCell() ;
+
+ assertNotNull( cellStr ) ;
+ assertEquals( cell, cellStr ) ;
+ }
+
+ public void testSetWorkbookUtil() {
+ ExcelAntWorkbookUtil util = ExcelAntWorkbookUtilFactory.getInstance(
+ mortgageCalculatorFileName ) ;
+
+ assertNotNull( util ) ;
+
+ fixture.setWorkbookUtil( util ) ;
+ }
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/TestExcelAntSetDoubleCell.java b/src/excelant/testcases/org/apache/poi/ss/excelant/TestExcelAntSetDoubleCell.java
new file mode 100755
index 0000000000..1b9e527e07
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/excelant/TestExcelAntSetDoubleCell.java
@@ -0,0 +1,66 @@
+/* ====================================================================
+ 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.excelant;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.excelant.util.ExcelAntWorkbookUtil;
+import org.apache.poi.ss.excelant.util.ExcelAntWorkbookUtilFactory;
+
+public class TestExcelAntSetDoubleCell extends TestCase {
+
+ private ExcelAntSetDoubleCell fixture ;
+
+ private final String mortgageCalculatorFileName =
+ "test-data/spreadsheet/mortgage-calculation.xls" ;
+
+ private ExcelAntWorkbookUtil util ;
+
+ @Override
+ public void setUp() {
+ fixture = new ExcelAntSetDoubleCell() ;
+ util = ExcelAntWorkbookUtilFactory.getInstance(
+ mortgageCalculatorFileName ) ;
+ fixture.setWorkbookUtil( util ) ;
+ }
+
+ @Override
+ public void tearDown() {
+ fixture = null ;
+ }
+
+ public void testSetDouble() {
+ String cellId = "'Sheet3'!$A$1" ;
+ double testValue = 1.1 ;
+
+ fixture.setCell( cellId ) ;
+ fixture.setValue( testValue ) ;
+
+ double value = fixture.getCellValue() ;
+
+ assertTrue( value > 0 ) ;
+ assertEquals( testValue, value, 0.0 ) ;
+
+ fixture.execute() ;
+
+ double setValue = util.getCellAsDouble( cellId ) ;
+
+ assertEquals( setValue, testValue, 0.0 ) ;
+ }
+
+
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtilTestHelper.java b/src/excelant/testcases/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtilTestHelper.java
new file mode 100755
index 0000000000..cf7538c20b
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtilTestHelper.java
@@ -0,0 +1,55 @@
+/* ====================================================================
+ 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.excelant.util;
+
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+import org.apache.poi.ss.formula.udf.UDFFinder;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Workbook;
+
+/**
+ * A helper class to allow testing of protected methods and constructors.
+ *
+ * @author jsvede
+ *
+ */
+public class ExcelAntWorkbookUtilTestHelper extends ExcelAntWorkbookUtil {
+
+ public ExcelAntWorkbookUtilTestHelper(String fName) {
+ super(fName);
+ // TODO Auto-generated constructor stub
+ }
+
+ public ExcelAntWorkbookUtilTestHelper(Workbook wb) {
+ super(wb);
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public UDFFinder getFunctions() {
+ // TODO Auto-generated method stub
+ return super.getFunctions();
+ }
+
+ @Override
+ public FormulaEvaluator getEvaluator(String excelFileName) {
+ // TODO Auto-generated method stub
+ return super.getEvaluator(excelFileName);
+ }
+
+
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/util/TestExcelAntEvaluationResult.java b/src/excelant/testcases/org/apache/poi/ss/excelant/util/TestExcelAntEvaluationResult.java
new file mode 100755
index 0000000000..833dea67a6
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/excelant/util/TestExcelAntEvaluationResult.java
@@ -0,0 +1,67 @@
+/* ====================================================================
+ 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.excelant.util;
+
+import junit.framework.TestCase;
+
+public class TestExcelAntEvaluationResult extends TestCase {
+
+ private ExcelAntEvaluationResult fixture ;
+
+ private boolean completedWithError = false ;
+ private boolean passed = false ;
+ private double retValue = 1.1 ;
+ private String errMessage = "error message" ;
+ private double delta = 2.2 ;
+ private String cellId = "testCell!$F$1" ;
+
+ public void setUp() {
+ fixture = new ExcelAntEvaluationResult( completedWithError,
+ passed,
+ retValue,
+ errMessage,
+ delta,
+ cellId ) ;
+ }
+
+ public void tearDown() {
+ fixture = null ;
+ }
+
+ public void testCompletedWithErrorMessage() {
+ String errMsg = fixture.getErrorMessage() ;
+ assertNotNull( errMsg ) ;
+ assertEquals( errMsg, errMessage ) ;
+ }
+
+ public void testPassed() {
+ boolean passedValue = fixture.didTestPass() ;
+ assertEquals( passedValue, passed ) ;
+ }
+
+ public void testDelta() {
+ double deltaValue = fixture.getDelta() ;
+ assertEquals(deltaValue, delta, 0.0 ) ;
+ }
+
+ public void testCellId() {
+ String cellIdValue = fixture.getCellName() ;
+ assertNotNull( cellIdValue ) ;
+ assertEquals( cellIdValue, cellId ) ;
+ }
+
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/util/TestExcelAntWorkbookUtil.java b/src/excelant/testcases/org/apache/poi/ss/excelant/util/TestExcelAntWorkbookUtil.java
new file mode 100755
index 0000000000..5b0d3e8027
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/excelant/util/TestExcelAntWorkbookUtil.java
@@ -0,0 +1,140 @@
+/* ====================================================================
+ 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.excelant.util;
+
+import java.util.ArrayList;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.examples.formula.CalculateMortgage;
+import org.apache.poi.ss.formula.udf.UDFFinder;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Workbook;
+
+public class TestExcelAntWorkbookUtil extends TestCase {
+
+ private final String mortgageCalculatorFileName =
+ "test-data/spreadsheet/excelant.xls" ;
+ private ExcelAntWorkbookUtilTestHelper fixture ;
+
+
+ public void tearDown() {
+ fixture = null ;
+ }
+
+ public void testStringConstructor() {
+ fixture = new ExcelAntWorkbookUtilTestHelper(
+ mortgageCalculatorFileName ) ;
+
+ assertNotNull( fixture ) ;
+
+ }
+
+ public void testAddFunction() {
+ fixture = new ExcelAntWorkbookUtilTestHelper(
+ mortgageCalculatorFileName ) ;
+
+ assertNotNull( fixture ) ;
+
+ fixture.addFunction("h2_ZFactor", new CalculateMortgage() ) ;
+
+ UDFFinder functions = fixture.getFunctions() ;
+
+ assertNotNull( functions ) ;
+ }
+
+ public void testGetWorkbook() {
+ fixture = new ExcelAntWorkbookUtilTestHelper(
+ mortgageCalculatorFileName ) ;
+
+ assertNotNull( fixture ) ;
+
+ Workbook workbook = fixture.getWorkbook() ;
+
+ assertNotNull( workbook ) ;
+ }
+
+ public void testFileName() {
+ fixture = new ExcelAntWorkbookUtilTestHelper(
+ mortgageCalculatorFileName ) ;
+
+ assertNotNull( fixture ) ;
+
+ String fileName = fixture.getFileName() ;
+
+ assertNotNull( fileName ) ;
+
+ assertEquals( mortgageCalculatorFileName, fileName ) ;
+
+ }
+
+ public void testGetEvaluator() {
+ fixture = new ExcelAntWorkbookUtilTestHelper(
+ mortgageCalculatorFileName ) ;
+
+ FormulaEvaluator evaluator = fixture.getEvaluator(
+ mortgageCalculatorFileName ) ;
+
+ assertNotNull( evaluator ) ;
+
+
+ }
+
+ public void testEvaluateCell() {
+ String cell = "'MortgageCalculator'!B4" ;
+ double expectedValue = 790.79 ;
+ double precision = 0.1 ;
+
+ fixture = new ExcelAntWorkbookUtilTestHelper(
+ mortgageCalculatorFileName ) ;
+
+ ExcelAntEvaluationResult result = fixture.evaluateCell( cell,
+ expectedValue,
+ precision ) ;
+
+ System.out.println( result ) ;
+
+ assertTrue( result.didTestPass() ) ;
+ }
+
+ public void testGetSheets() {
+ fixture = new ExcelAntWorkbookUtilTestHelper(
+ mortgageCalculatorFileName ) ;
+
+ ArrayList sheets = fixture.getSheets() ;
+
+ assertNotNull( sheets ) ;
+ assertEquals( sheets.size(), 3 ) ;
+ }
+
+ public void testSetString() {
+ String cell = "'MortgageCalculator'!C14" ;
+ String cellValue = "testString" ;
+
+ fixture = new ExcelAntWorkbookUtilTestHelper(
+ mortgageCalculatorFileName ) ;
+
+ fixture.setStringValue( cell, cellValue ) ;
+
+ String value = fixture.getCellAsString( cell ) ;
+
+ assertNotNull( value ) ;
+
+ assertEquals( cellValue, value ) ;
+
+ }
+}
diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/util/TestExcelAntWorkbookUtilFactory.java b/src/excelant/testcases/org/apache/poi/ss/excelant/util/TestExcelAntWorkbookUtilFactory.java
new file mode 100755
index 0000000000..79c898a034
--- /dev/null
+++ b/src/excelant/testcases/org/apache/poi/ss/excelant/util/TestExcelAntWorkbookUtilFactory.java
@@ -0,0 +1,69 @@
+/* ====================================================================
+ 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.excelant.util;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Tests for the ExcelAntWorbookUtilFactory.
+ *
+ * @author Jon Svede ( jon [at] loquatic [dot] com )
+ * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
+ *
+ */
+public class TestExcelAntWorkbookUtilFactory extends TestCase{
+
+ private final String mortgageCalculatorWorkbookFile =
+ "test-data/spreadsheet/mortgage-calculation.xls" ;
+
+
+ /**
+ * Simple test to determine if the factory properly returns an non-null
+ * instance of the ExcelAntWorkbookUtil class.
+ */
+ public void testGetNewWorkbookUtilInstance() {
+
+ ExcelAntWorkbookUtil util = ExcelAntWorkbookUtilFactory.getInstance(
+ mortgageCalculatorWorkbookFile ) ;
+
+ assertNotNull( util ) ;
+
+ }
+
+
+ /**
+ * Test whether or not the factory will properly return the same reference
+ * to an ExcelAnt WorkbookUtil when two different Strings, that point to
+ * the same resource, are passed in.
+ */
+ public void testVerifyEquivalence() {
+ String sameFileName = "test-data/spreadsheet/mortgage-calculation.xls" ;
+
+ ExcelAntWorkbookUtil util = ExcelAntWorkbookUtilFactory.getInstance(
+ mortgageCalculatorWorkbookFile ) ;
+
+ ExcelAntWorkbookUtil util2 = ExcelAntWorkbookUtilFactory.getInstance(
+ sameFileName ) ;
+
+ assertNotNull( util ) ;
+ assertNotNull( util2 ) ;
+
+ assertEquals( util, util2 ) ;
+ }
+
+}
diff --git a/test-data/spreadsheet/excelant.xls b/test-data/spreadsheet/excelant.xls
new file mode 100644
index 0000000000..e41edfbfd2
Binary files /dev/null and b/test-data/spreadsheet/excelant.xls differ
diff --git a/test-data/spreadsheet/mortgage-calculation.xls b/test-data/spreadsheet/mortgage-calculation.xls
new file mode 100644
index 0000000000..92e5779b5e
Binary files /dev/null and b/test-data/spreadsheet/mortgage-calculation.xls differ