[github-181] make Value function work with arrays. Thanks to Miłosz Rembisz. This closes #181

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1878541 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
PJ Fanning 2020-06-06 09:30:30 +00:00
parent 5a18307eb0
commit b7930fc65c
3 changed files with 175 additions and 148 deletions

View File

@ -30,15 +30,17 @@ import java.time.DateTimeException;
* Implementation for Excel VALUE() function.<p>
*
* <b>Syntax</b>:<br> <b>VALUE</b>(<b>text</b>)<br>
*
* <p>
* Converts the text argument to a number. Leading and/or trailing whitespace is
* ignored. Currency symbols and thousands separators are stripped out.
* Scientific notation is also supported. If the supplied text does not convert
* properly the result is <b>#VALUE!</b> error. Blank string converts to zero.
*/
public final class Value extends Fixed1ArgFunction {
public final class Value extends Fixed1ArgFunction implements ArrayFunction {
/** "1,0000" is valid, "1,00" is not */
/**
* "1,0000" is valid, "1,00" is not
*/
private static final int MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR = 4;
private static final Double ZERO = Double.valueOf(0.0);
@ -51,13 +53,23 @@ public final class Value extends Fixed1ArgFunction {
}
String strText = OperandResolver.coerceValueToString(veText);
Double result = convertTextToNumber(strText);
if(result == null) result = parseDateTime(strText);
if (result == null) result = parseDateTime(strText);
if (result == null) {
return ErrorEval.VALUE_INVALID;
}
return new NumberEval(result.doubleValue());
}
@Override
public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
if (args.length != 1) {
return ErrorEval.VALUE_INVALID;
}
return evaluateOneArrayArg(args[0], srcRowIndex, srcColumnIndex, (valA) ->
evaluate(srcRowIndex, srcColumnIndex, valA)
);
}
/**
* TODO see if the same functionality is needed in {@link OperandResolver#parseDouble(String)}
*
@ -129,7 +141,7 @@ public final class Value extends Fixed1ArgFunction {
String remainingTextTrimmed = strText.substring(i).trim();
// support for value[space]%
if (remainingTextTrimmed.equals("%")) {
foundPercentage= true;
foundPercentage = true;
break;
}
if (remainingTextTrimmed.length() > 0) {
@ -191,7 +203,7 @@ public final class Value extends Fixed1ArgFunction {
return null;
}
double result = foundUnaryMinus ? -d : d;
return foundPercentage ? result/100. : result;
return foundPercentage ? result / 100. : result;
}
public static Double parseDateTime(String pText) {

View File

@ -2903,6 +2903,21 @@ public final class TestBugs extends BaseTestBugzillaIssues {
public void test63819() throws IOException {
simpleTest("63819.xls");
}
/**
* Test that VALUE behaves properly as array function and its result is handled by aggregate function
*/
@Test
public void testValueAsArrayFunction() throws IOException {
try (final Workbook wb = openSampleWorkbook("TestValueAsArrayFunction.xls")) {
wb.getCreationHelper().createFormulaEvaluator().evaluateAll();
Sheet sheet = wb.getSheetAt(0);
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
assertEquals(6.0, cell.getNumericCellValue(), 0.0);
}
}
// a simple test which rewrites the file once and evaluates its formulas
private void simpleTest(String fileName) throws IOException {
simpleTest(fileName, null);

Binary file not shown.