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 [1/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...

Author: nick
Date: Sat Sep 13 06:48:27 2008
New Revision: 694947

URL: http://svn.apache.org/viewvc?rev=694947&view=rev
Log:
Merged revisions 693591,693639,693658,693939,693941,693947,693990,694050,694065,694153,694534,694615,694619-694620,694631,694643,694877,694881 via svnmerge from 
https://svn.apache.org/repos/asf/poi/trunk

........
  r693591 | josh | 2008-09-09 21:25:16 +0100 (Tue, 09 Sep 2008) | 1 line
  
  Added support for parsing array constants in formulas. (Helping investigation for bug 45752)
........
  r693639 | josh | 2008-09-09 23:26:28 +0100 (Tue, 09 Sep 2008) | 1 line
  
  removed debug code accidentally submitted with r693591
........
  r693658 | josh | 2008-09-10 00:46:46 +0100 (Wed, 10 Sep 2008) | 2 lines
  
  Fixed special cases of INDEX function (single columns / single rows, and errors)
........
  r693939 | josh | 2008-09-10 20:23:43 +0100 (Wed, 10 Sep 2008) | 1 line
  
  Fixing error value handling for numeric functions. Refactored hierarchy.
........
  r693941 | josh | 2008-09-10 20:27:24 +0100 (Wed, 10 Sep 2008) | 1 line
  
  (Should have been submitted with 693939) Fixing error value handling for numeric functions. Refactored hierarchy.
........
  r693947 | josh | 2008-09-10 20:33:58 +0100 (Wed, 10 Sep 2008) | 1 line
  
  (Should have been submitted with 693939) Fixing error value handling for numeric functions. Refactored hierarchy.
........
  r693990 | josh | 2008-09-10 22:21:28 +0100 (Wed, 10 Sep 2008) | 1 line
  
  Refactored hierarchy of MultiOperandNumericFunction. Fixed error value handling.  Enabled error value check in TestFormulasFromSpreadsheet
........
  r694050 | josh | 2008-09-10 23:43:30 +0100 (Wed, 10 Sep 2008) | 1 line
  
  Refactored finance functions.
........
  r694065 | josh | 2008-09-11 00:37:22 +0100 (Thu, 11 Sep 2008) | 1 line
  
  fixed special cases of MODE function
........
  r694153 | josh | 2008-09-11 08:16:20 +0100 (Thu, 11 Sep 2008) | 1 line
  
  Refactoring MultiOperandNumericFunction - removed Ref2DEval.
........
  r694534 | josh | 2008-09-12 00:18:50 +0100 (Fri, 12 Sep 2008) | 1 line
  
  Fix for bug 45639 - cleaned up index logic inside ColumnInfoRecordsAggregate
........
  r694615 | josh | 2008-09-12 07:14:07 +0100 (Fri, 12 Sep 2008) | 1 line
  
  small tweak to unit test which was silently creating UnknownPtgs 
........
  r694619 | josh | 2008-09-12 07:58:52 +0100 (Fri, 12 Sep 2008) | 1 line
  
  Removed trailing comma from output of HexDump.toHex()
........
  r694620 | josh | 2008-09-12 08:03:00 +0100 (Fri, 12 Sep 2008) | 1 line
  
  clarification of ArrayPtg size increment
........
  r694631 | josh | 2008-09-12 08:43:20 +0100 (Fri, 12 Sep 2008) | 1 line
  
  Extended support for cached results of formula cells
........
  r694643 | josh | 2008-09-12 09:18:54 +0100 (Fri, 12 Sep 2008) | 2 lines
  
  Made HSSFFormulaEvaluator no longer require initialisation with sheet or row.
........
  r694877 | josh | 2008-09-13 06:14:26 +0100 (Sat, 13 Sep 2008) | 1 line
  
  Refactored TextFunctions. Some minor fixes - test cases added.
........
  r694881 | josh | 2008-09-13 06:43:41 +0100 (Sat, 13 Sep 2008) | 1 line
  
  Added toString methods formatAsString to CellValue. Changed deprecation on CellValue.getRichTextStringValue
........

Added:
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java
      - copied unchanged from r694881, poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/DateFunc.java
      - copied unchanged from r694881, poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/DateFunc.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/MinaMaxa.java
      - copied unchanged from r694881, poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/MinaMaxa.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/LazyAreaEval.java
      - copied, changed from r694881, poi/trunk/src/java/org/apache/poi/hssf/usermodel/LazyAreaEval.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/LazyRefEval.java
      - copied, changed from r694881, poi/trunk/src/java/org/apache/poi/hssf/usermodel/LazyRefEval.java
    poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyAreaEval.java   (with props)
    poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/LazyRefEval.java   (with props)
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/IndexFunctionTestCaseData.xls
      - copied unchanged from r694881, poi/trunk/src/testcases/org/apache/poi/hssf/data/IndexFunctionTestCaseData.xls
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java
      - copied, changed from r694881, poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java
Removed:
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/eval/LazyAreaEval.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/eval/LazyRefEval.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/eval/ValueEvalToNumericXlator.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Atan2.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Avedev.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Average.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Ceiling.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Combin.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Concatenate.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Date.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Devsq.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Exact.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Floor.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Fv.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Large.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Left.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Len.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Log.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Lower.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Max.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Maxa.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Median.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Mid.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Min.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Mina.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Mod.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Nper.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/NumericFunctionOneArg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Pmt.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Power.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Product.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Pv.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Right.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Round.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Rounddown.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Roundup.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Small.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Stdev.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Sum.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Sumsq.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Trim.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Upper.java
Modified:
    poi/branches/ooxml/   (props changed)
    poi/branches/ooxml/src/documentation/content/xdocs/changes.xml
    poi/branches/ooxml/src/documentation/content/xdocs/status.xml
    poi/branches/ooxml/src/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/model/FormulaParser.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/model/OperandClassTransformer.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/model/Sheet.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/FormulaRecord.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/aggregates/ColumnInfoRecordsAggregate.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java   (props changed)
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/aggregates/SharedValueManager.java   (props changed)
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java   (props changed)
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area2DPtgBase.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/ErrPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Ptg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/atp/ParityFunction.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/atp/YearFrac.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/eval/ExternalFunction.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/eval/OperandResolver.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Even.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/FreeRefFunction.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Index.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/NumericFunction.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Odd.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Replace.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/StatsLib.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/Substitute.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/functions/TextFunction.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFDataValidation.java   (props changed)
    poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/util/CellRangeAddressList.java   (props changed)
    poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/EvaluationCycleDetector.java
    poi/branches/ooxml/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java
    poi/branches/ooxml/src/java/org/apache/poi/util/HexDump.java
    poi/branches/ooxml/src/java/org/apache/poi/util/HexRead.java
    poi/branches/ooxml/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/Cell.java
    poi/branches/ooxml/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/Comment.java
    poi/branches/ooxml/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Cell.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherBSERecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherBlipWMFRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherChildAnchorRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherClientAnchorRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherClientDataRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherContainerRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherDgRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherDggRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherOptRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherPropertyFactory.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherSpRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherSpgrRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestEscherSplitMenuColorsRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/ddf/TestUnknownEscherRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/data/testRVA.xls
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/model/TestFormulaParserEval.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/model/TestRVA.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/model/TestSheet.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/model/TestSheetAdditional.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestDrawingGroupRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestEscherAggregate.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/aggregates/TestColumnInfoRecordsAggregate.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/aggregates/TestFormulaRecordAggregate.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestExternalFunctionFormulas.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/atp/TestYearFracCalculatorFromSpreadsheet.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestCircularReferences.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulaBugs.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/AllIndividualFunctionEvaluationTests.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestAverage.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestDate.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndex.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIsBlank.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLen.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestPmt.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestRoundFuncs.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestStatsLib.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTrim.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestBug42464.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestBug43093.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorDocs.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDataFormatter.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFFormulaEvaluator.java

Propchange: poi/branches/ooxml/
------------------------------------------------------------------------------
    svn:mergeinfo = /poi/trunk:693591-694881

Propchange: poi/branches/ooxml/
------------------------------------------------------------------------------
    (empty)

Propchange: poi/branches/ooxml/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Sat Sep 13 06:48:27 2008
@@ -1 +1 @@
-/poi/trunk:1-638784,638786-639486,639488-639601,639603-640056,640058-642562,642564-642566,642568-642574,642576-642736,642739-650914,650916-693438
+/poi/trunk:1-638784,638786-639486,639488-639601,639603-640056,640058-642562,642564-642566,642568-642574,642576-642736,642739-650914,650916-694946

Modified: poi/branches/ooxml/src/documentation/content/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/documentation/content/xdocs/changes.xml?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/documentation/content/xdocs/changes.xml (original)
+++ poi/branches/ooxml/src/documentation/content/xdocs/changes.xml Sat Sep 13 06:48:27 2008
@@ -65,6 +65,10 @@
            <action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
         </release>
         <release version="3.1.1-alpha1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="add">Made HSSFFormulaEvaluator no longer require initialisation with sheet or row</action>
+           <action dev="POI-DEVELOPERS" type="add">Extended support for cached results of formula cells</action>
+           <action dev="POI-DEVELOPERS" type="fix">45639 - Fixed AIOOBE due to bad index logic in ColumnInfoRecordsAggregate</action>
+           <action dev="POI-DEVELOPERS" type="fix">Fixed special cases of INDEX function (single column/single row, errors)</action>
            <action dev="POI-DEVELOPERS" type="add">45761 - Support for Very Hidden excel sheets in HSSF</action>
            <action dev="POI-DEVELOPERS" type="add">45738 - Initial HWPF support for Office Art Shapes</action>
            <action dev="POI-DEVELOPERS" type="fix">45720 - Fixed HSSFWorkbook.cloneSheet to correctly clone sheets with drawings</action>

Modified: poi/branches/ooxml/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/documentation/content/xdocs/status.xml?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/documentation/content/xdocs/status.xml (original)
+++ poi/branches/ooxml/src/documentation/content/xdocs/status.xml Sat Sep 13 06:48:27 2008
@@ -62,6 +62,10 @@
            <action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
         </release>
         <release version="3.1.1-alpha1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="add">Made HSSFFormulaEvaluator no longer require initialisation with sheet or row</action>
+           <action dev="POI-DEVELOPERS" type="add">Extended support for cached results of formula cells</action>
+           <action dev="POI-DEVELOPERS" type="fix">45639 - Fixed AIOOBE due to bad index logic in ColumnInfoRecordsAggregate</action>
+           <action dev="POI-DEVELOPERS" type="fix">Fixed special cases of INDEX function (single column/single row, errors)</action>
            <action dev="POI-DEVELOPERS" type="add">45761 - Support for Very Hidden excel sheets in HSSF</action>
            <action dev="POI-DEVELOPERS" type="add">45738 - Initial HWPF support for Office Art Shapes</action>
            <action dev="POI-DEVELOPERS" type="fix">45720 - Fixed HSSFWorkbook.cloneSheet to correctly clone sheets with drawings</action>

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java Sat Sep 13 06:48:27 2008
@@ -14,6 +14,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
+
 package org.apache.poi.hssf.extractor;
 
 import java.io.IOException;
@@ -49,10 +50,10 @@
 /**
  * A text extractor for Excel files, that is based
  *  on the hssf eventusermodel api.
- * It will typically use less memory than 
+ * It will typically use less memory than
  *  {@link ExcelExtractor}, but may not provide
  *  the same richness of formatting.
- * Returns the textual content of the file, suitable for 
+ * Returns the textual content of the file, suitable for
  *  indexing by something like Lucene, but not really
  *  intended for display to the user.
  * To turn an excel file into a CSV or similar, then see
@@ -63,8 +64,8 @@
 	private POIFSFileSystem fs;
 	private boolean includeSheetNames = true;
 	private boolean formulasNotResults = false;
-	
-	public EventBasedExcelExtractor(POIFSFileSystem fs) throws IOException {
+
+	public EventBasedExcelExtractor(POIFSFileSystem fs) {
 		super(null);
 		this.fs = fs;
 	}
@@ -98,8 +99,8 @@
 	public void setFormulasNotResults(boolean formulasNotResults) {
 		this.formulasNotResults = formulasNotResults;
 	}
-	
-	
+
+
 	/**
 	 * Retreives the text contents of the file
 	 */
@@ -107,7 +108,7 @@
 		String text = null;
 		try {
 			TextListener tl = triggerExtraction();
-			
+
 			text = tl.text.toString();
 			if(! text.endsWith("\n")) {
 				text = text + "\n";
@@ -115,37 +116,37 @@
 		} catch(IOException e) {
 			throw new RuntimeException(e);
 		}
-		
+
 		return text;
 	}
-	
+
 	private TextListener triggerExtraction() throws IOException {
 		TextListener tl = new TextListener();
 		FormatTrackingHSSFListener ft = new FormatTrackingHSSFListener(tl);
 		tl.ft = ft;
-		
+
 		// Register and process
 		HSSFEventFactory factory = new HSSFEventFactory();
 		HSSFRequest request = new HSSFRequest();
 		request.addListenerForAllRecords(ft);
-		
+
 		factory.processWorkbookEvents(request, fs);
-		
+
 		return tl;
 	}
-	
+
 	private class TextListener implements HSSFListener {
 		private FormatTrackingHSSFListener ft;
 		private SSTRecord sstRecord;
-		
+
 		private List sheetNames = new ArrayList();
 		private StringBuffer text = new StringBuffer();
 		private int sheetNum = -1;
 		private int rowNum;
-		
+
 		private boolean outputNextStringValue = false;
 		private int nextRow = -1;
-		
+
 		public void processRecord(Record record) {
 			String thisText = null;
 			int thisRow = -1;
@@ -160,7 +161,7 @@
 				if(bof.getType() == BOFRecord.TYPE_WORKSHEET) {
 					sheetNum++;
 					rowNum = -1;
-					
+
 					if(includeSheetNames) {
 						if(text.length() > 0) text.append("\n");
 						text.append(sheetNames.get(sheetNum));
@@ -170,60 +171,60 @@
 			case SSTRecord.sid:
 				sstRecord = (SSTRecord)record;
 				break;
-			
-	        case FormulaRecord.sid:
-	        	FormulaRecord frec = (FormulaRecord) record;
-	        	thisRow = frec.getRow();
-	        	
-	        	if(formulasNotResults) {
-	        		thisText = FormulaParser.toFormulaString(null, frec.getParsedExpression());
-	        	} else {
-	        		if(Double.isNaN( frec.getValue() )) {
-	        			// Formula result is a string
-	        			// This is stored in the next record
-	        			outputNextStringValue = true;
-	    	        	nextRow = frec.getRow();
-	        		} else {
-	        			thisText = formatNumberDateCell(frec, frec.getValue());
-	        		}
-	        	}
-	            break;
-	        case StringRecord.sid:
-	        	if(outputNextStringValue) {
-	        		// String for formula
-	        		StringRecord srec = (StringRecord)record;
-	        		thisText = srec.getString(); 
-	        		thisRow = nextRow;
-	        		outputNextStringValue = false;
-	        	}
-	            break;
-	        case LabelRecord.sid:
-	        	LabelRecord lrec = (LabelRecord) record;
-	            thisRow = lrec.getRow();
-	            thisText = lrec.getValue();
-	            break;
-	        case LabelSSTRecord.sid:
-	        	LabelSSTRecord lsrec = (LabelSSTRecord) record;
-	            thisRow = lsrec.getRow();
-	            if(sstRecord == null) {
-	            	throw new IllegalStateException("No SST record found");
-	            }
-	            thisText = sstRecord.getString(lsrec.getSSTIndex()).toString();
-	            break;
-	        case NoteRecord.sid:
-	        	NoteRecord nrec = (NoteRecord) record;
-	        	thisRow = nrec.getRow();
-	        	// TODO: Find object to match nrec.getShapeId()
-	            break;
-	        case NumberRecord.sid:
-	            NumberRecord numrec = (NumberRecord) record;
-	            thisRow = numrec.getRow();
-	            thisText = formatNumberDateCell(numrec, numrec.getValue());
-	            break;
-	        default:
-	        	break;
+
+			case FormulaRecord.sid:
+				FormulaRecord frec = (FormulaRecord) record;
+				thisRow = frec.getRow();
+
+				if(formulasNotResults) {
+					thisText = FormulaParser.toFormulaString(null, frec.getParsedExpression());
+				} else {
+					if(frec.hasCachedResultString()) {
+						// Formula result is a string
+						// This is stored in the next record
+						outputNextStringValue = true;
+						nextRow = frec.getRow();
+					} else {
+						thisText = formatNumberDateCell(frec, frec.getValue());
+					}
+				}
+				break;
+			case StringRecord.sid:
+				if(outputNextStringValue) {
+					// String for formula
+					StringRecord srec = (StringRecord)record;
+					thisText = srec.getString();
+					thisRow = nextRow;
+					outputNextStringValue = false;
+				}
+				break;
+			case LabelRecord.sid:
+				LabelRecord lrec = (LabelRecord) record;
+				thisRow = lrec.getRow();
+				thisText = lrec.getValue();
+				break;
+			case LabelSSTRecord.sid:
+				LabelSSTRecord lsrec = (LabelSSTRecord) record;
+				thisRow = lsrec.getRow();
+				if(sstRecord == null) {
+					throw new IllegalStateException("No SST record found");
+				}
+				thisText = sstRecord.getString(lsrec.getSSTIndex()).toString();
+				break;
+			case NoteRecord.sid:
+				NoteRecord nrec = (NoteRecord) record;
+				thisRow = nrec.getRow();
+				// TODO: Find object to match nrec.getShapeId()
+				break;
+			case NumberRecord.sid:
+				NumberRecord numrec = (NumberRecord) record;
+				thisRow = numrec.getRow();
+				thisText = formatNumberDateCell(numrec, numrec.getValue());
+				break;
+			default:
+				break;
 			}
-			
+
 			if(thisText != null) {
 				if(thisRow != rowNum) {
 					rowNum = thisRow;
@@ -235,42 +236,42 @@
 				text.append(thisText);
 			}
 		}
-		
+
 		/**
-		 * Formats a number or date cell, be that a real number, or the 
+		 * Formats a number or date cell, be that a real number, or the
 		 *  answer to a formula
 		 */
 		private String formatNumberDateCell(CellValueRecordInterface cell, double value) {
-	        // Get the built in format, if there is one
+			// Get the built in format, if there is one
 			int formatIndex = ft.getFormatIndex(cell);
 			String formatString = ft.getFormatString(cell);
-			
+
 			if(formatString == null) {
-	            return Double.toString(value);
-	        } else {
-	        	// Is it a date?
-	        	if(HSSFDateUtil.isADateFormat(formatIndex,formatString) &&
-	        			HSSFDateUtil.isValidExcelDate(value)) {
-	        		// Java wants M not m for month
-	        		formatString = formatString.replace('m','M');
-	        		// Change \- into -, if it's there
-	        		formatString = formatString.replaceAll("\\\\-","-");
-	        		
-	        		// Format as a date
-	        		Date d = HSSFDateUtil.getJavaDate(value, false);
-	        		DateFormat df = new SimpleDateFormat(formatString);
-		            return df.format(d);
-	        	} else {
-	        		if(formatString == "General") {
-	        			// Some sort of wierd default
-	        			return Double.toString(value);
-	        		}
-	        		
-	        		// Format as a number
-		            DecimalFormat df = new DecimalFormat(formatString);
-		            return df.format(value);
-	        	}
-	        }
+				return Double.toString(value);
+			} else {
+				// Is it a date?
+				if(HSSFDateUtil.isADateFormat(formatIndex,formatString) &&
+						HSSFDateUtil.isValidExcelDate(value)) {
+					// Java wants M not m for month
+					formatString = formatString.replace('m','M');
+					// Change \- into -, if it's there
+					formatString = formatString.replaceAll("\\\\-","-");
+
+					// Format as a date
+					Date d = HSSFDateUtil.getJavaDate(value, false);
+					DateFormat df = new SimpleDateFormat(formatString);
+					return df.format(d);
+				} else {
+					if(formatString == "General") {
+						// Some sort of wierd default
+						return Double.toString(value);
+					}
+
+					// Format as a number
+					DecimalFormat df = new DecimalFormat(formatString);
+					return df.format(value);
+				}
+			}
 		}
 	}
 }

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java Sat Sep 13 06:48:27 2008
@@ -14,12 +14,14 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
+
 package org.apache.poi.hssf.extractor;
 
 import java.io.IOException;
 
 import org.apache.poi.POIOLE2TextExtractor;
 import org.apache.poi.ss.usermodel.HeaderFooter;
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;
 import org.apache.poi.hssf.usermodel.HSSFCell;
 import org.apache.poi.hssf.usermodel.HSSFComment;
 import org.apache.poi.hssf.usermodel.HSSFRichTextString;
@@ -112,40 +114,52 @@
 				int lastCell = row.getLastCellNum();
 				for(int k=firstCell;k<lastCell;k++) {
 					HSSFCell cell = row.getCell(k);
-					boolean outputContents = false;
 					if(cell == null) { continue; }
+					boolean outputContents = true;
 					
 					switch(cell.getCellType()) {
+						case HSSFCell.CELL_TYPE_BLANK:
+							outputContents = false;
+							break;
 						case HSSFCell.CELL_TYPE_STRING:
 							text.append(cell.getRichStringCellValue().getString());
-							outputContents = true;
 							break;
 						case HSSFCell.CELL_TYPE_NUMERIC:
 							// Note - we don't apply any formatting!
 							text.append(cell.getNumericCellValue());
-							outputContents = true;
 							break;
 						case HSSFCell.CELL_TYPE_BOOLEAN:
 							text.append(cell.getBooleanCellValue());
-							outputContents = true;
+							break;
+						case HSSFCell.CELL_TYPE_ERROR:
+							text.append(ErrorEval.getText(cell.getErrorCellValue()));
 							break;
 						case HSSFCell.CELL_TYPE_FORMULA:
 							if(formulasNotResults) {
 								text.append(cell.getCellFormula());
 							} else {
-								// Try it as a string, if not as a number
-								HSSFRichTextString str = 
-									cell.getRichStringCellValue();
-								if(str != null && str.length() > 0) {
-									text.append(str.toString());
-								} else {
-									// Try and treat it as a number
-									double val = cell.getNumericCellValue();
-									text.append(val);
+								switch(cell.getCachedFormulaResultType()) {
+									case HSSFCell.CELL_TYPE_STRING:
+										HSSFRichTextString str = cell.getRichStringCellValue();
+										if(str != null && str.length() > 0) {
+											text.append(str.toString());
+										}
+										break;
+									case HSSFCell.CELL_TYPE_NUMERIC:
+										text.append(cell.getNumericCellValue());
+										break;
+									case HSSFCell.CELL_TYPE_BOOLEAN:
+										text.append(cell.getBooleanCellValue());
+										break;
+									case HSSFCell.CELL_TYPE_ERROR:
+										text.append(ErrorEval.getText(cell.getErrorCellValue()));
+										break;
+										
 								}
 							}
-							outputContents = true;
 							break;
+						default:
+							throw new RuntimeException("Unexpected cell type (" + cell.getCellType() + ")");
 					}
 					
 					// Output the comment, if requested and exists

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/model/FormulaParser.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/model/FormulaParser.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/model/FormulaParser.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/model/FormulaParser.java Sat Sep 13 06:48:27 2008
@@ -22,11 +22,14 @@
 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.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.HSSFFormulaEvaluator;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.hssf.util.AreaReference;
@@ -70,9 +73,9 @@
     public static final int FORMULA_TYPE_ARRAY =2;
     public static final int FORMULA_TYPE_CONDFORMAT = 3;
     public static final int FORMULA_TYPE_NAMEDRANGE = 4;
-    // this constant is currently very specific.  The exact differences from general data 
+    // this constant is currently very specific.  The exact differences from general data
     // validation formulas or conditional format formulas is not known yet
-    public static final int FORMULA_TYPE_DATAVALIDATION_LIST = 5;    
+    public static final int FORMULA_TYPE_DATAVALIDATION_LIST = 5;
 
     private final String formulaString;
     private final int formulaLength;
@@ -140,9 +143,9 @@
     /** Report What Was Expected */
     private RuntimeException expected(String s) {
         String msg;
-        
+
         if (look == '=' && formulaString.substring(0, pointer-1).trim().length() < 1) {
-            msg = "The specified formula '" + formulaString 
+            msg = "The specified formula '" + formulaString
                 + "' starts with an equals sign which is not allowed.";
         } else {
             msg = "Parse error near char " + (pointer-1) + " '" + look + "'"
@@ -194,8 +197,8 @@
     /**
      * Parses a sheet name, named range name, or simple cell reference.<br/>
      * Note - identifiers in Excel can contain dots, so this method may return a String
-     * which may need to be converted to an area reference.  For example, this method 
-     * may return a value like "A1..B2", in which case the caller must convert it to 
+     * which may need to be converted to an area reference.  For example, this method
+     * may return a value like "A1..B2", in which case the caller must convert it to
      * an area reference like "A1:B2"
      */
     private String parseIdentifier() {
@@ -251,7 +254,7 @@
     }
 
     private Ptg parseNameOrReference(String name) {
-        
+
         AreaReference areaRef = parseArea(name);
         if (areaRef != null) {
             // will happen if dots are used instead of colon
@@ -373,30 +376,28 @@
     private ParseNode function(String name) {
         Ptg nameToken = null;
         if(!AbstractFunctionPtg.isBuiltInFunctionName(name)) {
-        	// user defined function
+            // user defined function
             // in the token tree, the name is more or less the first argument
-        	
-        
-        	int nameIndex = book.getNameIndex(name);
-        	if (nameIndex >= 0) {
-        		Name hName = book.getNameAt(nameIndex);
-        		if (!hName.isFunctionName()) {
-        			throw new FormulaParseException("Attempt to use name '" + name 
-        					+ "' as a function, but defined name in workbook does not refer to a function");
-        		}
-        		
-        		// calls to user-defined functions within the workbook 
-        		// get a Name token which points to a defined name record
-        		nameToken = new NamePtg(name, this.book);
-        	} else {
+            int nameIndex = book.getNameIndex(name);
+            if (nameIndex >= 0) {
+                Name hName = book.getNameAt(nameIndex);
+                if (!hName.isFunctionName()) {
+                    throw new FormulaParseException("Attempt to use name '" + name
+                            + "' as a function, but defined name in workbook does not refer to a function");
+                }
+
+                // calls to user-defined functions within the workbook
+                // get a Name token which points to a defined name record
+                nameToken = new NamePtg(name, this.book);
+            } else {
 				if(book instanceof HSSFWorkbook) {
 					nameToken = ((HSSFWorkbook)book).getNameXPtg(name);
 				}
-        		if (nameToken == null) {
-        			throw new FormulaParseException("Name '" + name 
-        					+ "' is completely unknown in the current workbook");
-        		}
-        	}
+                if (nameToken == null) {
+                    throw new FormulaParseException("Name '" + name
+                            + "' is completely unknown in the current workbook");
+                }
+            }
         }
 
         Match('(');
@@ -544,7 +545,7 @@
         SkipWhite();
         switch(look) {
             case '#':
-                return new ParseNode(parseErrorLiteral());
+                return new ParseNode(ErrPtg.valueOf(parseErrorLiteral()));
             case '-':
                 Match('-');
                 return new ParseNode(UnaryMinusPtg.instance, powerFactor());
@@ -557,7 +558,12 @@
                 Match(')');
                 return new ParseNode(ParenthesisPtg.instance, inside);
             case '"':
-                return new ParseNode(parseStringLiteral());
+                return new ParseNode(new StringPtg(parseStringLiteral()));
+            case '{':
+                Match('{');
+                ParseNode arrayNode = parseArray();
+                Match('}');
+                return arrayNode;
         }
         if (IsAlpha(look) || look == '\''){
             return parseFunctionReferenceOrName();
@@ -567,6 +573,95 @@
     }
 
 
+    private ParseNode parseArray() {
+        List rowsData = new ArrayList();
+        while(true) {
+            Object[] singleRowData = parseArrayRow();
+            rowsData.add(singleRowData);
+            if (look == '}') {
+                break;
+            }
+            if (look != ';') {
+                throw expected("'}' or ';'");
+            }
+            Match(';');
+        }
+        int nRows = rowsData.size();
+        Object[][] values2d = new Object[nRows][];
+        rowsData.toArray(values2d);
+        int nColumns = values2d[0].length;
+        checkRowLengths(values2d, nColumns);
+
+        return new ParseNode(new ArrayPtg(values2d));
+    }
+    private void checkRowLengths(Object[][] values2d, int nColumns) {
+        for (int i = 0; i < values2d.length; i++) {
+            int rowLen = values2d[i].length;
+            if (rowLen != nColumns) {
+                throw new FormulaParseException("Array row " + i + " has length " + rowLen
+                        + " but row 0 has length " + nColumns);
+            }
+        }
+    }
+
+    private Object[] parseArrayRow() {
+        List temp = new ArrayList();
+        while (true) {
+            temp.add(parseArrayItem());
+            SkipWhite();
+            switch(look) {
+                case '}':
+                case ';':
+                    break;
+                case ',':
+                    Match(',');
+                    continue;
+                default:
+                    throw expected("'}' or ','");
+
+            }
+            break;
+        }
+
+        Object[] result = new Object[temp.size()];
+        temp.toArray(result);
+        return result;
+    }
+
+    private Object parseArrayItem() {
+        SkipWhite();
+        switch(look) {
+            case '"': return new UnicodeString(parseStringLiteral());
+            case '#': return ErrorConstant.valueOf(parseErrorLiteral());
+            case 'F': case 'f':
+            case 'T': case 't':
+                return parseBooleanLiteral();
+        }
+        // else assume number
+        return convertArrayNumber(parseNumber());
+    }
+
+    private Boolean parseBooleanLiteral() {
+        String iden = parseIdentifier();
+        if ("TRUE".equalsIgnoreCase(iden)) {
+            return Boolean.TRUE;
+        }
+        if ("FALSE".equalsIgnoreCase(iden)) {
+            return Boolean.FALSE;
+        }
+        throw expected("'TRUE' or 'FALSE'");
+    }
+
+    private static Double convertArrayNumber(Ptg ptg) {
+        if (ptg instanceof IntPtg) {
+            return new Double(((IntPtg)ptg).getValue());
+        }
+        if (ptg instanceof NumberPtg) {
+            return new Double(((NumberPtg)ptg).getValue());
+        }
+        throw new RuntimeException("Unexpected ptg (" + ptg.getClass().getName() + ")");
+    }
+
     private Ptg parseNumber() {
         String number2 = null;
         String exponent = null;
@@ -603,7 +698,7 @@
     }
 
 
-    private ErrPtg parseErrorLiteral() {
+    private int parseErrorLiteral() {
         Match('#');
         String part1 = parseIdentifier().toUpperCase();
 
@@ -611,13 +706,13 @@
             case 'V':
                 if(part1.equals("VALUE")) {
                     Match('!');
-                    return ErrPtg.VALUE_INVALID;
+                    return HSSFErrorConstants.ERROR_VALUE;
                 }
                 throw expected("#VALUE!");
             case 'R':
                 if(part1.equals("REF")) {
                     Match('!');
-                    return ErrPtg.REF_INVALID;
+                    return HSSFErrorConstants.ERROR_REF;
                 }
                 throw expected("#REF!");
             case 'D':
@@ -625,21 +720,21 @@
                     Match('/');
                     Match('0');
                     Match('!');
-                    return ErrPtg.DIV_ZERO;
+                    return HSSFErrorConstants.ERROR_DIV_0;
                 }
                 throw expected("#DIV/0!");
             case 'N':
                 if(part1.equals("NAME")) {
                     Match('?');  // only one that ends in '?'
-                    return ErrPtg.NAME_INVALID;
+                    return HSSFErrorConstants.ERROR_NAME;
                 }
                 if(part1.equals("NUM")) {
                     Match('!');
-                    return ErrPtg.NUM_ERROR;
+                    return HSSFErrorConstants.ERROR_NUM;
                 }
                 if(part1.equals("NULL")) {
                     Match('!');
-                    return ErrPtg.NULL_INTERSECTION;
+                    return HSSFErrorConstants.ERROR_NULL;
                 }
                 if(part1.equals("N")) {
                     Match('/');
@@ -648,7 +743,7 @@
                     }
                     Match(look);
                     // Note - no '!' or '?' suffix
-                    return ErrPtg.N_A;
+                    return HSSFErrorConstants.ERROR_NA;
                 }
                 throw expected("#NAME?, #NUM!, #NULL! or #N/A");
 
@@ -701,7 +796,7 @@
     }
 
 
-    private StringPtg parseStringLiteral() {
+    private String parseStringLiteral() {
         Match('"');
 
         StringBuffer token = new StringBuffer();
@@ -715,7 +810,7 @@
             token.append(look);
             GetChar();
         }
-        return new StringPtg(token.toString());
+        return token.toString();
     }
 
     /** Parse and Translate a Math Term */
@@ -972,7 +1067,7 @@
         }
         return result;
     }
-    
+
     private static String[] getOperands(Stack stack, int nOperands) {
         String[] operands = new String[nOperands];
 

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/model/OperandClassTransformer.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/model/OperandClassTransformer.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/model/OperandClassTransformer.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/model/OperandClassTransformer.java Sat Sep 13 06:48:27 2008
@@ -74,7 +74,7 @@
 						+ _formulaType + ") not supported yet");
 		
 		}
-		transformNode(rootNode, rootNodeOperandClass, false, false);
+		transformNode(rootNode, rootNodeOperandClass, false);
 	}
 
 	/**
@@ -83,22 +83,35 @@
 	 * the function return value).
 	 */
 	private void transformNode(ParseNode node, byte desiredOperandClass,
-			boolean callerForceArrayFlag, boolean isDirectChildOfValueOperator) {
+			boolean callerForceArrayFlag) {
 		Ptg token = node.getToken();
 		ParseNode[] children = node.getChildren();
+		boolean isSimpleValueFunc = isSimpleValueFunction(token);
+		
+		if (isSimpleValueFunc) {
+			boolean localForceArray = desiredOperandClass == Ptg.CLASS_ARRAY;
+			for (int i = 0; i < children.length; i++) {
+				transformNode(children[i], desiredOperandClass, localForceArray);
+			}
+			setSimpleValueFuncClass((AbstractFunctionPtg) token, desiredOperandClass, callerForceArrayFlag);
+			return;
+		}
+		
 		if (token instanceof ValueOperatorPtg || token instanceof ControlPtg) {
 			// Value Operator Ptgs and Control are base tokens, so token will be unchanged
-			
 			// but any child nodes are processed according to desiredOperandClass and callerForceArrayFlag
+			
+			// As per OOO documentation Sec 3.2.4 "Token Class Transformation", "Step 1"
+			// All direct operands of value operators that are initially 'R' type will 
+			// be converted to 'V' type.
+			byte localDesiredOperandClass = desiredOperandClass == Ptg.CLASS_REF ? Ptg.CLASS_VALUE : desiredOperandClass;
 			for (int i = 0; i < children.length; i++) {
-				ParseNode child = children[i];
-				transformNode(child, desiredOperandClass, callerForceArrayFlag, true);
+				transformNode(children[i], localDesiredOperandClass, callerForceArrayFlag);
 			}
 			return;
 		}
 		if (token instanceof AbstractFunctionPtg) {
-			transformFunctionNode((AbstractFunctionPtg) token, children, desiredOperandClass,
-					callerForceArrayFlag);
+			transformFunctionNode((AbstractFunctionPtg) token, children, desiredOperandClass, callerForceArrayFlag);
 			return;
 		}
 		if (children.length > 0) {
@@ -109,15 +122,24 @@
 			// nothing to do
 			return;
 		}
-		if (isDirectChildOfValueOperator) {
-			// As per OOO documentation Sec 3.2.4 "Token Class Transformation", "Step 1"
-			// All direct operands of value operators that are initially 'R' type will 
-			// be converted to 'V' type.
-			if (token.getPtgClass() == Ptg.CLASS_REF) {
-				token.setClass(Ptg.CLASS_VALUE); 
+		token.setClass(transformClass(token.getPtgClass(), desiredOperandClass, callerForceArrayFlag));
+	}
+
+	private static boolean isSimpleValueFunction(Ptg token) {
+		if (token instanceof AbstractFunctionPtg) {
+			AbstractFunctionPtg aptg = (AbstractFunctionPtg) token;
+			if (aptg.getDefaultOperandClass() != Ptg.CLASS_VALUE) {
+				return false;
+			}
+			int numberOfOperands = aptg.getNumberOfOperands();
+			for (int i=numberOfOperands-1; i>=0; i--) {
+				if (aptg.getParameterClass(i) != Ptg.CLASS_VALUE) {
+					return false;
+				}
 			}
+			return true;
 		}
-		token.setClass(transformClass(token.getPtgClass(), desiredOperandClass, callerForceArrayFlag));
+		return false;
 	}
 
 	private byte transformClass(byte currentOperandClass, byte desiredOperandClass,
@@ -185,6 +207,7 @@
 						switch (defaultReturnOperandClass) {
 							case Ptg.CLASS_REF:
 								afp.setClass(Ptg.CLASS_REF);
+//								afp.setClass(Ptg.CLASS_ARRAY);
 								break;
 							case Ptg.CLASS_VALUE:
 								afp.setClass(Ptg.CLASS_ARRAY);
@@ -220,7 +243,17 @@
 		for (int i = 0; i < children.length; i++) {
 			ParseNode child = children[i];
 			byte paramOperandClass = afp.getParameterClass(i);
-			transformNode(child, paramOperandClass, localForceArrayFlag, false);
+			transformNode(child, paramOperandClass, localForceArrayFlag);
+		}
+	}
+
+	private void setSimpleValueFuncClass(AbstractFunctionPtg afp,
+			byte desiredOperandClass, boolean callerForceArrayFlag) {
+
+		if (callerForceArrayFlag  || desiredOperandClass == Ptg.CLASS_ARRAY) {
+			afp.setClass(Ptg.CLASS_ARRAY);
+		} else {
+			afp.setClass(Ptg.CLASS_VALUE); 
 		}
 	}
 }

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/model/Sheet.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/model/Sheet.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/model/Sheet.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/model/Sheet.java Sat Sep 13 06:48:27 2008
@@ -1055,7 +1055,7 @@
 
         ColumnInfoRecord ci = _columnInfos.findColumnInfo(columnIndex);
         if (ci != null) {
-            return ci.getColumnWidth();
+            return (short)ci.getColumnWidth();
         }
         //default column width is measured in characters
         //multiply
@@ -1079,8 +1079,8 @@
     public short getXFIndexForColAt(short columnIndex) {
         ColumnInfoRecord ci = _columnInfos.findColumnInfo(columnIndex);
         if (ci != null) {
-            return ci.getXFIndex();
-         }
+            return (short)ci.getXFIndex();
+        }
         return 0xF;
     }
 
@@ -1138,8 +1138,7 @@
      * @param indent        if true the group will be indented by one level,
      *                      if false indenting will be removed by one level.
      */
-    public void groupColumnRange(short fromColumn, short toColumn, boolean indent)
-    {
+    public void groupColumnRange(int fromColumn, int toColumn, boolean indent) {
 
         // Set the level for each column
         _columnInfos.groupColumnRange( fromColumn, toColumn, indent);
@@ -1709,17 +1708,13 @@
     }
 
 
-    public void setColumnGroupCollapsed( short columnNumber, boolean collapsed )
-    {
-        if (collapsed)
-        {
-            _columnInfos.collapseColumn( columnNumber );
-        }
-        else
-        {
-            _columnInfos.expandColumn( columnNumber );
-        }
-    }
+    public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) {
+		if (collapsed) {
+			_columnInfos.collapseColumn(columnNumber);
+		} else {
+			_columnInfos.expandColumn(columnNumber);
+		}
+	}
 
     /**
      * protect a spreadsheet with a password (not encypted, just sets protect

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java Sat Sep 13 06:48:27 2008
@@ -17,6 +17,7 @@
 
 package org.apache.poi.hssf.record;
 
+import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
@@ -30,19 +31,24 @@
  */
 public final class ColumnInfoRecord extends Record {
     public static final short     sid = 0x7d;
-    private short                 field_1_first_col;
-    private short                 field_2_last_col;
-    private short                 field_3_col_width;
-    private short                 field_4_xf_index;
-    private short                 field_5_options;
+    private int field_1_first_col;
+    private int field_2_last_col;
+    private int field_3_col_width;
+    private int field_4_xf_index;
+    private int field_5_options;
     private static final BitField hidden    = BitFieldFactory.getInstance(0x01);
     private static final BitField outlevel  = BitFieldFactory.getInstance(0x0700);
     private static final BitField collapsed = BitFieldFactory.getInstance(0x1000);
     // Excel seems write values 2, 10, and 260, even though spec says "must be zero"
     private short                 field_6_reserved;
 
-    public ColumnInfoRecord()
-    {
+    /**
+     * Creates a column info record with default width and format
+     */
+    public ColumnInfoRecord() {
+        setColumnWidth(2275);
+        field_5_options = 2; 
+        field_4_xf_index = 0x0f;
         field_6_reserved = 2; // seems to be the most common value
     }
 
@@ -90,7 +96,7 @@
      * @param fc - the first column index (0-based)
      */
 
-    public void setFirstColumn(short fc)
+    public void setFirstColumn(int fc)
     {
         field_1_first_col = fc;
     }
@@ -100,7 +106,7 @@
      * @param lc - the last column index (0-based)
      */
 
-    public void setLastColumn(short lc)
+    public void setLastColumn(int lc)
     {
         field_2_last_col = lc;
     }
@@ -110,7 +116,7 @@
      * @param cw - column width
      */
 
-    public void setColumnWidth(short cw)
+    public void setColumnWidth(int cw)
     {
         field_3_col_width = cw;
     }
@@ -121,20 +127,11 @@
      * @see org.apache.poi.hssf.record.ExtendedFormatRecord
      */
 
-    public void setXFIndex(short xfi)
+    public void setXFIndex(int xfi)
     {
         field_4_xf_index = xfi;
     }
 
-    /**
-     * set the options bitfield - use the bitsetters instead
-     * @param options - the bitfield raw value
-     */
-
-    public void setOptions(short options)
-    {
-        field_5_options = options;
-    }
 
     // start options bitfield
 
@@ -146,7 +143,7 @@
 
     public void setHidden(boolean ishidden)
     {
-        field_5_options = hidden.setShortBoolean(field_5_options, ishidden);
+        field_5_options = hidden.setBoolean(field_5_options, ishidden);
     }
 
     /**
@@ -155,9 +152,9 @@
      * @param olevel -outline level for the cells
      */
 
-    public void setOutlineLevel(short olevel)
+    public void setOutlineLevel(int olevel)
     {
-        field_5_options = outlevel.setShortValue(field_5_options, olevel);
+        field_5_options = outlevel.setValue(field_5_options, olevel);
     }
 
     /**
@@ -168,7 +165,7 @@
 
     public void setCollapsed(boolean iscollapsed)
     {
-        field_5_options = collapsed.setShortBoolean(field_5_options,
+        field_5_options = collapsed.setBoolean(field_5_options,
                                                     iscollapsed);
     }
 
@@ -179,7 +176,7 @@
      * @return the first column index (0-based)
      */
 
-    public short getFirstColumn()
+    public int getFirstColumn()
     {
         return field_1_first_col;
     }
@@ -189,7 +186,7 @@
      * @return the last column index (0-based)
      */
 
-    public short getLastColumn()
+    public int getLastColumn()
     {
         return field_2_last_col;
     }
@@ -199,7 +196,7 @@
      * @return column width
      */
 
-    public short getColumnWidth()
+    public int getColumnWidth()
     {
         return field_3_col_width;
     }
@@ -210,21 +207,18 @@
      * @see org.apache.poi.hssf.record.ExtendedFormatRecord
      */
 
-    public short getXFIndex()
+    public int getXFIndex()
     {
         return field_4_xf_index;
     }
 
-    /**
-     * get the options bitfield - use the bitsetters instead
-     * @return the bitfield raw value
-     */
-
-    public short getOptions()
-    {
+    public int getOptions() {
         return field_5_options;
     }
-
+    public void setOptions(int field_5_options) {
+        this.field_5_options = field_5_options;
+    }
+    
     // start options bitfield
 
     /**
@@ -244,9 +238,9 @@
      * @return outline level for the cells
      */
 
-    public short getOutlineLevel()
+    public int getOutlineLevel()
     {
-        return outlevel.getShortValue(field_5_options);
+        return outlevel.getValue(field_5_options);
     }
 
     /**
@@ -261,6 +255,31 @@
     }
 
     // end options bitfield
+    
+    public boolean containsColumn(int columnIndex) {
+        return field_1_first_col <= columnIndex && columnIndex <= field_2_last_col; 
+    }
+    public boolean isAdjacentBefore(ColumnInfoRecord other) {
+        return field_2_last_col == other.field_1_first_col - 1;
+    }
+   
+    /**
+     * @return <code>true</code> if the format, options and column width match
+     */
+    public boolean formatMatches(ColumnInfoRecord other) {
+        if (field_4_xf_index != other.field_4_xf_index) {
+            return false;
+        }
+        if (field_5_options != other.field_5_options) {
+            return false;
+        }
+        if (field_3_col_width != other.field_3_col_width) {
+            return false;
+        }
+        return true;
+    }
+    
+    
     public short getSid()
     {
         return sid;
@@ -269,13 +288,13 @@
     public int serialize(int offset, byte [] data)
     {
         LittleEndian.putShort(data, 0 + offset, sid);
-        LittleEndian.putShort(data, 2 + offset, ( short ) 12);
-        LittleEndian.putShort(data, 4 + offset, getFirstColumn());
-        LittleEndian.putShort(data, 6 + offset, getLastColumn());
-        LittleEndian.putShort(data, 8 + offset, getColumnWidth());
-        LittleEndian.putShort(data, 10 + offset, getXFIndex());
-        LittleEndian.putShort(data, 12 + offset, getOptions());
-        LittleEndian.putShort(data, 14 + offset, field_6_reserved);   
+        LittleEndian.putUShort(data, 2 + offset, 12);
+        LittleEndian.putUShort(data, 4 + offset, getFirstColumn());
+        LittleEndian.putUShort(data, 6 + offset, getLastColumn());
+        LittleEndian.putUShort(data, 8 + offset, getColumnWidth());
+        LittleEndian.putUShort(data, 10 + offset, getXFIndex());
+        LittleEndian.putUShort(data, 12 + offset, field_5_options);
+        LittleEndian.putUShort(data, 14 + offset, field_6_reserved);   
         return getRecordSize();
     }
 
@@ -286,24 +305,19 @@
 
     public String toString()
     {
-        StringBuffer buffer = new StringBuffer();
+        StringBuffer sb = new StringBuffer();
 
-        buffer.append("[COLINFO]\n");
-        buffer.append("colfirst       = ").append(getFirstColumn())
-            .append("\n");
-        buffer.append("collast        = ").append(getLastColumn())
-            .append("\n");
-        buffer.append("colwidth       = ").append(getColumnWidth())
-            .append("\n");
-        buffer.append("xfindex        = ").append(getXFIndex()).append("\n");
-        buffer.append("options        = ").append(getOptions()).append("\n");
-        buffer.append("  hidden       = ").append(getHidden()).append("\n");
-        buffer.append("  olevel       = ").append(getOutlineLevel())
-            .append("\n");
-        buffer.append("  collapsed    = ").append(getCollapsed())
-            .append("\n");
-        buffer.append("[/COLINFO]\n");
-        return buffer.toString();
+        sb.append("[COLINFO]\n");
+        sb.append("  colfirst = ").append(getFirstColumn()).append("\n");
+        sb.append("  collast  = ").append(getLastColumn()).append("\n");
+        sb.append("  colwidth = ").append(getColumnWidth()).append("\n");
+        sb.append("  xfindex  = ").append(getXFIndex()).append("\n");
+        sb.append("  options  = ").append(HexDump.shortToHex(field_5_options)).append("\n");
+        sb.append("    hidden   = ").append(getHidden()).append("\n");
+        sb.append("    olevel   = ").append(getOutlineLevel()).append("\n");
+        sb.append("    collapsed= ").append(getCollapsed()).append("\n");
+        sb.append("[/COLINFO]\n");
+        return sb.toString();
     }
 
     public Object clone() {

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/FormulaRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/FormulaRecord.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/FormulaRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/FormulaRecord.java Sat Sep 13 06:48:27 2008
@@ -18,6 +18,8 @@
 package org.apache.poi.hssf.record;
 
 import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;
+import org.apache.poi.hssf.usermodel.HSSFCell;
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
 import org.apache.poi.util.HexDump;
@@ -32,264 +34,430 @@
  */
 public final class FormulaRecord extends Record implements CellValueRecordInterface {
 
-    public static final short sid = 0x0006;   // docs say 406...because of a bug Microsoft support site article #Q184647)
-    private static int FIXED_SIZE = 22;
+	public static final short sid = 0x0006;   // docs say 406...because of a bug Microsoft support site article #Q184647)
+	private static int FIXED_SIZE = 22;
 
-    private static final BitField alwaysCalc = BitFieldFactory.getInstance(0x0001);
-    private static final BitField calcOnLoad = BitFieldFactory.getInstance(0x0002);
-    private static final BitField sharedFormula = BitFieldFactory.getInstance(0x0008);
-
-    private int               field_1_row;
-    private short             field_2_column;
-    private short             field_3_xf;
-    private double            field_4_value;
-    private short             field_5_options;
-    private int               field_6_zero;
-    private Ptg[]             field_8_parsed_expr;
-
-    /**
-     * Since the NaN support seems sketchy (different constants) we'll store and spit it out directly
-     */
-    private byte[]            value_data;
-
-    /** Creates new FormulaRecord */
-
-    public FormulaRecord() {
-        field_8_parsed_expr = Ptg.EMPTY_PTG_ARRAY;
-    }
-
-    /**
-     * Constructs a Formula record and sets its fields appropriately.
-     * Note - id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an
-     * "explanation of this bug in the documentation) or an exception
-     *  will be throw upon validation
-     *
-     * @param in the RecordInputstream to read the record from
-     */
-
-    public FormulaRecord(RecordInputStream in) {
-        super(in);
-    }
-
-    protected void fillFields(RecordInputStream in) {
-          field_1_row            = in.readUShort();
-          field_2_column         = in.readShort();
-          field_3_xf             = in.readShort();
-          field_4_value          = in.readDouble();
-          field_5_options        = in.readShort();
-
-        if (Double.isNaN(field_4_value)) {
-            value_data = in.getNANData();
-        }
-
-          field_6_zero           = in.readInt();
-          int field_7_expression_len = in.readShort(); // this length does not include any extra array data
-          field_8_parsed_expr = Ptg.readTokens(field_7_expression_len, in);
-        if (in.remaining() == 10) {
-            // TODO - this seems to occur when IntersectionPtg is present
-            // 10 extra bytes are just 0x01 and 0x00
-            // This causes POI stderr: "WARN. Unread 10 bytes of record 0x6"
-        }
-    }
-
-    public void setRow(int row) {
-        field_1_row = row;
-    }
-
-    public void setColumn(short column) {
-        field_2_column = column;
-    }
-
-    public void setXFIndex(short xf) {
-        field_3_xf = xf;
-    }
-
-    /**
-     * set the calculated value of the formula
-     *
-     * @param value  calculated value
-     */
-    public void setValue(double value) {
-        field_4_value = value;
-    }
-
-    /**
-     * set the option flags
-     *
-     * @param options  bitmask
-     */
-    public void setOptions(short options) {
-        field_5_options = options;
-    }
-
-    public int getRow() {
-        return field_1_row;
-    }
-
-    public short getColumn() {
-        return field_2_column;
-    }
-
-    public short getXFIndex() {
-        return field_3_xf;
-    }
-
-    /**
-     * get the calculated value of the formula
-     *
-     * @return calculated value
-     */
-    public double getValue() {
-        return field_4_value;
-    }
-
-    /**
-     * get the option flags
-     *
-     * @return bitmask
-     */
-    public short getOptions() {
-        return field_5_options;
-    }
-
-    public boolean isSharedFormula() {
-        return sharedFormula.isSet(field_5_options);
-    }
-    public void setSharedFormula(boolean flag) {
-        field_5_options =
-            sharedFormula.setShortBoolean(field_5_options, flag);
-    }
-
-    public boolean isAlwaysCalc() {
-        return alwaysCalc.isSet(field_5_options);
-    }
-    public void setAlwaysCalc(boolean flag) {
-        field_5_options =
-            alwaysCalc.setShortBoolean(field_5_options, flag);
-    }
-
-    public boolean isCalcOnLoad() {
-        return calcOnLoad.isSet(field_5_options);
-    }
-    public void setCalcOnLoad(boolean flag) {
-        field_5_options =
-            calcOnLoad.setShortBoolean(field_5_options, flag);
-    }
-
-    /**
-     * @return the formula tokens. never <code>null</code>
-     */
-    public Ptg[] getParsedExpression() {
-        return (Ptg[]) field_8_parsed_expr.clone();
-    }
-
-    public void setParsedExpression(Ptg[] ptgs) {
-        field_8_parsed_expr = ptgs;
-    }
-
-    /**
-     * called by constructor, should throw runtime exception in the event of a
-     * record passed with a differing ID.
-     *
-     * @param id alleged id for this record
-     */
-    protected void validateSid(short id) {
-        if (id != sid) {
-            throw new RecordFormatException("NOT A FORMULA RECORD");
-        }
-    }
-
-    public short getSid() {
-        return sid;
-    }
-
-    private int getDataSize() {
-        return FIXED_SIZE + Ptg.getEncodedSize(field_8_parsed_expr);
-    }
-    public int serialize(int offset, byte [] data) {
-
-        int dataSize = getDataSize();
-
-        LittleEndian.putShort(data, 0 + offset, sid);
-        LittleEndian.putUShort(data, 2 + offset, dataSize);
-        LittleEndian.putUShort(data, 4 + offset, getRow());
-        LittleEndian.putShort(data, 6 + offset, getColumn());
-        LittleEndian.putShort(data, 8 + offset, getXFIndex());
-
-        //only reserialize if the value is still NaN and we have old nan data
-        if (Double.isNaN(getValue()) && value_data != null) {
-            System.arraycopy(value_data,0,data,10 + offset,value_data.length);
-        } else {
-            LittleEndian.putDouble(data, 10 + offset, field_4_value);
-        }
-
-        LittleEndian.putShort(data, 18 + offset, getOptions());
-
-        //when writing the chn field (offset 20), it's supposed to be 0 but ignored on read
-        //Microsoft Excel Developer's Kit Page 318
-        LittleEndian.putInt(data, 20 + offset, 0);
-        int formulaTokensSize = Ptg.getEncodedSizeWithoutArrayData(field_8_parsed_expr);
-        LittleEndian.putUShort(data, 24 + offset, formulaTokensSize);
-        Ptg.serializePtgs(field_8_parsed_expr, data, 26+offset);
-        return 4 + dataSize;
-    }
-
-    public int getRecordSize() {
-        return 4 + getDataSize();
-    }
-
-    public boolean isInValueSection() {
-        return true;
-    }
-
-    public boolean isValue() {
-        return true;
-    }
-
-    public String toString() {
-
-        StringBuffer sb = new StringBuffer();
-        sb.append("[FORMULA]\n");
-        sb.append("    .row       = ").append(HexDump.shortToHex(getRow())).append("\n");
-        sb.append("    .column    = ").append(HexDump.shortToHex(getColumn())).append("\n");
-        sb.append("    .xf        = ").append(HexDump.shortToHex(getXFIndex())).append("\n");
-        sb.append("    .value     = ");
-        if (Double.isNaN(this.getValue()) && value_data != null) {
-            sb.append("(NaN)").append(HexDump.dump(value_data,0,0)).append("\n");
-        } else {
-            sb.append(getValue()).append("\n");
-        }
-        sb.append("    .options   = ").append(HexDump.shortToHex(getOptions())).append("\n");
-        sb.append("    .alwaysCalc= ").append(alwaysCalc.isSet(getOptions())).append("\n");
-        sb.append("    .calcOnLoad= ").append(calcOnLoad.isSet(getOptions())).append("\n");
-        sb.append("    .shared    = ").append(sharedFormula.isSet(getOptions())).append("\n");
-        sb.append("    .zero      = ").append(HexDump.intToHex(field_6_zero)).append("\n");
-
-        for (int k = 0; k < field_8_parsed_expr.length; k++ ) {
-            sb.append("     Ptg[").append(k).append("]=");
-            Ptg ptg = field_8_parsed_expr[k];
-            sb.append(ptg.toString()).append(ptg.getRVAType()).append("\n");
-        }
-        sb.append("[/FORMULA]\n");
-        return sb.toString();
-    }
-
-    public Object clone() {
-      FormulaRecord rec = new FormulaRecord();
-      rec.field_1_row = field_1_row;
-      rec.field_2_column = field_2_column;
-      rec.field_3_xf = field_3_xf;
-      rec.field_4_value = field_4_value;
-      rec.field_5_options = field_5_options;
-      rec.field_6_zero = field_6_zero;
-      int nTokens = field_8_parsed_expr.length;
-      Ptg[] ptgs = new Ptg[nTokens];
-      for (int i=0; i< nTokens; i++) {
-        ptgs[i] = field_8_parsed_expr[i].copy();
-      }
-      rec.field_8_parsed_expr = ptgs;
-      rec.value_data = value_data;
-      return rec;
-    }
+	private static final BitField alwaysCalc = BitFieldFactory.getInstance(0x0001);
+	private static final BitField calcOnLoad = BitFieldFactory.getInstance(0x0002);
+	private static final BitField sharedFormula = BitFieldFactory.getInstance(0x0008);
+
+	/**
+	 * Manages the cached formula result values of other types besides numeric.
+	 * Excel encodes the same 8 bytes that would be field_4_value with various NaN
+	 * values that are decoded/encoded by this class. 
+	 */
+	private static final class SpecialCachedValue {
+		/** deliberately chosen by Excel in order to encode other values within Double NaNs */
+		private static final long BIT_MARKER = 0xFFFF000000000000L;
+		private static final int VARIABLE_DATA_LENGTH = 6;
+		private static final int DATA_INDEX = 2;
+
+		public static final int STRING = 0;
+		public static final int BOOLEAN = 1;
+		public static final int ERROR_CODE = 2;
+		public static final int EMPTY = 3;
+
+		private final byte[] _variableData;
+
+		private SpecialCachedValue(byte[] data) {
+			_variableData = data;
+		}
+		public int getTypeCode() {
+			return _variableData[0];
+		}
+
+		/**
+		 * @return <code>null</code> if the double value encoded by <tt>valueLongBits</tt> 
+		 * is a normal (non NaN) double value.
+		 */
+		public static SpecialCachedValue create(long valueLongBits) {
+			if ((BIT_MARKER & valueLongBits) != BIT_MARKER) {
+				return null;
+			}
+
+			byte[] result = new byte[VARIABLE_DATA_LENGTH];
+			long x = valueLongBits;
+			for (int i=0; i<VARIABLE_DATA_LENGTH; i++) {
+				result[i] = (byte) x;
+				x >>= 8;
+			}
+			switch (result[0]) {
+				case STRING:
+				case BOOLEAN:
+				case ERROR_CODE:
+				case EMPTY:
+					break;
+				default:
+					throw new RecordFormatException("Bad special value code (" + result[0] + ")");
+			}
+			return new SpecialCachedValue(result);
+		}
+		public void serialize(byte[] data, int offset) {
+			System.arraycopy(_variableData, 0, data, offset, VARIABLE_DATA_LENGTH);
+			LittleEndian.putUShort(data, offset+VARIABLE_DATA_LENGTH, 0xFFFF);
+		}
+		public String formatDebugString() {
+			return formatValue() + ' ' + HexDump.toHex(_variableData);
+		}
+		private String formatValue() {
+			int typeCode = getTypeCode();
+			switch (typeCode) {
+				case STRING:	 return "<string>";
+				case BOOLEAN:	return getDataValue() == 0 ? "FALSE" : "TRUE";
+				case ERROR_CODE: return ErrorEval.getText(getDataValue());
+				case EMPTY:	  return "<empty>";
+			}
+			return "#error(type=" + typeCode + ")#";
+		}
+		private int getDataValue() {
+			return _variableData[DATA_INDEX];
+		}
+		public static SpecialCachedValue createCachedEmptyValue() {
+			return create(EMPTY, 0);
+		}
+		public static SpecialCachedValue createForString() {
+			return create(STRING, 0);
+		}
+		public static SpecialCachedValue createCachedBoolean(boolean b) {
+			return create(BOOLEAN, b ? 0 : 1);
+		}
+		public static SpecialCachedValue createCachedErrorCode(int errorCode) {
+			return create(ERROR_CODE, errorCode);
+		}
+		private static SpecialCachedValue create(int code, int data) {
+			byte[] vd = {
+					(byte) code,
+					0,
+					(byte) data,
+					0,
+					0,
+					0,
+			};
+			return new SpecialCachedValue(vd);
+		}
+		public String toString() {
+			StringBuffer sb = new StringBuffer(64);
+			sb.append(getClass().getName());
+			sb.append('[').append(formatValue()).append(']');
+			return sb.toString();
+		}
+		public int getValueType() {
+			int typeCode = getTypeCode();
+			switch (typeCode) {
+				case STRING:	 return HSSFCell.CELL_TYPE_STRING;
+				case BOOLEAN:	return HSSFCell.CELL_TYPE_BOOLEAN;
+				case ERROR_CODE: return HSSFCell.CELL_TYPE_ERROR;
+				case EMPTY:	  return HSSFCell.CELL_TYPE_STRING; // is this correct?
+			}
+			throw new IllegalStateException("Unexpected type id (" + typeCode + ")");
+		}
+		public boolean getBooleanValue() {
+			if (getTypeCode() != BOOLEAN) {
+				throw new IllegalStateException("Not a boolean cached value - " + formatValue());
+			}
+			return getDataValue() != 0;
+		}
+		public int getErrorValue() {
+			if (getTypeCode() != ERROR_CODE) {
+				throw new IllegalStateException("Not an error cached value - " + formatValue());
+			}
+			return getDataValue();
+		}
+	}
+
+
+
+	private int    field_1_row;
+	private short  field_2_column;
+	private short  field_3_xf;
+	private double field_4_value;
+	private short  field_5_options;
+	private int    field_6_zero;
+	private Ptg[]  field_8_parsed_expr;
+
+	/**
+	 * Since the NaN support seems sketchy (different constants) we'll store and spit it out directly
+	 */
+	private SpecialCachedValue specialCachedValue;
+
+	/** Creates new FormulaRecord */
+
+	public FormulaRecord() {
+		field_8_parsed_expr = Ptg.EMPTY_PTG_ARRAY;
+	}
+
+	/**
+	 * Constructs a Formula record and sets its fields appropriately.
+	 * Note - id must be 0x06 (NOT 0x406 see MSKB #Q184647 for an
+	 * "explanation of this bug in the documentation) or an exception
+	 *  will be throw upon validation
+	 *
+	 * @param in the RecordInputstream to read the record from
+	 */
+
+	public FormulaRecord(RecordInputStream in) {
+		super(in);
+	}
+
+	protected void fillFields(RecordInputStream in) {
+		field_1_row	 = in.readUShort();
+		field_2_column  = in.readShort();
+		field_3_xf	  = in.readShort();
+		long valueLongBits  = in.readLong();
+		field_5_options = in.readShort();
+		specialCachedValue = SpecialCachedValue.create(valueLongBits);
+		if (specialCachedValue == null) {
+			field_4_value = Double.longBitsToDouble(valueLongBits);
+		}
+
+		field_6_zero		   = in.readInt();
+		int field_7_expression_len = in.readShort(); // this length does not include any extra array data
+		field_8_parsed_expr = Ptg.readTokens(field_7_expression_len, in);
+		if (in.remaining() == 10) {
+			// TODO - this seems to occur when IntersectionPtg is present
+			// 10 extra bytes are just 0x01 and 0x00
+			// This causes POI stderr: "WARN. Unread 10 bytes of record 0x6"
+		}
+	}
+
+
+	public void setRow(int row) {
+		field_1_row = row;
+	}
+
+	public void setColumn(short column) {
+		field_2_column = column;
+	}
+
+	public void setXFIndex(short xf) {
+		field_3_xf = xf;
+	}
+
+	/**
+	 * set the calculated value of the formula
+	 *
+	 * @param value  calculated value
+	 */
+	public void setValue(double value) {
+		field_4_value = value;
+		specialCachedValue = null;
+	}
+
+	public void setCachedResultTypeEmptyString() {
+		specialCachedValue = SpecialCachedValue.createCachedEmptyValue();
+	}
+	public void setCachedResultTypeString() {
+		specialCachedValue = SpecialCachedValue.createForString();
+	}
+	public void setCachedResultErrorCode(int errorCode) {
+		specialCachedValue = SpecialCachedValue.createCachedErrorCode(errorCode);
+	}
+	public void setCachedResultBoolean(boolean value) {
+		specialCachedValue = SpecialCachedValue.createCachedBoolean(value);
+	}
+	/**
+	 * @return <code>true</code> if this {@link FormulaRecord} is followed by a
+	 *  {@link StringRecord} representing the cached text result of the formula
+	 *  evaluation.
+	 */
+	public boolean hasCachedResultString() {
+		if (specialCachedValue == null) {
+			return false;
+		}
+		return specialCachedValue.getTypeCode() == SpecialCachedValue.STRING;
+	}
+
+	public int getCachedResultType() {
+		if (specialCachedValue == null) {
+			return HSSFCell.CELL_TYPE_NUMERIC;
+		}
+		return specialCachedValue.getValueType();
+	}
+
+	public boolean getCachedBooleanValue() {
+		return specialCachedValue.getBooleanValue();
+	}
+	public int getCachedErrorValue() {
+		return specialCachedValue.getErrorValue();
+	}
+
+
+	/**
+	 * set the option flags
+	 *
+	 * @param options  bitmask
+	 */
+	public void setOptions(short options) {
+		field_5_options = options;
+	}
+
+	public int getRow() {
+		return field_1_row;
+	}
+
+	public short getColumn() {
+		return field_2_column;
+	}
+
+	public short getXFIndex() {
+		return field_3_xf;
+	}
+
+	/**
+	 * get the calculated value of the formula
+	 *
+	 * @return calculated value
+	 */
+	public double getValue() {
+		return field_4_value;
+	}
+
+	/**
+	 * get the option flags
+	 *
+	 * @return bitmask
+	 */
+	public short getOptions() {
+		return field_5_options;
+	}
+
+	public boolean isSharedFormula() {
+		return sharedFormula.isSet(field_5_options);
+	}
+	public void setSharedFormula(boolean flag) {
+		field_5_options =
+			sharedFormula.setShortBoolean(field_5_options, flag);
+	}
+
+	public boolean isAlwaysCalc() {
+		return alwaysCalc.isSet(field_5_options);
+	}
+	public void setAlwaysCalc(boolean flag) {
+		field_5_options =
+			alwaysCalc.setShortBoolean(field_5_options, flag);
+	}
+
+	public boolean isCalcOnLoad() {
+		return calcOnLoad.isSet(field_5_options);
+	}
+	public void setCalcOnLoad(boolean flag) {
+		field_5_options =
+			calcOnLoad.setShortBoolean(field_5_options, flag);
+	}
+
+	/**
+	 * @return the formula tokens. never <code>null</code>
+	 */
+	public Ptg[] getParsedExpression() {
+		return (Ptg[]) field_8_parsed_expr.clone();
+	}
+
+	public void setParsedExpression(Ptg[] ptgs) {
+		field_8_parsed_expr = ptgs;
+	}
+
+	/**
+	 * called by constructor, should throw runtime exception in the event of a
+	 * record passed with a differing ID.
+	 *
+	 * @param id alleged id for this record
+	 */
+	protected void validateSid(short id) {
+		if (id != sid) {
+			throw new RecordFormatException("NOT A FORMULA RECORD");
+		}
+	}
+
+	public short getSid() {
+		return sid;
+	}
+
+	private int getDataSize() {
+		return FIXED_SIZE + Ptg.getEncodedSize(field_8_parsed_expr);
+	}
+	public int serialize(int offset, byte [] data) {
+
+		int dataSize = getDataSize();
+
+		LittleEndian.putShort(data, 0 + offset, sid);
+		LittleEndian.putUShort(data, 2 + offset, dataSize);
+		LittleEndian.putUShort(data, 4 + offset, getRow());
+		LittleEndian.putShort(data, 6 + offset, getColumn());
+		LittleEndian.putShort(data, 8 + offset, getXFIndex());
+
+		if (specialCachedValue == null) {
+			LittleEndian.putDouble(data, 10 + offset, field_4_value);
+		} else {
+			specialCachedValue.serialize(data, 10+offset);
+		}
+
+		LittleEndian.putShort(data, 18 + offset, getOptions());
+
+		//when writing the chn field (offset 20), it's supposed to be 0 but ignored on read
+		//Microsoft Excel Developer's Kit Page 318
+		LittleEndian.putInt(data, 20 + offset, 0);
+		int formulaTokensSize = Ptg.getEncodedSizeWithoutArrayData(field_8_parsed_expr);
+		LittleEndian.putUShort(data, 24 + offset, formulaTokensSize);
+		Ptg.serializePtgs(field_8_parsed_expr, data, 26+offset);
+		return 4 + dataSize;
+	}
+
+	public int getRecordSize() {
+		return 4 + getDataSize();
+	}
+
+	public boolean isInValueSection() {
+		return true;
+	}
+
+	public boolean isValue() {
+		return true;
+	}
+
+	public String toString() {
+
+		StringBuffer sb = new StringBuffer();
+		sb.append("[FORMULA]\n");
+		sb.append("	.row	   = ").append(HexDump.shortToHex(getRow())).append("\n");
+		sb.append("	.column	= ").append(HexDump.shortToHex(getColumn())).append("\n");
+		sb.append("	.xf		= ").append(HexDump.shortToHex(getXFIndex())).append("\n");
+		sb.append("	.value	 = ");
+		if (specialCachedValue == null) {
+			sb.append(field_4_value).append("\n");
+		} else {
+			sb.append(specialCachedValue.formatDebugString()).append("\n");
+		}
+		sb.append("	.options   = ").append(HexDump.shortToHex(getOptions())).append("\n");
+		sb.append("	.alwaysCalc= ").append(alwaysCalc.isSet(getOptions())).append("\n");
+		sb.append("	.calcOnLoad= ").append(calcOnLoad.isSet(getOptions())).append("\n");
+		sb.append("	.shared	= ").append(sharedFormula.isSet(getOptions())).append("\n");
+		sb.append("	.zero	  = ").append(HexDump.intToHex(field_6_zero)).append("\n");
+
+		for (int k = 0; k < field_8_parsed_expr.length; k++ ) {
+			sb.append("	 Ptg[").append(k).append("]=");
+			Ptg ptg = field_8_parsed_expr[k];
+			sb.append(ptg.toString()).append(ptg.getRVAType()).append("\n");
+		}
+		sb.append("[/FORMULA]\n");
+		return sb.toString();
+	}
+
+	public Object clone() {
+		FormulaRecord rec = new FormulaRecord();
+		rec.field_1_row = field_1_row;
+		rec.field_2_column = field_2_column;
+		rec.field_3_xf = field_3_xf;
+		rec.field_4_value = field_4_value;
+		rec.field_5_options = field_5_options;
+		rec.field_6_zero = field_6_zero;
+		int nTokens = field_8_parsed_expr.length;
+		Ptg[] ptgs = new Ptg[nTokens];
+		for (int i = 0; i < nTokens; i++) {
+			ptgs[i] = field_8_parsed_expr[i].copy();
+		}
+		rec.field_8_parsed_expr = ptgs;
+		rec.specialCachedValue = specialCachedValue;
+		return rec;
+	}
 }
 

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java?rev=694947&r1=694946&r2=694947&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java Sat Sep 13 06:48:27 2008
@@ -209,30 +209,18 @@
     return result;
   }
 
-  byte[] NAN_data = null;
   public double readDouble() {
-    checkRecordPosition();    
-    //Reset NAN data
-    NAN_data = null;
-    double result = LittleEndian.getDouble(data, recordOffset);
-    //Excel represents NAN in several ways, at this point in time we do not often
-    //know the sequence of bytes, so as a hack we store the NAN byte sequence
-    //so that it is not corrupted.
+    checkRecordPosition();
+    long valueLongBits = LittleEndian.getLong(data, recordOffset);
+    double result = Double.longBitsToDouble(valueLongBits);
     if (Double.isNaN(result)) {
-      NAN_data = new byte[8];
-      System.arraycopy(data, recordOffset, NAN_data, 0, 8);
+      throw new RuntimeException("Did not expect to read NaN");
     }
-    
     recordOffset += LittleEndian.DOUBLE_SIZE;
     pos += LittleEndian.DOUBLE_SIZE;
     return result;
   }
-  
-  public byte[] getNANData() {
-    if (NAN_data == null)
-      throw new RecordFormatException("Do NOT call getNANData without calling readDouble that returns NaN");
-    return NAN_data;
-  }
+
   
   public short[] readShortArray() {
     checkRecordPosition();
@@ -276,9 +264,6 @@
   }
     
   public String readCompressedUnicode(int length) {
-    if(length == 0) {
-        return "";
-    }
     if ((length < 0) || ((remaining() < length) && !isContinueNext())) {
             throw new IllegalArgumentException("Illegal length " + length);
     }
@@ -291,9 +276,7 @@
           if(compressByte != 0) throw new IllegalArgumentException("compressByte in continue records must be 0 while reading compressed unicode");
       }
       byte b = readByte();
-      //Typecast direct to char from byte with high bit set causes all ones
-      //in the high byte of the char (which is of course incorrect)
-      char ch = (char)( (short)0xff & (short)b );
+      char ch = (char)(0x00FF & b); // avoid sex
       buf.append(ch); 
     }
     return buf.toString();    



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