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