StringBuffer buf = new StringBuffer();
if (token instanceof ExpPtg) return;
- buf.append(((OperationPtg) token).toFormulaString((HSSFWorkbook)null));
+ buf.append(((OperationPtg) token).toFormulaString());
buf.append(sep);
switch (token.getPtgClass()) {
case Ptg.CLASS_REF :
Ptg[] tokens = record.getParsedExpression();
for (int i = 0; i < tokens.length; i++) {
Ptg token = tokens[i];
- buf.append( token.toFormulaString((HSSFWorkbook)null));
+ buf.append( token.toFormulaString());
switch (token.getPtgClass()) {
case Ptg.CLASS_REF :
buf.append("(R)");
import java.util.ArrayList;
import java.util.List;
-import java.util.Stack;
-//import PTGs .. since we need everything, import *
import org.apache.poi.hssf.record.UnicodeString;
import org.apache.poi.hssf.record.constant.ErrorConstant;
-import org.apache.poi.hssf.record.formula.*;
+import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
+import org.apache.poi.hssf.record.formula.AddPtg;
+import org.apache.poi.hssf.record.formula.Area3DPtg;
+import org.apache.poi.hssf.record.formula.AreaPtg;
+import org.apache.poi.hssf.record.formula.ArrayPtg;
+import org.apache.poi.hssf.record.formula.BoolPtg;
+import org.apache.poi.hssf.record.formula.ConcatPtg;
+import org.apache.poi.hssf.record.formula.DividePtg;
+import org.apache.poi.hssf.record.formula.EqualPtg;
+import org.apache.poi.hssf.record.formula.ErrPtg;
+import org.apache.poi.hssf.record.formula.FuncPtg;
+import org.apache.poi.hssf.record.formula.FuncVarPtg;
+import org.apache.poi.hssf.record.formula.GreaterEqualPtg;
+import org.apache.poi.hssf.record.formula.GreaterThanPtg;
+import org.apache.poi.hssf.record.formula.IntPtg;
+import org.apache.poi.hssf.record.formula.LessEqualPtg;
+import org.apache.poi.hssf.record.formula.LessThanPtg;
+import org.apache.poi.hssf.record.formula.MissingArgPtg;
+import org.apache.poi.hssf.record.formula.MultiplyPtg;
+import org.apache.poi.hssf.record.formula.NamePtg;
+import org.apache.poi.hssf.record.formula.NameXPtg;
+import org.apache.poi.hssf.record.formula.NotEqualPtg;
+import org.apache.poi.hssf.record.formula.NumberPtg;
+import org.apache.poi.hssf.record.formula.ParenthesisPtg;
+import org.apache.poi.hssf.record.formula.PercentPtg;
+import org.apache.poi.hssf.record.formula.PowerPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.Ref3DPtg;
+import org.apache.poi.hssf.record.formula.RefPtg;
+import org.apache.poi.hssf.record.formula.StringPtg;
+import org.apache.poi.hssf.record.formula.SubtractPtg;
+import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
+import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.AreaReference;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.hssf.util.CellReference.NameType;
+import org.apache.poi.ss.formula.FormulaRenderer;
/**
* This class parses a formula string into a List of tokens in RPN order.
* @param lptgs list of Ptg, can be null or empty
* @return a human readable String
*/
- public static String toFormulaString(Workbook book, List lptgs) {
+ public static String toFormulaString(HSSFWorkbook book, List lptgs) {
String retval = null;
if (lptgs == null || lptgs.size() == 0) return "#NAME";
Ptg[] ptgs = new Ptg[lptgs.size()];
retval = toFormulaString(book, ptgs);
return retval;
}
- /**
- * Convenience method which takes in a list then passes it to the
- * other toFormulaString signature. Works on the current
- * workbook for 3D and named references
- * @param lptgs list of Ptg, can be null or empty
- * @return a human readable String
- */
- public String toFormulaString(List lptgs) {
- return toFormulaString(book, lptgs);
- }
/**
* Static method to convert an array of Ptgs in RPN order
* @param ptgs array of Ptg, can be null or empty
* @return a human readable String
*/
- public static String toFormulaString(Workbook book, Ptg[] ptgs) {
- if (ptgs == null || ptgs.length == 0) {
- // TODO - what is the justification for returning "#NAME" (which is not "#NAME?", btw)
- return "#NAME";
- }
- Stack stack = new Stack();
-
- for (int i=0 ; i < ptgs.length; i++) {
- Ptg ptg = ptgs[i];
- // TODO - what about MemNoMemPtg?
- if(ptg instanceof MemAreaPtg || ptg instanceof MemFuncPtg || ptg instanceof MemErrPtg) {
- // marks the start of a list of area expressions which will be naturally combined
- // by their trailing operators (e.g. UnionPtg)
- // TODO - put comment and throw exception in toFormulaString() of these classes
- continue;
- }
- 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()) {
- 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.toString());
- }
-
- if (! (ptg instanceof OperationPtg)) {
- stack.push(ptg.toFormulaString(book));
- continue;
- }
-
- OperationPtg o = (OperationPtg) ptg;
- String[] operands = getOperands(stack, o.getNumberOfOperands());
- stack.push(o.toFormulaString(operands));
- }
- if(stack.isEmpty()) {
- // inspection of the code above reveals that every stack.pop() is followed by a
- // stack.push(). So this is either an internal error or impossible.
- throw new IllegalStateException("Stack underflow");
- }
- String result = (String) stack.pop();
- if(!stack.isEmpty()) {
- // Might be caused by some tokens like AttrPtg and Mem*Ptg, which really shouldn't
- // put anything on the stack
- throw new IllegalStateException("too much stuff left on the stack");
- }
- return result;
- }
-
- private static String[] getOperands(Stack stack, int nOperands) {
- String[] operands = new String[nOperands];
-
- for (int j = nOperands-1; j >= 0; j--) { // reverse iteration because args were pushed in-order
- if(stack.isEmpty()) {
- String msg = "Too few arguments supplied to operation. Expected (" + nOperands
- + ") operands but got (" + (nOperands - j - 1) + ")";
- throw new IllegalStateException(msg);
- }
- operands[j] = (String) stack.pop();
- }
- return operands;
- }
- /**
- * Static method to convert an array of Ptgs in RPN order
- * to a human readable string format in infix mode. Works
- * on the current workbook for named and 3D references.
- * @param ptgs array of Ptg, can be null or empty
- * @return a human readable String
- */
- public String toFormulaString(Ptg[] ptgs) {
- return toFormulaString(book, ptgs);
+ public static String toFormulaString(HSSFWorkbook book, Ptg[] ptgs) {
+ return FormulaRenderer.toFormulaString(HSSFEvaluationWorkbook.create(book), ptgs);
}
}
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
return field_2_fnc_index == FUNCTION_INDEX_EXTERNAL;
}
- public String toFormulaString(Workbook book) {
+ public String toFormulaString() {
return getName();
}
package org.apache.poi.hssf.record.formula;\r
\r
import org.apache.poi.hssf.record.RecordInputStream;\r
-import org.apache.poi.ss.usermodel.Workbook;\r
import org.apache.poi.util.LittleEndian;\r
\r
/**\r
public final int getSize() {\r
return SIZE;\r
}\r
- public final String toFormulaString(Workbook book) {\r
+ public final String toFormulaString() {\r
return formatReferenceAsString();\r
}\r
public final String toString() {\r
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.ss.util.AreaReference;
-import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.ss.formula.WorkbookDependentFormula;
+import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
import org.apache.poi.util.LittleEndian;
/**
* @author Jason Height (jheight at chariot dot net dot au)
* @version 1.0-pre
*/
-public final class Area3DPtg extends AreaPtgBase {
+public final class Area3DPtg extends AreaPtgBase implements WorkbookDependentFormula {
public final static byte sid = 0x3b;
private final static int SIZE = 11; // 10 + 1 for Ptg
* @return text representation of this area reference that can be used in text
* formulas. The sheet name will get properly delimited if required.
*/
- public String toFormulaString(Workbook book) {
+ public String toFormulaString(FormulaRenderingWorkbook book) {
return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, formatReferenceAsString());
}
+ public String toFormulaString() {
+ throw new RuntimeException("3D references need a workbook to determine formula text");
+ }
}
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.ss.usermodel.ErrorConstants;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
import org.apache.poi.util.LittleEndian;
/**
LittleEndian.putInt(array, offset + 5, unused2);
}
-
- public String toFormulaString(Workbook book) {
- return ErrorConstants.getText(ErrorConstants.ERROR_REF);
+ public String toFormulaString() {
+ return HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF);
}
public byte getDefaultOperandClass() {
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.ss.util.AreaReference;
+import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
-
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.AreaReference;
-import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.LittleEndian;
/**
* Specifies a rectangular area of cells A1:A4 for instance.
return topLeft.formatAsString() + ":" + botRight.formatAsString();
}
- public String toFormulaString(Workbook book) {
+ public String toFormulaString() {
return formatReferenceAsString();
}
import org.apache.poi.hssf.record.UnicodeString;
import org.apache.poi.hssf.record.constant.ConstantValueParser;
import org.apache.poi.hssf.record.constant.ErrorConstant;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LittleEndian;
/**
+ ConstantValueParser.getEncodedSize(token_3_arrayValues);
}
- public String formatAsString() {
+ public String formatAsString() { // TODO - fold into toFormulaString
StringBuffer b = new StringBuffer();
b.append("{");
for (int y=0;y<getRowCount();y++) {
b.append("}");
return b.toString();
}
- public String toFormulaString(Workbook book) {
+ public String toFormulaString() {
return formatAsString();
}
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.record.RecordInputStream;
-
-import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.LittleEndian;
/**
* "Special Attributes"
if(space.isSet(field_1_options)) {
return operands[ 0 ];
} else if (optiIf.isSet(field_1_options)) {
- return toFormulaString((Workbook)null) + "(" + operands[ 0 ] +")";
+ return toFormulaString() + "(" + operands[ 0 ] +")";
} else if (optGoto.isSet(field_1_options)) {
- return toFormulaString((Workbook)null) + operands[0]; //goto isn't a real formula element should not show up
+ return toFormulaString() + operands[0]; //goto isn't a real formula element should not show up
} else {
- return toFormulaString((Workbook)null) + "(" + operands[ 0 ] + ")";
+ return toFormulaString() + "(" + operands[ 0 ] + ")";
}
}
return -1;
}
- public String toFormulaString(Workbook book) {
+ public String toFormulaString() {
if(semiVolatile.isSet(field_1_options)) {
return "ATTR(semiVolatile)";
}
return SIZE;
}
- protected String toFormulaString() {
+ public String toFormulaString() {
return _value ? "TRUE" : "FALSE";
}
}
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.ss.usermodel.ErrorConstants;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+import org.apache.poi.ss.formula.WorkbookDependentFormula;
+import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
import org.apache.poi.util.LittleEndian;
/**
* @author Patrick Luby
* @version 1.0-pre
*/
-public final class DeletedArea3DPtg extends OperandPtg {
+public final class DeletedArea3DPtg extends OperandPtg implements WorkbookDependentFormula {
public final static byte sid = 0x3d;
private final int field_1_index_extern_sheet;
private final int unused1;
unused1 = in.readInt();
unused2 = in.readInt();
}
-
- public String toFormulaString(Workbook book) {
+ public String toFormulaString(FormulaRenderingWorkbook book) {
return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet,
- ErrorConstants.getText(ErrorConstants.ERROR_REF));
+ HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF));
+ }
+ public String toFormulaString() {
+ throw new RuntimeException("3D references need a workbook to determine formula text");
}
public byte getDefaultOperandClass() {
return Ptg.CLASS_REF;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.ss.usermodel.ErrorConstants;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+import org.apache.poi.ss.formula.WorkbookDependentFormula;
+import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
import org.apache.poi.util.LittleEndian;
/**
* @author Patrick Luby
* @version 1.0-pre
*/
-public final class DeletedRef3DPtg extends OperandPtg {
+public final class DeletedRef3DPtg extends OperandPtg implements WorkbookDependentFormula {
public final static byte sid = 0x3c;
private final int field_1_index_extern_sheet;
private final int unused1;
unused1 = 0;
}
- public String toFormulaString(Workbook book) {
+ public String toFormulaString(FormulaRenderingWorkbook book) {
return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet,
- ErrorConstants.getText(ErrorConstants.ERROR_REF));
+ HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF));
+ }
+ public String toFormulaString() {
+ throw new RuntimeException("3D references need a workbook to determine formula text");
}
public byte getDefaultOperandClass() {
return Ptg.CLASS_REF;
array[offset + 1] = (byte)field_1_error_code;
}
- protected String toFormulaString() {
+ public String toFormulaString() {
return HSSFErrorConstants.getText(field_1_error_code);
}
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.record.RecordInputStream;
-
import org.apache.poi.util.LittleEndian;
/**
return field_2_first_col;
}
- public String toFormulaString(Workbook book)
+ public String toFormulaString()
{
throw new RecordFormatException("Coding Error: Expected ExpPtg to be converted from Shared to Non-Shared Formula by ValueRecordsAggregate, but it wasn't");
}
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
/**
* @author Josh Micich
// no instances of this class
}
- public static String prependSheetName(Workbook book, int field_1_index_extern_sheet, String cellRefText) {
- String sheetName = book.findSheetNameFromExternSheet(field_1_index_extern_sheet);
+ public static String prependSheetName(FormulaRenderingWorkbook book, int field_1_index_extern_sheet, String cellRefText) {
+ String sheetName = book.getSheetNameByExternSheet(field_1_index_extern_sheet);
StringBuffer sb = new StringBuffer(sheetName.length() + cellRefText.length() + 4);
if (sheetName.length() < 1) {
// What excel does if sheet has been deleted
sb.append("#REF"); // note - '!' added just once below
} else {
- SheetNameFormatter.appendFormat(sb, sheetName);
+ SheetNameFormatter.appendFormat(sb, sheetName);
}
- sb.append('!');
+ sb.append('!');
sb.append(cellRefText);
return sb.toString();
}
return SIZE;
}
- protected String toFormulaString() {
+ public String toFormulaString() {
return String.valueOf(getValue());
}
}
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
}
/** Implementation of method from Ptg */
- public String toFormulaString(Workbook book)
+ public String toFormulaString()
{
return " ";
}
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.LittleEndian;
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
return SIZE;
}
- public String toFormulaString(Workbook book)
+ public String toFormulaString()
{
return ""; // TODO: Not sure how to format this. -- DN
}
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
*
array[offset] = (byte) (sid + getPtgClass());
}
- public String toFormulaString(Workbook book)
+ public String toFormulaString()
{
return "ERR#";
}
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.LittleEndian;
/**
* @author Glen Stampoultzis (glens at apache.org)
LittleEndian.putUShort( array, offset + 1, field_1_len_ref_subexpression );
}
- public String toFormulaString(Workbook book)
+ public String toFormulaString()
{
return "";
}
return SIZE;
}
- protected String toFormulaString() {
+ public String toFormulaString() {
return " ";
}
}
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.formula.WorkbookDependentFormula;
+import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
import org.apache.poi.util.LittleEndian;
/**
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
-public final class NamePtg extends OperandPtg {
+public final class NamePtg extends OperandPtg implements WorkbookDependentFormula {
public final static short sid = 0x23;
private final static int SIZE = 5;
/** one-based index to defined name record */
return SIZE;
}
- public String toFormulaString(Workbook book)
+ public String toFormulaString(FormulaRenderingWorkbook book)
{
- return book.getNameName(field_1_label_index - 1);
+ return book.getNameText(this);
}
+ public String toFormulaString() {
+ throw new RuntimeException("3D references need a workbook to determine formula text");
+ }
public byte getDefaultOperandClass() {
return Ptg.CLASS_REF;
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.ss.formula.WorkbookDependentFormula;
+import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
+import org.apache.poi.util.LittleEndian;
/**
*
* @author aviks
*/
-public final class NameXPtg extends OperandPtg {
+public final class NameXPtg extends OperandPtg implements WorkbookDependentFormula {
public final static short sid = 0x39;
private final static int SIZE = 7;
return SIZE;
}
- public String toFormulaString(Workbook book) {
+ public String toFormulaString(FormulaRenderingWorkbook book) {
// -1 to convert definedNameIndex from 1-based to zero-based
- return book.resolveNameXText(_sheetRefIndex, _nameNumber - 1);
+ return book.resolveNameXText(this);
+ }
+ public String toFormulaString() {
+ throw new RuntimeException("3D references need a workbook to determine formula text");
}
public byte getDefaultOperandClass() {
return SIZE;
}
- protected String toFormulaString() {
+ public String toFormulaString() {
// TODO - java's rendering of double values is not quite same as excel's
// Maybe use HSSFDataFormatter?
return String.valueOf(field_1_value);
package org.apache.poi.hssf.record.formula;
+
/**
* @author Josh Micich
*/
// TODO remove "int getType();" from Eval hierarchy
throw new RuntimeException("remove this method");
}
-
}
package org.apache.poi.hssf.record.formula;
-import java.util.List;
-
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.hssf.record.RecordInputStream;
/**
* While formula tokens are stored in RPN order and thus do not need parenthesis for
return SIZE;
}
- public String toFormulaString(Workbook book)
+ public String toFormulaString()
{
return "()";
}
import java.util.Stack;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* <tt>Ptg</tt> represents a syntactic token in a formula. 'PTG' is an acronym for
/**
* return a string representation of this token alone
*/
- public abstract String toFormulaString(Workbook book);
+ public abstract String toFormulaString();
/**
* dump a debug representation (hexdump) to a string
*/
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
array[ offset + 0 ] = sid;
}
- public String toFormulaString(Workbook book)
+ public String toFormulaString()
{
return ":";
}
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LittleEndian;
/**
LittleEndian.putByte(array, offset+0, getSid() + getPtgClass());
writeCoordinates(array, offset+1);
}
- public final String toFormulaString(Workbook book) {
+ public final String toFormulaString() {
return formatReferenceAsString();
}
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.ss.formula.WorkbookDependentFormula;
+import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
import org.apache.poi.util.LittleEndian;
/**
* @author Jason Height (jheight at chariot dot net dot au)
* @version 1.0-pre
*/
-public final class Ref3DPtg extends RefPtgBase {
+public final class Ref3DPtg extends RefPtgBase implements WorkbookDependentFormula {
public final static byte sid = 0x3a;
private final static int SIZE = 7; // 6 + 1 for Ptg
* @return text representation of this cell reference that can be used in text
* formulas. The sheet name will get properly delimited if required.
*/
- public String toFormulaString(Workbook book) {
+ public String toFormulaString(FormulaRenderingWorkbook book) {
return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, formatReferenceAsString());
}
+ public String toFormulaString() {
+ throw new RuntimeException("3D references need a workbook to determine formula text");
+ }
}
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.ss.usermodel.ErrorConstants;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.LittleEndian;
/**
return SIZE;
}
- public String toFormulaString(Workbook book) {
- return ErrorConstants.getText(ErrorConstants.ERROR_REF);
+ public String toFormulaString() {
+ return HSSFErrorConstants.getText(HSSFErrorConstants.ERROR_REF);
}
public byte getDefaultOperandClass() {
\r
package org.apache.poi.hssf.record.formula;\r
\r
-import org.apache.poi.ss.usermodel.Workbook;\r
\r
/**\r
* @author Josh Micich\r
return Ptg.CLASS_VALUE;\r
}\r
\r
- public final String toFormulaString(Workbook book) {\r
- return toFormulaString();\r
- }\r
-\r
- protected abstract String toFormulaString();\r
-\r
public final String toString() {\r
StringBuffer sb = new StringBuffer(64);\r
sb.append(getClass().getName()).append(" [");\r
}
}
- protected String toFormulaString() {
+ public String toFormulaString() {
String value = field_3_string;
int len = value.length();
StringBuffer sb = new StringBuffer(len + 4);
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.record.RecordInputStream;
-
import org.apache.poi.util.LittleEndian;
/**
return field_2_first_col;
}
- public String toFormulaString(Workbook book)
+ public String toFormulaString()
{
// table(....)[][]
throw new RecordFormatException("Table and Arrays are not yet supported");
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
/**
* @author Glen Stampoultzis (glens at apache.org)
array[ offset + 0 ] = sid;
}
- public String toFormulaString(Workbook book)
+ public String toFormulaString()
{
return ",";
}
==================================================================== */
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.record.RecordInputStream;
/**
return size;
}
- public String toFormulaString(Workbook book)
+ public String toFormulaString()
{
return "UNKNOWN";
}
package org.apache.poi.hssf.record.formula;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Common superclass of all value operators.
public final int getSize() {
return 1;
}
- public final String toFormulaString(Workbook book) {
+ public final String toFormulaString() {
// TODO - prune this method out of the hierarchy
throw new RuntimeException("toFormulaString(String[] operands) should be used for subclasses of OperationPtgs");
}
--- /dev/null
+package org.apache.poi.hssf.usermodel;\r
+\r
+import org.apache.poi.hssf.model.Workbook;\r
+import org.apache.poi.hssf.record.formula.NamePtg;\r
+import org.apache.poi.hssf.record.formula.NameXPtg;\r
+import org.apache.poi.ss.formula.FormulaRenderingWorkbook;\r
+\r
+/**\r
+ * Internal POI use only\r
+ * \r
+ * @author Josh Micich\r
+ */\r
+public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook {\r
+\r
+ private final Workbook _iBook;\r
+ \r
+ public static HSSFEvaluationWorkbook create(HSSFWorkbook book) {\r
+ if (book == null) {\r
+ return null;\r
+ }\r
+ return new HSSFEvaluationWorkbook(book);\r
+ }\r
+\r
+ private HSSFEvaluationWorkbook(HSSFWorkbook book) {\r
+ _iBook = book.getWorkbook();\r
+ }\r
+\r
+ public String resolveNameXText(NameXPtg n) {\r
+ return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());\r
+ }\r
+\r
+ public String getSheetNameByExternSheet(int externSheetIndex) {\r
+ return _iBook.findSheetNameFromExternSheet(externSheetIndex);\r
+ }\r
+ public String getNameText(NamePtg namePtg) {\r
+ return _iBook.getNameRecord(namePtg.getIndex()).getNameText();\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.ss.formula;\r
+\r
+import java.util.List;\r
+import java.util.Stack;\r
+\r
+import org.apache.poi.hssf.record.formula.AttrPtg;\r
+import org.apache.poi.hssf.record.formula.MemAreaPtg;\r
+import org.apache.poi.hssf.record.formula.MemErrPtg;\r
+import org.apache.poi.hssf.record.formula.MemFuncPtg;\r
+import org.apache.poi.hssf.record.formula.OperationPtg;\r
+import org.apache.poi.hssf.record.formula.ParenthesisPtg;\r
+import org.apache.poi.hssf.record.formula.Ptg;\r
+\r
+public class FormulaRenderer {\r
+ /**\r
+ * Convenience method which takes in a list then passes it to the\r
+ * other toFormulaString signature.\r
+ * @param book workbook for 3D and named references\r
+ * @param lptgs list of Ptg, can be null or empty\r
+ * @return a human readable String\r
+ */\r
+ public static String toFormulaString(FormulaRenderingWorkbook book, List lptgs) {\r
+ String retval = null;\r
+ if (lptgs == null || lptgs.size() == 0) return "#NAME";\r
+ Ptg[] ptgs = new Ptg[lptgs.size()];\r
+ ptgs = (Ptg[])lptgs.toArray(ptgs);\r
+ retval = toFormulaString(book, ptgs);\r
+ return retval;\r
+ }\r
+ \r
+ /**\r
+ * Static method to convert an array of Ptgs in RPN order\r
+ * to a human readable string format in infix mode.\r
+ * @param book workbook for named and 3D references\r
+ * @param ptgs array of Ptg, can be null or empty\r
+ * @return a human readable String\r
+ */\r
+ public static String toFormulaString(FormulaRenderingWorkbook book, Ptg[] ptgs) {\r
+ if (ptgs == null || ptgs.length == 0) {\r
+ // TODO - what is the justification for returning "#NAME" (which is not "#NAME?", btw)\r
+ return "#NAME";\r
+ }\r
+ Stack stack = new Stack();\r
+\r
+ for (int i=0 ; i < ptgs.length; i++) {\r
+ Ptg ptg = ptgs[i];\r
+ // TODO - what about MemNoMemPtg?\r
+ if(ptg instanceof MemAreaPtg || ptg instanceof MemFuncPtg || ptg instanceof MemErrPtg) {\r
+ // marks the start of a list of area expressions which will be naturally combined\r
+ // by their trailing operators (e.g. UnionPtg)\r
+ // TODO - put comment and throw exception in toFormulaString() of these classes\r
+ continue;\r
+ }\r
+ if (ptg instanceof ParenthesisPtg) {\r
+ String contents = (String)stack.pop();\r
+ stack.push ("(" + contents + ")");\r
+ continue;\r
+ }\r
+ if (ptg instanceof AttrPtg) {\r
+ AttrPtg attrPtg = ((AttrPtg) ptg);\r
+ if (attrPtg.isOptimizedIf() || attrPtg.isOptimizedChoose() || attrPtg.isGoto()) {\r
+ continue;\r
+ }\r
+ if (attrPtg.isSpace()) {\r
+ // POI currently doesn't render spaces in formulas\r
+ continue;\r
+ // but if it ever did, care must be taken:\r
+ // tAttrSpace comes *before* the operand it applies to, which may be consistent\r
+ // with how the formula text appears but is against the RPN ordering assumed here\r
+ }\r
+ if (attrPtg.isSemiVolatile()) {\r
+ // similar to tAttrSpace - RPN is violated\r
+ continue;\r
+ }\r
+ if (attrPtg.isSum()) {\r
+ String[] operands = getOperands(stack, attrPtg.getNumberOfOperands());\r
+ stack.push(attrPtg.toFormulaString(operands));\r
+ continue;\r
+ }\r
+ throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());\r
+ }\r
+\r
+ if (ptg instanceof WorkbookDependentFormula) {\r
+ WorkbookDependentFormula optg = (WorkbookDependentFormula) ptg;\r
+ stack.push(optg.toFormulaString(book));\r
+ continue;\r
+ }\r
+ if (! (ptg instanceof OperationPtg)) {\r
+ stack.push(ptg.toFormulaString());\r
+ continue;\r
+ }\r
+\r
+ OperationPtg o = (OperationPtg) ptg;\r
+ String[] operands = getOperands(stack, o.getNumberOfOperands());\r
+ stack.push(o.toFormulaString(operands));\r
+ }\r
+ if(stack.isEmpty()) {\r
+ // inspection of the code above reveals that every stack.pop() is followed by a\r
+ // stack.push(). So this is either an internal error or impossible.\r
+ throw new IllegalStateException("Stack underflow");\r
+ }\r
+ String result = (String) stack.pop();\r
+ if(!stack.isEmpty()) {\r
+ // Might be caused by some tokens like AttrPtg and Mem*Ptg, which really shouldn't\r
+ // put anything on the stack\r
+ throw new IllegalStateException("too much stuff left on the stack");\r
+ }\r
+ return result;\r
+ }\r
+\r
+ private static String[] getOperands(Stack stack, int nOperands) {\r
+ String[] operands = new String[nOperands];\r
+\r
+ for (int j = nOperands-1; j >= 0; j--) { // reverse iteration because args were pushed in-order\r
+ if(stack.isEmpty()) {\r
+ String msg = "Too few arguments supplied to operation. Expected (" + nOperands\r
+ + ") operands but got (" + (nOperands - j - 1) + ")";\r
+ throw new IllegalStateException(msg);\r
+ }\r
+ operands[j] = (String) stack.pop();\r
+ }\r
+ return operands;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.ss.formula;\r
+\r
+import org.apache.poi.hssf.record.formula.NamePtg;\r
+import org.apache.poi.hssf.record.formula.NameXPtg;\r
+\r
+public interface FormulaRenderingWorkbook {\r
+\r
+ String getSheetNameByExternSheet(int externSheetIndex);\r
+ String resolveNameXText(NameXPtg nameXPtg);\r
+ String getNameText(NamePtg namePtg);\r
+}\r
--- /dev/null
+package org.apache.poi.ss.formula;\r
+\r
+public interface WorkbookDependentFormula {\r
+ String toFormulaString(FormulaRenderingWorkbook book);\r
+}\r
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\r
+<!--\r
+ ====================================================================\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
+<html>\r
+<head>\r
+</head>\r
+<body bgcolor="white">\r
+\r
+This package contains common internal POI code for manipulating formulas.\r
+Client applications should not refer to these classes directly.\r
+\r
+</body>\r
+</html>\r
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.Ref3DPtg;
+import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
/**
assertTrue(ptgs[0] instanceof Ref3DPtg);
Ref3DPtg ptg = (Ref3DPtg)ptgs[0];
- assertEquals("Sheet1!A1", ptg.toFormulaString(stubHSSF));
+ HSSFEvaluationWorkbook book = HSSFEvaluationWorkbook.create(stubHSSF);
+ assertEquals("Sheet1!A1", ptg.toFormulaString(book));
// Now check we get the right formula back for
import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
import org.apache.poi.hssf.usermodel.HSSFName;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
public void testMacroFunction() {
// testNames.xls contains a VB function called 'myFunc'
HSSFWorkbook w = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
+ HSSFEvaluationWorkbook book = HSSFEvaluationWorkbook.create(w);
Ptg[] ptg = FormulaParser.parse("myFunc()", w);
// myFunc() actually takes 1 parameter. Don't know if POI will ever be able to detect this problem
// the name gets encoded as the first arg
NamePtg tname = (NamePtg) ptg[0];
- assertEquals("myFunc", tname.toFormulaString(w));
+ assertEquals("myFunc", tname.toFormulaString(book));
AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1];
assertTrue(tfunc.isExternalFunction());
assertEquals(2, ptgs.length);
Ptg ptg0 = ptgs[0];
assertEquals(ArrayPtg.class, ptg0.getClass());
- assertEquals("{1.0,2.0,2.0,#REF!;FALSE,3.0,3.0,2.0}", ptg0.toFormulaString(null));
+ assertEquals("{1.0,2.0,2.0,#REF!;FALSE,3.0,3.0,2.0}", ptg0.toFormulaString());
ArrayPtg aptg = (ArrayPtg) ptg0;
Object[][] values = aptg.getTokenArrayValues();
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.RefPtg;
import org.apache.poi.hssf.record.formula.StringPtg;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Tests <tt>FormulaParser</tt> specifically with respect to IF() functions
assertEquals(true, flag.getValue());
assertEquals("Y", y.getValue());
assertEquals("N", n.getValue());
- assertEquals("IF", funif.toFormulaString((HSSFWorkbook) null));
+ assertEquals("IF", funif.toFormulaString());
assertTrue("Goto ptg exists", goto1.isGoto());
}
/**
Ptg[] convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 100, 200);
RefPtg refPtg = (RefPtg) convertedFormula[1];
- assertEquals("$C101", refPtg.toFormulaString(null));
+ assertEquals("$C101", refPtg.toFormulaString());
if (refPtg.getPtgClass() == Ptg.CLASS_REF) {
throw new AssertionFailedError("Identified bug 45123");
}
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
+import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
*/
public final class TestArea3DPtg extends AbstractPtgTestCase {
- /**
- * confirms that sheet names get properly escaped
- */
+ /**
+ * confirms that sheet names get properly escaped
+ */
public void testToFormulaString() {
-
+
Area3DPtg target = new Area3DPtg("A1:B1", (short)0);
-
+
String sheetName = "my sheet";
- HSSFWorkbook book = createWorkbookWithSheet(sheetName);
+ HSSFWorkbook wb = createWorkbookWithSheet(sheetName);
+ HSSFEvaluationWorkbook book = HSSFEvaluationWorkbook.create(wb);
assertEquals("'my sheet'!A1:B1", target.toFormulaString(book));
-
- book.setSheetName(0, "Sheet1");
- assertEquals("Sheet1!A1:B1", target.toFormulaString(book));
-
- book.setSheetName(0, "C64");
- assertEquals("'C64'!A1:B1", target.toFormulaString(book));
+
+ wb.setSheetName(0, "Sheet1");
+ assertEquals("Sheet1!A1:B1", target.toFormulaString(book));
+
+ wb.setSheetName(0, "C64");
+ assertEquals("'C64'!A1:B1", target.toFormulaString(book));
}
}
import junit.framework.TestCase;
import org.apache.poi.hssf.model.FormulaParser;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Tests for {@link AreaPtg}.
assertEquals("Relative references changed", expectedFormula2, newFormula2);
}
- private String shiftAllColumnsBy1(String formula)
- {
+ private static String shiftAllColumnsBy1(String formula) {
int letUsShiftColumn1By1Column=1;
-
- FormulaParser parser = new FormulaParser(formula,null);
- parser.parse();
-
- final Ptg[] ptgs = parser.getRPNPtg();
+ HSSFWorkbook wb = null;
+ Ptg[] ptgs = FormulaParser.parse(formula, wb);
for(int i=0; i<ptgs.length; i++)
{
Ptg ptg = ptgs[i];
aptg.setLastColumn((short)(aptg.getLastColumn()+letUsShiftColumn1By1Column));
}
}
- String newFormula = parser.toFormulaString(ptgs);
+ String newFormula = FormulaParser.toFormulaString(wb, ptgs);
return newFormula;
}
-
-
-
}
String actualFormula;
try {
- actualFormula = ptg.toFormulaString(null);
+ actualFormula = ptg.toFormulaString();
} catch (IllegalArgumentException e) {
if (e.getMessage().equals("Unexpected constant class (java.lang.Boolean)")) {
throw new AssertionFailedError("Identified bug 45380");
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record.formula;
+import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
public final class TestRef3DPtg extends AbstractPtgTestCase {
public void testToFormulaString() {
-
+
Ref3DPtg target = new Ref3DPtg("A1", (short)0);
-
- HSSFWorkbook book = createWorkbookWithSheet("my sheet");
-
+
+ HSSFWorkbook wb = createWorkbookWithSheet("my sheet");
+ HSSFEvaluationWorkbook book = HSSFEvaluationWorkbook.create(wb);
assertEquals("'my sheet'!A1", target.toFormulaString(book));
- book.setSheetName(0, "ProfitAndLoss");
- assertEquals("ProfitAndLoss!A1", target.toFormulaString(book));
-
- book.setSheetName(0, "profit+loss");
- assertEquals("'profit+loss'!A1", target.toFormulaString(book));
+ wb.setSheetName(0, "ProfitAndLoss");
+ assertEquals("ProfitAndLoss!A1", target.toFormulaString(book));
+
+ wb.setSheetName(0, "profit+loss");
+ assertEquals("'profit+loss'!A1", target.toFormulaString(book));
}
}
assertEquals(2, ptg.getLastColumn());
assertEquals(0, ptg.getFirstRow());
assertEquals(65535, ptg.getLastRow());
- assertEquals("C:C", ptg.toFormulaString(wb));
+ assertEquals("C:C", ptg.toFormulaString());
// Will show as C:C, but won't know how many
// rows it covers as we don't have the sheet
evaluator.evaluate(cell);
int evalCount = evaluator.getEvaluationCount();
// With caching, the evaluationCount is 8 which is a big improvement
+ assertTrue(evalCount > 0); // make sure the counter is actually working
if (evalCount > 10) {
// Without caching, evaluating cell 'A9' takes 21845 evaluations which consumes
// much time (~3 sec on Core 2 Duo 2.2GHz)
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.UnionPtg;
import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
import org.apache.poi.hssf.usermodel.HSSFName;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
InputStream is = HSSFTestDataSamples.openSampleFileStream("44167.xls");
HSSFWB wb = new HSSFWB(is);
Workbook workbook = wb.getWorkbook();
+ HSSFEvaluationWorkbook eb = HSSFEvaluationWorkbook.create(wb);
assertEquals(1, wb.getNumberOfNames());
String sheetName = "Tabelle1";
Area3DPtg ptgB = (Area3DPtg)def[1];
Area3DPtg ptgC = (Area3DPtg)def[2];
UnionPtg ptgD = (UnionPtg)def[3];
- assertEquals("", ptgA.toFormulaString(wb));
- assertEquals(refA, ptgB.toFormulaString(wb));
- assertEquals(refB, ptgC.toFormulaString(wb));
- assertEquals(",", ptgD.toFormulaString(wb));
+ assertEquals("", ptgA.toFormulaString());
+ assertEquals(refA, ptgB.toFormulaString(eb));
+ assertEquals(refB, ptgC.toFormulaString(eb));
+ assertEquals(",", ptgD.toFormulaString());
assertEquals(ref, nr.getAreaReference(wb));