private void setClass(Node n, byte theClass) {
Ptg p = n.getValue();
+ if (p.isBaseToken()) {
+ return;
+ }
+
if (p instanceof AbstractFunctionPtg || !(p instanceof OperationPtg)) {
p.setClass(theClass);
} else {
// TODO - put comment and throw exception in toFormulaString() of these classes
continue;
}
- if (! (ptg instanceof OperationPtg)) {
- stack.push(ptg.toFormulaString(book));
+ if (ptg instanceof ParenthesisPtg) {
+ String contents = (String)stack.pop();
+ stack.push ("(" + contents + ")");
continue;
}
-
if (ptg instanceof AttrPtg) {
AttrPtg attrPtg = ((AttrPtg) ptg);
if (attrPtg.isOptimizedIf() || attrPtg.isOptimizedChoose() || attrPtg.isGoto()) {
// similar to tAttrSpace - RPN is violated
continue;
}
- if (!attrPtg.isSum()) {
- throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());
+ if (attrPtg.isSum()) {
+ String[] operands = getOperands(stack, attrPtg.getNumberOfOperands());
+ stack.push(attrPtg.toFormulaString(operands));
+ continue;
}
+ throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());
+ }
+
+ if (! (ptg instanceof OperationPtg)) {
+ stack.push(ptg.toFormulaString(book));
+ continue;
}
OperationPtg o = (OperationPtg) ptg;
protected byte field_1_num_args;
protected short field_2_fnc_index;
+ public final boolean isBaseToken() {
+ return false;
+ }
+
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
limitations under the License.
==================================================================== */
-/*
- * AddPtg.java
- *
- * Created on October 29, 2001, 7:48 PM
- */
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
* @author Andrew C. Oliver (acoliver@apache.org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
-
-public class AddPtg
- extends OperationPtg
-{
+public final class AddPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x03;
buffer.append(operands[ 1 ]);
return buffer.toString();
}
-
- public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new AddPtg();
* @author Jason Height (jheight at chariot dot net dot au)
* @version 1.0-pre
*/
-public class Area3DPtg extends Ptg implements AreaI
-{
+public class Area3DPtg extends OperandPtg implements AreaI {
public final static byte sid = 0x3b;
private final static int SIZE = 11; // 10 + 1 for Ptg
private short field_1_index_extern_sheet;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
-public class AreaPtg extends Ptg implements AreaI {
+public class AreaPtg extends OperandPtg implements AreaI {
/**
* TODO - (May-2008) fix subclasses of AreaPtg 'AreaN~' which are used in shared formulas.
* see similar comment in ReferencePtg
protected Object[] token_3_arrayValues;
protected ArrayPtg() {
- //Required for clone methods
+ //Required for clone methods
}
public ArrayPtg(RecordInputStream in)
}
}
+ public boolean isBaseToken() {
+ return false;
+ }
+
/**
* Read in the actual token (array) values. This occurs
* AFTER the last Ptg in the expression.
for (int x=0;x<getColumnCount();x++) {
for (int y=0;y<getRowCount();y++) {
Object o = token_3_arrayValues[getValueIndex(x, y)];
- buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n");
+ buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n");
}
}
return buffer.toString();
return size;
}
- public String toFormulaString(HSSFWorkbook book) {
+ public String toFormulaString(HSSFWorkbook book)
+ {
StringBuffer b = new StringBuffer();
b.append("{");
- for (int x = 0; x < getColumnCount(); x++) {
- if (x > 0) {
+ for (int x=0;x<getColumnCount();x++) {
+ if (x > 0) {
b.append(";");
}
- for (int y = 0; y < getRowCount(); y++) {
+ for (int y=0;y<getRowCount();y++) {
if (y > 0) {
b.append(",");
}
- Object o = token_3_arrayValues[getValueIndex(x, y)];
- b.append(getConstantText(o));
- }
- }
+ Object o = token_3_arrayValues[getValueIndex(x, y)];
+ b.append(getConstantText(o));
+ }
+ }
b.append("}");
return b.toString();
}
return "\"" + ((UnicodeString)o).getString() + "\"";
}
if (o instanceof Double) {
- // TODO - numeric array elements need default Excel number formatting
return ((Double)o).toString();
}
if (o instanceof Boolean) {
}
public Object clone() {
- ArrayPtg ptg = new ArrayPtg();
- ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
-
- ptg.token_1_columns = token_1_columns;
- ptg.token_2_rows = token_2_rows;
- ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
- ptg.setClass(ptgClass);
- return ptg;
+ ArrayPtg ptg = new ArrayPtg();
+ ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
+
+ ptg.token_1_columns = token_1_columns;
+ ptg.token_2_rows = token_2_rows;
+ ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
+ ptg.setClass(ptgClass);
+ return ptg;
}
}
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
-
-public final class AttrPtg extends OperationPtg {
+public final class AttrPtg extends ControlPtg {
public final static byte sid = 0x19;
private final static int SIZE = 4;
private byte field_1_options;
}
return "UNKNOWN ATTRIBUTE";
}
-
-
-
- public byte getDefaultOperandClass() {
- return Ptg.CLASS_VALUE;
- }
public Object clone() {
int[] jt;
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
-
-public class BoolPtg
- extends Ptg
-{
+public final class BoolPtg extends ScalarConstantPtg {
public final static int SIZE = 2;
public final static byte sid = 0x1d;
private boolean field_1_value;
return field_1_value ? "TRUE" : "FALSE";
}
- public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
-
public Object clone() {
BoolPtg ptg = new BoolPtg();
ptg.field_1_value = field_1_value;
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
-
-public class ConcatPtg
- extends OperationPtg
-{
+public final class ConcatPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x08;
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
-public abstract class ControlPtg
- extends Ptg
-{
-
+/**
+ * Common superclass for
+ * tExp
+ * tTbl
+ * tParen
+ * tNlr
+ * tAttr
+ * tSheet
+ * tEndSheet
+ */
+public abstract class ControlPtg extends Ptg {
+
+ public boolean isBaseToken() {
+ return true;
+ }
+ public final byte getDefaultOperandClass() {
+// TODO throw new IllegalStateException("Control tokens are not classified");
+ return Ptg.CLASS_VALUE;
+ }
}
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
* @author Andrew C. Oliver acoliver at apache dot org
* @author Jason Height (jheight at chariot dot net dot au)
*/
-
-public class DividePtg
- extends OperationPtg
-{
+public final class DividePtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x06;
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
*
* @author andy
*/
-
-public class EqualPtg
- extends OperationPtg
-{
+public final class EqualPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x0b;
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
*/
-public final class ErrPtg extends Ptg {
+public final class ErrPtg extends ScalarConstantPtg {
// convenient access to namespace
private static final HSSFErrorConstants EC = null;
return SIZE;
}
- public byte getDefaultOperandClass() {
- return Ptg.CLASS_VALUE;
- }
-
public Object clone() {
return new ErrPtg(field_1_error_code);
}
* @author dmui (save existing implementation)
*/
-public class ExpPtg
- extends Ptg
-{
+public final class ExpPtg extends ControlPtg {
private final static int SIZE = 5;
public final static short sid = 0x1;
private short field_1_first_row;
field_1_first_row = in.readShort();
field_2_first_col = in.readShort();
}
-
+
public void writeBytes(byte [] array, int offset)
{
array[offset+0]= (byte) (sid);
return buffer.toString();
}
- public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
-
public Object clone() {
ExpPtg result = new ExpPtg();
result.field_1_first_row = field_1_first_row;
throw new RuntimeException("Invalid built-in function index (" + field_2_fnc_index + ")");
}
numParams = fm.getMinParams();
+ returnClass = fm.getReturnClassCode();
+ paramClass = fm.getParameterClassCodes();
}
public FuncPtg(int functionIndex) {
field_2_fnc_index = (short) functionIndex;
public FuncVarPtg(RecordInputStream in) {
field_1_num_args = in.readByte();
field_2_fnc_index = in.readShort();
+ FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(field_2_fnc_index);
+ if(fm == null) {
+ // Happens only as a result of a call to FormulaParser.parse(), with a non-built-in function name
+ returnClass = Ptg.CLASS_VALUE;
+ paramClass = new byte[] {Ptg.CLASS_VALUE};
+ } else {
+ returnClass = fm.getReturnClassCode();
+ paramClass = fm.getParameterClassCodes();
+ }
}
/**
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordInputStream;
-
/**
* PTG class to implement greater or equal to
*
* @author fred at stsci dot edu
*/
-
-public class GreaterEqualPtg
- extends OperationPtg
-{
+public final class GreaterEqualPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x0c;
limitations under the License.
==================================================================== */
-
-/*
- * GreaterThanPtg.java
- *
- * Created on January 23, 2003, 9:47 AM
- */
package org.apache.poi.hssf.record.formula;
-import java.util.List;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Greater than operator PTG ">"
* @author Cameron Riley (criley at ekmail.com)
*/
-public class GreaterThanPtg
- extends OperationPtg
-{
+public final class GreaterThanPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x0D;
private final static String GREATERTHAN = ">";
return buffer.toString();
}
- /**
- * Get the default operands class value
- * @return byte the Ptg Class Value as a byte from the Ptg Parent object
- */
- public byte getDefaultOperandClass()
- {
- return Ptg.CLASS_VALUE;
- }
-
/**
* Implementation of clone method from Object
* @return Object a clone of this class as an Object
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
-public final class IntPtg extends Ptg {
+public final class IntPtg extends ScalarConstantPtg {
// 16 bit unsigned integer
private static final int MIN_VALUE = 0x0000;
private static final int MAX_VALUE = 0xFFFF;
public String toFormulaString(HSSFWorkbook book) {
return String.valueOf(getValue());
}
- public byte getDefaultOperandClass() {
- return Ptg.CLASS_VALUE;
- }
public Object clone() {
return new IntPtg(field_1_value);
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
*/
-public class IntersectionPtg extends OperationPtg
-{
+public final class IntersectionPtg extends OperationPtg {
public final static byte sid = 0x0f;
// doesn't need anything
}
+ public final boolean isBaseToken() {
+ return true;
+ }
public int getSize()
{
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
*
* @author fred at stsci dot edu
*/
-public class LessEqualPtg
- extends OperationPtg
-{
+public final class LessEqualPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x0a;
limitations under the License.
==================================================================== */
-
-/*
- * LessThanPtg.java
- *
- * Created on January 23, 2003, 9:47 AM
- */
package org.apache.poi.hssf.record.formula;
-//JDK
-import java.util.List;
-
-//POI
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordInputStream;
* Table 3.5.7
* @author Cameron Riley (criley at ekmail.com)
*/
-public class LessThanPtg
- extends OperationPtg
-{
+public final class LessThanPtg extends ValueOperatorPtg {
/** the size of the Ptg */
public final static int SIZE = 1;
return buffer.toString();
}
- /**
- * Get the default operands class value
- * @return byte the Ptg Class Value as a byte from the Ptg Parent object
- */
- public byte getDefaultOperandClass()
- {
- return Ptg.CLASS_VALUE;
- }
-
/**
* Implementation of clone method from Object
* @return Object a clone of this class as an Object
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
limitations under the License.
==================================================================== */
-
-/*
- * MemAreaPtg.java
- *
- * Created on November 21, 2001, 8:46 AM
- */
package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
*/
-public class MemAreaPtg
- extends Ptg
-{
+public class MemAreaPtg extends OperandPtg {
public final static short sid = 0x26;
private final static int SIZE = 7;
private int field_1_reserved;
/**
* @author Glen Stampoultzis (glens at apache.org)
*/
-public class MemFuncPtg extends ControlPtg
-{
+public class MemFuncPtg extends OperandPtg {
public final static byte sid = 0x29;
private short field_1_len_ref_subexpression = 0;
* Avik Sengupta <avik at apache.org>
* @author Jason Height (jheight at chariot dot net dot au)
*/
-public class MissingArgPtg
- extends Ptg
-{
+public final class MissingArgPtg extends ScalarConstantPtg {
private final static int SIZE = 1;
public final static byte sid = 0x16;
{
return " ";
}
-
- public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new MissingArgPtg();
* @author Jason Height (jheight at chariot dot net dot au)
*/
-public class MultiplyPtg
- extends OperationPtg
-{
+public final class MultiplyPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x05;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
-
-public class NamePtg
- extends Ptg
-{
+public final class NamePtg extends OperandPtg {
public final static short sid = 0x23;
private final static int SIZE = 5;
/** one-based index to defined name record */
*
* @author aviks
*/
-public final class NameXPtg extends Ptg {
+public final class NameXPtg extends OperandPtg {
public final static short sid = 0x39;
private final static int SIZE = 7;
private short field_1_ixals; // index to REF entry in externsheet record
*
* @author fred at stsci dot edu
*/
-public class NotEqualPtg
- extends OperationPtg
-{
+public final class NotEqualPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x0e;
* @author Avik Sengupta
* @author Jason Height (jheight at chariot dot net dot au)
*/
-
-public class NumberPtg
- extends Ptg
-{
+public final class NumberPtg extends ScalarConstantPtg {
public final static int SIZE = 9;
public final static byte sid = 0x1f;
private double field_1_value;
{
return "" + getValue();
}
- public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
NumberPtg ptg = new NumberPtg();
--- /dev/null
+/* ====================================================================
+ 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;
+
+/**
+ * @author Josh Micich
+ */
+public abstract class OperandPtg extends Ptg {
+
+ /**
+ * All Operand <tt>Ptg</tt>s are classifed ('relative', 'value', 'array')
+ */
+ public final boolean isBaseToken() {
+ return false;
+ }
+}
* Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
-public class ParenthesisPtg
- extends OperationPtg
-{
+public final class ParenthesisPtg extends ControlPtg {
private final static int SIZE = 1;
public final static byte sid = 0x15;
return SIZE;
}
- public int getType()
- {
- return TYPE_BINARY;
- }
-
- public int getNumberOfOperands()
- {
- return 1;
- }
-
public String toFormulaString(HSSFWorkbook book)
{
return "()";
public String toFormulaString(String[] operands) {
return "("+operands[0]+")";
}
-
- public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new ParenthesisPtg();
* @author Daniel Noll (daniel at nuix.com.au)
*/
-public class PercentPtg
- extends OperationPtg
-{
+public final class PercentPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x14;
return buffer.toString();
}
- public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
-
public Object clone() {
return new PercentPtg();
}
package org.apache.poi.hssf.record.formula;
-import java.util.List;
-
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordInputStream;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
-
-public class PowerPtg
- extends OperationPtg
-{
+public final class PowerPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x07;
return stack;
}
- public static Ptg createPtg(RecordInputStream in)
- {
- byte id = in.readByte();
- Ptg retval = null;
-
- switch (id)
- {
- case ExpPtg.sid : // 0x01
- retval = new ExpPtg(in);
- break;
-
- case AddPtg.sid : // 0x03
- retval = new AddPtg(in);
- break;
-
- case SubtractPtg.sid : // 0x04
- retval = new SubtractPtg(in);
- break;
-
- case MultiplyPtg.sid : // 0x05
- retval = new MultiplyPtg(in);
- break;
-
- case DividePtg.sid : // 0x06
- retval = new DividePtg(in);
- break;
-
- case PowerPtg.sid : // 0x07
- retval = new PowerPtg(in);
- break;
-
- case ConcatPtg.sid : // 0x08
- retval = new ConcatPtg(in);
- break;
-
- case LessThanPtg.sid: // 0x09
- retval = new LessThanPtg(in);
- break;
-
- case LessEqualPtg.sid : // 0x0a
- retval = new LessEqualPtg(in);
- break;
-
- case EqualPtg.sid : // 0x0b
- retval = new EqualPtg(in);
- break;
-
- case GreaterEqualPtg.sid : // 0x0c
- retval = new GreaterEqualPtg(in);
- break;
-
- case GreaterThanPtg.sid : // 0x0d
- retval = new GreaterThanPtg(in);
- break;
-
- case NotEqualPtg.sid : // 0x0e
- retval = new NotEqualPtg(in);
- break;
-
- case IntersectionPtg.sid : // 0x0f
- retval = new IntersectionPtg(in);
- break;
- case UnionPtg.sid : // 0x10
- retval = new UnionPtg(in);
- break;
-
- case RangePtg.sid : // 0x11
- retval = new RangePtg(in);
- break;
-
- case UnaryPlusPtg.sid : // 0x12
- retval = new UnaryPlusPtg(in);
- break;
-
- case UnaryMinusPtg.sid : // 0x13
- retval = new UnaryMinusPtg(in);
- break;
-
- case PercentPtg.sid : // 0x14
- retval = new PercentPtg(in);
- break;
-
- case ParenthesisPtg.sid : // 0x15
- retval = new ParenthesisPtg(in);
- break;
-
- case MissingArgPtg.sid : // 0x16
- retval = new MissingArgPtg(in);
- break;
-
- case StringPtg.sid : // 0x17
- retval = new StringPtg(in);
- break;
-
- case AttrPtg.sid : // 0x19
- case 0x1a :
- retval = new AttrPtg(in);
- break;
-
- case ErrPtg.sid : // 0x1c
- retval = new ErrPtg(in);
- break;
-
- case BoolPtg.sid : // 0x1d
- retval = new BoolPtg(in);
- break;
-
- case IntPtg.sid : // 0x1e
- retval = new IntPtg(in);
- break;
-
- case NumberPtg.sid : // 0x1f
- retval = new NumberPtg(in);
- break;
-
- case ArrayPtg.sid : // 0x20
- retval = new ArrayPtg(in);
- break;
- case ArrayPtgV.sid : // 0x40
- retval = new ArrayPtgV(in);
- break;
- case ArrayPtgA.sid : // 0x60
- retval = new ArrayPtgA(in);
- break;
-
- case FuncPtg.sid : // 0x21
- case FuncPtg.sid + 0x20 : // 0x41
- case FuncPtg.sid + 0x40 : // 0x61
- retval = new FuncPtg(in);
- break;
-
- case FuncVarPtg.sid : // 0x22
- case FuncVarPtg.sid + 0x20 : // 0x42
- case FuncVarPtg.sid + 0x40 : // 0x62
- retval = new FuncVarPtg(in);
- break;
-
- case ReferencePtg.sid : // 0x24
- retval = new ReferencePtg(in);
- break;
- case RefAPtg.sid : // 0x64
- retval = new RefAPtg(in);
- break;
- case RefVPtg.sid : // 0x44
- retval = new RefVPtg(in);
- break;
- case RefNAPtg.sid : // 0x6C
- retval = new RefNAPtg(in);
- break;
- case RefNPtg.sid : // 0x2C
- retval = new RefNPtg(in);
- break;
- case RefNVPtg.sid : // 0x4C
- retval = new RefNVPtg(in);
- break;
-
- case AreaPtg.sid : // 0x25
- retval = new AreaPtg(in);
- break;
- case AreaVPtg.sid: // 0x45
- retval = new AreaVPtg(in);
- break;
- case AreaAPtg.sid: // 0x65
- retval = new AreaAPtg(in);
- break;
- case AreaNAPtg.sid : // 0x6D
- retval = new AreaNAPtg(in);
- break;
- case AreaNPtg.sid : // 0x2D
- retval = new AreaNPtg(in);
- break;
- case AreaNVPtg.sid : // 0x4D
- retval = new AreaNVPtg(in);
- break;
-
- case MemAreaPtg.sid : // 0x26
- case MemAreaPtg.sid + 0x40 : // 0x46
- case MemAreaPtg.sid + 0x20 : // 0x66
- retval = new MemAreaPtg(in);
- break;
-
- case MemErrPtg.sid : // 0x27
- case MemErrPtg.sid + 0x20 : // 0x47
- case MemErrPtg.sid + 0x40 : // 0x67
- retval = new MemErrPtg(in);
- break;
-
- case MemFuncPtg.sid : // 0x29
- retval = new MemFuncPtg(in);
- break;
-
- case RefErrorPtg.sid : // 0x2a
- case RefErrorPtg.sid + 0x20 : // 0x4a
- case RefErrorPtg.sid + 0x40 : // 0x6a
- retval = new RefErrorPtg(in);
- break;
-
- case AreaErrPtg.sid : // 0x2b
- case AreaErrPtg.sid + 0x20 : // 0x4b
- case AreaErrPtg.sid + 0x40 : // 0x6b
- retval = new AreaErrPtg(in);
- break;
-
- case NamePtg.sid : // 0x23
- case NamePtg.sid + 0x20 : // 0x43
- case NamePtg.sid + 0x40 : // 0x63
- retval = new NamePtg(in);
- break;
-
- case NameXPtg.sid : // 0x39
- case NameXPtg.sid + 0x20 : // 0x45
- case NameXPtg.sid + 0x40 : // 0x79
- retval = new NameXPtg(in);
- break;
-
- case Area3DPtg.sid : // 0x3b
- case Area3DPtg.sid + 0x20 : // 0x5b
- case Area3DPtg.sid + 0x40 : // 0x7b
- retval = new Area3DPtg(in);
- break;
-
- case Ref3DPtg.sid : // 0x3a
- case Ref3DPtg.sid + 0x20: // 0x5a
- case Ref3DPtg.sid + 0x40: // 0x7a
- retval = new Ref3DPtg(in);
- break;
-
- case DeletedRef3DPtg.sid: // 0x3c
- case DeletedRef3DPtg.sid + 0x20: // 0x5c
- case DeletedRef3DPtg.sid + 0x40: // 0x7c
- retval = new DeletedRef3DPtg(in);
- break;
-
- case DeletedArea3DPtg.sid : // 0x3d
- case DeletedArea3DPtg.sid + 0x20 : // 0x5d
- case DeletedArea3DPtg.sid + 0x40 : // 0x7d
- retval = new DeletedArea3DPtg(in);
- break;
-
- case 0x00:
- retval = new UnknownPtg();
- break;
-
- default :
- //retval = new UnknownPtg();
- throw new java.lang.UnsupportedOperationException(" Unknown Ptg in Formula: 0x"+
- Integer.toHexString(( int ) id) + " (" + ( int ) id + ")");
+ public static Ptg createPtg(RecordInputStream in) {
+ byte id = in.readByte();
+
+ if (id < 0x20) {
+ return createBasePtg(id, in);
}
+
+ Ptg retval = createClassifiedPtg(id, in);
if (id > 0x60) {
retval.setClass(CLASS_ARRAY);
}
+ private static Ptg createClassifiedPtg(byte id, RecordInputStream in) {
+
+ int baseId = id & 0x1F | 0x20;
+
+ switch (baseId) {
+ case FuncPtg.sid: return new FuncPtg(in); // 0x21, 0x41, 0x61
+ case FuncVarPtg.sid: return new FuncVarPtg(in); // 0x22, 0x42, 0x62
+ case NamePtg.sid: return new NamePtg(in); // 0x23, 0x43, 0x63
+
+ case MemAreaPtg.sid: return new MemAreaPtg(in); // 0x26, 0x46, 0x66
+ case MemErrPtg.sid: return new MemErrPtg(in); // 0x27, 0x47, 0x67
+ case MemFuncPtg.sid: return new MemFuncPtg(in); // 0x29, 0x49, 0x69
+ case RefErrorPtg.sid: return new RefErrorPtg(in);// 0x2a, 0x4a, 0x6a
+ case AreaErrPtg.sid: return new AreaErrPtg(in); // 0x2b, 0x4b, 0x6b
+
+ case NameXPtg.sid: return new NameXPtg(in); // 0x39, 0x49, 0x79
+ case Ref3DPtg.sid: return new Ref3DPtg(in); // 0x3a, 0x5a, 0x7a
+ case Area3DPtg.sid: return new Area3DPtg(in); // 0x3b, 0x5b, 0x7b
+ case DeletedRef3DPtg.sid: return new DeletedRef3DPtg(in); // 0x3c, 0x5c, 0x7c
+ case DeletedArea3DPtg.sid: return new DeletedArea3DPtg(in); // 0x3d, 0x5d, 0x7d
+ }
+
+
+ switch (id) {
+ // TODO - why are specific subclasses needed for these Ptgs?
+ case ArrayPtg.sid: return new ArrayPtg(in); // 0x20
+ case ArrayPtgV.sid: return new ArrayPtgV(in); // 0x40
+ case ArrayPtgA.sid: return new ArrayPtgA(in); // 0x60
+
+ case ReferencePtg.sid: return new ReferencePtg(in);// 0x24
+ case RefAPtg.sid: return new RefAPtg(in); // 0x64
+ case RefVPtg.sid: return new RefVPtg(in); // 0x44
+
+ case RefNAPtg.sid: return new RefNAPtg(in); // 0x6C
+ case RefNPtg.sid: return new RefNPtg(in); // 0x2C
+ case RefNVPtg.sid: return new RefNVPtg(in); // 0x4C
+
+ case AreaPtg.sid: return new AreaPtg(in); // 0x25
+ case AreaVPtg.sid: return new AreaVPtg(in); // 0x45
+ case AreaAPtg.sid: return new AreaAPtg(in); // 0x65
+
+ case AreaNAPtg.sid: return new AreaNAPtg(in); // 0x6D
+ case AreaNPtg.sid: return new AreaNPtg(in); // 0x2D
+ case AreaNVPtg.sid: return new AreaNVPtg(in); // 0x4D
+
+ }
+ throw new UnsupportedOperationException(" Unknown Ptg in Formula: 0x"+
+ Integer.toHexString(id) + " (" + ( int ) id + ")");
+ }
+
+ private static Ptg createBasePtg(byte id, RecordInputStream in) {
+ switch(id) {
+ case 0x00: return new UnknownPtg(); // TODO - not a real Ptg
+ case ExpPtg.sid: return new ExpPtg(in); // 0x01
+ case AddPtg.sid: return new AddPtg(in); // 0x03
+ case SubtractPtg.sid: return new SubtractPtg(in); // 0x04
+ case MultiplyPtg.sid: return new MultiplyPtg(in); // 0x05
+ case DividePtg.sid: return new DividePtg(in); // 0x06
+ case PowerPtg.sid: return new PowerPtg(in); // 0x07
+ case ConcatPtg.sid: return new ConcatPtg(in); // 0x08
+ case LessThanPtg.sid: return new LessThanPtg(in); // 0x09
+ case LessEqualPtg.sid: return new LessEqualPtg(in); // 0x0a
+ case EqualPtg.sid: return new EqualPtg(in); // 0x0b
+ case GreaterEqualPtg.sid: return new GreaterEqualPtg(in);// 0x0c
+ case GreaterThanPtg.sid: return new GreaterThanPtg(in); // 0x0d
+ case NotEqualPtg.sid: return new NotEqualPtg(in); // 0x0e
+ case IntersectionPtg.sid: return new IntersectionPtg(in);// 0x0f
+ case UnionPtg.sid: return new UnionPtg(in); // 0x10
+ case RangePtg.sid: return new RangePtg(in); // 0x11
+ case UnaryPlusPtg.sid: return new UnaryPlusPtg(in); // 0x12
+ case UnaryMinusPtg.sid: return new UnaryMinusPtg(in); // 0x13
+ case PercentPtg.sid: return new PercentPtg(in); // 0x14
+ case ParenthesisPtg.sid: return new ParenthesisPtg(in); // 0x15
+ case MissingArgPtg.sid: return new MissingArgPtg(in); // 0x16
+ case StringPtg.sid: return new StringPtg(in); // 0x17
+ case AttrPtg.sid:
+ case 0x1a: return new AttrPtg(in); // 0x19
+ case ErrPtg.sid: return new ErrPtg(in); // 0x1c
+ case BoolPtg.sid: return new BoolPtg(in); // 0x1d
+ case IntPtg.sid: return new IntPtg(in); // 0x1e
+ case NumberPtg.sid: return new NumberPtg(in); // 0x1f
+ }
+ throw new RuntimeException("Unexpected base token id (" + id + ")");
+ }
+ /**
+ *
+ *
+ */
+ public static int getEncodedSize(Stack ptgs) {
+ return getEncodedSize(toPtgArray(ptgs));
+ }
+ private static Ptg[] toPtgArray(List l) {
+ Ptg[] result = new Ptg[l.size()];
+ l.toArray(result);
+ return result;
+ }
+ private static Stack createStack(Ptg[] formulaTokens) {
+ Stack result = new Stack();
+ for (int i = 0; i < formulaTokens.length; i++) {
+ result.add(formulaTokens[i]);
+ }
+ return result;
+ }
+ // TODO - several duplicates of this code should be refactored here
+ public static int getEncodedSize(Ptg[] ptgs) {
+ int result = 0;
+ for (int i = 0; i < ptgs.length; i++) {
+ result += ptgs[i].getSize();
+ }
+ return result;
+ }
+
public static int serializePtgStack(Stack expression, byte[] array, int offset) {
int pos = 0;
int size = 0;
return pos;
}
+ /**
+ * @return the encoded length of this Ptg, including the initial Ptg type identifier byte.
+ */
public abstract int getSize();
+
+ /**
+ * @return the encoded length of this Ptg, not including the initial Ptg type identifier byte.
+ */
+// public abstract int getDataSize();
public final byte [] getBytes()
{
protected byte ptgClass = CLASS_REF; //base ptg
public void setClass(byte thePtgClass) {
+ if (isBaseToken()) {
+ throw new RuntimeException("setClass should not be called on a base token");
+ }
ptgClass = thePtgClass;
}
public abstract Object clone();
-
+ /**
+ * @return <code>false</code> if this token is classified as 'reference', 'value', or 'array'
+ */
+ public abstract boolean isBaseToken();
}
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
*/
-public class RangePtg extends OperationPtg
-{
+public final class RangePtg extends OperationPtg {
public final static int SIZE = 1;
public final static byte sid = 0x11;
// No contents
}
+ public final boolean isBaseToken() {
+ return true;
+ }
+
public int getSize()
{
* @author Jason Height (jheight at chariot dot net dot au)
* @version 1.0-pre
*/
-
-public class Ref3DPtg extends Ptg {
+public class Ref3DPtg extends OperandPtg {
public final static byte sid = 0x3a;
private final static int SIZE = 7; // 6 + 1 for Ptg
private short field_1_index_extern_sheet;
* RefError - handles deleted cell reference
* @author Jason Height (jheight at chariot dot net dot au)
*/
+public final class RefErrorPtg extends OperandPtg {
-public class RefErrorPtg extends Ptg
-{
private final static int SIZE = 5;
public final static byte sid = 0x2a;
private int field_1_reserved;
* @author Andrew C. Oliver (acoliver@apache.org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
-public class ReferencePtg extends Ptg {
+public class ReferencePtg extends OperandPtg {
/**
* TODO - (May-2008) fix subclasses of ReferencePtg 'RefN~' which are used in shared formulas.
* (See bugzilla 44921)
- * The 'RefN~' instances do not work properly, and are expected to be converted by
- * SharedFormulaRecord.convertSharedFormulas().
- * This conversion currently does not take place for formulas of named ranges, conditional
- * format rules and data validation rules.
+ * The 'RefN~' instances do not work properly, and are expected to be converted by
+ * SharedFormulaRecord.convertSharedFormulas().
+ * This conversion currently does not take place for formulas of named ranges, conditional
+ * format rules and data validation rules.
* Furthermore, conversion is probably not appropriate in those instances.
*/
protected final RuntimeException notImplemented() {
private final static int SIZE = 5;
public final static byte sid = 0x24;
- private final static int MAX_ROW_NUMBER = 65536;
+ private final static int MAX_ROW_NUMBER = 65536;
/** The row index - zero based unsigned 16 bit value */
private int field_1_row;
- /** Field 2
- * - lower 8 bits is the zero based unsigned byte column index
+ /** Field 2
+ * - lower 8 bits is the zero based unsigned byte column index
* - bit 16 - isRowRelative
- * - bit 15 - isColumnRelative
+ * - bit 15 - isColumnRelative
*/
private int field_2_col;
private static final BitField rowRelative = BitFieldFactory.getInstance(0x8000);
protected ReferencePtg() {
//Required for clone methods
}
-
+
/**
- * Takes in a String represnetation of a cell reference and fills out the
+ * Takes in a String represnetation of a cell reference and fills out the
* numeric fields.
*/
public ReferencePtg(String cellref) {
setColRelative(!c.isColAbsolute());
setRowRelative(!c.isRowAbsolute());
}
-
+
public ReferencePtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
setRow(row);
setColumn(column);
setRowRelative(isRowRelative);
setColRelative(isColumnRelative);
- }
+ }
/** Creates new ValueReferencePtg */
field_1_row = in.readUShort();
field_2_col = in.readUShort();
}
-
+
public String getRefPtgName() {
return "ReferencePtg";
- }
-
- public String toString()
- {
- StringBuffer buffer = new StringBuffer("[");
- buffer.append(getRefPtgName());
- buffer.append("]\n");
+ }
- buffer.append("row = ").append(getRow()).append("\n");
- buffer.append("col = ").append(getColumn()).append("\n");
- buffer.append("rowrelative = ").append(isRowRelative()).append("\n");
- buffer.append("colrelative = ").append(isColRelative()).append("\n");
- return buffer.toString();
+ public String toString() {
+ CellReference cr = new CellReference(getRow(), getColumn(), !isRowRelative(),!isColRelative());
+ StringBuffer sb = new StringBuffer();
+ sb.append(getClass().getName());
+ sb.append(" [");
+ sb.append(cr.formatAsString());
+ sb.append("]");
+ return sb.toString();
}
public void writeBytes(byte [] array, int offset)
{
return rowRelative.isSet(field_2_col);
}
-
+
public void setRowRelative(boolean rel) {
field_2_col=rowRelative.setBoolean(field_2_col,rel);
}
-
+
public boolean isColRelative()
{
return colRelative.isSet(field_2_col);
}
-
+
public void setColRelative(boolean rel) {
field_2_col=colRelative.setBoolean(field_2_col,rel);
}
//TODO -- should we store a cellreference instance in this ptg?? but .. memory is an issue, i believe!
return (new CellReference(getRowAsInt(),getColumn(),!isRowRelative(),!isColRelative())).formatAsString();
}
-
+
public byte getDefaultOperandClass() {
return Ptg.CLASS_REF;
}
-
+
public Object clone() {
ReferencePtg ptg = new ReferencePtg();
ptg.field_1_row = field_1_row;
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.hssf.record.formula;\r
+\r
+/**\r
+ * @author Josh Micich\r
+ */\r
+abstract class ScalarConstantPtg extends Ptg {\r
+ public boolean isBaseToken() {\r
+ return true;\r
+ }\r
+ public final byte getDefaultOperandClass() {\r
+ return Ptg.CLASS_VALUE;\r
+ }\r
+ \r
+}\r
* @author Jason Height (jheight at chariot dot net dot au)
* @author Bernard Chesnoy
*/
-public final class StringPtg extends Ptg {
+public final class StringPtg extends ScalarConstantPtg {
public final static int SIZE = 9;
public final static byte sid = 0x17;
private static final BitField fHighByte = BitFieldFactory.getInstance(0x01);
return sb.toString();
}
- public byte getDefaultOperandClass() {
- return Ptg.CLASS_VALUE;
- }
-
public Object clone() {
StringPtg ptg = new StringPtg();
ptg.field_1_length = field_1_length;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
-
-public class SubtractPtg
- extends OperationPtg
-{
+public final class SubtractPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x04;
* @author Avik Sengupta
*/
-public class UnaryMinusPtg extends OperationPtg
-{
+public final class UnaryMinusPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x13;
return buffer.toString();
}
- public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
-
public Object clone() {
return new UnaryPlusPtg();
}
* @author Avik Sengupta
*/
-public class UnaryPlusPtg extends OperationPtg
-{
+public final class UnaryPlusPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x12;
return buffer.toString();
}
- public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
-
public Object clone() {
return new UnaryPlusPtg();
}
/**
* @author Glen Stampoultzis (glens at apache.org)
*/
-public class UnionPtg extends OperationPtg
-{
+public final class UnionPtg extends OperationPtg {
public final static byte sid = 0x10;
// doesn't need anything
}
+ public final boolean isBaseToken() {
+ return true;
+ }
public int getSize()
{
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
-
-public class UnknownPtg
- extends Ptg
-{
+public class UnknownPtg extends Ptg {
private short size = 1;
/** Creates new UnknownPtg */
{
}
- public UnknownPtg(RecordInputStream in)
- {
-
+ public UnknownPtg(RecordInputStream in) {
// doesn't need anything
}
+ public boolean isBaseToken() {
+ return true;
+ }
public void writeBytes(byte [] array, int offset)
{
}
--- /dev/null
+/* ====================================================================
+ 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;
+
+/**
+ * Common superclass of all value operators.
+ * Subclasses include all unary and binary operators except for the reference operators (IntersectionPtg, RangePtg, UnionPtg)
+ *
+ * @author Josh Micich
+ */
+public abstract class ValueOperatorPtg extends OperationPtg {
+
+ /**
+ * All Operator <tt>Ptg</tt>s are base tokens (i.e. are not RVA classifed)
+ */
+ public final boolean isBaseToken() {
+ return true;
+ }
+ public final byte getDefaultOperandClass() {
+ return Ptg.CLASS_VALUE;
+ }
+}
}
private static ValueEval evaluateCell(HSSFWorkbook workbook, HSSFSheet sheet,
int srcRowNum, short srcColNum, String cellFormulaText) {
- FormulaParser parser = new FormulaParser(cellFormulaText, workbook);
- parser.parse();
- Ptg[] ptgs = parser.getRPNPtg();
- // -- parsing over --
-
+
+ Ptg[] ptgs = FormulaParser.parse(cellFormulaText, workbook);
Stack stack = new Stack();
for (int i = 0, iSize = ptgs.length; i < iSize; i++) {
// since we don't know how to handle these yet :(
Ptg ptg = ptgs[i];
- if (ptg instanceof ControlPtg) { continue; }
+ if (ptg instanceof ControlPtg) {
+ // skip Parentheses, Attr, etc
+ continue;
+ }
if (ptg instanceof MemErrPtg) { continue; }
if (ptg instanceof MissingArgPtg) { continue; }
if (ptg instanceof NamePtg) {
- // named ranges, macro functions
+ // named ranges, macro functions
NamePtg namePtg = (NamePtg) ptg;
stack.push(new NameEval(namePtg.getIndex()));
continue;
}
if (ptg instanceof NameXPtg) {
- // TODO - external functions
+ // TODO - external functions
continue;
}
if (ptg instanceof UnknownPtg) { continue; }
if (ptg instanceof OperationPtg) {
OperationPtg optg = (OperationPtg) ptg;
- // parens can be ignored since we have RPN tokens
- if (optg instanceof ParenthesisPtg) { continue; }
- if (optg instanceof AttrPtg) { continue; }
if (optg instanceof UnionPtg) { continue; }
OperationEval operation = OperationEvaluatorFactory.create(optg);