Some more clean up of array formula support in preparation for patch 48292
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@888577 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f26db72b4b
commit
37790e51e4
@ -19,6 +19,7 @@ package org.apache.poi.hssf.record.formula;
|
|||||||
|
|
||||||
import org.apache.poi.hssf.record.constant.ConstantValueParser;
|
import org.apache.poi.hssf.record.constant.ConstantValueParser;
|
||||||
import org.apache.poi.hssf.record.constant.ErrorConstant;
|
import org.apache.poi.hssf.record.constant.ErrorConstant;
|
||||||
|
import org.apache.poi.ss.util.NumberToTextConverter;
|
||||||
import org.apache.poi.util.LittleEndianInput;
|
import org.apache.poi.util.LittleEndianInput;
|
||||||
import org.apache.poi.util.LittleEndianOutput;
|
import org.apache.poi.util.LittleEndianOutput;
|
||||||
|
|
||||||
@ -193,7 +194,7 @@ public final class ArrayPtg extends Ptg {
|
|||||||
return "\"" + (String)o + "\"";
|
return "\"" + (String)o + "\"";
|
||||||
}
|
}
|
||||||
if (o instanceof Double) {
|
if (o instanceof Double) {
|
||||||
return ((Double)o).toString();
|
return NumberToTextConverter.toText(((Double)o).doubleValue());
|
||||||
}
|
}
|
||||||
if (o instanceof Boolean) {
|
if (o instanceof Boolean) {
|
||||||
return ((Boolean)o).booleanValue() ? "TRUE" : "FALSE";
|
return ((Boolean)o).booleanValue() ? "TRUE" : "FALSE";
|
||||||
|
@ -21,16 +21,15 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.UnicodeString;
|
|
||||||
import org.apache.poi.hssf.record.constant.ErrorConstant;
|
import org.apache.poi.hssf.record.constant.ErrorConstant;
|
||||||
import org.apache.poi.hssf.record.formula.*;
|
import org.apache.poi.hssf.record.formula.*;
|
||||||
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
|
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
|
||||||
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
|
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
|
||||||
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
import org.apache.poi.ss.util.AreaReference;
|
import org.apache.poi.ss.util.AreaReference;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
import org.apache.poi.ss.util.CellReference.NameType;
|
import org.apache.poi.ss.util.CellReference.NameType;
|
||||||
import org.apache.poi.ss.SpreadsheetVersion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class parses a formula string into a List of tokens in RPN order.
|
* This class parses a formula string into a List of tokens in RPN order.
|
||||||
@ -1205,7 +1204,7 @@ public final class FormulaParser {
|
|||||||
private Object parseArrayItem() {
|
private Object parseArrayItem() {
|
||||||
SkipWhite();
|
SkipWhite();
|
||||||
switch(look) {
|
switch(look) {
|
||||||
case '"': return new UnicodeString(parseStringLiteral());
|
case '"': return parseStringLiteral();
|
||||||
case '#': return ErrorConstant.valueOf(parseErrorLiteral());
|
case '#': return ErrorConstant.valueOf(parseErrorLiteral());
|
||||||
case 'F': case 'f':
|
case 'F': case 'f':
|
||||||
case 'T': case 't':
|
case 'T': case 't':
|
||||||
|
@ -17,11 +17,14 @@
|
|||||||
|
|
||||||
package org.apache.poi.hssf.model;
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||||
import org.apache.poi.hssf.record.NameRecord;
|
import org.apache.poi.hssf.record.NameRecord;
|
||||||
|
import org.apache.poi.hssf.record.UnicodeString;
|
||||||
import org.apache.poi.hssf.record.constant.ErrorConstant;
|
import org.apache.poi.hssf.record.constant.ErrorConstant;
|
||||||
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
|
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
|
||||||
import org.apache.poi.hssf.record.formula.AddPtg;
|
import org.apache.poi.hssf.record.formula.AddPtg;
|
||||||
@ -71,6 +74,8 @@ import org.apache.poi.ss.formula.FormulaParser;
|
|||||||
import org.apache.poi.ss.formula.FormulaType;
|
import org.apache.poi.ss.formula.FormulaType;
|
||||||
import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues;
|
import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues;
|
||||||
import org.apache.poi.ss.usermodel.Name;
|
import org.apache.poi.ss.usermodel.Name;
|
||||||
|
import org.apache.poi.util.HexRead;
|
||||||
|
import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the low level formula parser functionality. High level tests are to
|
* Test the low level formula parser functionality. High level tests are to
|
||||||
@ -830,7 +835,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
Ptg[] ptgs;
|
Ptg[] ptgs;
|
||||||
ptgs = parseFormula("mode({1,2,2,#REF!;FALSE,3,3,2})");
|
ptgs = parseFormula("mode({1,2,2,#REF!;FALSE,3,3,2})");
|
||||||
confirmTokenClasses(ptgs, ArrayPtg.class, FuncVarPtg.class);
|
confirmTokenClasses(ptgs, ArrayPtg.class, FuncVarPtg.class);
|
||||||
assertEquals("{1.0,2.0,2.0,#REF!;FALSE,3.0,3.0,2.0}", ptgs[0].toFormulaString());
|
assertEquals("{1,2,2,#REF!;FALSE,3,3,2}", ptgs[0].toFormulaString());
|
||||||
|
|
||||||
ArrayPtg aptg = (ArrayPtg) ptgs[0];
|
ArrayPtg aptg = (ArrayPtg) ptgs[0];
|
||||||
Object[][] values = aptg.getTokenArrayValues();
|
Object[][] values = aptg.getTokenArrayValues();
|
||||||
@ -838,6 +843,34 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
assertEquals(Boolean.FALSE, values[1][0]);
|
assertEquals(Boolean.FALSE, values[1][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testParseStringElementInArray() {
|
||||||
|
Ptg[] ptgs;
|
||||||
|
ptgs = parseFormula("MAX({\"5\"},3)");
|
||||||
|
confirmTokenClasses(ptgs, ArrayPtg.class, IntPtg.class, FuncVarPtg.class);
|
||||||
|
Object element = ((ArrayPtg)ptgs[0]).getTokenArrayValues()[0][0];
|
||||||
|
if (element instanceof UnicodeString) {
|
||||||
|
// this would cause ClassCastException below
|
||||||
|
throw new AssertionFailedError("Wrong encoding of array element value");
|
||||||
|
}
|
||||||
|
assertEquals(String.class, element.getClass());
|
||||||
|
|
||||||
|
// make sure the formula encodes OK
|
||||||
|
int encSize = Ptg.getEncodedSize(ptgs);
|
||||||
|
byte[] data = new byte[encSize];
|
||||||
|
Ptg.serializePtgs(ptgs, data, 0);
|
||||||
|
byte[] expData = HexRead.readFromString(
|
||||||
|
"20 00 00 00 00 00 00 00 " // tArray
|
||||||
|
+ "1E 03 00 " // tInt(3)
|
||||||
|
+ "42 02 07 00 " // tFuncVar(MAX) 2-arg
|
||||||
|
+ "00 00 00 " // Array data: 1 col, 1 row
|
||||||
|
+ "02 01 00 00 35" // elem (type=string, len=1, "5")
|
||||||
|
);
|
||||||
|
assertTrue(Arrays.equals(expData, data));
|
||||||
|
int initSize = Ptg.getEncodedSizeWithoutArrayData(ptgs);
|
||||||
|
Ptg[] ptgs2 = Ptg.readTokens(initSize, new LittleEndianByteArrayInputStream(data));
|
||||||
|
confirmTokenClasses(ptgs2, ArrayPtg.class, IntPtg.class, FuncVarPtg.class);
|
||||||
|
}
|
||||||
|
|
||||||
public void testRangeOperator() {
|
public void testRangeOperator() {
|
||||||
|
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
@ -106,12 +106,11 @@ public final class TestArrayPtg extends TestCase {
|
|||||||
|
|
||||||
// The formula has an array with 3 rows and 5 columns
|
// The formula has an array with 3 rows and 5 columns
|
||||||
String formula = wb.getSheetAt(0).getRow(0).getCell(0).getCellFormula();
|
String formula = wb.getSheetAt(0).getRow(0).getCell(0).getCellFormula();
|
||||||
// TODO - These number literals should not have '.0'. Excel has different number rendering rules
|
|
||||||
|
|
||||||
if (formula.equals("SUM({1.0,6.0,11.0;2.0,7.0,12.0;3.0,8.0,13.0;4.0,9.0,14.0;5.0,10.0,15.0})")) {
|
if (formula.equals("SUM({1,6,11;2,7,12;3,8,13;4,9,14;5,10,15})")) {
|
||||||
throw new AssertionFailedError("Identified bug 42564 b");
|
throw new AssertionFailedError("Identified bug 42564 b");
|
||||||
}
|
}
|
||||||
assertEquals("SUM({1.0,2.0,3.0,4.0,5.0;6.0,7.0,8.0,9.0,10.0;11.0,12.0,13.0,14.0,15.0})", formula);
|
assertEquals("SUM({1,2,3,4,5;6,7,8,9,10;11,12,13,14,15})", formula);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testToFormulaString() {
|
public void testToFormulaString() {
|
||||||
@ -125,7 +124,7 @@ public final class TestArrayPtg extends TestCase {
|
|||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
assertEquals("{TRUE,\"ABCD\",\"E\";0.0,FALSE,\"FG\"}", actualFormula);
|
assertEquals("{TRUE,\"ABCD\",\"E\";0,FALSE,\"FG\"}", actualFormula);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user