git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@829293 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_6
<changes> | <changes> | ||||
<release version="3.6-beta1" date="2009-??-??"> | <release version="3.6-beta1" date="2009-??-??"> | ||||
<action dev="POI-DEVELOPERS" type="add">48044 - added implementation for CountBlank function</action> | |||||
<action dev="POI-DEVELOPERS" type="fix">48036 - added IntersectionEval to allow evaluation of the intersection formula operator</action> | <action dev="POI-DEVELOPERS" type="fix">48036 - added IntersectionEval to allow evaluation of the intersection formula operator</action> | ||||
<action dev="POI-DEVELOPERS" type="fix">47999 - avoid un-needed call to the JVM Garbage Collector when working on OOXML OPC Packages</action> | <action dev="POI-DEVELOPERS" type="fix">47999 - avoid un-needed call to the JVM Garbage Collector when working on OOXML OPC Packages</action> | ||||
<action dev="POI-DEVELOPERS" type="add">47922 - added example HSMF application that converts a .msg file to text and extracts attachments</action> | <action dev="POI-DEVELOPERS" type="add">47922 - added example HSMF application that converts a .msg file to text and extracts attachments</action> |
retval[345] = new Sumif(); | retval[345] = new Sumif(); | ||||
retval[346] = new Countif(); | retval[346] = new Countif(); | ||||
retval[347] = new Countblank(); | |||||
retval[359] = new Hyperlink(); | retval[359] = new Hyperlink(); | ||||
/* ==================================================================== | |||||
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.hssf.record.formula.functions; | |||||
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.NumberEval; | |||||
import org.apache.poi.hssf.record.formula.eval.RefEval; | |||||
import org.apache.poi.hssf.record.formula.eval.ValueEval; | |||||
import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate; | |||||
/** | |||||
* Implementation for the function COUNTBLANK | |||||
* <p> | |||||
* Syntax: COUNTBLANK ( range ) | |||||
* <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions"> | |||||
* <tr><th>range </th><td>is the range of cells to count blanks</td></tr> | |||||
* </table> | |||||
* </p> | |||||
* | |||||
* @author Mads Mohr Christensen | |||||
*/ | |||||
public final class Countblank implements Function { | |||||
public ValueEval evaluate(ValueEval[] args, int srcRowIndex, short srcColumnIndex) { | |||||
if (args.length != 1) { | |||||
// TODO - it doesn't seem to be possible to enter COUNTBLANK() into Excel with the wrong arg count | |||||
// perhaps this should be an exception | |||||
return ErrorEval.VALUE_INVALID; | |||||
} | |||||
double result; | |||||
ValueEval arg0 = args[0]; | |||||
if (arg0 instanceof RefEval) { | |||||
result = CountUtils.countMatchingCell((RefEval) arg0, predicate); | |||||
} else if (arg0 instanceof AreaEval) { | |||||
result = CountUtils.countMatchingCellsInArea((AreaEval) arg0, predicate); | |||||
} else { | |||||
throw new IllegalArgumentException("Bad range arg type (" + arg0.getClass().getName() + ")"); | |||||
} | |||||
return new NumberEval(result); | |||||
} | |||||
private static final I_MatchPredicate predicate = new I_MatchPredicate() { | |||||
public boolean matches(ValueEval valueEval) { | |||||
// Note - only BlankEval counts | |||||
return valueEval == BlankEval.INSTANCE; | |||||
} | |||||
}; | |||||
} |
private static final String NULL = null; | private static final String NULL = null; | ||||
public void testCountBlank() { | |||||
AreaEval range; | |||||
ValueEval[] values; | |||||
values = new ValueEval[] { | |||||
new NumberEval(0), | |||||
new StringEval(""), // note - does not match blank | |||||
BoolEval.TRUE, | |||||
BoolEval.FALSE, | |||||
ErrorEval.DIV_ZERO, | |||||
BlankEval.INSTANCE, | |||||
}; | |||||
range = EvalFactory.createAreaEval("A1:B3", values); | |||||
confirmCountBlank(1, range); | |||||
values = new ValueEval[] { | |||||
new NumberEval(0), | |||||
new StringEval(""), // note - does not match blank | |||||
BlankEval.INSTANCE, | |||||
BoolEval.FALSE, | |||||
BoolEval.TRUE, | |||||
BlankEval.INSTANCE, | |||||
}; | |||||
range = EvalFactory.createAreaEval("A1:B3", values); | |||||
confirmCountBlank(2, range); | |||||
} | |||||
public void testCountA() { | public void testCountA() { | ||||
ValueEval[] args; | ValueEval[] args; | ||||
double result = NumericFunctionInvoker.invoke(new Countif(), args); | double result = NumericFunctionInvoker.invoke(new Countif(), args); | ||||
assertEquals(expected, result, 0); | assertEquals(expected, result, 0); | ||||
} | } | ||||
private static void confirmCountBlank(int expected, AreaEval range) { | |||||
ValueEval[] args = { range }; | |||||
double result = NumericFunctionInvoker.invoke(new Countblank(), args); | |||||
assertEquals(expected, result, 0); | |||||
} | |||||
private static I_MatchPredicate createCriteriaPredicate(ValueEval ev) { | private static I_MatchPredicate createCriteriaPredicate(ValueEval ev) { | ||||
return Countif.createCriteriaPredicate(ev, 0, 0); | return Countif.createCriteriaPredicate(ev, 0, 0); | ||||
} | } | ||||
public void testCountifFromSpreadsheet() { | public void testCountifFromSpreadsheet() { | ||||
final String FILE_NAME = "countifExamples.xls"; | |||||
final int START_ROW_IX = 1; | |||||
final int COL_IX_ACTUAL = 2; | |||||
final int COL_IX_EXPECTED = 3; | |||||
testCountFunctionFromSpreadsheet("countifExamples.xls", 1, 2, 3, "countif"); | |||||
} | |||||
public void testCountBlankFromSpreadsheet() { | |||||
testCountFunctionFromSpreadsheet("countblankExamples.xls", 1, 3, 4, "countblank"); | |||||
} | |||||
private static void testCountFunctionFromSpreadsheet(String FILE_NAME, int START_ROW_IX, int COL_IX_ACTUAL, int COL_IX_EXPECTED, String functionName) { | |||||
int failureCount = 0; | int failureCount = 0; | ||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(FILE_NAME); | HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(FILE_NAME); | ||||
} | } | ||||
if (failureCount > 0) { | if (failureCount > 0) { | ||||
throw new AssertionFailedError(failureCount + " countif evaluations failed. See stderr for more details"); | |||||
throw new AssertionFailedError(failureCount + " " + functionName | |||||
+ " evaluations failed. See stderr for more details"); | |||||
} | } | ||||
} | } | ||||
} | } |