use of org.apache.poi.ss.formula.ptg.MemFuncPtg in project poi by apache.
the class TestFormulaParser method testComplexExplicitRangeEncodings.
/**
* Checks that the area-ref and explicit range operators get the right associativity
* and that the {@link MemFuncPtg} / {@link MemAreaPtg} is added correctly
*/
@Test
public void testComplexExplicitRangeEncodings() {
Ptg[] ptgs;
ptgs = parseFormula("SUM(OFFSET(A1,0,0):B2:C3:D4:E5:OFFSET(F6,1,1):G7)");
confirmTokenClasses(ptgs, // len 57
MemFuncPtg.class, // [A1]
RefPtg.class, // [0]
IntPtg.class, // [0]
IntPtg.class, // [OFFSET nArgs=3]
FuncVarPtg.class, // [B2:C3]
AreaPtg.class, RangePtg.class, // [D4:E5]
AreaPtg.class, RangePtg.class, // [F6]
RefPtg.class, // [1]
IntPtg.class, // [1]
IntPtg.class, // [OFFSET nArgs=3]
FuncVarPtg.class, RangePtg.class, // [G7]
RefPtg.class, RangePtg.class, // [sum ]
AttrPtg.class);
MemFuncPtg mf = (MemFuncPtg) ptgs[0];
assertEquals(57, mf.getLenRefSubexpression());
assertEquals("D4:E5", ((AreaPtgBase) ptgs[7]).toFormulaString());
assertTrue(((AttrPtg) ptgs[16]).isSum());
ptgs = parseFormula("SUM(A1:B2:C3:D4)");
confirmTokenClasses(ptgs, // len 19
MemAreaPtg.class, // [A1:B2]
AreaPtg.class, // [C3:D4]
AreaPtg.class, RangePtg.class, // [sum ]
AttrPtg.class);
MemAreaPtg ma = (MemAreaPtg) ptgs[0];
assertEquals(19, ma.getLenRefSubexpression());
}
use of org.apache.poi.ss.formula.ptg.MemFuncPtg in project poi by apache.
the class TestAreaReference method testDiscontinousReference.
public void testDiscontinousReference() throws Exception {
InputStream is = HSSFTestDataSamples.openSampleFileStream("44167.xls");
HSSFWorkbook wb = new HSSFWorkbook(is);
InternalWorkbook workbook = TestHSSFWorkbook.getInternalWorkbook(wb);
HSSFEvaluationWorkbook eb = HSSFEvaluationWorkbook.create(wb);
assertEquals(1, wb.getNumberOfNames());
String sheetName = "Tabelle1";
String rawRefA = "$C$10:$C$14";
String rawRefB = "$C$16:$C$18";
String refA = sheetName + "!" + rawRefA;
String refB = sheetName + "!" + rawRefB;
String ref = refA + "," + refB;
// Check the low level record
NameRecord nr = workbook.getNameRecord(0);
assertNotNull(nr);
assertEquals("test", nr.getNameText());
Ptg[] def = nr.getNameDefinition();
assertEquals(4, def.length);
MemFuncPtg ptgA = (MemFuncPtg) def[0];
Area3DPtg ptgB = (Area3DPtg) def[1];
Area3DPtg ptgC = (Area3DPtg) def[2];
UnionPtg ptgD = (UnionPtg) def[3];
assertEquals("", ptgA.toFormulaString());
assertEquals(refA, ptgB.toFormulaString(eb));
assertEquals(refB, ptgC.toFormulaString(eb));
assertEquals(",", ptgD.toFormulaString());
assertEquals(ref, HSSFFormulaParser.toFormulaString(wb, nr.getNameDefinition()));
// Check the high level definition
int idx = wb.getNameIndex("test");
assertEquals(0, idx);
HSSFName aNamedCell = wb.getNameAt(idx);
// Should have 2 references
assertEquals(ref, aNamedCell.getRefersToFormula());
// Check the parsing of the reference into cells
assertFalse(AreaReference.isContiguous(aNamedCell.getRefersToFormula()));
AreaReference[] arefs = AreaReference.generateContiguous(aNamedCell.getRefersToFormula());
assertEquals(2, arefs.length);
assertEquals(refA, arefs[0].formatAsString());
assertEquals(refB, arefs[1].formatAsString());
for (AreaReference ar : arefs) {
confirmResolveCellRef(wb, ar.getFirstCell());
confirmResolveCellRef(wb, ar.getLastCell());
}
}
use of org.apache.poi.ss.formula.ptg.MemFuncPtg in project poi by apache.
the class FormulaRenderer method toFormulaString.
/**
* Static method to convert an array of {@link Ptg}s in RPN order
* to a human readable string format in infix mode.
* @param book used for defined names and 3D references
* @param ptgs must not be <code>null</code>
* @return a human readable String
*/
public static String toFormulaString(FormulaRenderingWorkbook book, Ptg[] ptgs) {
if (ptgs == null || ptgs.length == 0) {
throw new IllegalArgumentException("ptgs must not be null");
}
Stack<String> stack = new Stack<String>();
for (Ptg ptg : ptgs) {
// TODO - what about MemNoMemPtg?
if (ptg instanceof MemAreaPtg || ptg instanceof MemFuncPtg || ptg instanceof MemErrPtg) {
// TODO - put comment and throw exception in toFormulaString() of these classes
continue;
}
if (ptg instanceof ParenthesisPtg) {
String contents = stack.pop();
stack.push("(" + contents + ")");
continue;
}
if (ptg instanceof AttrPtg) {
AttrPtg attrPtg = ((AttrPtg) ptg);
if (attrPtg.isOptimizedIf() || attrPtg.isOptimizedChoose() || attrPtg.isSkip()) {
continue;
}
if (attrPtg.isSpace()) {
// POI currently doesn't render spaces in formulas
continue;
// but if it ever did, care must be taken:
// tAttrSpace comes *before* the operand it applies to, which may be consistent
// with how the formula text appears but is against the RPN ordering assumed here
}
if (attrPtg.isSemiVolatile()) {
// similar to tAttrSpace - RPN is violated
continue;
}
if (attrPtg.isSum()) {
String[] operands = getOperands(stack, attrPtg.getNumberOfOperands());
stack.push(attrPtg.toFormulaString(operands));
continue;
}
throw new RuntimeException("Unexpected tAttr: " + attrPtg);
}
if (ptg instanceof WorkbookDependentFormula) {
WorkbookDependentFormula optg = (WorkbookDependentFormula) ptg;
stack.push(optg.toFormulaString(book));
continue;
}
if (!(ptg instanceof OperationPtg)) {
stack.push(ptg.toFormulaString());
continue;
}
OperationPtg o = (OperationPtg) ptg;
String[] operands = getOperands(stack, o.getNumberOfOperands());
stack.push(o.toFormulaString(operands));
}
if (stack.isEmpty()) {
// stack.push(). So this is either an internal error or impossible.
throw new IllegalStateException("Stack underflow");
}
String result = stack.pop();
if (!stack.isEmpty()) {
// put anything on the stack
throw new IllegalStateException("too much stuff left on the stack");
}
return result;
}
use of org.apache.poi.ss.formula.ptg.MemFuncPtg in project poi by apache.
the class OperandClassTransformer method transformNode.
/**
* @param callerForceArrayFlag <code>true</code> if one of the current node's parents is a
* function Ptg which has been changed from default 'V' to 'A' type (due to requirements on
* the function return value).
*/
private void transformNode(ParseNode node, byte desiredOperandClass, boolean callerForceArrayFlag) {
Ptg token = node.getToken();
ParseNode[] children = node.getChildren();
boolean isSimpleValueFunc = isSimpleValueFunction(token);
if (isSimpleValueFunc) {
boolean localForceArray = desiredOperandClass == Ptg.CLASS_ARRAY;
for (int i = 0; i < children.length; i++) {
transformNode(children[i], desiredOperandClass, localForceArray);
}
setSimpleValueFuncClass((AbstractFunctionPtg) token, desiredOperandClass, callerForceArrayFlag);
return;
}
if (isSingleArgSum(token)) {
// Need to process the argument of SUM with transformFunctionNode below
// so make a dummy FuncVarPtg for that call.
token = FuncVarPtg.SUM;
// Note - the tAttrSum token (node.getToken()) is a base
// token so does not need to have its operand class set
}
if (token instanceof ValueOperatorPtg || token instanceof ControlPtg || token instanceof MemFuncPtg || token instanceof MemAreaPtg || token instanceof UnionPtg || token instanceof IntersectionPtg) {
// Value Operator Ptgs and Control are base tokens, so token will be unchanged
// but any child nodes are processed according to desiredOperandClass and callerForceArrayFlag
// As per OOO documentation Sec 3.2.4 "Token Class Transformation", "Step 1"
// All direct operands of value operators that are initially 'R' type will
// be converted to 'V' type.
byte localDesiredOperandClass = desiredOperandClass == Ptg.CLASS_REF ? Ptg.CLASS_VALUE : desiredOperandClass;
for (int i = 0; i < children.length; i++) {
transformNode(children[i], localDesiredOperandClass, callerForceArrayFlag);
}
return;
}
if (token instanceof AbstractFunctionPtg) {
transformFunctionNode((AbstractFunctionPtg) token, children, desiredOperandClass, callerForceArrayFlag);
return;
}
if (children.length > 0) {
if (token == RangePtg.instance) {
// TODO is any token transformation required under the various ref operators?
return;
}
throw new IllegalStateException("Node should not have any children");
}
if (token.isBaseToken()) {
// nothing to do
return;
}
token.setClass(transformClass(token.getPtgClass(), desiredOperandClass, callerForceArrayFlag));
}
use of org.apache.poi.ss.formula.ptg.MemFuncPtg in project poi by apache.
the class TestFormulaParser method testExplicitRangeWithTwoSheetNames.
@Test
public void testExplicitRangeWithTwoSheetNames() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
wb.createSheet("Sheet1");
Ptg[] ptgs = HSSFFormulaParser.parse("Sheet1!F1:Sheet1!G2", wb);
confirmTokenClasses(ptgs, MemFuncPtg.class, Ref3DPtg.class, Ref3DPtg.class, RangePtg.class);
MemFuncPtg mf;
mf = (MemFuncPtg) ptgs[0];
assertEquals(15, mf.getLenRefSubexpression());
wb.close();
}
Aggregations