You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ni...@apache.org on 2008/09/13 15:48:31 UTC

svn commit: r694947 [4/6] - in /poi/branches/ooxml: ./ src/documentation/content/xdocs/ src/java/org/apache/poi/hssf/extractor/ src/java/org/apache/poi/hssf/model/ src/java/org/apache/poi/hssf/record/ src/java/org/apache/poi/hssf/record/aggregates/ src...

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java Sat Sep 13 06:48:27 2008
@@ -23,6 +23,7 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 
 import org.apache.poi.hssf.model.FormulaParser;
 import org.apache.poi.hssf.model.Sheet;
@@ -60,8 +61,8 @@
  * Cells can be numeric, formula-based or string-based (text).  The cell type
  * specifies this.  String cells cannot conatin numbers and numeric cells cannot
  * contain strings (at least according to our model).  Client apps should do the
- * conversions themselves.  Formula cells have the formula string, as well as 
- * the formula result, which can be numeric or string. 
+ * conversions themselves.  Formula cells have the formula string, as well as
+ * the formula result, which can be numeric or string.
  * <p>
  * Cells should have their number (0 based) before being added to a row.  Only
  * cells that have values should be added.
@@ -86,14 +87,15 @@
     public final static int CELL_TYPE_BOOLEAN = 4;
     /** Error   Cell type (5) @see #setCellType(int) @see #getCellType() */
     public final static int CELL_TYPE_ERROR   = 5;
-    
+
     public final static short        ENCODING_UNCHANGED          = -1;
     public final static short        ENCODING_COMPRESSED_UNICODE = 0;
     public final static short        ENCODING_UTF_16             = 1;
+
+    private final HSSFWorkbook       book;
+    private final HSSFSheet          sheet;
     private int                      cellType;
     private HSSFRichTextString       stringValue;
-    private HSSFWorkbook             book;
-    private Sheet                    sheet;
     private CellValueRecordInterface record;
     private HSSFComment              comment;
 
@@ -113,7 +115,7 @@
      *
      * @see org.apache.poi.hssf.usermodel.HSSFRow#createCell(short)
      */
-    protected HSSFCell(HSSFWorkbook book, Sheet sheet, int row, short col)
+    protected HSSFCell(HSSFWorkbook book, HSSFSheet sheet, int row, short col)
     {
         checkBounds(col);
         stringValue  = null;
@@ -123,9 +125,12 @@
         // Relying on the fact that by default the cellType is set to 0 which
         // is different to CELL_TYPE_BLANK hence the following method call correctly
         // creates a new blank cell.
-        short xfindex = sheet.getXFIndexForColAt(col);
+        short xfindex = sheet.getSheet().getXFIndexForColAt(col);
         setCellType(CELL_TYPE_BLANK, false, row, col,xfindex);
     }
+    public HSSFSheet getSheet() {
+        return sheet;
+    }
 
     /**
      * Creates new Cell - Should only be called by HSSFRow.  This creates a cell
@@ -140,7 +145,7 @@
      *                Type of cell
      * @see org.apache.poi.hssf.usermodel.HSSFRow#createCell(short,int)
      */
-    protected HSSFCell(HSSFWorkbook book, Sheet sheet, int row, short col,
+    protected HSSFCell(HSSFWorkbook book, HSSFSheet sheet, int row, short col,
                        int type)
     {
         checkBounds(col);
@@ -148,8 +153,8 @@
         stringValue  = null;
         this.book    = book;
         this.sheet   = sheet;
-        
-        short xfindex = sheet.getXFIndexForColAt(col);
+
+        short xfindex = sheet.getSheet().getXFIndexForColAt(col);
         setCellType(type,false,row,col,xfindex);
     }
 
@@ -161,7 +166,7 @@
      * @param sheet - Sheet record of the sheet containing this cell
      * @param cval - the Cell Value Record we wish to represent
      */
-    protected HSSFCell(HSSFWorkbook book, Sheet sheet, CellValueRecordInterface cval) {
+    protected HSSFCell(HSSFWorkbook book, HSSFSheet sheet, CellValueRecordInterface cval) {
         record      = cval;
         cellType    = determineType(cval);
         stringValue = null;
@@ -190,10 +195,10 @@
      * used internally -- given a cell value record, figure out its type
      */
     private static int determineType(CellValueRecordInterface cval) {
-    	if (cval instanceof FormulaRecordAggregate) {
-    		return HSSFCell.CELL_TYPE_FORMULA;
-    	}
-    	// all others are plain BIFF records
+        if (cval instanceof FormulaRecordAggregate) {
+            return HSSFCell.CELL_TYPE_FORMULA;
+        }
+        // all others are plain BIFF records
         Record record = ( Record ) cval;
         switch (record.getSid()) {
 
@@ -209,13 +214,13 @@
         }
         throw new RuntimeException("Bad cell value rec (" + cval.getClass().getName() + ")");
     }
-    
+
     /**
      * Returns the Workbook that this Cell is bound to
      * @return
      */
     protected Workbook getBoundWorkbook() {
-    	return book.getWorkbook();
+        return book.getWorkbook();
     }
 
     /**
@@ -233,7 +238,7 @@
     {
         record.setColumn(num);
     }
-    
+
     /**
      * Updates the cell record's idea of what
      *  column it belongs in (0 based)
@@ -241,7 +246,7 @@
      */
     protected void updateCellNum(short num)
     {
-    	record.setColumn(num);
+        record.setColumn(num);
     }
 
     /**
@@ -295,7 +300,7 @@
                 FormulaRecordAggregate frec;
 
                 if (cellType != this.cellType) {
-                    frec = sheet.createFormula(row, col);
+                    frec = sheet.getSheet().createFormula(row, col);
                 } else {
                     frec = (FormulaRecordAggregate) record;
                     frec.setRow(row);
@@ -421,17 +426,17 @@
                 errRec.setColumn(col);
                 if (setValue)
                 {
-                    errRec.setValue(getErrorCellValue());
+                    errRec.setValue((byte)HSSFErrorConstants.ERROR_VALUE);
                 }
                 errRec.setXFIndex(styleIndex);
                 errRec.setRow(row);
                 record = errRec;
                 break;
         }
-        if (cellType != this.cellType && 
+        if (cellType != this.cellType &&
             this.cellType!=-1 )  // Special Value to indicate an uninitialized Cell
         {
-            sheet.replaceValueRecord(record);
+            sheet.getSheet().replaceValueRecord(record);
         }
         this.cellType = cellType;
     }
@@ -457,21 +462,20 @@
      *        precalculated value, for numerics we'll set its value. For other types we
      *        will change the cell to a numeric cell and set its value.
      */
-    public void setCellValue(double value)
-    {
+    public void setCellValue(double value) {
         int row=record.getRow();
         short col=record.getColumn();
         short styleIndex=record.getXFIndex();
-        if ((cellType != CELL_TYPE_NUMERIC) && (cellType != CELL_TYPE_FORMULA))
-        {
-            setCellType(CELL_TYPE_NUMERIC, false, row, col, styleIndex);
-        }
-        
-        // Save into the appropriate record
-        if(record instanceof FormulaRecordAggregate) {
-        	(( FormulaRecordAggregate ) record).getFormulaRecord().setValue(value);
-        } else {
-        	(( NumberRecord ) record).setValue(value);
+
+        switch (cellType) {
+            default:
+                setCellType(CELL_TYPE_NUMERIC, false, row, col, styleIndex);
+            case CELL_TYPE_ERROR:
+                (( NumberRecord ) record).setValue(value);
+                break;
+            case CELL_TYPE_FORMULA:
+                ((FormulaRecordAggregate)record).getFormulaRecord().setValue(value);
+                break;
         }
     }
 
@@ -491,7 +495,7 @@
     /**
      * set a date value for the cell. Excel treats dates as numeric so you will need to format the cell as
      * a date.
-     * 
+     *
      * This will set the cell value based on the Calendar's timezone. As Excel
      * does not support timezones this means that both 20:00+03:00 and
      * 20:00-03:00 will be reported as the same value (20:00) even that there
@@ -547,31 +551,20 @@
             return;
         }
         if (cellType == CELL_TYPE_FORMULA) {
-            // Set the 'pre-evaluated result' for the formula 
+            // Set the 'pre-evaluated result' for the formula
             // note - formulas do not preserve text formatting.
             FormulaRecordAggregate fr = (FormulaRecordAggregate) record;
-            
-            // Save the string into a String Record, creating
-            //  one if required
-            StringRecord sr = fr.getStringRecord();
-            if(sr == null) {
-            	// Wasn't a string before, need a new one
-            	sr = new StringRecord();
-                fr.setStringRecord(sr);
-            }
-            
-            // Save, loosing the formatting
-            sr.setString(hvalue.getString());
+            fr.setCachedStringResult(hvalue.getString());
             // Update our local cache to the un-formatted version
-            stringValue = new HSSFRichTextString(sr.getString());
-            
+            stringValue = new HSSFRichTextString(value.getString());
+
             // All done
             return;
         }
 
         // If we get here, we're not dealing with a formula,
         //  so handle things as a normal rich text cell
-        
+
         if (cellType != CELL_TYPE_STRING) {
             setCellType(CELL_TYPE_STRING, false, row, col, styleIndex);
         }
@@ -599,95 +592,95 @@
         FormulaRecord frec = rec.getFormulaRecord();
         frec.setOptions((short) 2);
         frec.setValue(0);
-        
+
         //only set to default if there is no extended format index already set
         if (rec.getXFIndex() == (short)0) {
-			rec.setXFIndex((short) 0x0f);
-		}
+            rec.setXFIndex((short) 0x0f);
+        }
         Ptg[] ptgs = FormulaParser.parse(formula, book);
         frec.setParsedExpression(ptgs);
     }
+    /* package */ void setFormulaOnly(Ptg[] ptgs) {
+        if (ptgs == null) {
+            throw new IllegalArgumentException("ptgs must not be null");
+        }
+        ((FormulaRecordAggregate)record).getFormulaRecord().setParsedExpression(ptgs);
+    }
 
     public String getCellFormula() {
         return FormulaParser.toFormulaString(book, ((FormulaRecordAggregate)record).getFormulaRecord().getParsedExpression());
     }
 
+    /**
+     * Used to help format error messages
+     */
+    private static String getCellTypeName(int cellTypeCode) {
+        switch (cellTypeCode) {
+            case CELL_TYPE_BLANK:   return "blank";
+            case CELL_TYPE_STRING:  return "text";
+            case CELL_TYPE_BOOLEAN: return "boolean";
+            case CELL_TYPE_ERROR:   return "error";
+            case CELL_TYPE_NUMERIC: return "numeric";
+            case CELL_TYPE_FORMULA: return "formula";
+        }
+        return "#unknown cell type (" + cellTypeCode + ")#";
+    }
+
+    private static RuntimeException typeMismatch(int expectedTypeCode, int actualTypeCode, boolean isFormulaCell) {
+        String msg = "Cannot get a "
+            + getCellTypeName(expectedTypeCode) + " value from a "
+            + getCellTypeName(actualTypeCode) + " " + (isFormulaCell ? "formula " : "") + "cell";
+        return new IllegalStateException(msg);
+    }
+    private static void checkFormulaCachedValueType(int expectedTypeCode, FormulaRecord fr) {
+        int cachedValueType = fr.getCachedResultType();
+        if (cachedValueType != expectedTypeCode) {
+            throw typeMismatch(expectedTypeCode, cachedValueType, true);
+        }
+    }
 
     /**
-     * Get the value of the cell as a number.  
+     * Get the value of the cell as a number.
      * For strings we throw an exception.
      * For blank cells we return a 0.
      * See {@link HSSFDataFormatter} for turning this
      *  number into a string similar to that which
-     *  Excel would render this number as. 
+     *  Excel would render this number as.
      */
-    public double getNumericCellValue()
-    {
-        if (cellType == CELL_TYPE_BLANK)
-        {
-            return 0;
-        }
-        if (cellType == CELL_TYPE_STRING)
-        {
-            throw new NumberFormatException(
-                "You cannot get a numeric value from a String based cell");
-        }
-        if (cellType == CELL_TYPE_BOOLEAN)
-        {
-            throw new NumberFormatException(
-                "You cannot get a numeric value from a boolean cell");
-        }
-        if (cellType == CELL_TYPE_ERROR)
-        {
-            throw new NumberFormatException(
-                "You cannot get a numeric value from an error cell");
-        }
-        if(cellType == CELL_TYPE_NUMERIC)
-        {
-          return ((NumberRecord)record).getValue();
-        }
-        if(cellType == CELL_TYPE_FORMULA)
-        {
-          return ((FormulaRecordAggregate)record).getFormulaRecord().getValue();
+    public double getNumericCellValue() {
+
+        switch(cellType) {
+            case CELL_TYPE_BLANK:
+                return 0.0;
+            case CELL_TYPE_NUMERIC:
+                return ((NumberRecord)record).getValue();
+            default:
+                throw typeMismatch(CELL_TYPE_NUMERIC, cellType, false);
+            case CELL_TYPE_FORMULA:
+                break;
         }
-        throw new NumberFormatException("Unknown Record Type in Cell:"+cellType);
+        FormulaRecord fr = ((FormulaRecordAggregate)record).getFormulaRecord();
+        checkFormulaCachedValueType(CELL_TYPE_NUMERIC, fr);
+        return fr.getValue();
     }
 
     /**
-     * Get the value of the cell as a date.  
+     * Get the value of the cell as a date.
      * For strings we throw an exception.
      * For blank cells we return a null.
      * See {@link HSSFDataFormatter} for formatting
      *  this date into a string similar to how excel does.
      */
-    public Date getDateCellValue()
-    {
-        if (cellType == CELL_TYPE_BLANK)
-        {
+    public Date getDateCellValue() {
+
+        if (cellType == CELL_TYPE_BLANK) {
             return null;
         }
-        if (cellType == CELL_TYPE_STRING)
-        {
-            throw new NumberFormatException(
-                "You cannot get a date value from a String based cell");
-        }
-        if (cellType == CELL_TYPE_BOOLEAN)
-        {
-            throw new NumberFormatException(
-                "You cannot get a date value from a boolean cell");
-        }
-        if (cellType == CELL_TYPE_ERROR)
-        {
-            throw new NumberFormatException(
-                "You cannot get a date value from an error cell");
-        }
-        double value=this.getNumericCellValue();
+        double value = getNumericCellValue();
         if (book.getWorkbook().isUsing1904DateWindowing()) {
-            return HSSFDateUtil.getJavaDate(value,true);
-        }
-        else {
-            return HSSFDateUtil.getJavaDate(value,false);
+            return HSSFDateUtil.getJavaDate(value, true);
         }
+        return HSSFDateUtil.getJavaDate(value, false);
     }
 
     /**
@@ -708,33 +701,22 @@
      * For blank cells we return an empty string.
      * For formulaCells that are not string Formulas, we return empty String
      */
+    public HSSFRichTextString getRichStringCellValue() {
 
-    public HSSFRichTextString getRichStringCellValue()
-    {
-        if (cellType == CELL_TYPE_BLANK)
-        {
-            return new HSSFRichTextString("");
-        }
-        if (cellType == CELL_TYPE_NUMERIC)
-        {
-            throw new NumberFormatException(
-                "You cannot get a string value from a numeric cell");
-        }
-        if (cellType == CELL_TYPE_BOOLEAN)
-        {
-            throw new NumberFormatException(
-                "You cannot get a string value from a boolean cell");
-        }
-        if (cellType == CELL_TYPE_ERROR)
-        {
-            throw new NumberFormatException(
-                "You cannot get a string value from an error cell");
-        }
-        if (cellType == CELL_TYPE_FORMULA) 
-        {
-            if (stringValue==null) return new HSSFRichTextString("");
+        switch(cellType) {
+            case CELL_TYPE_BLANK:
+                return new HSSFRichTextString("");
+            case CELL_TYPE_STRING:
+                return stringValue;
+            default:
+                throw typeMismatch(CELL_TYPE_STRING, cellType, false);
+            case CELL_TYPE_FORMULA:
+                break;
         }
-        return stringValue;
+        FormulaRecordAggregate fra = ((FormulaRecordAggregate)record);
+        checkFormulaCachedValueType(CELL_TYPE_STRING, fra.getFormulaRecord());
+        String strVal = fra.getStringValue();
+        return new HSSFRichTextString(strVal == null ? "" : strVal);
     }
 
     /**
@@ -745,47 +727,56 @@
      *        will change the cell to a boolean cell and set its value.
      */
 
-    public void setCellValue(boolean value)
-    {
+    public void setCellValue(boolean value) {
         int row=record.getRow();
         short col=record.getColumn();
         short styleIndex=record.getXFIndex();
-        if ((cellType != CELL_TYPE_BOOLEAN ) && ( cellType != CELL_TYPE_FORMULA))
-        {
-            setCellType(CELL_TYPE_BOOLEAN, false, row, col, styleIndex);
+
+        switch (cellType) {
+            default:
+                setCellType(CELL_TYPE_BOOLEAN, false, row, col, styleIndex);
+            case CELL_TYPE_ERROR:
+                (( BoolErrRecord ) record).setValue(value);
+                break;
+            case CELL_TYPE_FORMULA:
+                ((FormulaRecordAggregate)record).getFormulaRecord().setCachedResultBoolean(value);
+                break;
         }
-        (( BoolErrRecord ) record).setValue(value);
     }
 
     /**
      * set a error value for the cell
      *
-     * @param value the error value to set this cell to.  For formulas we'll set the
-     *        precalculated value ??? IS THIS RIGHT??? , for errors we'll set
+     * @param errorCode the error value to set this cell to.  For formulas we'll set the
+     *        precalculated value , for errors we'll set
      *        its value. For other types we will change the cell to an error
      *        cell and set its value.
      */
-
-    public void setCellErrorValue(byte value)
-    {
+    public void setCellErrorValue(byte errorCode) {
         int row=record.getRow();
         short col=record.getColumn();
         short styleIndex=record.getXFIndex();
-        if (cellType != CELL_TYPE_ERROR) {
-            setCellType(CELL_TYPE_ERROR, false, row, col, styleIndex);
+        switch (cellType) {
+            default:
+                setCellType(CELL_TYPE_ERROR, false, row, col, styleIndex);
+            case CELL_TYPE_ERROR:
+                (( BoolErrRecord ) record).setValue(errorCode);
+                break;
+            case CELL_TYPE_FORMULA:
+                ((FormulaRecordAggregate)record).getFormulaRecord().setCachedResultErrorCode(errorCode);
+                break;
         }
-        (( BoolErrRecord ) record).setValue(value);
     }
     /**
      * Chooses a new boolean value for the cell when its type is changing.<p/>
-     * 
-     * Usually the caller is calling setCellType() with the intention of calling 
+     *
+     * Usually the caller is calling setCellType() with the intention of calling
      * setCellValue(boolean) straight afterwards.  This method only exists to give
      * the cell a somewhat reasonable value until the setCellValue() call (if at all).
      * TODO - perhaps a method like setCellTypeAndValue(int, Object) should be introduced to avoid this
      */
     private boolean convertCellValueToBoolean() {
-        
+
         switch (cellType) {
             case CELL_TYPE_BOOLEAN:
                 return (( BoolErrRecord ) record).getBooleanValue();
@@ -796,11 +787,11 @@
 
             // All other cases convert to false
             // These choices are not well justified.
-            case CELL_TYPE_FORMULA:  
+            case CELL_TYPE_FORMULA:
                 // should really evaluate, but HSSFCell can't call HSSFFormulaEvaluator
             case CELL_TYPE_ERROR:
             case CELL_TYPE_BLANK:
-                return false;  
+                return false;
         }
         throw new RuntimeException("Unexpected cell type (" + cellType + ")");
     }
@@ -809,38 +800,39 @@
      * get the value of the cell as a boolean.  For strings, numbers, and errors, we throw an exception.
      * For blank cells we return a false.
      */
+    public boolean getBooleanCellValue() {
 
-    public boolean getBooleanCellValue()
-    {
-        if (cellType == CELL_TYPE_BOOLEAN)
-        {
-            return (( BoolErrRecord ) record).getBooleanValue();
-        }
-        if (cellType == CELL_TYPE_BLANK)
-        {
-            return false;
+        switch(cellType) {
+            case CELL_TYPE_BLANK:
+                return false;
+            case CELL_TYPE_BOOLEAN:
+                return (( BoolErrRecord ) record).getBooleanValue();
+            default:
+                throw typeMismatch(CELL_TYPE_BOOLEAN, cellType, false);
+            case CELL_TYPE_FORMULA:
+                break;
         }
-        throw new NumberFormatException(
-            "You cannot get a boolean value from a non-boolean cell");
+        FormulaRecord fr = ((FormulaRecordAggregate)record).getFormulaRecord();
+        checkFormulaCachedValueType(CELL_TYPE_BOOLEAN, fr);
+        return fr.getCachedBooleanValue();
     }
 
     /**
      * get the value of the cell as an error code.  For strings, numbers, and booleans, we throw an exception.
      * For blank cells we return a 0.
      */
-
-    public byte getErrorCellValue()
-    {
-        if (cellType == CELL_TYPE_ERROR)
-        {
-            return (( BoolErrRecord ) record).getErrorValue();
-        }
-        if (cellType == CELL_TYPE_BLANK)
-        {
-            return ( byte ) 0;
+    public byte getErrorCellValue() {
+        switch(cellType) {
+            case CELL_TYPE_ERROR:
+                return (( BoolErrRecord ) record).getErrorValue();
+            default:
+                throw typeMismatch(CELL_TYPE_ERROR, cellType, false);
+            case CELL_TYPE_FORMULA:
+                break;
         }
-        throw new NumberFormatException(
-            "You cannot get an error value from a non-error cell");
+        FormulaRecord fr = ((FormulaRecordAggregate)record).getFormulaRecord();
+        checkFormulaCachedValueType(CELL_TYPE_ERROR, fr);
+        return (byte) fr.getCachedErrorValue();
     }
 
     /**
@@ -897,7 +889,7 @@
           throw new RuntimeException("You cannot reference columns with an index of less then 0.");
       }
     }
-    
+
     /**
      * Sets this cell as the active cell for the worksheet
      */
@@ -905,45 +897,45 @@
     {
         int row=record.getRow();
         short col=record.getColumn();
-        this.sheet.setActiveCellRow(row);
-        this.sheet.setActiveCellCol(col);
+        this.sheet.getSheet().setActiveCellRow(row);
+        this.sheet.getSheet().setActiveCellCol(col);
     }
-    
+
     /**
      * Returns a string representation of the cell
-     * 
-     * This method returns a simple representation, 
+     *
+     * This method returns a simple representation,
      * anthing more complex should be in user code, with
-     * knowledge of the semantics of the sheet being processed. 
-     * 
-     * Formula cells return the formula string, 
-     * rather than the formula result. 
+     * knowledge of the semantics of the sheet being processed.
+     *
+     * Formula cells return the formula string,
+     * rather than the formula result.
      * Dates are displayed in dd-MMM-yyyy format
      * Errors are displayed as #ERR&lt;errIdx&gt;
      */
     public String toString() {
-    	switch (getCellType()) {
-    		case CELL_TYPE_BLANK:
-    			return "";
-    		case CELL_TYPE_BOOLEAN:
-    			return getBooleanCellValue()?"TRUE":"FALSE";
-    		case CELL_TYPE_ERROR:
-    			return ErrorEval.getText((( BoolErrRecord ) record).getErrorValue());
-    		case CELL_TYPE_FORMULA:
-    			return getCellFormula();
-    		case CELL_TYPE_NUMERIC:
-    			//TODO apply the dataformat for this cell
-    			if (HSSFDateUtil.isCellDateFormatted(this)) {
-    				DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
-    				return sdf.format(getDateCellValue());
-    			} else {
-    				return  getNumericCellValue() + "";
-    			}
-    		case CELL_TYPE_STRING:
-    			return getStringCellValue();
-    		default:
-    			return "Unknown Cell Type: " + getCellType();
-    	}
+        switch (getCellType()) {
+            case CELL_TYPE_BLANK:
+                return "";
+            case CELL_TYPE_BOOLEAN:
+                return getBooleanCellValue()?"TRUE":"FALSE";
+            case CELL_TYPE_ERROR:
+                return ErrorEval.getText((( BoolErrRecord ) record).getErrorValue());
+            case CELL_TYPE_FORMULA:
+                return getCellFormula();
+            case CELL_TYPE_NUMERIC:
+                //TODO apply the dataformat for this cell
+                if (HSSFDateUtil.isCellDateFormatted(this)) {
+                    DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
+                    return sdf.format(getDateCellValue());
+                } else {
+                    return  getNumericCellValue() + "";
+                }
+            case CELL_TYPE_STRING:
+                return getStringCellValue();
+            default:
+                return "Unknown Cell Type: " + getCellType();
+        }
     }
 
     /**
@@ -954,14 +946,14 @@
      * @param comment comment associated with this cell
      */
     public void setCellComment(Comment comment){
-    	if(comment == null) {
-    		removeCellComment();
-    		return;
-    	}
-
-        this.comment = (HSSFComment) comment;
-        this.comment.setRow((short)record.getRow());
-        this.comment.setColumn(record.getColumn());
+        if(comment == null) {
+            removeCellComment();
+            return;
+        }
+
+        comment.setRow((short)record.getRow());
+        comment.setColumn(record.getColumn());
+        this.comment = (HSSFComment)comment;
     }
 
     /**
@@ -971,11 +963,11 @@
      */
      public HSSFComment getCellComment(){
         if (comment == null) {
-            comment = findCellComment(sheet, record.getRow(), record.getColumn());
+            comment = findCellComment(sheet.getSheet(), record.getRow(), record.getColumn());
         }
         return comment;
     }
-     
+
     /**
      * Removes the comment for this cell, if
      *  there is one.
@@ -983,40 +975,41 @@
      *  all comments after performing this action!
      */
     public void removeCellComment() {
-    	HSSFComment comment = findCellComment(sheet, record.getRow(), record.getColumn());
-		this.comment = null;
-    	
-    	if(comment == null) {
-    		// Nothing to do
-    		return;
-    	}
-    	
-    	// Zap the underlying NoteRecord
-    	sheet.getRecords().remove(comment.getNoteRecord());
-    	
-    	// If we have a TextObjectRecord, is should
-    	//  be proceeed by:
-    	// MSODRAWING with container
-    	// OBJ
-    	// MSODRAWING with EscherTextboxRecord
-    	if(comment.getTextObjectRecord() != null) {
-    		TextObjectRecord txo = comment.getTextObjectRecord();
-    		int txoAt = sheet.getRecords().indexOf(txo);
-    		
-    		if(sheet.getRecords().get(txoAt-3) instanceof DrawingRecord &&
-    			sheet.getRecords().get(txoAt-2) instanceof ObjRecord &&
-    			sheet.getRecords().get(txoAt-1) instanceof DrawingRecord) {
-    			// Zap these, in reverse order
-    			sheet.getRecords().remove(txoAt-1);
-    			sheet.getRecords().remove(txoAt-2);
-    			sheet.getRecords().remove(txoAt-3);
-    		} else {
-    			throw new IllegalStateException("Found the wrong records before the TextObjectRecord, can't remove comment");
-    		}
-    		
-    		// Now remove the text record
-    		sheet.getRecords().remove(txo);
-    	}
+        HSSFComment comment = findCellComment(sheet.getSheet(), record.getRow(), record.getColumn());
+        this.comment = null;
+
+        if(comment == null) {
+            // Nothing to do
+            return;
+        }
+
+        // Zap the underlying NoteRecord
+        List sheetRecords = sheet.getSheet().getRecords();
+        sheetRecords.remove(comment.getNoteRecord());
+
+        // If we have a TextObjectRecord, is should
+        //  be proceeed by:
+        // MSODRAWING with container
+        // OBJ
+        // MSODRAWING with EscherTextboxRecord
+        if(comment.getTextObjectRecord() != null) {
+            TextObjectRecord txo = comment.getTextObjectRecord();
+            int txoAt = sheetRecords.indexOf(txo);
+
+            if(sheetRecords.get(txoAt-3) instanceof DrawingRecord &&
+                sheetRecords.get(txoAt-2) instanceof ObjRecord &&
+                sheetRecords.get(txoAt-1) instanceof DrawingRecord) {
+                // Zap these, in reverse order
+                sheetRecords.remove(txoAt-1);
+                sheetRecords.remove(txoAt-2);
+                sheetRecords.remove(txoAt-3);
+            } else {
+                throw new IllegalStateException("Found the wrong records before the TextObjectRecord, can't remove comment");
+            }
+
+            // Now remove the text record
+            sheetRecords.remove(txo);
+        }
     }
 
     /**
@@ -1070,7 +1063,7 @@
      * @return hyperlink associated with this cell or null if not found
      */
     public HSSFHyperlink getHyperlink(){
-        for (Iterator it = sheet.getRecords().iterator(); it.hasNext(); ) {
+        for (Iterator it = sheet.getSheet().getRecords().iterator(); it.hasNext(); ) {
             RecordBase rec = (RecordBase) it.next();
             if (rec instanceof HyperlinkRecord){
                 HyperlinkRecord link = (HyperlinkRecord)rec;
@@ -1108,7 +1101,19 @@
                 break;
         }
 
-        int eofLoc = sheet.findFirstRecordLocBySid( EOFRecord.sid );
-        sheet.getRecords().add( eofLoc, link.record );
+        int eofLoc = sheet.getSheet().findFirstRecordLocBySid( EOFRecord.sid );
+        sheet.getSheet().getRecords().add( eofLoc, link.record );
+    }
+    /**
+     * Only valid for formula cells
+     * @return one of ({@link #CELL_TYPE_NUMERIC}, {@link #CELL_TYPE_STRING},
+     *     {@link #CELL_TYPE_BOOLEAN}, {@link #CELL_TYPE_ERROR}) depending
+     * on the cached value of the formula
+     */
+    public int getCachedFormulaResultType() {
+        if (this.cellType != CELL_TYPE_FORMULA) {
+            throw new IllegalStateException("Only formula cells have cached results");
+        }
+        return ((FormulaRecordAggregate)record).getFormulaRecord().getCachedResultType();
     }
 }

Propchange: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFDataValidation.java
            ('svn:mergeinfo' removed)

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java Sat Sep 13 06:48:27 2008
@@ -31,6 +31,9 @@
     public HSSFFormulaEvaluator(HSSFSheet sheet, HSSFWorkbook workbook) {
     	super(sheet, workbook);
     }
+    public HSSFFormulaEvaluator(HSSFWorkbook workbook) {
+    	super(workbook);
+    }
 
     /**
      * Returns an underlying FormulaParser, for the specified

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java Sat Sep 13 06:48:27 2008
@@ -20,7 +20,6 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
-import org.apache.poi.hssf.model.Sheet;
 import org.apache.poi.hssf.record.CellValueRecordInterface;
 import org.apache.poi.hssf.record.RowRecord;
 import org.apache.poi.ss.usermodel.Cell;
@@ -55,7 +54,7 @@
     /**
      * reference to containing Sheet
      */
-    private Sheet sheet;
+    private HSSFSheet sheet;
 
     /**
      * Creates new HSSFRow from scratch. Only HSSFSheet should do this.
@@ -65,7 +64,7 @@
      * @param rowNum the row number of this row (0 based)
      * @see org.apache.poi.hssf.usermodel.HSSFSheet#createRow(int)
      */
-    HSSFRow(HSSFWorkbook book, Sheet sheet, int rowNum)
+    HSSFRow(HSSFWorkbook book, HSSFSheet sheet, int rowNum)
     {
         this.rowNum = rowNum;
         this.book = book;
@@ -84,7 +83,7 @@
      * @param record the low level api object this row should represent
      * @see org.apache.poi.hssf.usermodel.HSSFSheet#createRow(int)
      */
-    HSSFRow(HSSFWorkbook book, Sheet sheet, RowRecord record)
+    HSSFRow(HSSFWorkbook book, HSSFSheet sheet, RowRecord record)
     {
         this.book = book;
         this.sheet = sheet;
@@ -139,7 +138,7 @@
 
         HSSFCell cell = new HSSFCell(book, sheet, getRowNum(), shortCellNum, type);
         addCell(cell);
-        sheet.addValueRecord(getRowNum(), cell.getCellValueRecord());
+        sheet.getSheet().addValueRecord(getRowNum(), cell.getCellValueRecord());
         return cell;
     }
 
@@ -166,7 +165,7 @@
         
         if(alsoRemoveRecords) {
             CellValueRecordInterface cval = cell.getCellValueRecord();
-            sheet.removeValueRecord(getRowNum(), cval);
+            sheet.getSheet().removeValueRecord(getRowNum(), cval);
         }
         
         if (cell.getCellNum()+1 == row.getLastCol()) {
@@ -465,7 +464,7 @@
 
         //The low-order 15 bits contain the row height.
         //The 0x8000 bit indicates that the row is standard height (optional) 
-        if ((height & 0x8000) != 0) height = sheet.getDefaultRowHeight();
+        if ((height & 0x8000) != 0) height = sheet.getSheet().getDefaultRowHeight();
         else height &= 0x7FFF;
 
         return height;

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java Sat Sep 13 06:48:27 2008
@@ -207,7 +207,7 @@
      */
     public HSSFRow createRow(int rownum)
     {
-        HSSFRow row = new HSSFRow(workbook, sheet, rownum);
+        HSSFRow row = new HSSFRow(workbook, this, rownum);
 
         addRow(row, true);
         return row;
@@ -222,7 +222,7 @@
 
     private HSSFRow createRowFromRecord(RowRecord row)
     {
-        HSSFRow hrow = new HSSFRow(workbook, sheet, row);
+        HSSFRow hrow = new HSSFRow(workbook, this, row);
 
         addRow(hrow, false);
         return hrow;
@@ -390,7 +390,7 @@
         
         for(int index=0; index<records.size(); index++) {
            if(records.get(index) instanceof DVRecord) {
-        	   dvRecords.add(records.get(index));
+               dvRecords.add(records.get(index));
            }
         }
         return dvRecords;
@@ -1301,9 +1301,7 @@
                     // If any references were changed, then
                     //  re-create the formula string
                     if(changed) {
-                        c.setCellFormula(
-                             FormulaParser.toFormulaString(workbook, ptgs)
-                        );
+                        c.setFormulaOnly(ptgs);
                     }
                 }
             }
@@ -1602,14 +1600,32 @@
     }
 
     /**
+     * @deprecated (Sep 2008) use {@link #setColumnGroupCollapsed(int, boolean)}
+     */
+    public void setColumnGroupCollapsed(short columnNumber, boolean collapsed) {
+        setColumnGroupCollapsed(columnNumber & 0xFFFF, collapsed);
+    }
+    /**
+     * @deprecated (Sep 2008) use {@link #groupColumn(int, int)}
+     */
+    public void groupColumn(short fromColumn, short toColumn) {
+        groupColumn(fromColumn & 0xFFFF, toColumn & 0xFFFF);
+    }
+    /**
+     * @deprecated (Sep 2008) use {@link #ungroupColumn(int, int)}
+     */
+    public void ungroupColumn(short fromColumn, short toColumn) {
+        ungroupColumn(fromColumn & 0xFFFF, toColumn & 0xFFFF);
+    }
+
+    /**
      * Expands or collapses a column group.
      *
      * @param columnNumber      One of the columns in the group.
      * @param collapsed         true = collapse group, false = expand group.
      */
-    public void setColumnGroupCollapsed( short columnNumber, boolean collapsed )
-    {
-        sheet.setColumnGroupCollapsed( columnNumber, collapsed );
+    public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) {
+        sheet.setColumnGroupCollapsed(columnNumber, collapsed);
     }
 
     /**
@@ -1618,14 +1634,12 @@
      * @param fromColumn        beginning of the column range.
      * @param toColumn          end of the column range.
      */
-    public void groupColumn(short fromColumn, short toColumn)
-    {
-        sheet.groupColumnRange( fromColumn, toColumn, true );
+    public void groupColumn(int fromColumn, int toColumn) {
+        sheet.groupColumnRange(fromColumn, toColumn, true);
     }
 
-    public void ungroupColumn( short fromColumn, short toColumn )
-    {
-        sheet.groupColumnRange( fromColumn, toColumn, false );
+    public void ungroupColumn(int fromColumn, int toColumn) {
+        sheet.groupColumnRange(fromColumn, toColumn, false);
     }
 
     public void groupRow(int fromRow, int toRow)

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java Sat Sep 13 06:48:27 2008
@@ -661,6 +661,16 @@
         return -1;
     }
 
+    /* package */ int findSheetIndex(Sheet sheet) {
+        for(int i=0; i<_sheets.size(); i++) {
+            HSSFSheet hSheet = (HSSFSheet) _sheets.get(i);
+            if(hSheet.getSheet() == sheet) {
+                return i;
+            }
+        }
+        throw new IllegalArgumentException("Specified sheet not found in this workbook");
+    }
+
     /**
      * Returns the external sheet index of the sheet
      *  with the given internal index, creating one

Copied: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/LazyAreaEval.java (from r694881, poi/trunk/src/java/org/apache/poi/hssf/usermodel/LazyAreaEval.java)
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/LazyAreaEval.java?p2=poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/LazyAreaEval.java&p1=poi/trunk/src/java/org/apache/poi/hssf/usermodel/LazyAreaEval.java&r1=694881&r2=694947&rev=694947&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/LazyAreaEval.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/LazyAreaEval.java Sat Sep 13 06:48:27 2008
@@ -16,64 +16,14 @@
 ==================================================================== */
 
 package org.apache.poi.hssf.usermodel;
-
 import org.apache.poi.hssf.record.formula.AreaI;
-import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
-import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.AreaEvalBase;
-import org.apache.poi.hssf.record.formula.eval.BlankEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.hssf.util.CellReference;
 
 /**
  *
  * @author Josh Micich 
  */
-final class LazyAreaEval extends AreaEvalBase {
-
-	private final HSSFSheet _sheet;
-	private HSSFFormulaEvaluator _evaluator;
-
+final class LazyAreaEval extends org.apache.poi.ss.usermodel.LazyAreaEval {
 	public LazyAreaEval(AreaI ptg, HSSFSheet sheet, HSSFFormulaEvaluator evaluator) {
-		super(ptg);
-		_sheet = sheet;
-		_evaluator = evaluator;
-	}
-
-	public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) { 
-		
-		int rowIx = (relativeRowIndex + getFirstRow() ) & 0xFFFF;
-		int colIx = (relativeColumnIndex + getFirstColumn() ) & 0x00FF;
-		
-		HSSFRow row = _sheet.getRow(rowIx);
-		if (row == null) {
-			return BlankEval.INSTANCE;
-		}
-		HSSFCell cell = row.getCell(colIx);
-		if (cell == null) {
-			return BlankEval.INSTANCE;
-		}
-		return _evaluator.getEvalForCell(cell);
-	}
-
-	public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
-		AreaI area = new OffsetArea(getFirstRow(), getFirstColumn(),
-				relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
-
-		return new LazyAreaEval(area, _sheet, _evaluator);
-	}
-	public String toString() {
-		CellReference crA = new CellReference(getFirstRow(), getFirstColumn());
-		CellReference crB = new CellReference(getLastRow(), getLastColumn());
-		StringBuffer sb = new StringBuffer();
-		sb.append(getClass().getName()).append("[");
-		String sheetName = _evaluator.getSheetName(_sheet);
-		sb.append(sheetName);
-		sb.append('!');
-		sb.append(crA.formatAsString());
-		sb.append(':');
-		sb.append(crB.formatAsString());
-		sb.append("]");
-		return sb.toString();
+		super(ptg, sheet, evaluator);
 	}
 }

Copied: poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/LazyRefEval.java (from r694881, poi/trunk/src/java/org/apache/poi/hssf/usermodel/LazyRefEval.java)
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/LazyRefEval.java?p2=poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/LazyRefEval.java&p1=poi/trunk/src/java/org/apache/poi/hssf/usermodel/LazyRefEval.java&r1=694881&r2=694947&rev=694947&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/LazyRefEval.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/LazyRefEval.java Sat Sep 13 06:48:27 2008
@@ -16,70 +16,18 @@
 ==================================================================== */
 
 package org.apache.poi.hssf.usermodel;
-
-import org.apache.poi.hssf.record.formula.AreaI;
 import org.apache.poi.hssf.record.formula.Ref3DPtg;
 import org.apache.poi.hssf.record.formula.RefPtg;
-import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
-import org.apache.poi.hssf.record.formula.eval.AreaEval;
-import org.apache.poi.hssf.record.formula.eval.BlankEval;
-import org.apache.poi.hssf.record.formula.eval.RefEvalBase;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.hssf.util.CellReference;
 
 /**
 *
 * @author Josh Micich 
 */
-final class LazyRefEval extends RefEvalBase {
-
-	private final HSSFSheet _sheet;
-	private final HSSFFormulaEvaluator _evaluator;
-
-
+final class LazyRefEval extends org.apache.poi.ss.usermodel.LazyRefEval {
 	public LazyRefEval(RefPtg ptg, HSSFSheet sheet, HSSFFormulaEvaluator evaluator) {
-		super(ptg.getRow(), ptg.getColumn());
-		_sheet = sheet;
-		_evaluator = evaluator;
+		super(ptg, sheet, evaluator);
 	}
 	public LazyRefEval(Ref3DPtg ptg, HSSFSheet sheet, HSSFFormulaEvaluator evaluator) {
-		super(ptg.getRow(), ptg.getColumn());
-		_sheet = sheet;
-		_evaluator = evaluator;
-	}
-
-	public ValueEval getInnerValueEval() {
-		int rowIx = getRow();
-		int colIx = getColumn();
-		
-		HSSFRow row = _sheet.getRow(rowIx);
-		if (row == null) {
-			return BlankEval.INSTANCE;
-		}
-		HSSFCell cell = row.getCell(colIx);
-		if (cell == null) {
-			return BlankEval.INSTANCE;
-		}
-		return _evaluator.getEvalForCell(cell);
-	}
-	
-	public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
-		
-		AreaI area = new OffsetArea(getRow(), getColumn(),
-				relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
-
-		return new LazyAreaEval(area, _sheet, _evaluator);
-	}
-	
-	public String toString() {
-		CellReference cr = new CellReference(getRow(), getColumn());
-		StringBuffer sb = new StringBuffer();
-		sb.append(getClass().getName()).append("[");
-		String sheetName = _evaluator.getSheetName(_sheet);
-		sb.append(sheetName);
-		sb.append('!');
-		sb.append(cr.formatAsString());
-		sb.append("]");
-		return sb.toString();
+		super(ptg, sheet, evaluator);
 	}
 }

Propchange: poi/branches/ooxml/src/java/org/apache/poi/hssf/util/CellRangeAddressList.java
            ('svn:mergeinfo' removed)

Modified: poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/EvaluationCycleDetector.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/EvaluationCycleDetector.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/EvaluationCycleDetector.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/EvaluationCycleDetector.java Sat Sep 13 06:48:27 2008
@@ -20,12 +20,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-
 /**
  * Instances of this class keep track of multiple dependent cell evaluations due
- * to recursive calls to <tt>HSSFFormulaEvaluator.internalEvaluate()</tt>.
+ * to recursive calls to <tt>FormulaEvaluator.internalEvaluate()</tt>.
  * The main purpose of this class is to detect an attempt to evaluate a cell
  * that is already being evaluated. In other words, it detects circular
  * references in spreadsheet formulas.
@@ -40,19 +37,19 @@
 	private static final class CellEvaluationFrame {
 
 		private final Workbook _workbook;
-		private final Sheet _sheet;
+		private final int _sheetIndex;
 		private final int _srcRowNum;
 		private final int _srcColNum;
 
-		public CellEvaluationFrame(Workbook workbook, Sheet sheet, int srcRowNum, int srcColNum) {
+		public CellEvaluationFrame(Workbook workbook, int sheetIndex, int srcRowNum, int srcColNum) {
 			if (workbook == null) {
 				throw new IllegalArgumentException("workbook must not be null");
 			}
-			if (sheet == null) {
-				throw new IllegalArgumentException("sheet must not be null");
+			if (sheetIndex < 0) {
+				throw new IllegalArgumentException("sheetIndex must not be negative");
 			}
 			_workbook = workbook;
-			_sheet = sheet;
+			_sheetIndex = sheetIndex;
 			_srcRowNum = srcRowNum;
 			_srcColNum = srcColNum;
 		}
@@ -62,7 +59,7 @@
 			if (_workbook != other._workbook) {
 				return false;
 			}
-			if (_sheet != other._sheet) {
+			if (_sheetIndex != other._sheetIndex) {
 				return false;
 			}
 			if (_srcRowNum != other._srcRowNum) {
@@ -78,7 +75,7 @@
 		 * @return human readable string for debug purposes
 		 */
 		public String formatAsString() {
-			return "R=" + _srcRowNum + " C=" + _srcColNum + " ShIx=" + _workbook.getSheetIndex(_sheet);
+			return "R=" + _srcRowNum + " C=" + _srcColNum + " ShIx=" + _sheetIndex;
 		}
 
 		public String toString() {
@@ -111,8 +108,8 @@
 	 * @return <code>true</code> if the specified cell has not been visited yet in the current 
 	 * evaluation. <code>false</code> if the specified cell is already being evaluated.
 	 */
-	public boolean startEvaluate(Workbook workbook, Sheet sheet, int srcRowNum, int srcColNum) {
-		CellEvaluationFrame cef = new CellEvaluationFrame(workbook, sheet, srcRowNum, srcColNum);
+	public boolean startEvaluate(Workbook workbook, int sheetIndex, int srcRowNum, int srcColNum) {
+		CellEvaluationFrame cef = new CellEvaluationFrame(workbook, sheetIndex, srcRowNum, srcColNum);
 		if (_evaluationFrames.contains(cef)) {
 			return false;
 		}
@@ -132,7 +129,7 @@
 	 * required. However, they have been included to assert correct behaviour,
 	 * and form more meaningful error messages.
 	 */
-	public void endEvaluate(Workbook workbook, Sheet sheet, int srcRowNum, int srcColNum) {
+	public void endEvaluate(Workbook workbook, int sheetIndex, int srcRowNum, int srcColNum) {
 		int nFrames = _evaluationFrames.size();
 		if (nFrames < 1) {
 			throw new IllegalStateException("Call to endEvaluate without matching call to startEvaluate");
@@ -140,7 +137,7 @@
 
 		nFrames--;
 		CellEvaluationFrame cefExpected = (CellEvaluationFrame) _evaluationFrames.get(nFrames);
-		CellEvaluationFrame cefActual = new CellEvaluationFrame(workbook, sheet, srcRowNum, srcColNum);
+		CellEvaluationFrame cefActual = new CellEvaluationFrame(workbook, sheetIndex, srcRowNum, srcColNum);
 		if (!cefActual.equals(cefExpected)) {
 			throw new RuntimeException("Wrong cell specified. "
 					+ "Corresponding startEvaluate() call was for cell {"

Modified: poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java Sat Sep 13 06:48:27 2008
@@ -20,9 +20,6 @@
 import java.util.Iterator;
 import java.util.Stack;
 
-import org.apache.poi.ss.util.AreaReference;
-import org.apache.poi.ss.util.CellReference;
-
 import org.apache.poi.hssf.model.FormulaParser;
 import org.apache.poi.hssf.record.NameRecord;
 import org.apache.poi.hssf.record.formula.Area3DPtg;
@@ -49,8 +46,6 @@
 import org.apache.poi.hssf.record.formula.eval.ErrorEval;
 import org.apache.poi.hssf.record.formula.eval.Eval;
 import org.apache.poi.hssf.record.formula.eval.FunctionEval;
-import org.apache.poi.hssf.record.formula.eval.LazyAreaEval;
-import org.apache.poi.hssf.record.formula.eval.LazyRefEval;
 import org.apache.poi.hssf.record.formula.eval.NameEval;
 import org.apache.poi.hssf.record.formula.eval.NameXEval;
 import org.apache.poi.hssf.record.formula.eval.NumberEval;
@@ -58,6 +53,7 @@
 import org.apache.poi.hssf.record.formula.eval.RefEval;
 import org.apache.poi.hssf.record.formula.eval.StringEval;
 import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.hssf.util.CellReference;
 
 /**
  * Evaluates formula cells.<p/>
@@ -70,29 +66,37 @@
  * @author Josh Micich
  */
 public class FormulaEvaluator {
-	/**
-	 * used to track the number of evaluations
-	 */
+
+    /**
+     * used to track the number of evaluations
+     */
     private static final class Counter {
         public int value;
+        public int depth;
         public Counter() {
             value = 0;
         }
     }
 
-    protected Sheet _sheet;
-    protected Workbook _workbook;
+    protected final Workbook _workbook;
     private final EvaluationCache _cache;
 
     private Counter _evaluationCounter;
 
-
+    /**
+     * @deprecated (Sep 2008) Sheet parameter is ignored
+     */
     public FormulaEvaluator(Sheet sheet, Workbook workbook) {
-        this(sheet, workbook, new EvaluationCache(), new Counter());
+        this(workbook);
+        if (false) {
+            sheet.toString(); // suppress unused parameter compiler warning
+        }
+    }
+    public FormulaEvaluator(Workbook workbook) {
+        this(workbook, new EvaluationCache(), new Counter());
     }
-    
-    private FormulaEvaluator(Sheet sheet, Workbook workbook, EvaluationCache cache, Counter evaluationCounter) {
-        _sheet = sheet;
+
+    private FormulaEvaluator(Workbook workbook, EvaluationCache cache, Counter evaluationCounter) {
         _workbook = workbook;
         _cache = cache;
         _evaluationCounter = evaluationCounter;
@@ -140,7 +144,6 @@
         _cache.clear();
     }
 
-
     /**
      * If cell contains a formula, the formula is evaluated and returned,
      * else the CellValue simply copies the appropriate cell value from
@@ -150,34 +153,23 @@
      * @param cell
      */
     public CellValue evaluate(Cell cell) {
-        CellValue retval = null;
-        if (cell != null) {
-            switch (cell.getCellType()) {
-            case Cell.CELL_TYPE_BLANK:
-                retval = new CellValue(Cell.CELL_TYPE_BLANK, _workbook.getCreationHelper());
-                break;
+        if (cell == null) {
+            return null;
+        }
+        
+        switch (cell.getCellType()) {
             case Cell.CELL_TYPE_BOOLEAN:
-                retval = new CellValue(Cell.CELL_TYPE_BOOLEAN, _workbook.getCreationHelper());
-                retval.setBooleanValue(cell.getBooleanCellValue());
-                break;
+                return CellValue.valueOf(cell.getBooleanCellValue());
             case Cell.CELL_TYPE_ERROR:
-                retval = new CellValue(Cell.CELL_TYPE_ERROR, _workbook.getCreationHelper());
-                retval.setErrorValue(cell.getErrorCellValue());
-                break;
+                return CellValue.getError(cell.getErrorCellValue());
             case Cell.CELL_TYPE_FORMULA:
-                retval = getCellValueForEval(internalEvaluate(cell, _sheet), _workbook.getCreationHelper());
-                break;
+                return evaluateFormulaCellValue(cell);
             case Cell.CELL_TYPE_NUMERIC:
-                retval = new CellValue(Cell.CELL_TYPE_NUMERIC, _workbook.getCreationHelper());
-                retval.setNumberValue(cell.getNumericCellValue());
-                break;
+                return new CellValue(cell.getNumericCellValue(), _workbook.getCreationHelper());
             case Cell.CELL_TYPE_STRING:
-                retval = new CellValue(Cell.CELL_TYPE_STRING, _workbook.getCreationHelper());
-                retval.setRichTextStringValue(cell.getRichStringCellValue());
-                break;
-            }
+                return new CellValue(cell.getRichStringCellValue().getString(), _workbook.getCreationHelper());
         }
-        return retval;
+        throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");
     }
 
 
@@ -200,32 +192,13 @@
      * @return The type of the formula result (the cell's type remains as Cell.CELL_TYPE_FORMULA however)
      */
     public int evaluateFormulaCell(Cell cell) {
-        if (cell != null) {
-            switch (cell.getCellType()) {
-            case Cell.CELL_TYPE_FORMULA:
-                CellValue cv = getCellValueForEval(internalEvaluate(cell, _sheet), _workbook.getCreationHelper());
-                switch (cv.getCellType()) {
-                case Cell.CELL_TYPE_BOOLEAN:
-                    cell.setCellValue(cv.getBooleanValue());
-                    break;
-                case Cell.CELL_TYPE_ERROR:
-                    cell.setCellValue(cv.getErrorValue());
-                    break;
-                case Cell.CELL_TYPE_NUMERIC:
-                    cell.setCellValue(cv.getNumberValue());
-                    break;
-                case Cell.CELL_TYPE_STRING:
-                    cell.setCellValue(cv.getRichTextStringValue());
-                    break;
-                case Cell.CELL_TYPE_BLANK:
-                    break;
-                case Cell.CELL_TYPE_FORMULA: // this will never happen, we have already evaluated the formula
-                    break;
-                }
-                return cv.getCellType();
-            }
+        if (cell == null || cell.getCellType() != Cell.CELL_TYPE_FORMULA) {
+            return -1;
         }
-        return -1;
+        CellValue cv = evaluateFormulaCellValue(cell);
+        // cell remains a formula cell, but the cached value is changed
+        setCellValue(cell, cv);
+        return cv.getCellType();
     }
 
     /**
@@ -245,35 +218,56 @@
      * @param cell
      */
     public Cell evaluateInCell(Cell cell) {
-        if (cell != null) {
-            switch (cell.getCellType()) {
-            case Cell.CELL_TYPE_FORMULA:
-                CellValue cv = getCellValueForEval(internalEvaluate(cell, _sheet), _workbook.getCreationHelper());
-                switch (cv.getCellType()) {
-                case Cell.CELL_TYPE_BOOLEAN:
-                    cell.setCellType(Cell.CELL_TYPE_BOOLEAN);
-                    cell.setCellValue(cv.getBooleanValue());
-                    break;
-                case Cell.CELL_TYPE_ERROR:
-                    cell.setCellErrorValue(cv.getErrorValue());
-                    break;
-                case Cell.CELL_TYPE_NUMERIC:
-                    cell.setCellType(Cell.CELL_TYPE_NUMERIC);
-                    cell.setCellValue(cv.getNumberValue());
-                    break;
-                case Cell.CELL_TYPE_STRING:
-                    cell.setCellType(Cell.CELL_TYPE_STRING);
-                    cell.setCellValue(cv.getRichTextStringValue());
-                    break;
-                case Cell.CELL_TYPE_BLANK:
-                    break;
-                case Cell.CELL_TYPE_FORMULA: // this will never happen, we have already evaluated the formula
-                    break;
-                }
-            }
+        if (cell == null) {
+            return null;
+        }
+        if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
+            CellValue cv = evaluateFormulaCellValue(cell);
+            setCellType(cell, cv); // cell will no longer be a formula cell
+            setCellValue(cell, cv);
         }
         return cell;
     }
+    private static void setCellType(Cell cell, CellValue cv) {
+        int cellType = cv.getCellType();
+        switch (cellType) {
+            case Cell.CELL_TYPE_BOOLEAN:
+            case Cell.CELL_TYPE_ERROR:
+            case Cell.CELL_TYPE_NUMERIC:
+            case Cell.CELL_TYPE_STRING:
+                cell.setCellType(cellType);
+                return;
+            case Cell.CELL_TYPE_BLANK:
+                // never happens - blanks eventually get translated to zero
+            case Cell.CELL_TYPE_FORMULA:
+                // this will never happen, we have already evaluated the formula
+        }
+        throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
+    }
+
+    private static void setCellValue(Cell cell, CellValue cv) {
+        int cellType = cv.getCellType();
+        switch (cellType) {
+            case Cell.CELL_TYPE_BOOLEAN:
+                cell.setCellValue(cv.getBooleanValue());
+                break;
+            case Cell.CELL_TYPE_ERROR:
+                cell.setCellErrorValue(cv.getErrorValue());
+                break;
+            case Cell.CELL_TYPE_NUMERIC:
+                cell.setCellValue(cv.getNumberValue());
+                break;
+            case Cell.CELL_TYPE_STRING:
+                cell.setCellValue(cv.getRichTextStringValue());
+                break;
+            case Cell.CELL_TYPE_BLANK:
+                // never happens - blanks eventually get translated to zero
+            case Cell.CELL_TYPE_FORMULA:
+                // this will never happen, we have already evaluated the formula
+            default:
+                throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
+        }
+    }
 
     /**
      * Loops over all cells in all sheets of the supplied
@@ -287,9 +281,9 @@
      *  cells, and calling evaluateFormulaCell on each one.
      */
     public static void evaluateAllFormulaCells(Workbook wb) {
+        FormulaEvaluator evaluator = new FormulaEvaluator(wb);
         for(int i=0; i<wb.getNumberOfSheets(); i++) {
             Sheet sheet = wb.getSheetAt(i);
-            FormulaEvaluator evaluator = new FormulaEvaluator(sheet, wb);
 
             for (Iterator rit = sheet.rowIterator(); rit.hasNext();) {
                 Row r = (Row)rit.next();
@@ -303,72 +297,61 @@
         }
     }
 
-
     /**
      * Returns a CellValue wrapper around the supplied ValueEval instance.
      * @param eval
      */
-    private static CellValue getCellValueForEval(ValueEval eval, CreationHelper cHelper) {
-        CellValue retval = null;
-        if (eval != null) {
-            if (eval instanceof NumberEval) {
-                NumberEval ne = (NumberEval) eval;
-                retval = new CellValue(Cell.CELL_TYPE_NUMERIC, cHelper);
-                retval.setNumberValue(ne.getNumberValue());
-            }
-            else if (eval instanceof BoolEval) {
-                BoolEval be = (BoolEval) eval;
-                retval = new CellValue(Cell.CELL_TYPE_BOOLEAN, cHelper);
-                retval.setBooleanValue(be.getBooleanValue());
-            }
-            else if (eval instanceof StringEval) {
-                StringEval ne = (StringEval) eval;
-                retval = new CellValue(Cell.CELL_TYPE_STRING, cHelper);
-                retval.setStringValue(ne.getStringValue());
-            }
-            else if (eval instanceof BlankEval) {
-                retval = new CellValue(Cell.CELL_TYPE_BLANK, cHelper);
-            }
-            else if (eval instanceof ErrorEval) {
-                retval = new CellValue(Cell.CELL_TYPE_ERROR, cHelper);
-                retval.setErrorValue((byte)((ErrorEval)eval).getErrorCode());
-//                retval.setRichTextStringValue(new RichTextString("#An error occurred. check cell.getErrorCode()"));
-            }
-            else {
-                retval = new CellValue(Cell.CELL_TYPE_ERROR, cHelper);
-            }
+    private CellValue evaluateFormulaCellValue(Cell cell) {
+        ValueEval eval = internalEvaluate(cell);
+        if (eval instanceof NumberEval) {
+            NumberEval ne = (NumberEval) eval;
+            return new CellValue(ne.getNumberValue(), _workbook.getCreationHelper());
+        }
+        if (eval instanceof BoolEval) {
+            BoolEval be = (BoolEval) eval;
+            return CellValue.valueOf(be.getBooleanValue());
+        }
+        if (eval instanceof StringEval) {
+            StringEval ne = (StringEval) eval;
+            return new CellValue(ne.getStringValue(), _workbook.getCreationHelper());
+        }
+        if (eval instanceof ErrorEval) {
+            return CellValue.getError(((ErrorEval)eval).getErrorCode());
         }
-        return retval;
+        throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")");
     }
 
     /**
      * Dev. Note: Internal evaluate must be passed only a formula cell
      * else a runtime exception will be thrown somewhere inside the method.
      * (Hence this is a private method.)
+     * @return never <code>null</code>, never {@link BlankEval}
      */
-    private ValueEval internalEvaluate(Cell srcCell, Sheet sheet) {
+    private ValueEval internalEvaluate(Cell srcCell) {
         int srcRowNum = srcCell.getRowIndex();
         int srcColNum = srcCell.getCellNum();
 
         ValueEval result;
 
-        int sheetIndex = _workbook.getSheetIndex(sheet);
+        int sheetIndex = _workbook.getSheetIndex(srcCell.getSheet());
         result = _cache.getValue(sheetIndex, srcRowNum, srcColNum);
         if (result != null) {
-           return result;
+            return result;
         }
         _evaluationCounter.value++;
+        _evaluationCounter.depth++;
 
         EvaluationCycleDetector tracker = EvaluationCycleDetectorManager.getTracker();
 
-        if(!tracker.startEvaluate(_workbook, sheet, srcRowNum, srcColNum)) {
+        if(!tracker.startEvaluate(_workbook, sheetIndex, srcRowNum, srcColNum)) {
             return ErrorEval.CIRCULAR_REF_ERROR;
         }
         try {
-            result = evaluateCell(srcRowNum, (short)srcColNum, srcCell.getCellFormula());
+            result = evaluateCell(sheetIndex, srcRowNum, (short)srcColNum, srcCell.getCellFormula());
         } finally {
-            tracker.endEvaluate(_workbook, sheet, srcRowNum, srcColNum);
+            tracker.endEvaluate(_workbook, sheetIndex, srcRowNum, srcColNum);
             _cache.setValue(sheetIndex, srcRowNum, srcColNum, result);
+            _evaluationCounter.depth--;
         }
         if (isDebugLogEnabled()) {
             String sheetName = _workbook.getSheetName(sheetIndex);
@@ -377,7 +360,7 @@
         }
         return result;
     }
-    private ValueEval evaluateCell(int srcRowNum, short srcColNum, String cellFormulaText) {
+    private ValueEval evaluateCell(int sheetIndex, int srcRowNum, short srcColNum, String cellFormulaText) {
 
         Ptg[] ptgs = FormulaParser.parse(cellFormulaText, _workbook);
 
@@ -392,8 +375,8 @@
             }
             if (ptg instanceof MemErrPtg) { continue; }
             if (ptg instanceof MissingArgPtg) {
-               // TODO - might need to push BlankEval or MissingArgEval
-               continue;
+                // TODO - might need to push BlankEval or MissingArgEval
+                continue;
             }
             Eval opResult;
             if (ptg instanceof OperationPtg) {
@@ -411,15 +394,15 @@
                     Eval p = (Eval) stack.pop();
                     ops[j] = p;
                 }
-                logDebug("invoke " + operation + " (nAgs=" + numops + ")");
-                opResult = invokeOperation(operation, ops, srcRowNum, srcColNum, _workbook, _sheet);
+//                logDebug("invoke " + operation + " (nAgs=" + numops + ")");
+                opResult = invokeOperation(operation, ops, _workbook, sheetIndex, srcRowNum, srcColNum);
             } else {
-                opResult = getEvalForPtg(ptg, _sheet);
+                opResult = getEvalForPtg(ptg, sheetIndex);
             }
             if (opResult == null) {
                 throw new RuntimeException("Evaluation result must not be null");
             }
-            logDebug("push " + opResult);
+//            logDebug("push " + opResult);
             stack.push(opResult);
         }
 
@@ -428,7 +411,7 @@
             throw new IllegalStateException("evaluation stack not empty");
         }
         value = dereferenceValue(value, srcRowNum, srcColNum);
-        if (value instanceof BlankEval) {
+        if (value == BlankEval.INSTANCE) {
             // Note Excel behaviour here. A blank final final value is converted to zero.
             return NumberEval.ZERO;
             // Formulas _never_ evaluate to blank.  If a formula appears to have evaluated to
@@ -464,24 +447,21 @@
         return evaluationResult;
     }
 
-    private static Eval invokeOperation(OperationEval operation, Eval[] ops, int srcRowNum, short srcColNum,
-            Workbook workbook, Sheet sheet) {
+    private static Eval invokeOperation(OperationEval operation, Eval[] ops, 
+            Workbook workbook, int sheetIndex, int srcRowNum, int srcColNum) {
 
         if(operation instanceof FunctionEval) {
             FunctionEval fe = (FunctionEval) operation;
             if(fe.isFreeRefFunction()) {
-                return fe.getFreeRefFunction().evaluate(ops, srcRowNum, srcColNum, workbook, sheet);
+                return fe.getFreeRefFunction().evaluate(ops, workbook, sheetIndex, srcRowNum, srcColNum);
             }
         }
-        return operation.evaluate(ops, srcRowNum, srcColNum);
+        return operation.evaluate(ops, srcRowNum, (short)srcColNum);
     }
 
     private Sheet getOtherSheet(int externSheetIndex) {
         return _workbook.getSheetAt(_workbook.getSheetIndexFromExternSheetIndex(externSheetIndex));
     }
-    private FormulaEvaluator createEvaluatorForAnotherSheet(Sheet sheet) {
-        return new FormulaEvaluator(sheet, _workbook, _cache, _evaluationCounter);
-    }
 
     /**
      * returns an appropriate Eval impl instance for the Ptg. The Ptg must be
@@ -489,7 +469,7 @@
      * StringPtg, BoolPtg <br/>special Note: OperationPtg subtypes cannot be
      * passed here!
      */
-    private Eval getEvalForPtg(Ptg ptg, Sheet sheet) {
+    private Eval getEvalForPtg(Ptg ptg, int sheetIndex) {
         if (ptg instanceof NamePtg) {
             // named ranges, macro functions
             NamePtg namePtg = (NamePtg) ptg;
@@ -499,41 +479,23 @@
                 throw new RuntimeException("Bad name index (" + nameIndex
                         + "). Allowed range is (0.." + (numberOfNames-1) + ")");
             }
-            if(_workbook instanceof org.apache.poi.hssf.usermodel.HSSFWorkbook) { 
-				org.apache.poi.hssf.usermodel.HSSFWorkbook hssfWb = 
-					(org.apache.poi.hssf.usermodel.HSSFWorkbook)_workbook;
-				NameRecord nameRecord = hssfWb.getNameRecord(nameIndex);
+			if(_workbook instanceof org.apache.poi.hssf.usermodel.HSSFWorkbook) {
+				NameRecord nameRecord = ((org.apache.poi.hssf.usermodel.HSSFWorkbook)_workbook).getNameRecord(nameIndex);
 				if (nameRecord.isFunctionName()) {
 					return new NameEval(nameRecord.getNameText());
 				}
 				if (nameRecord.hasFormula()) {
-					return evaluateNameFormula(nameRecord.getNameDefinition(), sheet);
+					return evaluateNameFormula(nameRecord.getNameDefinition(), sheetIndex);
 				}
-				throw new RuntimeException("Don't know how to evalate name '" + nameRecord.getNameText() + "'");
-			} else {
-				throw new RuntimeException("Don't know how to evaluate name records for XSSF");
+
+				throw new RuntimeException("Don't now how to evalate name '" + nameRecord.getNameText() + "'");
 			}
+			throw new RuntimeException("Don't now how to evalate name for XSSFWorkbook");
         }
         if (ptg instanceof NameXPtg) {
             NameXPtg nameXPtg = (NameXPtg) ptg;
             return new NameXEval(nameXPtg.getSheetRefIndex(), nameXPtg.getNameIndex());
         }
-        if (ptg instanceof RefPtg) {
-            return new LazyRefEval(((RefPtg) ptg), sheet, this);
-        }
-        if (ptg instanceof Ref3DPtg) {
-            Ref3DPtg refPtg = (Ref3DPtg) ptg;
-            Sheet xsheet = getOtherSheet(refPtg.getExternSheetIndex());
-            return new LazyRefEval(refPtg, xsheet, createEvaluatorForAnotherSheet(xsheet));
-        }
-        if (ptg instanceof AreaPtg) {
-            return new LazyAreaEval(((AreaPtg) ptg), sheet, this);
-        }
-        if (ptg instanceof Area3DPtg) {
-            Area3DPtg a3dp = (Area3DPtg) ptg;
-            Sheet xsheet = getOtherSheet(a3dp.getExternSheetIndex());
-            return new LazyAreaEval(a3dp, xsheet, createEvaluatorForAnotherSheet(xsheet));
-        }
 
         if (ptg instanceof IntPtg) {
             return new NumberEval(((IntPtg)ptg).getValue());
@@ -550,17 +512,38 @@
         if (ptg instanceof ErrPtg) {
             return ErrorEval.valueOf(((ErrPtg) ptg).getErrorCode());
         }
+        Sheet sheet = _workbook.getSheetAt(sheetIndex);
+        if (ptg instanceof RefPtg) {
+            return new LazyRefEval(((RefPtg) ptg), sheet, this);
+        }
+        if (ptg instanceof AreaPtg) {
+            return new LazyAreaEval(((AreaPtg) ptg), sheet, this);
+        }
+        if (ptg instanceof Ref3DPtg) {
+            Ref3DPtg refPtg = (Ref3DPtg) ptg;
+            Sheet xsheet = getOtherSheet(refPtg.getExternSheetIndex());
+            return new LazyRefEval(refPtg, xsheet, this);
+        }
+        if (ptg instanceof Area3DPtg) {
+            Area3DPtg a3dp = (Area3DPtg) ptg;
+            Sheet xsheet = getOtherSheet(a3dp.getExternSheetIndex());
+            return new LazyAreaEval(a3dp, xsheet, this);
+        }
+
         if (ptg instanceof UnknownPtg) {
-            // TODO - remove UnknownPtg
+            // POI uses UnknownPtg when the encoded Ptg array seems to be corrupted.
+            // This seems to occur in very rare cases (e.g. unused name formulas in bug 44774, attachment 21790)
+            // In any case, formulas are re-parsed before execution, so UnknownPtg should not get here 
             throw new RuntimeException("UnknownPtg not allowed");
         }
+        
         throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")");
     }
-    private Eval evaluateNameFormula(Ptg[] ptgs, Sheet sheet) {
+    private Eval evaluateNameFormula(Ptg[] ptgs, int sheetIndex) {
         if (ptgs.length > 1) {
             throw new RuntimeException("Complex name formulas not supported yet");
         }
-        return getEvalForPtg(ptgs[0], sheet);
+        return getEvalForPtg(ptgs[0], sheetIndex);
     }
 
     /**
@@ -568,11 +551,8 @@
      * impl instance and return that. Since the cell could be an external
      * reference, we need the sheet that this belongs to.
      * Non existent cells are treated as empty.
-     * @param cell
-     * @param sheet
-     * @param workbook
      */
-    public ValueEval getEvalForCell(Cell cell, Sheet sheet) {
+    public ValueEval getEvalForCell(Cell cell) {
 
         if (cell == null) {
             return BlankEval.INSTANCE;
@@ -583,7 +563,7 @@
             case Cell.CELL_TYPE_STRING:
                 return new StringEval(cell.getRichStringCellValue().getString());
             case Cell.CELL_TYPE_FORMULA:
-                return internalEvaluate(cell, sheet);
+                return internalEvaluate(cell);
             case Cell.CELL_TYPE_BOOLEAN:
                 return BoolEval.valueOf(cell.getBooleanCellValue());
             case Cell.CELL_TYPE_BLANK:
@@ -600,93 +580,99 @@
      * or Number or boolean type.
      * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
      */
-    public static class CellValue {
-        private CreationHelper creationHelper;
-        private int cellType;
-        private RichTextString richTextStringValue;
-        private double numberValue;
-        private boolean booleanValue;
-        private byte errorValue;
-
-        /**
-         * CellType should be one of the types defined in Cell
-         * @param cellType
-         */
-        public CellValue(int cellType, CreationHelper creationHelper) {
-            super();
-            this.creationHelper = creationHelper;
-            this.cellType = cellType;
+    public static final class CellValue {
+        public static final CellValue TRUE = new CellValue(Cell.CELL_TYPE_BOOLEAN, 0.0, true,  null, 0, null);
+        public static final CellValue FALSE= new CellValue(Cell.CELL_TYPE_BOOLEAN, 0.0, false, null, 0, null);
+        
+        private final int _cellType;
+        private final double _numberValue;
+        private final boolean _booleanValue;
+        private final String _textValue;
+        private final int _errorCode;
+		private CreationHelper _creationHelper;
+
+        private CellValue(int cellType, double numberValue, boolean booleanValue, 
+                String textValue, int errorCode, CreationHelper creationHelper) {
+            _cellType = cellType;
+            _numberValue = numberValue;
+            _booleanValue = booleanValue;
+            _textValue = textValue;
+            _errorCode = errorCode;
+			_creationHelper = creationHelper;
+        }
+        
+        
+        /* package*/ CellValue(double numberValue, CreationHelper creationHelper) {
+            this(Cell.CELL_TYPE_NUMERIC, numberValue, false, null, 0, creationHelper);
+        }
+        /* package*/ static CellValue valueOf(boolean booleanValue) {
+            return booleanValue ? TRUE : FALSE;
         }
+        /* package*/ CellValue(String stringValue, CreationHelper creationHelper) {
+            this(Cell.CELL_TYPE_STRING, 0.0, false, stringValue, 0, creationHelper);
+        }
+        /* package*/ static CellValue getError(int errorCode) {
+            return new CellValue(Cell.CELL_TYPE_ERROR, 0.0, false, null, errorCode, null);
+        }
+        
+        
         /**
          * @return Returns the booleanValue.
          */
         public boolean getBooleanValue() {
-            return booleanValue;
-        }
-        /**
-         * @param booleanValue The booleanValue to set.
-         */
-        public void setBooleanValue(boolean booleanValue) {
-            this.booleanValue = booleanValue;
+            return _booleanValue;
         }
         /**
          * @return Returns the numberValue.
          */
         public double getNumberValue() {
-            return numberValue;
-        }
-        /**
-         * @param numberValue The numberValue to set.
-         */
-        public void setNumberValue(double numberValue) {
-            this.numberValue = numberValue;
+            return _numberValue;
         }
         /**
-         * @return Returns the stringValue. This method is deprecated, use
-         * getRichTextStringValue instead
-         * @deprecated
+         * @return Returns the stringValue.
          */
         public String getStringValue() {
-            return richTextStringValue.getString();
-        }
-        /**
-         * @param stringValue The stringValue to set. This method is deprecated, use
-         * getRichTextStringValue instead.
-         * @deprecated
-         */
-        public void setStringValue(String stringValue) {
-            this.richTextStringValue = 
-                  creationHelper.createRichTextString(stringValue);
+            return _textValue;
         }
         /**
          * @return Returns the cellType.
          */
         public int getCellType() {
-            return cellType;
+            return _cellType;
         }
         /**
          * @return Returns the errorValue.
          */
         public byte getErrorValue() {
-            return errorValue;
-        }
-        /**
-         * @param errorValue The errorValue to set.
-         */
-        public void setErrorValue(byte errorValue) {
-            this.errorValue = errorValue;
+            return (byte) _errorCode;
         }
         /**
          * @return Returns the richTextStringValue.
+         * @deprecated (Sep 2008) Text formatting is lost during formula evaluation.  Use {@link #getStringValue()}  
          */
         public RichTextString getRichTextStringValue() {
-            return richTextStringValue;
+            return _creationHelper.createRichTextString(_textValue);
         }
-        /**
-         * @param richTextStringValue The richTextStringValue to set.
-         */
-        public void setRichTextStringValue(RichTextString richTextStringValue) {
-            this.richTextStringValue = richTextStringValue;
+        public String toString() {
+            StringBuffer sb = new StringBuffer(64);
+            sb.append(getClass().getName()).append(" [");
+            sb.append(formatAsString());
+            sb.append("]");
+            return sb.toString();
+        }
+
+        public String formatAsString() {
+            switch (_cellType) {
+                case Cell.CELL_TYPE_NUMERIC:
+                    return String.valueOf(_numberValue);
+                case Cell.CELL_TYPE_STRING:
+                    return '"' + _textValue + '"';
+                case Cell.CELL_TYPE_BOOLEAN:
+                    return _booleanValue ? "TRUE" : "FALSE";
+                case Cell.CELL_TYPE_ERROR:
+                    return ErrorEval.getText(_errorCode);
+            }
+            return "<error unexpected cell type " + _cellType + ">";
         }
     }
 }

Added: poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyAreaEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyAreaEval.java?rev=694947&view=auto
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyAreaEval.java (added)
+++ poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyAreaEval.java Sat Sep 13 06:48:27 2008
@@ -0,0 +1,79 @@
+/* ====================================================================
+   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.ss.usermodel;
+
+import org.apache.poi.hssf.record.formula.AreaI;
+import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
+import org.apache.poi.hssf.record.formula.eval.AreaEval;
+import org.apache.poi.hssf.record.formula.eval.AreaEvalBase;
+import org.apache.poi.hssf.record.formula.eval.BlankEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.hssf.util.CellReference;
+
+/**
+ *
+ * @author Josh Micich 
+ */
+public class LazyAreaEval extends AreaEvalBase {
+
+	private final Sheet _sheet;
+	private FormulaEvaluator _evaluator;
+
+	public LazyAreaEval(AreaI ptg, Sheet sheet, FormulaEvaluator evaluator) {
+		super(ptg);
+		_sheet = sheet;
+		_evaluator = evaluator;
+	}
+
+	public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) { 
+		
+		int rowIx = (relativeRowIndex + getFirstRow() ) & 0xFFFF;
+		int colIx = (relativeColumnIndex + getFirstColumn() ) & 0x00FF;
+		
+		Row row = _sheet.getRow(rowIx);
+		if (row == null) {
+			return BlankEval.INSTANCE;
+		}
+		Cell cell = row.getCell(colIx);
+		if (cell == null) {
+			return BlankEval.INSTANCE;
+		}
+		return _evaluator.getEvalForCell(cell);
+	}
+
+	public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
+		AreaI area = new OffsetArea(getFirstRow(), getFirstColumn(),
+				relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
+
+		return new LazyAreaEval(area, _sheet, _evaluator);
+	}
+	public String toString() {
+		CellReference crA = new CellReference(getFirstRow(), getFirstColumn());
+		CellReference crB = new CellReference(getLastRow(), getLastColumn());
+		StringBuffer sb = new StringBuffer();
+		sb.append(getClass().getName()).append("[");
+		String sheetName = _evaluator.getSheetName(_sheet);
+		sb.append(sheetName);
+		sb.append('!');
+		sb.append(crA.formatAsString());
+		sb.append(':');
+		sb.append(crB.formatAsString());
+		sb.append("]");
+		return sb.toString();
+	}
+}

Propchange: poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyAreaEval.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyRefEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyRefEval.java?rev=694947&view=auto
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyRefEval.java (added)
+++ poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyRefEval.java Sat Sep 13 06:48:27 2008
@@ -0,0 +1,85 @@
+/* ====================================================================
+   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.ss.usermodel;
+
+import org.apache.poi.hssf.record.formula.AreaI;
+import org.apache.poi.hssf.record.formula.Ref3DPtg;
+import org.apache.poi.hssf.record.formula.RefPtg;
+import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
+import org.apache.poi.hssf.record.formula.eval.AreaEval;
+import org.apache.poi.hssf.record.formula.eval.BlankEval;
+import org.apache.poi.hssf.record.formula.eval.RefEvalBase;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.hssf.util.CellReference;
+
+/**
+*
+* @author Josh Micich 
+*/
+public class LazyRefEval extends RefEvalBase {
+
+	private final Sheet _sheet;
+	private final FormulaEvaluator _evaluator;
+
+
+	public LazyRefEval(RefPtg ptg, Sheet sheet, FormulaEvaluator evaluator) {
+		super(ptg.getRow(), ptg.getColumn());
+		_sheet = sheet;
+		_evaluator = evaluator;
+	}
+	public LazyRefEval(Ref3DPtg ptg, Sheet sheet, FormulaEvaluator evaluator) {
+		super(ptg.getRow(), ptg.getColumn());
+		_sheet = sheet;
+		_evaluator = evaluator;
+	}
+
+	public ValueEval getInnerValueEval() {
+		int rowIx = getRow();
+		int colIx = getColumn();
+		
+		Row row = _sheet.getRow(rowIx);
+		if (row == null) {
+			return BlankEval.INSTANCE;
+		}
+		Cell cell = row.getCell(colIx);
+		if (cell == null) {
+			return BlankEval.INSTANCE;
+		}
+		return _evaluator.getEvalForCell(cell);
+	}
+	
+	public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
+		
+		AreaI area = new OffsetArea(getRow(), getColumn(),
+				relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
+
+		return new LazyAreaEval(area, _sheet, _evaluator);
+	}
+	
+	public String toString() {
+		CellReference cr = new CellReference(getRow(), getColumn());
+		StringBuffer sb = new StringBuffer();
+		sb.append(getClass().getName()).append("[");
+		String sheetName = _evaluator.getSheetName(_sheet);
+		sb.append(sheetName);
+		sb.append('!');
+		sb.append(cr.formatAsString());
+		sb.append("]");
+		return sb.toString();
+	}
+}

Propchange: poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyRefEval.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: poi/branches/ooxml/src/java/org/apache/poi/util/HexDump.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/util/HexDump.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/util/HexDump.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/util/HexDump.java Sat Sep 13 06:48:27 2008
@@ -255,8 +255,10 @@
         retVal.append('[');
         for(int x = 0; x < value.length; x++)
         {
+            if (x>0) {
+                retVal.append(", ");
+            }
             retVal.append(toHex(value[x]));
-            retVal.append(", ");
         }
         retVal.append(']');
         return retVal.toString();

Modified: poi/branches/ooxml/src/java/org/apache/poi/util/HexRead.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/util/HexRead.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/util/HexRead.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/util/HexRead.java Sat Sep 13 06:48:27 2008
@@ -172,9 +172,12 @@
         return rval;
     }
 
-    static public byte[] readFromString(String data) throws IOException
-    {
-        return readData(new ByteArrayInputStream( data.getBytes() ), -1);
+    static public byte[] readFromString(String data) {
+        try {
+            return readData(new ByteArrayInputStream( data.getBytes() ), -1);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     static private void readToEOL( InputStream stream ) throws IOException



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org