diff options
author | Yegor Kozlov <yegor@apache.org> | 2010-11-21 11:54:40 +0000 |
---|---|---|
committer | Yegor Kozlov <yegor@apache.org> | 2010-11-21 11:54:40 +0000 |
commit | 41b294edbf16b4819856560ac0c889fd6cf9b506 (patch) | |
tree | 5ddc4d0c08b1415ca528beb246f9053f2ef89de2 | |
parent | af69c811999d73e463daa38f4f15175c38b5e374 (diff) | |
download | poi-41b294edbf16b4819856560ac0c889fd6cf9b506.tar.gz poi-41b294edbf16b4819856560ac0c889fd6cf9b506.zip |
moved common formula-related code to org.apache.poi.ss.formula, eliminated dependencies on HSSF, reduced the number of eclipse warnings
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1037432 13f79535-47bb-0310-9956-ffa450edef68
130 files changed, 27 insertions, 12285 deletions
diff --git a/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java b/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java index c2e234ce34..44de2d638d 100644 --- a/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java +++ b/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java @@ -24,7 +24,7 @@ import java.io.InputStream; import java.io.PrintStream; import org.apache.poi.POIOLE2TextExtractor; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFComment; diff --git a/src/java/org/apache/poi/hssf/model/InternalSheet.java b/src/java/org/apache/poi/hssf/model/InternalSheet.java index aae5496a1e..9890688f16 100644 --- a/src/java/org/apache/poi/hssf/model/InternalSheet.java +++ b/src/java/org/apache/poi/hssf/model/InternalSheet.java @@ -69,7 +69,7 @@ import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; import org.apache.poi.hssf.record.aggregates.WorksheetProtectionBlock; import org.apache.poi.hssf.record.aggregates.RecordAggregate.PositionTrackingVisitor; import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor; -import org.apache.poi.hssf.record.formula.FormulaShifter; +import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.hssf.util.PaneInformation; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.Internal; diff --git a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java index 28b6ac6263..ce8d011feb 100644 --- a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java +++ b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java @@ -82,7 +82,7 @@ import org.apache.poi.hssf.record.WriteAccessRecord; import org.apache.poi.hssf.record.WriteProtectRecord; import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.record.formula.NameXPtg; -import org.apache.poi.hssf.record.formula.FormulaShifter; +import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName; diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java index cd38fefd52..6568a91a78 100644 --- a/src/java/org/apache/poi/hssf/record/FormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -18,7 +18,7 @@ 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.ss.formula.eval.ErrorEval; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.ss.formula.Formula; import org.apache.poi.util.BitField; diff --git a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java index 9e5b9c8b38..30625628bb 100644 --- a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java @@ -21,6 +21,7 @@ import org.apache.poi.hssf.record.formula.*; import org.apache.poi.hssf.util.CellRangeAddress8Bit; import org.apache.poi.ss.formula.Formula; import org.apache.poi.ss.SpreadsheetVersion; +import org.apache.poi.ss.formula.SharedFormula; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; diff --git a/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java index 73f39db774..05dbec24df 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java @@ -26,7 +26,7 @@ import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.formula.AreaErrPtg; import org.apache.poi.hssf.record.formula.AreaPtg; -import org.apache.poi.hssf.record.formula.FormulaShifter; +import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.ss.util.CellRangeAddress; diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java b/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java index fa54923c08..cffa34173c 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java @@ -22,7 +22,7 @@ import java.util.List; import org.apache.poi.hssf.model.RecordStream; import org.apache.poi.hssf.record.CFHeaderRecord; -import org.apache.poi.hssf.record.formula.FormulaShifter; +import org.apache.poi.ss.formula.FormulaShifter; /** * Holds all the conditional formatting for a workbook sheet.<p/> diff --git a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java index 7a3791e2b7..afe6f2b1b1 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java @@ -38,7 +38,7 @@ import org.apache.poi.hssf.record.RowRecord; import org.apache.poi.hssf.record.SharedFormulaRecord; import org.apache.poi.hssf.record.TableRecord; import org.apache.poi.hssf.record.UnknownRecord; -import org.apache.poi.hssf.record.formula.FormulaShifter; +import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.SpreadsheetVersion; /** diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java index 17de37ed19..5c44c2ae82 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java @@ -29,7 +29,7 @@ import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.RecordBase; import org.apache.poi.hssf.record.StringRecord; import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor; -import org.apache.poi.hssf.record.formula.FormulaShifter; +import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.hssf.record.formula.Ptg; /** diff --git a/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java b/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java index c6a0dedd20..1e8d2f0cfc 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java @@ -17,8 +17,8 @@ package 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.formula.function.FunctionMetadata; +import org.apache.poi.ss.formula.function.FunctionMetadataRegistry; /** diff --git a/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java b/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java index 1a75a1ee65..b64977e3e8 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java @@ -17,7 +17,6 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.hssf.record.RecordFormatException; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; @@ -62,7 +61,7 @@ public final class ExpPtg extends ControlPtg { } public String toFormulaString() { - throw new RecordFormatException("Coding Error: Expected ExpPtg to be converted from Shared to Non-Shared Formula by ValueRecordsAggregate, but it wasn't"); + throw new RuntimeException("Coding Error: Expected ExpPtg to be converted from Shared to Non-Shared Formula by ValueRecordsAggregate, but it wasn't"); } public String toString() { diff --git a/src/java/org/apache/poi/hssf/record/formula/ExternSheetNameResolver.java b/src/java/org/apache/poi/hssf/record/formula/ExternSheetNameResolver.java index dadbcb8702..c1203e3e87 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ExternSheetNameResolver.java +++ b/src/java/org/apache/poi/hssf/record/formula/ExternSheetNameResolver.java @@ -19,6 +19,7 @@ package org.apache.poi.hssf.record.formula; import org.apache.poi.ss.formula.FormulaRenderingWorkbook; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet; +import org.apache.poi.ss.formula.SheetNameFormatter; /** * @author Josh Micich diff --git a/src/java/org/apache/poi/hssf/record/formula/FormulaShifter.java b/src/java/org/apache/poi/hssf/record/formula/FormulaShifter.java deleted file mode 100644 index 87683d64ee..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/FormulaShifter.java +++ /dev/null @@ -1,294 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula; - - -/** - * @author Josh Micich - */ -public final class FormulaShifter { - - /** - * Extern sheet index of sheet where moving is occurring - */ - private final int _externSheetIndex; - private final int _firstMovedIndex; - private final int _lastMovedIndex; - private final int _amountToMove; - - private FormulaShifter(int externSheetIndex, int firstMovedIndex, int lastMovedIndex, int amountToMove) { - if (amountToMove == 0) { - throw new IllegalArgumentException("amountToMove must not be zero"); - } - if (firstMovedIndex > lastMovedIndex) { - throw new IllegalArgumentException("firstMovedIndex, lastMovedIndex out of order"); - } - _externSheetIndex = externSheetIndex; - _firstMovedIndex = firstMovedIndex; - _lastMovedIndex = lastMovedIndex; - _amountToMove = amountToMove; - } - - public static FormulaShifter createForRowShift(int externSheetIndex, int firstMovedRowIndex, int lastMovedRowIndex, int numberOfRowsToMove) { - return new FormulaShifter(externSheetIndex, firstMovedRowIndex, lastMovedRowIndex, numberOfRowsToMove); - } - - public String toString() { - StringBuffer sb = new StringBuffer(); - - sb.append(getClass().getName()); - sb.append(" ["); - sb.append(_firstMovedIndex); - sb.append(_lastMovedIndex); - sb.append(_amountToMove); - return sb.toString(); - } - - /** - * @param ptgs - if necessary, will get modified by this method - * @param currentExternSheetIx - the extern sheet index of the sheet that contains the formula being adjusted - * @return <code>true</code> if a change was made to the formula tokens - */ - public boolean adjustFormula(Ptg[] ptgs, int currentExternSheetIx) { - boolean refsWereChanged = false; - for(int i=0; i<ptgs.length; i++) { - Ptg newPtg = adjustPtg(ptgs[i], currentExternSheetIx); - if (newPtg != null) { - refsWereChanged = true; - ptgs[i] = newPtg; - } - } - return refsWereChanged; - } - - private Ptg adjustPtg(Ptg ptg, int currentExternSheetIx) { - return adjustPtgDueToRowMove(ptg, currentExternSheetIx); - } - /** - * @return <code>true</code> if this Ptg needed to be changed - */ - private Ptg adjustPtgDueToRowMove(Ptg ptg, int currentExternSheetIx) { - if(ptg instanceof RefPtg) { - if (currentExternSheetIx != _externSheetIndex) { - // local refs on other sheets are unaffected - return null; - } - RefPtg rptg = (RefPtg)ptg; - return rowMoveRefPtg(rptg); - } - if(ptg instanceof Ref3DPtg) { - Ref3DPtg rptg = (Ref3DPtg)ptg; - if (_externSheetIndex != rptg.getExternSheetIndex()) { - // only move 3D refs that refer to the sheet with cells being moved - // (currentExternSheetIx is irrelevant) - return null; - } - return rowMoveRefPtg(rptg); - } - if(ptg instanceof Area2DPtgBase) { - if (currentExternSheetIx != _externSheetIndex) { - // local refs on other sheets are unaffected - return ptg; - } - return rowMoveAreaPtg((Area2DPtgBase)ptg); - } - if(ptg instanceof Area3DPtg) { - Area3DPtg aptg = (Area3DPtg)ptg; - if (_externSheetIndex != aptg.getExternSheetIndex()) { - // only move 3D refs that refer to the sheet with cells being moved - // (currentExternSheetIx is irrelevant) - return null; - } - return rowMoveAreaPtg(aptg); - } - return null; - } - - private Ptg rowMoveRefPtg(RefPtgBase rptg) { - int refRow = rptg.getRow(); - if (_firstMovedIndex <= refRow && refRow <= _lastMovedIndex) { - // Rows being moved completely enclose the ref. - // - move the area ref along with the rows regardless of destination - rptg.setRow(refRow + _amountToMove); - return rptg; - } - // else rules for adjusting area may also depend on the destination of the moved rows - - int destFirstRowIndex = _firstMovedIndex + _amountToMove; - int destLastRowIndex = _lastMovedIndex + _amountToMove; - - // ref is outside source rows - // check for clashes with destination - - if (destLastRowIndex < refRow || refRow < destFirstRowIndex) { - // destination rows are completely outside ref - return null; - } - - if (destFirstRowIndex <= refRow && refRow <= destLastRowIndex) { - // destination rows enclose the area (possibly exactly) - return createDeletedRef(rptg); - } - throw new IllegalStateException("Situation not covered: (" + _firstMovedIndex + ", " + - _lastMovedIndex + ", " + _amountToMove + ", " + refRow + ", " + refRow + ")"); - } - - private Ptg rowMoveAreaPtg(AreaPtgBase aptg) { - int aFirstRow = aptg.getFirstRow(); - int aLastRow = aptg.getLastRow(); - if (_firstMovedIndex <= aFirstRow && aLastRow <= _lastMovedIndex) { - // Rows being moved completely enclose the area ref. - // - move the area ref along with the rows regardless of destination - aptg.setFirstRow(aFirstRow + _amountToMove); - aptg.setLastRow(aLastRow + _amountToMove); - return aptg; - } - // else rules for adjusting area may also depend on the destination of the moved rows - - int destFirstRowIndex = _firstMovedIndex + _amountToMove; - int destLastRowIndex = _lastMovedIndex + _amountToMove; - - if (aFirstRow < _firstMovedIndex && _lastMovedIndex < aLastRow) { - // Rows moved were originally *completely* within the area ref - - // If the destination of the rows overlaps either the top - // or bottom of the area ref there will be a change - if (destFirstRowIndex < aFirstRow && aFirstRow <= destLastRowIndex) { - // truncate the top of the area by the moved rows - aptg.setFirstRow(destLastRowIndex+1); - return aptg; - } else if (destFirstRowIndex <= aLastRow && aLastRow < destLastRowIndex) { - // truncate the bottom of the area by the moved rows - aptg.setLastRow(destFirstRowIndex-1); - return aptg; - } - // else - rows have moved completely outside the area ref, - // or still remain completely within the area ref - return null; // - no change to the area - } - if (_firstMovedIndex <= aFirstRow && aFirstRow <= _lastMovedIndex) { - // Rows moved include the first row of the area ref, but not the last row - // btw: (aLastRow > _lastMovedIndex) - if (_amountToMove < 0) { - // simple case - expand area by shifting top upward - aptg.setFirstRow(aFirstRow + _amountToMove); - return aptg; - } - if (destFirstRowIndex > aLastRow) { - // in this case, excel ignores the row move - return null; - } - int newFirstRowIx = aFirstRow + _amountToMove; - if (destLastRowIndex < aLastRow) { - // end of area is preserved (will remain exact same row) - // the top area row is moved simply - aptg.setFirstRow(newFirstRowIx); - return aptg; - } - // else - bottom area row has been replaced - both area top and bottom may move now - int areaRemainingTopRowIx = _lastMovedIndex + 1; - if (destFirstRowIndex > areaRemainingTopRowIx) { - // old top row of area has moved deep within the area, and exposed a new top row - newFirstRowIx = areaRemainingTopRowIx; - } - aptg.setFirstRow(newFirstRowIx); - aptg.setLastRow(Math.max(aLastRow, destLastRowIndex)); - return aptg; - } - if (_firstMovedIndex <= aLastRow && aLastRow <= _lastMovedIndex) { - // Rows moved include the last row of the area ref, but not the first - // btw: (aFirstRow < _firstMovedIndex) - if (_amountToMove > 0) { - // simple case - expand area by shifting bottom downward - aptg.setLastRow(aLastRow + _amountToMove); - return aptg; - } - if (destLastRowIndex < aFirstRow) { - // in this case, excel ignores the row move - return null; - } - int newLastRowIx = aLastRow + _amountToMove; - if (destFirstRowIndex > aFirstRow) { - // top of area is preserved (will remain exact same row) - // the bottom area row is moved simply - aptg.setLastRow(newLastRowIx); - return aptg; - } - // else - top area row has been replaced - both area top and bottom may move now - int areaRemainingBottomRowIx = _firstMovedIndex - 1; - if (destLastRowIndex < areaRemainingBottomRowIx) { - // old bottom row of area has moved up deep within the area, and exposed a new bottom row - newLastRowIx = areaRemainingBottomRowIx; - } - aptg.setFirstRow(Math.min(aFirstRow, destFirstRowIndex)); - aptg.setLastRow(newLastRowIx); - return aptg; - } - // else source rows include none of the rows of the area ref - // check for clashes with destination - - if (destLastRowIndex < aFirstRow || aLastRow < destFirstRowIndex) { - // destination rows are completely outside area ref - return null; - } - - if (destFirstRowIndex <= aFirstRow && aLastRow <= destLastRowIndex) { - // destination rows enclose the area (possibly exactly) - return createDeletedRef(aptg); - } - - if (aFirstRow <= destFirstRowIndex && destLastRowIndex <= aLastRow) { - // destination rows are within area ref (possibly exact on top or bottom, but not both) - return null; // - no change to area - } - - if (destFirstRowIndex < aFirstRow && aFirstRow <= destLastRowIndex) { - // dest rows overlap top of area - // - truncate the top - aptg.setFirstRow(destLastRowIndex+1); - return aptg; - } - if (destFirstRowIndex < aLastRow && aLastRow <= destLastRowIndex) { - // dest rows overlap bottom of area - // - truncate the bottom - aptg.setLastRow(destFirstRowIndex-1); - return aptg; - } - throw new IllegalStateException("Situation not covered: (" + _firstMovedIndex + ", " + - _lastMovedIndex + ", " + _amountToMove + ", " + aFirstRow + ", " + aLastRow + ")"); - } - - private static Ptg createDeletedRef(Ptg ptg) { - if (ptg instanceof RefPtg) { - return new RefErrorPtg(); - } - if (ptg instanceof Ref3DPtg) { - Ref3DPtg rptg = (Ref3DPtg) ptg; - return new DeletedRef3DPtg(rptg.getExternSheetIndex()); - } - if (ptg instanceof AreaPtg) { - return new AreaErrPtg(); - } - if (ptg instanceof Area3DPtg) { - Area3DPtg area3DPtg = (Area3DPtg) ptg; - return new DeletedArea3DPtg(area3DPtg.getExternSheetIndex()); - } - - throw new IllegalArgumentException("Unexpected ref ptg class (" + ptg.getClass().getName() + ")"); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java b/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java index 4a2ca1bfcb..dffa48e73e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java @@ -17,8 +17,8 @@ package 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.formula.function.FunctionMetadata; +import org.apache.poi.ss.formula.function.FunctionMetadataRegistry; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; diff --git a/src/java/org/apache/poi/hssf/record/formula/FuncVarPtg.java b/src/java/org/apache/poi/hssf/record/formula/FuncVarPtg.java index 607a64f17a..f9c9c58d92 100644 --- a/src/java/org/apache/poi/hssf/record/formula/FuncVarPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/FuncVarPtg.java @@ -16,8 +16,8 @@ ==================================================================== */ package 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.formula.function.FunctionMetadata; +import org.apache.poi.ss.formula.function.FunctionMetadataRegistry; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; diff --git a/src/java/org/apache/poi/hssf/record/formula/SharedFormula.java b/src/java/org/apache/poi/hssf/record/formula/SharedFormula.java deleted file mode 100644 index db55a7015f..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/SharedFormula.java +++ /dev/null @@ -1,97 +0,0 @@ -/* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================== */
-package org.apache.poi.hssf.record.formula;
-
-import org.apache.poi.ss.SpreadsheetVersion;
-
-/**
- * Encapsulates logic to convert shared formulaa into non shared equivalent
- */
-public class SharedFormula {
-
- private final int _columnWrappingMask;
- private final int _rowWrappingMask;
-
- public SharedFormula(SpreadsheetVersion ssVersion){
- _columnWrappingMask = ssVersion.getLastColumnIndex(); //"IV" for .xls and "XFD" for .xlsx
- _rowWrappingMask = ssVersion.getLastRowIndex();
- }
-
- /**
- * Creates a non shared formula from the shared formula counterpart, i.e.
- * Converts the shared formula into the equivalent {@link Ptg} array that it would have,
- * were it not shared.
- *
- * @param ptgs parsed tokens of the shared formula
- * @param formulaRow
- * @param formulaColumn
- */
- public Ptg[] convertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) {
-
- Ptg[] newPtgStack = new Ptg[ptgs.length];
-
- for (int k = 0; k < ptgs.length; k++) {
- Ptg ptg = ptgs[k];
- byte originalOperandClass = -1;
- if (!ptg.isBaseToken()) {
- originalOperandClass = ptg.getPtgClass();
- }
- if (ptg instanceof RefPtgBase) {
- RefPtgBase refNPtg = (RefPtgBase)ptg;
- ptg = new RefPtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()),
- fixupRelativeColumn(formulaColumn,refNPtg.getColumn(),refNPtg.isColRelative()),
- refNPtg.isRowRelative(),
- refNPtg.isColRelative());
- ptg.setClass(originalOperandClass);
- } else if (ptg instanceof AreaPtgBase) {
- AreaPtgBase areaNPtg = (AreaPtgBase)ptg;
- ptg = new AreaPtg(fixupRelativeRow(formulaRow,areaNPtg.getFirstRow(),areaNPtg.isFirstRowRelative()),
- fixupRelativeRow(formulaRow,areaNPtg.getLastRow(),areaNPtg.isLastRowRelative()),
- fixupRelativeColumn(formulaColumn,areaNPtg.getFirstColumn(),areaNPtg.isFirstColRelative()),
- fixupRelativeColumn(formulaColumn,areaNPtg.getLastColumn(),areaNPtg.isLastColRelative()),
- areaNPtg.isFirstRowRelative(),
- areaNPtg.isLastRowRelative(),
- areaNPtg.isFirstColRelative(),
- areaNPtg.isLastColRelative());
- ptg.setClass(originalOperandClass);
- } else if (ptg instanceof OperandPtg) {
- // Any subclass of OperandPtg is mutable, so it's safest to not share these instances.
- ptg = ((OperandPtg) ptg).copy();
- } else {
- // all other Ptgs are immutable and can be shared
- }
- newPtgStack[k] = ptg;
- }
- return newPtgStack;
- }
-
- private int fixupRelativeColumn(int currentcolumn, int column, boolean relative) {
- if(relative) {
- // mask out upper bits to produce 'wrapping' at the maximum column ("IV" for .xls and "XFD" for .xlsx)
- return (column + currentcolumn) & _columnWrappingMask;
- }
- return column;
- }
-
- private int fixupRelativeRow(int currentrow, int row, boolean relative) {
- if(relative) {
- return (row+currentrow) & _rowWrappingMask;
- }
- return row;
- }
-
-}
diff --git a/src/java/org/apache/poi/hssf/record/formula/SheetNameFormatter.java b/src/java/org/apache/poi/hssf/record/formula/SheetNameFormatter.java deleted file mode 100644 index 2e84d2f9e0..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/SheetNameFormatter.java +++ /dev/null @@ -1,223 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.poi.hssf.util.CellReference; -import org.apache.poi.ss.SpreadsheetVersion; - -/** - * Formats sheet names for use in formula expressions. - * - * @author Josh Micich - */ -public final class SheetNameFormatter { - - private static final char DELIMITER = '\''; - - /** - * Matches a single cell ref with no absolute ('$') markers - */ - private static final Pattern CELL_REF_PATTERN = Pattern.compile("([A-Za-z]+)([0-9]+)"); - - private SheetNameFormatter() { - // no instances of this class - } - /** - * Used to format sheet names as they would appear in cell formula expressions. - * @return the sheet name unchanged if there is no need for delimiting. Otherwise the sheet - * name is enclosed in single quotes ('). Any single quotes which were already present in the - * sheet name will be converted to double single quotes (''). - */ - public static String format(String rawSheetName) { - StringBuffer sb = new StringBuffer(rawSheetName.length() + 2); - appendFormat(sb, rawSheetName); - return sb.toString(); - } - - /** - * Convenience method for ({@link #format(String)}) when a StringBuffer is already available. - * - * @param out - sheet name will be appended here possibly with delimiting quotes - */ - public static void appendFormat(StringBuffer out, String rawSheetName) { - boolean needsQuotes = needsDelimiting(rawSheetName); - if(needsQuotes) { - out.append(DELIMITER); - appendAndEscape(out, rawSheetName); - out.append(DELIMITER); - } else { - out.append(rawSheetName); - } - } - public static void appendFormat(StringBuffer out, String workbookName, String rawSheetName) { - boolean needsQuotes = needsDelimiting(workbookName) || needsDelimiting(rawSheetName); - if(needsQuotes) { - out.append(DELIMITER); - out.append('['); - appendAndEscape(out, workbookName.replace('[', '(').replace(']', ')')); - out.append(']'); - appendAndEscape(out, rawSheetName); - out.append(DELIMITER); - } else { - out.append('['); - out.append(workbookName); - out.append(']'); - out.append(rawSheetName); - } - } - - private static void appendAndEscape(StringBuffer sb, String rawSheetName) { - int len = rawSheetName.length(); - for(int i=0; i<len; i++) { - char ch = rawSheetName.charAt(i); - if(ch == DELIMITER) { - // single quotes (') are encoded as ('') - sb.append(DELIMITER); - } - sb.append(ch); - } - } - - private static boolean needsDelimiting(String rawSheetName) { - int len = rawSheetName.length(); - if(len < 1) { - throw new RuntimeException("Zero length string is an invalid sheet name"); - } - if(Character.isDigit(rawSheetName.charAt(0))) { - // sheet name with digit in the first position always requires delimiting - return true; - } - for(int i=0; i<len; i++) { - char ch = rawSheetName.charAt(i); - if(isSpecialChar(ch)) { - return true; - } - } - if(Character.isLetter(rawSheetName.charAt(0)) - && Character.isDigit(rawSheetName.charAt(len-1))) { - // note - values like "A$1:$C$20" don't get this far - if(nameLooksLikePlainCellReference(rawSheetName)) { - return true; - } - } - if (nameLooksLikeBooleanLiteral(rawSheetName)) { - return true; - } - // Error constant literals all contain '#' and other special characters - // so they don't get this far - return false; - } - - private static boolean nameLooksLikeBooleanLiteral(String rawSheetName) { - switch(rawSheetName.charAt(0)) { - case 'T': case 't': - return "TRUE".equalsIgnoreCase(rawSheetName); - case 'F': case 'f': - return "FALSE".equalsIgnoreCase(rawSheetName); - } - return false; - } - /** - * @return <code>true</code> if the presence of the specified character in a sheet name would - * require the sheet name to be delimited in formulas. This includes every non-alphanumeric - * character besides underscore '_' and dot '.'. - */ - /* package */ static boolean isSpecialChar(char ch) { - // note - Character.isJavaIdentifierPart() would allow dollars '$' - if(Character.isLetterOrDigit(ch)) { - return false; - } - switch(ch) { - case '.': // dot is OK - case '_': // underscore is OK - return false; - case '\n': - case '\r': - case '\t': - throw new RuntimeException("Illegal character (0x" - + Integer.toHexString(ch) + ") found in sheet name"); - } - return true; - } - - - /** - * Used to decide whether sheet names like 'AB123' need delimiting due to the fact that they - * look like cell references. - * <p/> - * This code is currently being used for translating formulas represented with <code>Ptg</code> - * tokens into human readable text form. In formula expressions, a sheet name always has a - * trailing '!' so there is little chance for ambiguity. It doesn't matter too much what this - * method returns but it is worth noting the likely consumers of these formula text strings: - * <ol> - * <li>POI's own formula parser</li> - * <li>Visual reading by human</li> - * <li>VBA automation entry into Excel cell contents e.g. ActiveCell.Formula = "=c64!A1"</li> - * <li>Manual entry into Excel cell contents</li> - * <li>Some third party formula parser</li> - * </ol> - * - * At the time of writing, POI's formula parser tolerates cell-like sheet names in formulas - * with or without delimiters. The same goes for Excel(2007), both manual and automated entry. - * <p/> - * For better or worse this implementation attempts to replicate Excel's formula renderer. - * Excel uses range checking on the apparent 'row' and 'column' components. Note however that - * the maximum sheet size varies across versions. - * @see org.apache.poi.hssf.util.CellReference - */ - /* package */ static boolean cellReferenceIsWithinRange(String lettersPrefix, String numbersSuffix) { - return CellReference.cellReferenceIsWithinRange(lettersPrefix, numbersSuffix, SpreadsheetVersion.EXCEL97); - } - - /** - * Note - this method assumes the specified rawSheetName has only letters and digits. It - * cannot be used to match absolute or range references (using the dollar or colon char). - * <p/> - * Some notable cases: - * <blockquote><table border="0" cellpadding="1" cellspacing="0" - * summary="Notable cases."> - * <tr><th>Input </th><th>Result </th><th>Comments</th></tr> - * <tr><td>"A1" </td><td>true</td><td> </td></tr> - * <tr><td>"a111" </td><td>true</td><td> </td></tr> - * <tr><td>"AA" </td><td>false</td><td> </td></tr> - * <tr><td>"aa1" </td><td>true</td><td> </td></tr> - * <tr><td>"A1A" </td><td>false</td><td> </td></tr> - * <tr><td>"A1A1" </td><td>false</td><td> </td></tr> - * <tr><td>"A$1:$C$20" </td><td>false</td><td>Not a plain cell reference</td></tr> - * <tr><td>"SALES20080101" </td><td>true</td> - * <td>Still needs delimiting even though well out of range</td></tr> - * </table></blockquote> - * - * @return <code>true</code> if there is any possible ambiguity that the specified rawSheetName - * could be interpreted as a valid cell name. - */ - /* package */ static boolean nameLooksLikePlainCellReference(String rawSheetName) { - Matcher matcher = CELL_REF_PATTERN.matcher(rawSheetName); - if(!matcher.matches()) { - return false; - } - - // rawSheetName == "Sheet1" gets this far. - String lettersPrefix = matcher.group(1); - String numbersSuffix = matcher.group(2); - return cellReferenceIsWithinRange(lettersPrefix, numbersSuffix); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/TblPtg.java b/src/java/org/apache/poi/hssf/record/formula/TblPtg.java index 280bd9c010..aba7129bc5 100644 --- a/src/java/org/apache/poi/hssf/record/formula/TblPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/TblPtg.java @@ -17,7 +17,6 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.hssf.record.RecordFormatException; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; @@ -69,7 +68,7 @@ public final class TblPtg extends ControlPtg { public String toFormulaString() { // table(....)[][] - throw new RecordFormatException("Table and Arrays are not yet supported"); + throw new RuntimeException("Table and Arrays are not yet supported"); } public String toString() { diff --git a/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java b/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java deleted file mode 100644 index 76e4edfeda..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java +++ /dev/null @@ -1,164 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.atp; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; -import org.apache.poi.hssf.record.formula.udf.UDFFinder; -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.NotImplementedException; - -/** - * @author Josh Micich - * @author Petr Udalau - systematized work of add-in libraries and user defined functions. - */ -public final class AnalysisToolPak implements UDFFinder { - - public static final UDFFinder instance = new AnalysisToolPak(); - - private static final class NotImplemented implements FreeRefFunction { - private final String _functionName; - - public NotImplemented(String functionName) { - _functionName = functionName; - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - throw new NotImplementedException(_functionName); - } - }; - - private final Map<String, FreeRefFunction> _functionsByName = createFunctionsMap(); - - - private AnalysisToolPak() { - // enforce singleton - } - - public FreeRefFunction findFunction(String name) { - return _functionsByName.get(name); - } - - private Map<String, FreeRefFunction> createFunctionsMap() { - Map<String, FreeRefFunction> m = new HashMap<String, FreeRefFunction>(100); - - r(m, "ACCRINT", null); - r(m, "ACCRINTM", null); - r(m, "AMORDEGRC", null); - r(m, "AMORLINC", null); - r(m, "BESSELI", null); - r(m, "BESSELJ", null); - r(m, "BESSELK", null); - r(m, "BESSELY", null); - r(m, "BIN2DEC", null); - r(m, "BIN2HEX", null); - r(m, "BIN2OCT", null); - r(m, "CO MPLEX", null); - r(m, "CONVERT", null); - r(m, "COUPDAYBS", null); - r(m, "COUPDAYS", null); - r(m, "COUPDAYSNC", null); - r(m, "COUPNCD", null); - r(m, "COUPNUM", null); - r(m, "COUPPCD", null); - r(m, "CUMIPMT", null); - r(m, "CUMPRINC", null); - r(m, "DEC2BIN", null); - r(m, "DEC2HEX", null); - r(m, "DEC2OCT", null); - r(m, "DELTA", null); - r(m, "DISC", null); - r(m, "DOLLARDE", null); - r(m, "DOLLARFR", null); - r(m, "DURATION", null); - r(m, "EDATE", null); - r(m, "EFFECT", null); - r(m, "EOMONTH", null); - r(m, "ERF", null); - r(m, "ERFC", null); - r(m, "FACTDOUBLE", null); - r(m, "FVSCHEDULE", null); - r(m, "GCD", null); - r(m, "GESTEP", null); - r(m, "HEX2BIN", null); - r(m, "HEX2DEC", null); - r(m, "HEX2OCT", null); - r(m, "IMABS", null); - r(m, "IMAGINARY", null); - r(m, "IMARGUMENT", null); - r(m, "IMCONJUGATE", null); - r(m, "IMCOS", null); - r(m, "IMDIV", null); - r(m, "IMEXP", null); - r(m, "IMLN", null); - r(m, "IMLOG10", null); - r(m, "IMLOG2", null); - r(m, "IMPOWER", null); - r(m, "IMPRODUCT", null); - r(m, "IMREAL", null); - r(m, "IMSIN", null); - r(m, "IMSQRT", null); - r(m, "IMSUB", null); - r(m, "IMSUM", null); - r(m, "INTRATE", null); - r(m, "ISEVEN", ParityFunction.IS_EVEN); - r(m, "ISODD", ParityFunction.IS_ODD); - r(m, "LCM", null); - r(m, "MDURATION", null); - r(m, "MROUND", null); - r(m, "MULTINOMIAL", null); - r(m, "NETWORKDAYS", null); - r(m, "NOMINAL", null); - r(m, "OCT2BIN", null); - r(m, "OCT2DEC", null); - r(m, "OCT2HEX", null); - r(m, "ODDFPRICE", null); - r(m, "ODDFYIELD", null); - r(m, "ODDLPRICE", null); - r(m, "ODDLYIELD", null); - r(m, "PRICE", null); - r(m, "PRICEDISC", null); - r(m, "PRICEMAT", null); - r(m, "QUOTIENT", null); - r(m, "RANDBETWEEN", RandBetween.instance); - r(m, "RECEIVED", null); - r(m, "SERIESSUM", null); - r(m, "SQRTPI", null); - r(m, "TBILLEQ", null); - r(m, "TBILLPRICE", null); - r(m, "TBILLYIELD", null); - r(m, "WEEKNUM", null); - r(m, "WORKDAY", null); - r(m, "XIRR", null); - r(m, "XNPV", null); - r(m, "YEARFRAC", YearFrac.instance); - r(m, "YIELD", null); - r(m, "YIELDDISC", null); - r(m, "YIELDMAT", null); - - return m; - } - - private static void r(Map<String, FreeRefFunction> m, String functionName, FreeRefFunction pFunc) { - FreeRefFunction func = pFunc == null ? new NotImplemented(functionName) : pFunc; - m.put(functionName, func); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/atp/ParityFunction.java b/src/java/org/apache/poi/hssf/record/formula/atp/ParityFunction.java deleted file mode 100644 index 5ab9a70b7b..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/atp/ParityFunction.java +++ /dev/null @@ -1,67 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.atp; - -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; -import org.apache.poi.ss.formula.OperationEvaluationContext; -/** - * Implementation of Excel 'Analysis ToolPak' function ISEVEN() ISODD()<br/> - * - * @author Josh Micich - */ -final class ParityFunction implements FreeRefFunction { - - public static final FreeRefFunction IS_EVEN = new ParityFunction(0); - public static final FreeRefFunction IS_ODD = new ParityFunction(1); - private final int _desiredParity; - - private ParityFunction(int desiredParity) { - _desiredParity = desiredParity; - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length != 1) { - return ErrorEval.VALUE_INVALID; - } - - int val; - try { - val = evaluateArgParity(args[0], ec.getRowIndex(), ec.getColumnIndex()); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - return BoolEval.valueOf(val == _desiredParity); - } - - private static int evaluateArgParity(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException { - ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, (short)srcCellCol); - - double d = OperandResolver.coerceValueToDouble(ve); - if (d < 0) { - d = -d; - } - long v = (long) Math.floor(d); - return (int) (v & 0x0001); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/atp/RandBetween.java b/src/java/org/apache/poi/hssf/record/formula/atp/RandBetween.java deleted file mode 100644 index 2f51f72e28..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/atp/RandBetween.java +++ /dev/null @@ -1,84 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hssf.record.formula.atp; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; -import org.apache.poi.ss.formula.OperationEvaluationContext; - -/** - * Implementation of Excel 'Analysis ToolPak' function RANDBETWEEN()<br/> - * - * Returns a random integer number between the numbers you specify.<p/> - * - * <b>Syntax</b><br/> - * <b>RANDBETWEEN</b>(<b>bottom</b>, <b>top</b>)<p/> - * - * <b>bottom</b> is the smallest integer RANDBETWEEN will return.<br/> - * <b>top</b> is the largest integer RANDBETWEEN will return.<br/> - - * @author Brendan Nolan - */ -final class RandBetween implements FreeRefFunction{ - - public static final FreeRefFunction instance = new RandBetween(); - - private RandBetween() { - //enforces singleton - } - - /** - * Evaluate for RANDBETWEEN(). Must be given two arguments. Bottom must be greater than top. - * Bottom is rounded up and top value is rounded down. After rounding top has to be set greater - * than top. - * - * @see org.apache.poi.hssf.record.formula.functions.FreeRefFunction#evaluate(org.apache.poi.hssf.record.formula.eval.ValueEval[], org.apache.poi.ss.formula.OperationEvaluationContext) - */ - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - - double bottom, top; - - if (args.length != 2) { - return ErrorEval.VALUE_INVALID; - } - - try { - bottom = OperandResolver.coerceValueToDouble(OperandResolver.getSingleValue(args[0], ec.getRowIndex(), ec.getColumnIndex())); - top = OperandResolver.coerceValueToDouble(OperandResolver.getSingleValue(args[1], ec.getRowIndex(), ec.getColumnIndex())); - if(bottom > top) { - return ErrorEval.NUM_ERROR; - } - } catch (EvaluationException e) { - return ErrorEval.VALUE_INVALID; - } - - bottom = Math.ceil(bottom); - top = Math.floor(top); - - if(bottom > top) { - top = bottom; - } - - return new NumberEval((bottom + (int)(Math.random() * ((top - bottom) + 1)))); - - } - -} diff --git a/src/java/org/apache/poi/hssf/record/formula/atp/YearFrac.java b/src/java/org/apache/poi/hssf/record/formula/atp/YearFrac.java deleted file mode 100644 index d36b05a36b..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/atp/YearFrac.java +++ /dev/null @@ -1,159 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.atp; - -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.regex.Pattern; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.usermodel.DateUtil; -/** - * Implementation of Excel 'Analysis ToolPak' function YEARFRAC()<br/> - * - * Returns the fraction of the year spanned by two dates.<p/> - * - * <b>Syntax</b><br/> - * <b>YEARFRAC</b>(<b>startDate</b>, <b>endDate</b>, basis)<p/> - * - * The <b>basis</b> optionally specifies the behaviour of YEARFRAC as follows: - * - * <table border="0" cellpadding="1" cellspacing="0" summary="basis parameter description"> - * <tr><th>Value</th><th>Days per Month</th><th>Days per Year</th></tr> - * <tr align='center'><td>0 (default)</td><td>30</td><td>360</td></tr> - * <tr align='center'><td>1</td><td>actual</td><td>actual</td></tr> - * <tr align='center'><td>2</td><td>actual</td><td>360</td></tr> - * <tr align='center'><td>3</td><td>actual</td><td>365</td></tr> - * <tr align='center'><td>4</td><td>30</td><td>360</td></tr> - * </table> - * - */ -final class YearFrac implements FreeRefFunction { - - public static final FreeRefFunction instance = new YearFrac(); - - private YearFrac() { - // enforce singleton - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - int srcCellRow = ec.getRowIndex(); - int srcCellCol = ec.getColumnIndex(); - double result; - try { - int basis = 0; // default - switch(args.length) { - case 3: - basis = evaluateIntArg(args[2], srcCellRow, srcCellCol); - case 2: - break; - default: - return ErrorEval.VALUE_INVALID; - } - double startDateVal = evaluateDateArg(args[0], srcCellRow, srcCellCol); - double endDateVal = evaluateDateArg(args[1], srcCellRow, srcCellCol); - result = YearFracCalculator.calculate(startDateVal, endDateVal, basis); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - return new NumberEval(result); - } - - private static double evaluateDateArg(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException { - ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, (short) srcCellCol); - - if (ve instanceof StringEval) { - String strVal = ((StringEval) ve).getStringValue(); - Double dVal = OperandResolver.parseDouble(strVal); - if (dVal != null) { - return dVal.doubleValue(); - } - Calendar date = parseDate(strVal); - return DateUtil.getExcelDate(date, false); - } - return OperandResolver.coerceValueToDouble(ve); - } - - private static Calendar parseDate(String strVal) throws EvaluationException { - String[] parts = Pattern.compile("/").split(strVal); - if (parts.length != 3) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - String part2 = parts[2]; - int spacePos = part2.indexOf(' '); - if (spacePos > 0) { - // drop time portion if present - part2 = part2.substring(0, spacePos); - } - int f0; - int f1; - int f2; - try { - f0 = Integer.parseInt(parts[0]); - f1 = Integer.parseInt(parts[1]); - f2 = Integer.parseInt(part2); - } catch (NumberFormatException e) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - if (f0<0 || f1<0 || f2<0 || (f0>12 && f1>12 && f2>12)) { - // easy to see this cannot be a valid date - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - - if (f0 >= 1900 && f0 < 9999) { - // when 4 digit value appears first, the format is YYYY/MM/DD, regardless of OS settings - return makeDate(f0, f1, f2); - } - // otherwise the format seems to depend on OS settings (default date format) - if (false) { - // MM/DD/YYYY is probably a good guess, if the in the US - return makeDate(f2, f0, f1); - } - // TODO - find a way to choose the correct date format - throw new RuntimeException("Unable to determine date format for text '" + strVal + "'"); - } - - /** - * @param month 1-based - */ - private static Calendar makeDate(int year, int month, int day) throws EvaluationException { - if (month < 1 || month > 12) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - Calendar cal = new GregorianCalendar(year, month-1, 1, 0, 0, 0); - cal.set(Calendar.MILLISECOND, 0); - if (day <1 || day>cal.getActualMaximum(Calendar.DAY_OF_MONTH)) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - cal.set(Calendar.DAY_OF_MONTH, day); - return cal; - } - - private static int evaluateIntArg(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException { - ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, (short) srcCellCol); - return OperandResolver.coerceValueToInt(ve); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/atp/YearFracCalculator.java b/src/java/org/apache/poi/hssf/record/formula/atp/YearFracCalculator.java deleted file mode 100644 index 9475db1bc6..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/atp/YearFracCalculator.java +++ /dev/null @@ -1,344 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.atp; - -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.ss.usermodel.DateUtil; - - -/** - * Internal calculation methods for Excel 'Analysis ToolPak' function YEARFRAC()<br/> - * - * Algorithm inspired by www.dwheeler.com/yearfrac - * - * @author Josh Micich - */ -final class YearFracCalculator { - /** use UTC time-zone to avoid daylight savings issues */ - private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC"); - private static final int MS_PER_HOUR = 60 * 60 * 1000; - private static final int MS_PER_DAY = 24 * MS_PER_HOUR; - private static final int DAYS_PER_NORMAL_YEAR = 365; - private static final int DAYS_PER_LEAP_YEAR = DAYS_PER_NORMAL_YEAR + 1; - - /** the length of normal long months i.e. 31 */ - private static final int LONG_MONTH_LEN = 31; - /** the length of normal short months i.e. 30 */ - private static final int SHORT_MONTH_LEN = 30; - private static final int SHORT_FEB_LEN = 28; - private static final int LONG_FEB_LEN = SHORT_FEB_LEN + 1; - - private YearFracCalculator() { - // no instances of this class - } - - - public static double calculate(double pStartDateVal, double pEndDateVal, int basis) throws EvaluationException { - - if (basis < 0 || basis >= 5) { - // if basis is invalid the result is #NUM! - throw new EvaluationException(ErrorEval.NUM_ERROR); - } - - // common logic for all bases - - // truncate day values - int startDateVal = (int) Math.floor(pStartDateVal); - int endDateVal = (int) Math.floor(pEndDateVal); - if (startDateVal == endDateVal) { - // when dates are equal, result is zero - return 0; - } - // swap start and end if out of order - if (startDateVal > endDateVal) { - int temp = startDateVal; - startDateVal = endDateVal; - endDateVal = temp; - } - - switch (basis) { - case 0: return basis0(startDateVal, endDateVal); - case 1: return basis1(startDateVal, endDateVal); - case 2: return basis2(startDateVal, endDateVal); - case 3: return basis3(startDateVal, endDateVal); - case 4: return basis4(startDateVal, endDateVal); - } - throw new IllegalStateException("cannot happen"); - } - - - /** - * @param startDateVal assumed to be less than or equal to endDateVal - * @param endDateVal assumed to be greater than or equal to startDateVal - */ - public static double basis0(int startDateVal, int endDateVal) { - SimpleDate startDate = createDate(startDateVal); - SimpleDate endDate = createDate(endDateVal); - int date1day = startDate.day; - int date2day = endDate.day; - - // basis zero has funny adjustments to the day-of-month fields when at end-of-month - if (date1day == LONG_MONTH_LEN && date2day == LONG_MONTH_LEN) { - date1day = SHORT_MONTH_LEN; - date2day = SHORT_MONTH_LEN; - } else if (date1day == LONG_MONTH_LEN) { - date1day = SHORT_MONTH_LEN; - } else if (date1day == SHORT_MONTH_LEN && date2day == LONG_MONTH_LEN) { - date2day = SHORT_MONTH_LEN; - // Note: If date2day==31, it STAYS 31 if date1day < 30. - // Special fixes for February: - } else if (startDate.month == 2 && isLastDayOfMonth(startDate)) { - // Note - these assignments deliberately set Feb 30 date. - date1day = SHORT_MONTH_LEN; - if (endDate.month == 2 && isLastDayOfMonth(endDate)) { - // only adjusted when first date is last day in Feb - date2day = SHORT_MONTH_LEN; - } - } - return calculateAdjusted(startDate, endDate, date1day, date2day); - } - /** - * @param startDateVal assumed to be less than or equal to endDateVal - * @param endDateVal assumed to be greater than or equal to startDateVal - */ - public static double basis1(int startDateVal, int endDateVal) { - SimpleDate startDate = createDate(startDateVal); - SimpleDate endDate = createDate(endDateVal); - double yearLength; - if (isGreaterThanOneYear(startDate, endDate)) { - yearLength = averageYearLength(startDate.year, endDate.year); - } else if (shouldCountFeb29(startDate, endDate)) { - yearLength = DAYS_PER_LEAP_YEAR; - } else { - yearLength = DAYS_PER_NORMAL_YEAR; - } - return dateDiff(startDate.tsMilliseconds, endDate.tsMilliseconds) / yearLength; - } - - /** - * @param startDateVal assumed to be less than or equal to endDateVal - * @param endDateVal assumed to be greater than or equal to startDateVal - */ - public static double basis2(int startDateVal, int endDateVal) { - return (endDateVal - startDateVal) / 360.0; - } - /** - * @param startDateVal assumed to be less than or equal to endDateVal - * @param endDateVal assumed to be greater than or equal to startDateVal - */ - public static double basis3(double startDateVal, double endDateVal) { - return (endDateVal - startDateVal) / 365.0; - } - /** - * @param startDateVal assumed to be less than or equal to endDateVal - * @param endDateVal assumed to be greater than or equal to startDateVal - */ - public static double basis4(int startDateVal, int endDateVal) { - SimpleDate startDate = createDate(startDateVal); - SimpleDate endDate = createDate(endDateVal); - int date1day = startDate.day; - int date2day = endDate.day; - - - // basis four has funny adjustments to the day-of-month fields when at end-of-month - if (date1day == LONG_MONTH_LEN) { - date1day = SHORT_MONTH_LEN; - } - if (date2day == LONG_MONTH_LEN) { - date2day = SHORT_MONTH_LEN; - } - // Note - no adjustments for end of Feb - return calculateAdjusted(startDate, endDate, date1day, date2day); - } - - - private static double calculateAdjusted(SimpleDate startDate, SimpleDate endDate, int date1day, - int date2day) { - double dayCount - = (endDate.year - startDate.year) * 360 - + (endDate.month - startDate.month) * SHORT_MONTH_LEN - + (date2day - date1day) * 1; - return dayCount / 360; - } - - private static boolean isLastDayOfMonth(SimpleDate date) { - if (date.day < SHORT_FEB_LEN) { - return false; - } - return date.day == getLastDayOfMonth(date); - } - - private static int getLastDayOfMonth(SimpleDate date) { - switch (date.month) { - case 1: - case 3: - case 5: - case 7: - case 8: - case 10: - case 12: - return LONG_MONTH_LEN; - case 4: - case 6: - case 9: - case 11: - return SHORT_MONTH_LEN; - } - if (isLeapYear(date.year)) { - return LONG_FEB_LEN; - } - return SHORT_FEB_LEN; - } - - /** - * Assumes dates are no more than 1 year apart. - * @return <code>true</code> if dates both within a leap year, or span a period including Feb 29 - */ - private static boolean shouldCountFeb29(SimpleDate start, SimpleDate end) { - boolean startIsLeapYear = isLeapYear(start.year); - if (startIsLeapYear && start.year == end.year) { - // note - dates may not actually span Feb-29, but it gets counted anyway in this case - return true; - } - - boolean endIsLeapYear = isLeapYear(end.year); - if (!startIsLeapYear && !endIsLeapYear) { - return false; - } - if (startIsLeapYear) { - switch (start.month) { - case SimpleDate.JANUARY: - case SimpleDate.FEBRUARY: - return true; - } - return false; - } - if (endIsLeapYear) { - switch (end.month) { - case SimpleDate.JANUARY: - return false; - case SimpleDate.FEBRUARY: - break; - default: - return true; - } - return end.day == LONG_FEB_LEN; - } - return false; - } - - /** - * @return the whole number of days between the two time-stamps. Both time-stamps are - * assumed to represent 12:00 midnight on the respective day. - */ - private static int dateDiff(long startDateMS, long endDateMS) { - long msDiff = endDateMS - startDateMS; - - // some extra checks to make sure we don't hide some other bug with the rounding - int remainderHours = (int) ((msDiff % MS_PER_DAY) / MS_PER_HOUR); - switch (remainderHours) { - case 0: // normal case - break; - case 1: // transition from normal time to daylight savings adjusted - case 23: // transition from daylight savings adjusted to normal time - // Unexpected since we are using UTC_TIME_ZONE - default: - throw new RuntimeException("Unexpected date diff between " + startDateMS + " and " + endDateMS); - - } - return (int) (0.5 + ((double)msDiff / MS_PER_DAY)); - } - - private static double averageYearLength(int startYear, int endYear) { - int dayCount = 0; - for (int i=startYear; i<=endYear; i++) { - dayCount += DAYS_PER_NORMAL_YEAR; - if (isLeapYear(i)) { - dayCount++; - } - } - double numberOfYears = endYear-startYear+1; - return dayCount / numberOfYears; - } - - private static boolean isLeapYear(int i) { - // leap years are always divisible by 4 - if (i % 4 != 0) { - return false; - } - // each 4th century is a leap year - if (i % 400 == 0) { - return true; - } - // all other centuries are *not* leap years - if (i % 100 == 0) { - return false; - } - return true; - } - - private static boolean isGreaterThanOneYear(SimpleDate start, SimpleDate end) { - if (start.year == end.year) { - return false; - } - if (start.year + 1 != end.year) { - return true; - } - - if (start.month > end.month) { - return false; - } - if (start.month < end.month) { - return true; - } - - return start.day < end.day; - } - - private static SimpleDate createDate(int dayCount) { - GregorianCalendar calendar = new GregorianCalendar(UTC_TIME_ZONE); - DateUtil.setCalendar(calendar, dayCount, 0, false); - return new SimpleDate(calendar); - } - - private static final class SimpleDate { - - public static final int JANUARY = 1; - public static final int FEBRUARY = 2; - - public final int year; - /** 1-based month */ - public final int month; - /** day of month */ - public final int day; - /** milliseconds since 1970 */ - public long tsMilliseconds; - - public SimpleDate(Calendar cal) { - year = cal.get(Calendar.YEAR); - month = cal.get(Calendar.MONTH) + 1; - day = cal.get(Calendar.DAY_OF_MONTH); - tsMilliseconds = cal.getTimeInMillis(); - } - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java deleted file mode 100644 index 733a6253e4..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java +++ /dev/null @@ -1,93 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.ss.formula.TwoDEval; -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public interface AreaEval extends TwoDEval { - - /** - * returns the 0-based index of the first row in - * this area. - */ - int getFirstRow(); - - /** - * returns the 0-based index of the last row in - * this area. - */ - int getLastRow(); - - /** - * returns the 0-based index of the first col in - * this area. - */ - int getFirstColumn(); - - /** - * returns the 0-based index of the last col in - * this area. - */ - int getLastColumn(); - - /** - * @return the ValueEval from within this area at the specified row and col index. Never - * <code>null</code> (possibly {@link BlankEval}). The specified indexes should be absolute - * indexes in the sheet and not relative indexes within the area. - */ - ValueEval getAbsoluteValue(int row, int col); - - /** - * returns true if the cell at row and col specified - * as absolute indexes in the sheet is contained in - * this area. - * @param row - * @param col - */ - boolean contains(int row, int col); - - /** - * returns true if the specified col is in range - * @param col - */ - boolean containsColumn(int col); - - /** - * returns true if the specified row is in range - * @param row - */ - boolean containsRow(int row); - - int getWidth(); - int getHeight(); - /** - * @return the ValueEval from within this area at the specified relativeRowIndex and - * relativeColumnIndex. Never <code>null</code> (possibly {@link BlankEval}). The - * specified indexes should relative to the top left corner of this area. - */ - ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex); - - /** - * Creates an {@link AreaEval} offset by a relative amount from from the upper left cell - * of this area - */ - AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java b/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java deleted file mode 100644 index 4d04fd126f..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java +++ /dev/null @@ -1,117 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.AreaI; - -/** - * @author Josh Micich - */ -public abstract class AreaEvalBase implements AreaEval { - - private final int _firstColumn; - private final int _firstRow; - private final int _lastColumn; - private final int _lastRow; - private final int _nColumns; - private final int _nRows; - - protected AreaEvalBase(int firstRow, int firstColumn, int lastRow, int lastColumn) { - _firstColumn = firstColumn; - _firstRow = firstRow; - _lastColumn = lastColumn; - _lastRow = lastRow; - - _nColumns = _lastColumn - _firstColumn + 1; - _nRows = _lastRow - _firstRow + 1; - } - - protected AreaEvalBase(AreaI ptg) { - _firstRow = ptg.getFirstRow(); - _firstColumn = ptg.getFirstColumn(); - _lastRow = ptg.getLastRow(); - _lastColumn = ptg.getLastColumn(); - - _nColumns = _lastColumn - _firstColumn + 1; - _nRows = _lastRow - _firstRow + 1; - } - - public final int getFirstColumn() { - return _firstColumn; - } - - public final int getFirstRow() { - return _firstRow; - } - - public final int getLastColumn() { - return _lastColumn; - } - - public final int getLastRow() { - return _lastRow; - } - public final ValueEval getAbsoluteValue(int row, int col) { - int rowOffsetIx = row - _firstRow; - int colOffsetIx = col - _firstColumn; - - if(rowOffsetIx < 0 || rowOffsetIx >= _nRows) { - throw new IllegalArgumentException("Specified row index (" + row - + ") is outside the allowed range (" + _firstRow + ".." + _lastRow + ")"); - } - if(colOffsetIx < 0 || colOffsetIx >= _nColumns) { - throw new IllegalArgumentException("Specified column index (" + col - + ") is outside the allowed range (" + _firstColumn + ".." + col + ")"); - } - return getRelativeValue(rowOffsetIx, colOffsetIx); - } - - public final boolean contains(int row, int col) { - return _firstRow <= row && _lastRow >= row - && _firstColumn <= col && _lastColumn >= col; - } - - public final boolean containsRow(int row) { - return _firstRow <= row && _lastRow >= row; - } - - public final boolean containsColumn(int col) { - return _firstColumn <= col && _lastColumn >= col; - } - - public final boolean isColumn() { - return _firstColumn == _lastColumn; - } - - public final boolean isRow() { - return _firstRow == _lastRow; - } - public int getHeight() { - return _lastRow-_firstRow+1; - } - - public final ValueEval getValue(int row, int col) { - return getRelativeValue(row, col); - } - - public abstract ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex); - - public int getWidth() { - return _lastColumn-_firstColumn+1; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/BlankEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/BlankEval.java deleted file mode 100644 index 3e5147122d..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/BlankEval.java +++ /dev/null @@ -1,35 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > This class is a - * marker class. It is a special value for empty cells. - */ -public final class BlankEval implements ValueEval { - - public static final BlankEval instance = new BlankEval(); - /** - * @deprecated (Nov 2009) use {@link #instance} - */ - public static final BlankEval INSTANCE = instance; - - private BlankEval() { - // enforce singleton - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/BoolEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/BoolEval.java deleted file mode 100644 index 6ca60899ad..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/BoolEval.java +++ /dev/null @@ -1,64 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public final class BoolEval implements NumericValueEval, StringValueEval { - - private boolean _value; - - public static final BoolEval FALSE = new BoolEval(false); - - public static final BoolEval TRUE = new BoolEval(true); - - /** - * Convenience method for the following:<br/> - * <code>(b ? BoolEval.TRUE : BoolEval.FALSE)</code> - * - * @return the <tt>BoolEval</tt> instance representing <tt>b</tt>. - */ - public static final BoolEval valueOf(boolean b) { - return b ? TRUE : FALSE; - } - - private BoolEval(boolean value) { - _value = value; - } - - public boolean getBooleanValue() { - return _value; - } - - public double getNumberValue() { - return _value ? 1 : 0; - } - - public String getStringValue() { - return _value ? "TRUE" : "FALSE"; - } - - public String toString() { - StringBuilder sb = new StringBuilder(64); - sb.append(getClass().getName()).append(" ["); - sb.append(getStringValue()); - sb.append("]"); - return sb.toString(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java deleted file mode 100644 index f52aea98f1..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java +++ /dev/null @@ -1,60 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.functions.Fixed2ArgFunction; -import org.apache.poi.hssf.record.formula.functions.Function; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public final class ConcatEval extends Fixed2ArgFunction { - - public static final Function instance = new ConcatEval(); - - private ConcatEval() { - // enforce singleton - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - ValueEval ve0; - ValueEval ve1; - try { - ve0 = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - ve1 = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - StringBuilder sb = new StringBuilder(); - sb.append(getText(ve0)); - sb.append(getText(ve1)); - return new StringEval(sb.toString()); - } - - private Object getText(ValueEval ve) { - if (ve instanceof StringValueEval) { - StringValueEval sve = (StringValueEval) ve; - return sve.getStringValue(); - } - if (ve == BlankEval.instance) { - return ""; - } - throw new IllegalAccessError("Unexpected value type (" - + ve.getClass().getName() + ")"); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/ErrorEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/ErrorEval.java deleted file mode 100644 index 13f51f5f80..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/ErrorEval.java +++ /dev/null @@ -1,111 +0,0 @@ -/* -* Licensed to the Apache Software Foundation (ASF) under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The ASF licenses this file to You under the Apache License, Version 2.0 -* (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.ss.usermodel.ErrorConstants; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public final class ErrorEval implements ValueEval { - - // convenient access to namespace - private static final ErrorConstants EC = null; - - /** <b>#NULL!</b> - Intersection of two cell ranges is empty */ - public static final ErrorEval NULL_INTERSECTION = new ErrorEval(EC.ERROR_NULL); - /** <b>#DIV/0!</b> - Division by zero */ - public static final ErrorEval DIV_ZERO = new ErrorEval(EC.ERROR_DIV_0); - /** <b>#VALUE!</b> - Wrong type of operand */ - public static final ErrorEval VALUE_INVALID = new ErrorEval(EC.ERROR_VALUE); - /** <b>#REF!</b> - Illegal or deleted cell reference */ - public static final ErrorEval REF_INVALID = new ErrorEval(EC.ERROR_REF); - /** <b>#NAME?</b> - Wrong function or range name */ - public static final ErrorEval NAME_INVALID = new ErrorEval(EC.ERROR_NAME); - /** <b>#NUM!</b> - Value range overflow */ - public static final ErrorEval NUM_ERROR = new ErrorEval(EC.ERROR_NUM); - /** <b>#N/A</b> - Argument or function not available */ - public static final ErrorEval NA = new ErrorEval(EC.ERROR_NA); - - - // POI internal error codes - private static final int CIRCULAR_REF_ERROR_CODE = 0xFFFFFFC4; - private static final int FUNCTION_NOT_IMPLEMENTED_CODE = 0xFFFFFFE2; - - // Note - Excel does not seem to represent this condition with an error code - public static final ErrorEval CIRCULAR_REF_ERROR = new ErrorEval(CIRCULAR_REF_ERROR_CODE); - - - /** - * Translates an Excel internal error code into the corresponding POI ErrorEval instance - * @param errorCode - */ - public static ErrorEval valueOf(int errorCode) { - switch(errorCode) { - case ErrorConstants.ERROR_NULL: return NULL_INTERSECTION; - case ErrorConstants.ERROR_DIV_0: return DIV_ZERO; - case ErrorConstants.ERROR_VALUE: return VALUE_INVALID; - case ErrorConstants.ERROR_REF: return REF_INVALID; - case ErrorConstants.ERROR_NAME: return NAME_INVALID; - case ErrorConstants.ERROR_NUM: return NUM_ERROR; - case ErrorConstants.ERROR_NA: return NA; - // non-std errors (conditions modeled as errors by POI) - case CIRCULAR_REF_ERROR_CODE: return CIRCULAR_REF_ERROR; - } - throw new RuntimeException("Unexpected error code (" + errorCode + ")"); - } - - /** - * Converts error codes to text. Handles non-standard error codes OK. - * For debug/test purposes (and for formatting error messages). - * @return the String representation of the specified Excel error code. - */ - public static String getText(int errorCode) { - if(ErrorConstants.isValidCode(errorCode)) { - return ErrorConstants.getText(errorCode); - } - // It is desirable to make these (arbitrary) strings look clearly different from any other - // value expression that might appear in a formula. In addition these error strings should - // look unlike the standard Excel errors. Hence tilde ('~') was used. - switch(errorCode) { - case CIRCULAR_REF_ERROR_CODE: return "~CIRCULAR~REF~"; - case FUNCTION_NOT_IMPLEMENTED_CODE: return "~FUNCTION~NOT~IMPLEMENTED~"; - } - return "~non~std~err(" + errorCode + ")~"; - } - - private int _errorCode; - /** - * @param errorCode an 8-bit value - */ - private ErrorEval(int errorCode) { - _errorCode = errorCode; - } - - public int getErrorCode() { - return _errorCode; - } - public String toString() { - StringBuffer sb = new StringBuffer(64); - sb.append(getClass().getName()).append(" ["); - sb.append(getText(_errorCode)); - sb.append("]"); - return sb.toString(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/EvaluationException.java b/src/java/org/apache/poi/hssf/record/formula/eval/EvaluationException.java deleted file mode 100644 index 7a23901b25..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/EvaluationException.java +++ /dev/null @@ -1,134 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -/** - * This class is used to simplify error handling logic <i>within</i> operator and function - * implementations. Note - <tt>OperationEval.evaluate()</tt> and <tt>Function.evaluate()</tt> - * method signatures do not throw this exception so it cannot propagate outside.<p/> - * - * Here is an example coded without <tt>EvaluationException</tt>, to show how it can help: - * <pre> - * public Eval evaluate(Eval[] args, int srcRow, short srcCol) { - * // ... - * Eval arg0 = args[0]; - * if(arg0 instanceof ErrorEval) { - * return arg0; - * } - * if(!(arg0 instanceof AreaEval)) { - * return ErrorEval.VALUE_INVALID; - * } - * double temp = 0; - * AreaEval area = (AreaEval)arg0; - * ValueEval[] values = area.getValues(); - * for (int i = 0; i < values.length; i++) { - * ValueEval ve = values[i]; - * if(ve instanceof ErrorEval) { - * return ve; - * } - * if(!(ve instanceof NumericValueEval)) { - * return ErrorEval.VALUE_INVALID; - * } - * temp += ((NumericValueEval)ve).getNumberValue(); - * } - * // ... - * } - * </pre> - * In this example, if any error is encountered while processing the arguments, an error is - * returned immediately. This code is difficult to refactor due to all the points where errors - * are returned.<br/> - * Using <tt>EvaluationException</tt> allows the error returning code to be consolidated to one - * place.<p/> - * <pre> - * public Eval evaluate(Eval[] args, int srcRow, short srcCol) { - * try { - * // ... - * AreaEval area = getAreaArg(args[0]); - * double temp = sumValues(area.getValues()); - * // ... - * } catch (EvaluationException e) { - * return e.getErrorEval(); - * } - *} - * - *private static AreaEval getAreaArg(Eval arg0) throws EvaluationException { - * if (arg0 instanceof ErrorEval) { - * throw new EvaluationException((ErrorEval) arg0); - * } - * if (arg0 instanceof AreaEval) { - * return (AreaEval) arg0; - * } - * throw EvaluationException.invalidValue(); - *} - * - *private double sumValues(ValueEval[] values) throws EvaluationException { - * double temp = 0; - * for (int i = 0; i < values.length; i++) { - * ValueEval ve = values[i]; - * if (ve instanceof ErrorEval) { - * throw new EvaluationException((ErrorEval) ve); - * } - * if (!(ve instanceof NumericValueEval)) { - * throw EvaluationException.invalidValue(); - * } - * temp += ((NumericValueEval) ve).getNumberValue(); - * } - * return temp; - *} - * </pre> - * It is not mandatory to use EvaluationException, doing so might give the following advantages:<br/> - * - Methods can more easily be extracted, allowing for re-use.<br/> - * - Type management (typecasting etc) is simpler because error conditions have been separated from - * intermediate calculation values.<br/> - * - Fewer local variables are required. Local variables can have stronger types.<br/> - * - It is easier to mimic common Excel error handling behaviour (exit upon encountering first - * error), because exceptions conveniently propagate up the call stack regardless of execution - * points or the number of levels of nested calls.<p/> - * - * <b>Note</b> - Only standard evaluation errors are represented by <tt>EvaluationException</tt> ( - * i.e. conditions expected to be encountered when evaluating arbitrary Excel formulas). Conditions - * that could never occur in an Excel spreadsheet should result in runtime exceptions. Care should - * be taken to not translate any POI internal error into an Excel evaluation error code. - * - * @author Josh Micich - */ -public final class EvaluationException extends Exception { - private final ErrorEval _errorEval; - - public EvaluationException(ErrorEval errorEval) { - _errorEval = errorEval; - } - // some convenience factory methods - - /** <b>#VALUE!</b> - Wrong type of operand */ - public static EvaluationException invalidValue() { - return new EvaluationException(ErrorEval.VALUE_INVALID); - } - /** <b>#REF!</b> - Illegal or deleted cell reference */ - public static EvaluationException invalidRef() { - return new EvaluationException(ErrorEval.REF_INVALID); - } - /** <b>#NUM!</b> - Value range overflow */ - public static EvaluationException numberError() { - return new EvaluationException(ErrorEval.NUM_ERROR); - } - - public ErrorEval getErrorEval() { - return _errorEval; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java deleted file mode 100644 index d7be348650..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java +++ /dev/null @@ -1,250 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.function.FunctionMetadata; -import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry; -import org.apache.poi.hssf.record.formula.functions.*; -import org.apache.poi.ss.formula.eval.NotImplementedException; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public final class FunctionEval { - /** - * Some function IDs that require special treatment - */ - private static final class FunctionID { - /** 1 */ - public static final int IF = FunctionMetadataRegistry.FUNCTION_INDEX_IF; - /** 4 */ - public static final int SUM = FunctionMetadataRegistry.FUNCTION_INDEX_SUM; - /** 78 */ - public static final int OFFSET = 78; - /** 100 */ - public static final int CHOOSE = FunctionMetadataRegistry.FUNCTION_INDEX_CHOOSE; - /** 148 */ - public static final int INDIRECT = FunctionMetadataRegistry.FUNCTION_INDEX_INDIRECT; - /** 255 */ - public static final int EXTERNAL_FUNC = FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL; - } - // convenient access to namespace - private static final FunctionID ID = null; - - /** - * Array elements corresponding to unimplemented functions are <code>null</code> - */ - protected static final Function[] functions = produceFunctions(); - - private static Function[] produceFunctions() { - Function[] retval = new Function[368]; - - retval[0] = new Count(); - retval[ID.IF] = new IfFunc(); - retval[2] = LogicalFunction.ISNA; - retval[3] = LogicalFunction.ISERROR; - retval[ID.SUM] = AggregateFunction.SUM; - retval[5] = AggregateFunction.AVERAGE; - retval[6] = AggregateFunction.MIN; - retval[7] = AggregateFunction.MAX; - retval[8] = new RowFunc(); // ROW - retval[9] = new Column(); - retval[10] = new Na(); - retval[11] = new Npv(); - retval[12] = AggregateFunction.STDEV; - retval[13] = NumericFunction.DOLLAR; - - retval[15] = NumericFunction.SIN; - retval[16] = NumericFunction.COS; - retval[17] = NumericFunction.TAN; - retval[18] = NumericFunction.ATAN; - retval[19] = NumericFunction.PI; - retval[20] = NumericFunction.SQRT; - retval[21] = NumericFunction.EXP; - retval[22] = NumericFunction.LN; - retval[23] = NumericFunction.LOG10; - retval[24] = NumericFunction.ABS; - retval[25] = NumericFunction.INT; - retval[26] = NumericFunction.SIGN; - retval[27] = NumericFunction.ROUND; - retval[28] = new Lookup(); - retval[29] = new Index(); - - retval[31] = TextFunction.MID; - retval[32] = TextFunction.LEN; - retval[33] = new Value(); - retval[34] = BooleanFunction.TRUE; - retval[35] = BooleanFunction.FALSE; - retval[36] = BooleanFunction.AND; - retval[37] = BooleanFunction.OR; - retval[38] = BooleanFunction.NOT; - retval[39] = NumericFunction.MOD; - retval[48] = TextFunction.TEXT; - - retval[56] = FinanceFunction.PV; - retval[57] = FinanceFunction.FV; - retval[58] = FinanceFunction.NPER; - retval[59] = FinanceFunction.PMT; - - retval[63] = NumericFunction.RAND; - retval[64] = new Match(); - retval[65] = DateFunc.instance; - retval[66] = new TimeFunc(); - retval[67] = CalendarFieldFunction.DAY; - retval[68] = CalendarFieldFunction.MONTH; - retval[69] = CalendarFieldFunction.YEAR; - - retval[74] = new Now(); - - retval[76] = new Rows(); - retval[77] = new Columns(); - retval[82] = TextFunction.SEARCH; - retval[ID.OFFSET] = new Offset(); - retval[82] = TextFunction.SEARCH; - - retval[97] = NumericFunction.ATAN2; - retval[98] = NumericFunction.ASIN; - retval[99] = NumericFunction.ACOS; - retval[ID.CHOOSE] = new Choose(); - retval[101] = new Hlookup(); - retval[102] = new Vlookup(); - - retval[105] = LogicalFunction.ISREF; - - retval[109] = NumericFunction.LOG; - - retval[112] = TextFunction.LOWER; - retval[113] = TextFunction.UPPER; - - retval[115] = TextFunction.LEFT; - retval[116] = TextFunction.RIGHT; - retval[117] = TextFunction.EXACT; - retval[118] = TextFunction.TRIM; - retval[119] = new Replace(); - retval[120] = new Substitute(); - - retval[124] = TextFunction.FIND; - - retval[127] = LogicalFunction.ISTEXT; - retval[128] = LogicalFunction.ISNUMBER; - retval[129] = LogicalFunction.ISBLANK; - retval[130] = new T(); - - retval[ID.INDIRECT] = null; // Indirect.evaluate has different signature - - retval[169] = new Counta(); - - retval[183] = AggregateFunction.PRODUCT; - retval[184] = NumericFunction.FACT; - - retval[190] = LogicalFunction.ISNONTEXT; - retval[197] = NumericFunction.TRUNC; - retval[198] = LogicalFunction.ISLOGICAL; - - retval[212] = NumericFunction.ROUNDUP; - retval[213] = NumericFunction.ROUNDDOWN; - - retval[220] = new Days360(); - retval[221] = new Today(); - - retval[227] = AggregateFunction.MEDIAN; - retval[228] = new Sumproduct(); - retval[229] = NumericFunction.SINH; - retval[230] = NumericFunction.COSH; - retval[231] = NumericFunction.TANH; - retval[232] = NumericFunction.ASINH; - retval[233] = NumericFunction.ACOSH; - retval[234] = NumericFunction.ATANH; - - retval[ID.EXTERNAL_FUNC] = null; // ExternalFunction is a FreeREfFunction - - retval[261] = new Errortype(); - - retval[269] = AggregateFunction.AVEDEV; - - retval[276] = NumericFunction.COMBIN; - - retval[279] = new Even(); - - retval[285] = NumericFunction.FLOOR; - - retval[288] = NumericFunction.CEILING; - - retval[298] = new Odd(); - - retval[300] = NumericFunction.POISSON; - - retval[303] = new Sumxmy2(); - retval[304] = new Sumx2my2(); - retval[305] = new Sumx2py2(); - - retval[318] = AggregateFunction.DEVSQ; - - retval[321] = AggregateFunction.SUMSQ; - - retval[325] = AggregateFunction.LARGE; - retval[326] = AggregateFunction.SMALL; - - retval[330] = new Mode(); - - retval[336] = TextFunction.CONCATENATE; - retval[337] = NumericFunction.POWER; - - retval[342] = NumericFunction.RADIANS; - retval[343] = NumericFunction.DEGREES; - - retval[344] = new Subtotal(); - retval[345] = new Sumif(); - retval[346] = new Countif(); - retval[347] = new Countblank(); - - retval[359] = new Hyperlink(); - - retval[362] = MinaMaxa.MAXA; - retval[363] = MinaMaxa.MINA; - - for (int i = 0; i < retval.length; i++) { - Function f = retval[i]; - if (f == null) { - FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(i); - if (fm == null) { - continue; - } - retval[i] = new NotImplementedFunction(fm.getName()); - } - } - return retval; - } - /** - * @return <code>null</code> if the specified functionIndex is for INDIRECT() or any external (add-in) function. - */ - public static Function getBasicFunction(int functionIndex) { - // check for 'free ref' functions first - switch (functionIndex) { - case FunctionID.INDIRECT: - case FunctionID.EXTERNAL_FUNC: - return null; - } - // else - must be plain function - Function result = functions[functionIndex]; - if (result == null) { - throw new NotImplementedException("FuncIx=" + functionIndex); - } - return result; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/IntersectionEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/IntersectionEval.java deleted file mode 100644 index e30df36f59..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/IntersectionEval.java +++ /dev/null @@ -1,96 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.functions.Fixed2ArgFunction; -import org.apache.poi.hssf.record.formula.functions.Function; - -/** - * @author Josh Micich - */ -public final class IntersectionEval extends Fixed2ArgFunction { - - public static final Function instance = new IntersectionEval(); - - private IntersectionEval() { - // enforces singleton - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - - try { - AreaEval reA = evaluateRef(arg0); - AreaEval reB = evaluateRef(arg1); - AreaEval result = resolveRange(reA, reB); - if (result == null) { - return ErrorEval.NULL_INTERSECTION; - } - return result; - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - - /** - * @return simple rectangular {@link AreaEval} which represents the intersection of areas - * <tt>aeA</tt> and <tt>aeB</tt>. If the two areas do not intersect, the result is <code>null</code>. - */ - private static AreaEval resolveRange(AreaEval aeA, AreaEval aeB) { - - int aeAfr = aeA.getFirstRow(); - int aeAfc = aeA.getFirstColumn(); - int aeBlc = aeB.getLastColumn(); - if (aeAfc > aeBlc) { - return null; - } - int aeBfc = aeB.getFirstColumn(); - if (aeBfc > aeA.getLastColumn()) { - return null; - } - int aeBlr = aeB.getLastRow(); - if (aeAfr > aeBlr) { - return null; - } - int aeBfr = aeB.getFirstRow(); - int aeAlr = aeA.getLastRow(); - if (aeBfr > aeAlr) { - return null; - } - - - int top = Math.max(aeAfr, aeBfr); - int bottom = Math.min(aeAlr, aeBlr); - int left = Math.max(aeAfc, aeBfc); - int right = Math.min(aeA.getLastColumn(), aeBlc); - - return aeA.offset(top-aeAfr, bottom-aeAfr, left-aeAfc, right-aeAfc); - } - - private static AreaEval evaluateRef(ValueEval arg) throws EvaluationException { - if (arg instanceof AreaEval) { - return (AreaEval) arg; - } - if (arg instanceof RefEval) { - return ((RefEval) arg).offset(0, 0, 0, 0); - } - if (arg instanceof ErrorEval) { - throw new EvaluationException((ErrorEval)arg); - } - throw new IllegalArgumentException("Unexpected ref arg class (" + arg.getClass().getName() + ")"); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/MissingArgEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/MissingArgEval.java deleted file mode 100644 index 984e6383ab..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/MissingArgEval.java +++ /dev/null @@ -1,36 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -/** - * Represents the (intermediate) evaluated result of a missing function argument. In most cases - * this can be translated into {@link BlankEval} but there are some notable exceptions. Functions - * COUNT and COUNTA <em>do</em> count their missing args. Note - the differences between - * {@link MissingArgEval} and {@link BlankEval} have not been investigated fully, so the POI - * evaluator may need to be updated to account for these as they are found. - * - * @author Josh Micich - */ -public final class MissingArgEval implements ValueEval { - - public static final MissingArgEval instance = new MissingArgEval(); - - private MissingArgEval() { - // enforce singleton - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/NameEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/NameEval.java deleted file mode 100644 index 9b5e21b184..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/NameEval.java +++ /dev/null @@ -1,46 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -/** - * @author Josh Micich - */ -public final class NameEval implements ValueEval { - - private final String _functionName; - - /** - * Creates a NameEval representing a function name - */ - public NameEval(String functionName) { - _functionName = functionName; - } - - - public String getFunctionName() { - return _functionName; - } - - public String toString() { - StringBuffer sb = new StringBuffer(64); - sb.append(getClass().getName()).append(" ["); - sb.append(_functionName); - sb.append("]"); - return sb.toString(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/NameXEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/NameXEval.java deleted file mode 100644 index d1b8ffef76..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/NameXEval.java +++ /dev/null @@ -1,44 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.NameXPtg; - -/** - * @author Josh Micich - */ -public final class NameXEval implements ValueEval { - - private final NameXPtg _ptg; - - public NameXEval(NameXPtg ptg) { - _ptg = ptg; - } - - public NameXPtg getPtg() { - return _ptg; - } - - public String toString() { - StringBuffer sb = new StringBuffer(64); - sb.append(getClass().getName()).append(" ["); - sb.append(_ptg.getSheetRefIndex()).append(", ").append(_ptg.getNameIndex()); - sb.append("]"); - return sb.toString(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java deleted file mode 100644 index 33aff2a493..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Licensed to the Apache Software Foundation (ASF) under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The ASF licenses this file to You under the Apache License, Version 2.0 -* (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -/* - * Created on May 8, 2005 - * - */ -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.IntPtg; -import org.apache.poi.hssf.record.formula.NumberPtg; -import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.ss.util.NumberToTextConverter; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public final class NumberEval implements NumericValueEval, StringValueEval { - - public static final NumberEval ZERO = new NumberEval(0); - - private final double _value; - private String _stringValue; - - public NumberEval(Ptg ptg) { - if (ptg == null) { - throw new IllegalArgumentException("ptg must not be null"); - } - if (ptg instanceof IntPtg) { - _value = ((IntPtg) ptg).getValue(); - } else if (ptg instanceof NumberPtg) { - _value = ((NumberPtg) ptg).getValue(); - } else { - throw new IllegalArgumentException("bad argument type (" + ptg.getClass().getName() + ")"); - } - } - - public NumberEval(double value) { - _value = value; - } - - public double getNumberValue() { - return _value; - } - - public String getStringValue() { - if (_stringValue == null) { - _stringValue = NumberToTextConverter.toText(_value); - } - return _stringValue; - } - public final String toString() { - StringBuffer sb = new StringBuffer(64); - sb.append(getClass().getName()).append(" ["); - sb.append(getStringValue()); - sb.append("]"); - return sb.toString(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/NumericValueEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/NumericValueEval.java deleted file mode 100644 index d5b92b8080..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/NumericValueEval.java +++ /dev/null @@ -1,30 +0,0 @@ -/* -* Licensed to the Apache Software Foundation (ASF) under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The ASF licenses this file to You under the Apache License, Version 2.0 -* (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -/* - * Created on May 8, 2005 - * - */ -package org.apache.poi.hssf.record.formula.eval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public interface NumericValueEval extends ValueEval { - - public abstract double getNumberValue(); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/OperandResolver.java b/src/java/org/apache/poi/hssf/record/formula/eval/OperandResolver.java deleted file mode 100644 index f81ebdde0f..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/OperandResolver.java +++ /dev/null @@ -1,324 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import java.util.regex.Pattern; - -/** - * Provides functionality for evaluating arguments to functions and operators. - * - * @author Josh Micich - * @author Brendan Nolan - */ -public final class OperandResolver { - - // Based on regular expression defined in JavaDoc at {@link java.lang.Double#valueOf} - // modified to remove support for NaN, Infinity, Hexadecimal support and floating type suffixes - private static final String Digits = "(\\p{Digit}+)"; - private static final String Exp = "[eE][+-]?"+Digits; - private static final String fpRegex = - ("[\\x00-\\x20]*" + - "[+-]?(" + - "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ - "(\\.("+Digits+")("+Exp+")?))))"+ - "[\\x00-\\x20]*"); - - - private OperandResolver() { - // no instances of this class - } - - /** - * Retrieves a single value from a variety of different argument types according to standard - * Excel rules. Does not perform any type conversion. - * @param arg the evaluated argument as passed to the function or operator. - * @param srcCellRow used when arg is a single column AreaRef - * @param srcCellCol used when arg is a single row AreaRef - * @return a <tt>NumberEval</tt>, <tt>StringEval</tt>, <tt>BoolEval</tt> or <tt>BlankEval</tt>. - * Never <code>null</code> or <tt>ErrorEval</tt>. - * @throws EvaluationException(#VALUE!) if srcCellRow or srcCellCol do not properly index into - * an AreaEval. If the actual value retrieved is an ErrorEval, a corresponding - * EvaluationException is thrown. - */ - public static ValueEval getSingleValue(ValueEval arg, int srcCellRow, int srcCellCol) - throws EvaluationException { - ValueEval result; - if (arg instanceof RefEval) { - result = ((RefEval) arg).getInnerValueEval(); - } else if (arg instanceof AreaEval) { - result = chooseSingleElementFromArea((AreaEval) arg, srcCellRow, srcCellCol); - } else { - result = arg; - } - if (result instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) result); - } - return result; - } - - /** - * Implements (some perhaps not well known) Excel functionality to select a single cell from an - * area depending on the coordinates of the calling cell. Here is an example demonstrating - * both selection from a single row area and a single column area in the same formula. - * - * <table border="1" cellpadding="1" cellspacing="1" summary="sample spreadsheet"> - * <tr><th> </th><th> A </th><th> B </th><th> C </th><th> D </th></tr> - * <tr><th>1</th><td>15</td><td>20</td><td>25</td><td> </td></tr> - * <tr><th>2</th><td> </td><td> </td><td> </td><td>200</td></tr> - * <tr><th>3</th><td> </td><td> </td><td> </td><td>300</td></tr> - * <tr><th>3</th><td> </td><td> </td><td> </td><td>400</td></tr> - * </table> - * - * If the formula "=1000+A1:B1+D2:D3" is put into the 9 cells from A2 to C4, the spreadsheet - * will look like this: - * - * <table border="1" cellpadding="1" cellspacing="1" summary="sample spreadsheet"> - * <tr><th> </th><th> A </th><th> B </th><th> C </th><th> D </th></tr> - * <tr><th>1</th><td>15</td><td>20</td><td>25</td><td> </td></tr> - * <tr><th>2</th><td>1215</td><td>1220</td><td>#VALUE!</td><td>200</td></tr> - * <tr><th>3</th><td>1315</td><td>1320</td><td>#VALUE!</td><td>300</td></tr> - * <tr><th>4</th><td>#VALUE!</td><td>#VALUE!</td><td>#VALUE!</td><td>400</td></tr> - * </table> - * - * Note that the row area (A1:B1) does not include column C and the column area (D2:D3) does - * not include row 4, so the values in C1(=25) and D4(=400) are not accessible to the formula - * as written, but in the 4 cells A2:B3, the row and column selection works ok.<p/> - * - * The same concept is extended to references across sheets, such that even multi-row, - * multi-column areas can be useful.<p/> - * - * Of course with carefully (or carelessly) chosen parameters, cyclic references can occur and - * hence this method <b>can</b> throw a 'circular reference' EvaluationException. Note that - * this method does not attempt to detect cycles. Every cell in the specified Area <tt>ae</tt> - * has already been evaluated prior to this method call. Any cell (or cell<b>s</b>) part of - * <tt>ae</tt> that would incur a cyclic reference error if selected by this method, will - * already have the value <t>ErrorEval.CIRCULAR_REF_ERROR</tt> upon entry to this method. It - * is assumed logic exists elsewhere to produce this behaviour. - * - * @return whatever the selected cell's evaluated value is. Never <code>null</code>. Never - * <tt>ErrorEval</tt>. - * @throws EvaluationException if there is a problem with indexing into the area, or if the - * evaluated cell has an error. - */ - public static ValueEval chooseSingleElementFromArea(AreaEval ae, - int srcCellRow, int srcCellCol) throws EvaluationException { - ValueEval result = chooseSingleElementFromAreaInternal(ae, srcCellRow, srcCellCol); - if (result instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) result); - } - return result; - } - - /** - * @return possibly <tt>ErrorEval</tt>, and <code>null</code> - */ - private static ValueEval chooseSingleElementFromAreaInternal(AreaEval ae, - int srcCellRow, int srcCellCol) throws EvaluationException { - - if(false) { - // this is too simplistic - if(ae.containsRow(srcCellRow) && ae.containsColumn(srcCellCol)) { - throw new EvaluationException(ErrorEval.CIRCULAR_REF_ERROR); - } - /* - Circular references are not dealt with directly here, but it is worth noting some issues. - - ANY one of the return statements in this method could return a cell that is identical - to the one immediately being evaluated. The evaluating cell is identified by srcCellRow, - srcCellRow AND sheet. The sheet is not available in any nearby calling method, so that's - one reason why circular references are not easy to detect here. (The sheet of the returned - cell can be obtained from ae if it is an Area3DEval.) - - Another reason there's little value in attempting to detect circular references here is - that only direct circular references could be detected. If the cycle involved two or more - cells this method could not detect it. - - Logic to detect evaluation cycles of all kinds has been coded in EvaluationCycleDetector - (and FormulaEvaluator). - */ - } - - if (ae.isColumn()) { - if(ae.isRow()) { - return ae.getRelativeValue(0, 0); - } - if(!ae.containsRow(srcCellRow)) { - throw EvaluationException.invalidValue(); - } - return ae.getAbsoluteValue(srcCellRow, ae.getFirstColumn()); - } - if(!ae.isRow()) { - // multi-column, multi-row area - if(ae.containsRow(srcCellRow) && ae.containsColumn(srcCellCol)) { - return ae.getAbsoluteValue(ae.getFirstRow(), ae.getFirstColumn()); - } - throw EvaluationException.invalidValue(); - } - if(!ae.containsColumn(srcCellCol)) { - throw EvaluationException.invalidValue(); - } - return ae.getAbsoluteValue(ae.getFirstRow(), srcCellCol); - } - - /** - * Applies some conversion rules if the supplied value is not already an integer.<br/> - * Value is first coerced to a <tt>double</tt> ( See <tt>coerceValueToDouble()</tt> ). - * Note - <tt>BlankEval</tt> is converted to <code>0</code>.<p/> - * - * Excel typically converts doubles to integers by truncating toward negative infinity.<br/> - * The equivalent java code is:<br/> - * <code>return (int)Math.floor(d);</code><br/> - * <b>not</b>:<br/> - * <code>return (int)d; // wrong - rounds toward zero</code> - * - */ - public static int coerceValueToInt(ValueEval ev) throws EvaluationException { - if (ev == BlankEval.instance) { - return 0; - } - double d = coerceValueToDouble(ev); - // Note - the standard java type conversion from double to int truncates toward zero. - // but Math.floor() truncates toward negative infinity - return (int)Math.floor(d); - } - - /** - * Applies some conversion rules if the supplied value is not already a number. - * Note - <tt>BlankEval</tt> is converted to {@link NumberEval#ZERO}. - * @param ev must be a {@link NumberEval}, {@link StringEval}, {@link BoolEval} or - * {@link BlankEval} - * @return actual, parsed or interpreted double value (respectively). - * @throws EvaluationException(#VALUE!) only if a StringEval is supplied and cannot be parsed - * as a double (See <tt>parseDouble()</tt> for allowable formats). - * @throws RuntimeException if the supplied parameter is not {@link NumberEval}, - * {@link StringEval}, {@link BoolEval} or {@link BlankEval} - */ - public static double coerceValueToDouble(ValueEval ev) throws EvaluationException { - - if (ev == BlankEval.instance) { - return 0.0; - } - if (ev instanceof NumericValueEval) { - // this also handles booleans - return ((NumericValueEval)ev).getNumberValue(); - } - if (ev instanceof StringEval) { - Double dd = parseDouble(((StringEval) ev).getStringValue()); - if (dd == null) { - throw EvaluationException.invalidValue(); - } - return dd.doubleValue(); - } - throw new RuntimeException("Unexpected arg eval type (" + ev.getClass().getName() + ")"); - } - - /** - * Converts a string to a double using standard rules that Excel would use.<br/> - * Tolerates leading and trailing spaces, <p/> - * - * Doesn't support currency prefixes, commas, percentage signs or arithmetic operations strings. - * - * Some examples:<br/> - * " 123 " -> 123.0<br/> - * ".123" -> 0.123<br/> - * "1E4" -> 1000<br/> - * "-123" -> -123.0<br/> - * These not supported yet:<br/> - * " $ 1,000.00 " -> 1000.0<br/> - * "$1.25E4" -> 12500.0<br/> - * "5**2" -> 500<br/> - * "250%" -> 2.5<br/> - * - * @return <code>null</code> if the specified text cannot be parsed as a number - */ - public static Double parseDouble(String pText) { - - if (Pattern.matches(fpRegex, pText)) - try { - return Double.parseDouble(pText); - } catch (NumberFormatException e) { - return null; - } - else { - return null; - } - - } - - /** - * @param ve must be a <tt>NumberEval</tt>, <tt>StringEval</tt>, <tt>BoolEval</tt>, or <tt>BlankEval</tt> - * @return the converted string value. never <code>null</code> - */ - public static String coerceValueToString(ValueEval ve) { - if (ve instanceof StringValueEval) { - StringValueEval sve = (StringValueEval) ve; - return sve.getStringValue(); - } - if (ve == BlankEval.instance) { - return ""; - } - throw new IllegalArgumentException("Unexpected eval class (" + ve.getClass().getName() + ")"); - } - - /** - * @return <code>null</code> to represent blank values - * @throws EvaluationException if ve is an ErrorEval, or if a string value cannot be converted - */ - public static Boolean coerceValueToBoolean(ValueEval ve, boolean stringsAreBlanks) throws EvaluationException { - - if (ve == null || ve == BlankEval.instance) { - // TODO - remove 've == null' condition once AreaEval is fixed - return null; - } - if (ve instanceof BoolEval) { - return Boolean.valueOf(((BoolEval) ve).getBooleanValue()); - } - - if (ve == BlankEval.instance) { - return null; - } - - if (ve instanceof StringEval) { - if (stringsAreBlanks) { - return null; - } - String str = ((StringEval) ve).getStringValue(); - if (str.equalsIgnoreCase("true")) { - return Boolean.TRUE; - } - if (str.equalsIgnoreCase("false")) { - return Boolean.FALSE; - } - // else - string cannot be converted to boolean - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - - if (ve instanceof NumericValueEval) { - NumericValueEval ne = (NumericValueEval) ve; - double d = ne.getNumberValue(); - if (Double.isNaN(d)) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - return Boolean.valueOf(d != 0); - } - if (ve instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) ve); - } - throw new RuntimeException("Unexpected eval (" + ve.getClass().getName() + ")"); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java deleted file mode 100644 index 93db027b30..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java +++ /dev/null @@ -1,49 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.functions.Fixed1ArgFunction; -import org.apache.poi.hssf.record.formula.functions.Function; - - -/** - * Implementation of Excel formula token '%'. <p/> - * @author Josh Micich - */ -public final class PercentEval extends Fixed1ArgFunction { - - public static final Function instance = new PercentEval(); - - private PercentEval() { - // enforce singleton - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - double d; - try { - ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - d = OperandResolver.coerceValueToDouble(ve); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - if (d == 0.0) { // this '==' matches +0.0 and -0.0 - return NumberEval.ZERO; - } - return new NumberEval(d / 100); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java deleted file mode 100644 index 6a8186c7b7..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java +++ /dev/null @@ -1,75 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.functions.Fixed2ArgFunction; -import org.apache.poi.hssf.record.formula.functions.Function; - - -/** - * - * @author Josh Micich - */ -public final class RangeEval extends Fixed2ArgFunction { - - public static final Function instance = new RangeEval(); - - private RangeEval() { - // enforces singleton - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - - try { - AreaEval reA = evaluateRef(arg0); - AreaEval reB = evaluateRef(arg1); - return resolveRange(reA, reB); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - - /** - * @return simple rectangular {@link AreaEval} which fully encloses both areas - * <tt>aeA</tt> and <tt>aeB</tt> - */ - private static AreaEval resolveRange(AreaEval aeA, AreaEval aeB) { - int aeAfr = aeA.getFirstRow(); - int aeAfc = aeA.getFirstColumn(); - - int top = Math.min(aeAfr, aeB.getFirstRow()); - int bottom = Math.max(aeA.getLastRow(), aeB.getLastRow()); - int left = Math.min(aeAfc, aeB.getFirstColumn()); - int right = Math.max(aeA.getLastColumn(), aeB.getLastColumn()); - - return aeA.offset(top-aeAfr, bottom-aeAfr, left-aeAfc, right-aeAfc); - } - - private static AreaEval evaluateRef(ValueEval arg) throws EvaluationException { - if (arg instanceof AreaEval) { - return (AreaEval) arg; - } - if (arg instanceof RefEval) { - return ((RefEval) arg).offset(0, 0, 0, 0); - } - if (arg instanceof ErrorEval) { - throw new EvaluationException((ErrorEval)arg); - } - throw new IllegalArgumentException("Unexpected ref arg class (" + arg.getClass().getName() + ")"); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/RefEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/RefEval.java deleted file mode 100644 index cb4a9e47dc..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/RefEval.java +++ /dev/null @@ -1,51 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -/** - * @author Amol S Deshmukh < amolweb at ya hoo dot com > - * - * RefEval is the super interface for Ref2D and Ref3DEval. Basically a RefEval - * impl should contain reference to the original ReferencePtg or Ref3DPtg as - * well as the final "value" resulting from the evaluation of the cell - * reference. Thus if the Cell has type CELL_TYPE_NUMERIC, the contained - * value object should be of type NumberEval; if cell type is CELL_TYPE_STRING, - * contained value object should be of type StringEval - */ -public interface RefEval extends ValueEval { - - /** - * @return the evaluated value of the cell referred to by this RefEval. - */ - ValueEval getInnerValueEval(); - - /** - * returns the zero based column index. - */ - int getColumn(); - - /** - * returns the zero based row index. - */ - int getRow(); - - /** - * Creates an {@link AreaEval} offset by a relative amount from this RefEval - */ - AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java b/src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java deleted file mode 100644 index 32cdc72e17..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java +++ /dev/null @@ -1,40 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -/** - * Common base class for implementors of {@link RefEval} - * - * @author Josh Micich - */ -public abstract class RefEvalBase implements RefEval { - - private final int _rowIndex; - private final int _columnIndex; - - protected RefEvalBase(int rowIndex, int columnIndex) { - _rowIndex = rowIndex; - _columnIndex = columnIndex; - } - public final int getRow() { - return _rowIndex; - } - public final int getColumn() { - return _columnIndex; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java deleted file mode 100644 index b9cace26a9..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java +++ /dev/null @@ -1,168 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.functions.Fixed2ArgFunction; -import org.apache.poi.hssf.record.formula.functions.Function; -import org.apache.poi.ss.util.NumberComparer; - -/** - * Base class for all comparison operator evaluators - * - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public abstract class RelationalOperationEval extends Fixed2ArgFunction { - - /** - * Converts a standard compare result (-1, 0, 1) to <code>true</code> or <code>false</code> - * according to subclass' comparison type. - */ - protected abstract boolean convertComparisonResult(int cmpResult); - - /** - * This is a description of how the relational operators apply in MS Excel. - * Use this as a guideline when testing/implementing the evaluate methods - * for the relational operators Evals. - * - * <pre> - * Bool.TRUE > any number. - * Bool > any string. ALWAYS - * Bool.TRUE > Bool.FALSE - * Bool.FALSE == Blank - * - * Strings are never converted to numbers or booleans - * String > any number. ALWAYS - * Non-empty String > Blank - * Empty String == Blank - * String are sorted dictionary wise - * - * Blank > Negative numbers - * Blank == 0 - * Blank < Positive numbers - * </pre> - */ - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - - ValueEval vA; - ValueEval vB; - try { - vA = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - vB = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - int cmpResult = doCompare(vA, vB); - boolean result = convertComparisonResult(cmpResult); - return BoolEval.valueOf(result); - } - - private static int doCompare(ValueEval va, ValueEval vb) { - // special cases when one operand is blank - if (va == BlankEval.instance) { - return compareBlank(vb); - } - if (vb == BlankEval.instance) { - return -compareBlank(va); - } - - if (va instanceof BoolEval) { - if (vb instanceof BoolEval) { - BoolEval bA = (BoolEval) va; - BoolEval bB = (BoolEval) vb; - if (bA.getBooleanValue() == bB.getBooleanValue()) { - return 0; - } - return bA.getBooleanValue() ? 1 : -1; - } - return 1; - } - if (vb instanceof BoolEval) { - return -1; - } - if (va instanceof StringEval) { - if (vb instanceof StringEval) { - StringEval sA = (StringEval) va; - StringEval sB = (StringEval) vb; - return sA.getStringValue().compareToIgnoreCase(sB.getStringValue()); - } - return 1; - } - if (vb instanceof StringEval) { - return -1; - } - if (va instanceof NumberEval) { - if (vb instanceof NumberEval) { - NumberEval nA = (NumberEval) va; - NumberEval nB = (NumberEval) vb; - return NumberComparer.compare(nA.getNumberValue(), nB.getNumberValue()); - } - } - throw new IllegalArgumentException("Bad operand types (" + va.getClass().getName() + "), (" - + vb.getClass().getName() + ")"); - } - - private static int compareBlank(ValueEval v) { - if (v == BlankEval.instance) { - return 0; - } - if (v instanceof BoolEval) { - BoolEval boolEval = (BoolEval) v; - return boolEval.getBooleanValue() ? -1 : 0; - } - if (v instanceof NumberEval) { - NumberEval ne = (NumberEval) v; - return NumberComparer.compare(0.0, ne.getNumberValue()); - } - if (v instanceof StringEval) { - StringEval se = (StringEval) v; - return se.getStringValue().length() < 1 ? 0 : -1; - } - throw new IllegalArgumentException("bad value class (" + v.getClass().getName() + ")"); - } - - public static final Function EqualEval = new RelationalOperationEval() { - protected boolean convertComparisonResult(int cmpResult) { - return cmpResult == 0; - } - }; - public static final Function GreaterEqualEval = new RelationalOperationEval() { - protected boolean convertComparisonResult(int cmpResult) { - return cmpResult >= 0; - } - }; - public static final Function GreaterThanEval = new RelationalOperationEval() { - protected boolean convertComparisonResult(int cmpResult) { - return cmpResult > 0; - } - }; - public static final Function LessEqualEval = new RelationalOperationEval() { - protected boolean convertComparisonResult(int cmpResult) { - return cmpResult <= 0; - } - }; - public static final Function LessThanEval = new RelationalOperationEval() { - protected boolean convertComparisonResult(int cmpResult) { - return cmpResult < 0; - } - }; - public static final Function NotEqualEval = new RelationalOperationEval() { - protected boolean convertComparisonResult(int cmpResult) { - return cmpResult != 0; - } - }; -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/StringEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/StringEval.java deleted file mode 100644 index 9c686dbe29..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/StringEval.java +++ /dev/null @@ -1,54 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.hssf.record.formula.StringPtg; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public final class StringEval implements StringValueEval { - - public static final StringEval EMPTY_INSTANCE = new StringEval(""); - - private final String _value; - - public StringEval(Ptg ptg) { - this(((StringPtg) ptg).getValue()); - } - - public StringEval(String value) { - if (value == null) { - throw new IllegalArgumentException("value must not be null"); - } - _value = value; - } - - public String getStringValue() { - return _value; - } - - public String toString() { - StringBuilder sb = new StringBuilder(64); - sb.append(getClass().getName()).append(" ["); - sb.append(_value); - sb.append("]"); - return sb.toString(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/StringValueEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/StringValueEval.java deleted file mode 100644 index 46c12236b9..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/StringValueEval.java +++ /dev/null @@ -1,30 +0,0 @@ -/* -* Licensed to the Apache Software Foundation (ASF) under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The ASF licenses this file to You under the Apache License, Version 2.0 -* (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -package org.apache.poi.hssf.record.formula.eval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public interface StringValueEval extends ValueEval { - - /** - * @return never <code>null</code>, possibly empty string. - */ - String getStringValue(); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java b/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java deleted file mode 100644 index 7e6ac88364..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java +++ /dev/null @@ -1,87 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.functions.Fixed2ArgFunction; -import org.apache.poi.hssf.record.formula.functions.Function; - -/** - * @author Josh Micich - */ -public abstract class TwoOperandNumericOperation extends Fixed2ArgFunction { - - protected final double singleOperandEvaluate(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException { - ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); - return OperandResolver.coerceValueToDouble(ve); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - double result; - try { - double d0 = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - result = evaluate(d0, d1); - if (result == 0.0) { // this '==' matches +0.0 and -0.0 - // Excel converts -0.0 to +0.0 for '*', '/', '%', '+' and '^' - if (!(this instanceof SubtractEvalClass)) { - return NumberEval.ZERO; - } - } - if (Double.isNaN(result) || Double.isInfinite(result)) { - return ErrorEval.NUM_ERROR; - } - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - - protected abstract double evaluate(double d0, double d1) throws EvaluationException; - - public static final Function AddEval = new TwoOperandNumericOperation() { - protected double evaluate(double d0, double d1) { - return d0+d1; - } - }; - public static final Function DivideEval = new TwoOperandNumericOperation() { - protected double evaluate(double d0, double d1) throws EvaluationException { - if (d1 == 0.0) { - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - return d0/d1; - } - }; - public static final Function MultiplyEval = new TwoOperandNumericOperation() { - protected double evaluate(double d0, double d1) { - return d0*d1; - } - }; - public static final Function PowerEval = new TwoOperandNumericOperation() { - protected double evaluate(double d0, double d1) { - return Math.pow(d0, d1); - } - }; - private static final class SubtractEvalClass extends TwoOperandNumericOperation { - public SubtractEvalClass() { - // - } - protected double evaluate(double d0, double d1) { - return d0-d1; - } - } - public static final Function SubtractEval = new SubtractEvalClass(); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java deleted file mode 100644 index ba5f197dce..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java +++ /dev/null @@ -1,47 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.functions.Fixed1ArgFunction; -import org.apache.poi.hssf.record.formula.functions.Function; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public final class UnaryMinusEval extends Fixed1ArgFunction { - - public static final Function instance = new UnaryMinusEval(); - - private UnaryMinusEval() { - // enforce singleton - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - double d; - try { - ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - d = OperandResolver.coerceValueToDouble(ve); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - if (d == 0.0) { // this '==' matches +0.0 and -0.0 - return NumberEval.ZERO; - } - return new NumberEval(-d); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java deleted file mode 100644 index b6f32e9b61..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java +++ /dev/null @@ -1,51 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -import org.apache.poi.hssf.record.formula.functions.Fixed1ArgFunction; -import org.apache.poi.hssf.record.formula.functions.Function; - - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public final class UnaryPlusEval extends Fixed1ArgFunction { - - public static final Function instance = new UnaryPlusEval(); - - private UnaryPlusEval() { - // enforce singleton - } - - public ValueEval evaluate(int srcCellRow, int srcCellCol, ValueEval arg0) { - double d; - try { - ValueEval ve = OperandResolver.getSingleValue(arg0, srcCellRow, srcCellCol); - if(ve instanceof StringEval) { - // Note - asymmetric with UnaryMinus - // -"hello" evaluates to #VALUE! - // but +"hello" evaluates to "hello" - return ve; - } - d = OperandResolver.coerceValueToDouble(ve); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(+d); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/ValueEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/ValueEval.java deleted file mode 100644 index 9b6bbae6d8..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/ValueEval.java +++ /dev/null @@ -1,25 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.eval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public interface ValueEval { - // no methods -} diff --git a/src/java/org/apache/poi/hssf/record/formula/function/FunctionDataBuilder.java b/src/java/org/apache/poi/hssf/record/formula/function/FunctionDataBuilder.java deleted file mode 100644 index 5f173a12db..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/function/FunctionDataBuilder.java +++ /dev/null @@ -1,91 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.function; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Temporarily collects <tt>FunctionMetadata</tt> instances for creation of a - * <tt>FunctionMetadataRegistry</tt>. - * - * @author Josh Micich - */ -final class FunctionDataBuilder { - private int _maxFunctionIndex; - private final Map _functionDataByName; - private final Map _functionDataByIndex; - /** stores indexes of all functions with footnotes (i.e. whose definitions might change) */ - private final Set _mutatingFunctionIndexes; - - public FunctionDataBuilder(int sizeEstimate) { - _maxFunctionIndex = -1; - _functionDataByName = new HashMap(sizeEstimate * 3 / 2); - _functionDataByIndex = new HashMap(sizeEstimate * 3 / 2); - _mutatingFunctionIndexes = new HashSet(); - } - - public void add(int functionIndex, String functionName, int minParams, int maxParams, - byte returnClassCode, byte[] parameterClassCodes, boolean hasFootnote) { - FunctionMetadata fm = new FunctionMetadata(functionIndex, functionName, minParams, maxParams, - returnClassCode, parameterClassCodes); - - Integer indexKey = Integer.valueOf(functionIndex); - - - if(functionIndex > _maxFunctionIndex) { - _maxFunctionIndex = functionIndex; - } - // allow function definitions to change only if both previous and the new items have footnotes - FunctionMetadata prevFM; - prevFM = (FunctionMetadata) _functionDataByName.get(functionName); - if(prevFM != null) { - if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) { - throw new RuntimeException("Multiple entries for function name '" + functionName + "'"); - } - _functionDataByIndex.remove(Integer.valueOf(prevFM.getIndex())); - } - prevFM = (FunctionMetadata) _functionDataByIndex.get(indexKey); - if(prevFM != null) { - if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) { - throw new RuntimeException("Multiple entries for function index (" + functionIndex + ")"); - } - _functionDataByName.remove(prevFM.getName()); - } - if(hasFootnote) { - _mutatingFunctionIndexes.add(indexKey); - } - _functionDataByIndex.put(indexKey, fm); - _functionDataByName.put(functionName, fm); - } - - public FunctionMetadataRegistry build() { - - FunctionMetadata[] jumbledArray = new FunctionMetadata[_functionDataByName.size()]; - _functionDataByName.values().toArray(jumbledArray); - FunctionMetadata[] fdIndexArray = new FunctionMetadata[_maxFunctionIndex+1]; - for (int i = 0; i < jumbledArray.length; i++) { - FunctionMetadata fd = jumbledArray[i]; - fdIndexArray[fd.getIndex()] = fd; - } - - return new FunctionMetadataRegistry(fdIndexArray, _functionDataByName); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadata.java b/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadata.java deleted file mode 100644 index 898a72ad44..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadata.java +++ /dev/null @@ -1,92 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.function; - -import org.apache.poi.ss.SpreadsheetVersion; - -/** - * Holds information about Excel built-in functions. - * - * @author Josh Micich - */ -public final class FunctionMetadata { - /** - * maxParams=30 in functionMetadata.txt means the maximum number arguments supported - * by the given version of Excel. Validation routines should take the actual limit (Excel 97 or 2007) - * from the SpreadsheetVersion enum. - * Perhaps a value like 'M' should be used instead of '30' in functionMetadata.txt - * to make that file more version neutral. - * @see org.apache.poi.ss.formula.FormulaParser#validateNumArgs(int, FunctionMetadata) - */ - private static final short FUNCTION_MAX_PARAMS = 30; - - private final int _index; - private final String _name; - private final int _minParams; - private final int _maxParams; - private final byte _returnClassCode; - private final byte[] _parameterClassCodes; - - /* package */ FunctionMetadata(int index, String name, int minParams, int maxParams, - byte returnClassCode, byte[] parameterClassCodes) { - _index = index; - _name = name; - _minParams = minParams; - _maxParams = maxParams; - _returnClassCode = returnClassCode; - _parameterClassCodes = parameterClassCodes; - } - public int getIndex() { - return _index; - } - public String getName() { - return _name; - } - public int getMinParams() { - return _minParams; - } - public int getMaxParams() { - return _maxParams; - } - public boolean hasFixedArgsLength() { - return _minParams == _maxParams; - } - public byte getReturnClassCode() { - return _returnClassCode; - } - public byte[] getParameterClassCodes() { - return _parameterClassCodes.clone(); - } - /** - * Some varags functions (like VLOOKUP) have a specific limit to the number of arguments that - * can be passed. Other functions (like SUM) don't have such a limit. For those functions, - * the spreadsheet version determines the maximum number of arguments that can be passed. - * @return <code>true</code> if this function can the maximum number of arguments allowable by - * the {@link SpreadsheetVersion} - */ - public boolean hasUnlimitedVarags() { - return FUNCTION_MAX_PARAMS == _maxParams; - } - public String toString() { - StringBuffer sb = new StringBuffer(64); - sb.append(getClass().getName()).append(" ["); - sb.append(_index).append(" ").append(_name); - sb.append("]"); - return sb.toString(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataReader.java b/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataReader.java deleted file mode 100644 index 5ce7327199..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataReader.java +++ /dev/null @@ -1,195 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.function; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Pattern; - -import org.apache.poi.hssf.record.formula.Ptg; - -/** - * Converts the text meta-data file into a <tt>FunctionMetadataRegistry</tt> - * - * @author Josh Micich - */ -final class FunctionMetadataReader { - - private static final String METADATA_FILE_NAME = "functionMetadata.txt"; - - /** plain ASCII text metadata file uses three dots for ellipsis */ - private static final String ELLIPSIS = "..."; - - private static final Pattern TAB_DELIM_PATTERN = Pattern.compile("\t"); - private static final Pattern SPACE_DELIM_PATTERN = Pattern.compile(" "); - private static final byte[] EMPTY_BYTE_ARRAY = { }; - - private static final String[] DIGIT_ENDING_FUNCTION_NAMES = { - // Digits at the end of a function might be due to a left-over footnote marker. - // except in these cases - "LOG10", "ATAN2", "DAYS360", "SUMXMY2", "SUMX2MY2", "SUMX2PY2", - }; - private static final Set DIGIT_ENDING_FUNCTION_NAMES_SET = new HashSet(Arrays.asList(DIGIT_ENDING_FUNCTION_NAMES)); - - public static FunctionMetadataRegistry createRegistry() { - InputStream is = FunctionMetadataReader.class.getResourceAsStream(METADATA_FILE_NAME); - if (is == null) { - throw new RuntimeException("resource '" + METADATA_FILE_NAME + "' not found"); - } - - BufferedReader br; - try { - br = new BufferedReader(new InputStreamReader(is,"UTF-8")); - } catch(UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - FunctionDataBuilder fdb = new FunctionDataBuilder(400); - - try { - while (true) { - String line = br.readLine(); - if (line == null) { - break; - } - if (line.length() < 1 || line.charAt(0) == '#') { - continue; - } - String trimLine = line.trim(); - if (trimLine.length() < 1) { - continue; - } - processLine(fdb, line); - } - br.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - - return fdb.build(); - } - - private static void processLine(FunctionDataBuilder fdb, String line) { - - String[] parts = TAB_DELIM_PATTERN.split(line, -2); - if(parts.length != 8) { - throw new RuntimeException("Bad line format '" + line + "' - expected 8 data fields"); - } - int functionIndex = parseInt(parts[0]); - String functionName = parts[1]; - int minParams = parseInt(parts[2]); - int maxParams = parseInt(parts[3]); - byte returnClassCode = parseReturnTypeCode(parts[4]); - byte[] parameterClassCodes = parseOperandTypeCodes(parts[5]); - // 6 isVolatile - boolean hasNote = parts[7].length() > 0; - - validateFunctionName(functionName); - // TODO - make POI use isVolatile - fdb.add(functionIndex, functionName, minParams, maxParams, - returnClassCode, parameterClassCodes, hasNote); - } - - - private static byte parseReturnTypeCode(String code) { - if(code.length() == 0) { - return Ptg.CLASS_REF; // happens for GETPIVOTDATA - } - return parseOperandTypeCode(code); - } - - private static byte[] parseOperandTypeCodes(String codes) { - if(codes.length() < 1) { - return EMPTY_BYTE_ARRAY; // happens for GETPIVOTDATA - } - if(isDash(codes)) { - // '-' means empty: - return EMPTY_BYTE_ARRAY; - } - String[] array = SPACE_DELIM_PATTERN.split(codes); - int nItems = array.length; - if(ELLIPSIS.equals(array[nItems-1])) { - // final ellipsis is optional, and ignored - // (all unspecified params are assumed to be the same as the last) - nItems --; - } - byte[] result = new byte[nItems]; - for (int i = 0; i < nItems; i++) { - result[i] = parseOperandTypeCode(array[i]); - } - return result; - } - - private static boolean isDash(String codes) { - if(codes.length() == 1) { - switch (codes.charAt(0)) { - case '-': - return true; - } - } - return false; - } - - private static byte parseOperandTypeCode(String code) { - if(code.length() != 1) { - throw new RuntimeException("Bad operand type code format '" + code + "' expected single char"); - } - switch(code.charAt(0)) { - case 'V': return Ptg.CLASS_VALUE; - case 'R': return Ptg.CLASS_REF; - case 'A': return Ptg.CLASS_ARRAY; - } - throw new IllegalArgumentException("Unexpected operand type code '" + code + "' (" + (int)code.charAt(0) + ")"); - } - - /** - * Makes sure that footnote digits from the original OOO document have not been accidentally - * left behind - */ - private static void validateFunctionName(String functionName) { - int len = functionName.length(); - int ix = len - 1; - if (!Character.isDigit(functionName.charAt(ix))) { - return; - } - while(ix >= 0) { - if (!Character.isDigit(functionName.charAt(ix))) { - break; - } - ix--; - } - if(DIGIT_ENDING_FUNCTION_NAMES_SET.contains(functionName)) { - return; - } - throw new RuntimeException("Invalid function name '" + functionName - + "' (is footnote number incorrectly appended)"); - } - - private static int parseInt(String valStr) { - try { - return Integer.parseInt(valStr); - } catch (NumberFormatException e) { - throw new RuntimeException("Value '" + valStr + "' could not be parsed as an integer"); - } - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataRegistry.java b/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataRegistry.java deleted file mode 100644 index 97891c1100..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataRegistry.java +++ /dev/null @@ -1,90 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.function; - -import java.util.Map; -import java.util.Set; -/** - * Allows clients to get {@link FunctionMetadata} instances for any built-in function of Excel. - * - * @author Josh Micich - */ -public final class FunctionMetadataRegistry { - /** - * The name of the IF function (i.e. "IF"). Extracted as a constant for clarity. - */ - public static final String FUNCTION_NAME_IF = "IF"; - - public static final int FUNCTION_INDEX_IF = 1; - public static final short FUNCTION_INDEX_SUM = 4; - public static final int FUNCTION_INDEX_CHOOSE = 100; - public static final short FUNCTION_INDEX_INDIRECT = 148; - public static final short FUNCTION_INDEX_EXTERNAL = 255; - - private static FunctionMetadataRegistry _instance; - - private final FunctionMetadata[] _functionDataByIndex; - private final Map<String, FunctionMetadata> _functionDataByName; - - private static FunctionMetadataRegistry getInstance() { - if (_instance == null) { - _instance = FunctionMetadataReader.createRegistry(); - } - return _instance; - } - - /* package */ FunctionMetadataRegistry(FunctionMetadata[] functionDataByIndex, Map<String, FunctionMetadata> functionDataByName) { - _functionDataByIndex = functionDataByIndex; - _functionDataByName = functionDataByName; - } - - /* package */ Set<String> getAllFunctionNames() { - return _functionDataByName.keySet(); - } - - - public static FunctionMetadata getFunctionByIndex(int index) { - return getInstance().getFunctionByIndexInternal(index); - } - - private FunctionMetadata getFunctionByIndexInternal(int index) { - return _functionDataByIndex[index]; - } - /** - * Resolves a built-in function index. - * @param name uppercase function name - * @return a negative value if the function name is not found. - * This typically occurs for external functions. - */ - public static short lookupIndexByName(String name) { - FunctionMetadata fd = getInstance().getFunctionByNameInternal(name); - if (fd == null) { - return -1; - } - return (short) fd.getIndex(); - } - - private FunctionMetadata getFunctionByNameInternal(String name) { - return _functionDataByName.get(name); - } - - - public static FunctionMetadata getFunctionByName(String name) { - return getInstance().getFunctionByNameInternal(name); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java deleted file mode 100644 index 2df9dd3e57..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java +++ /dev/null @@ -1,145 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public abstract class AggregateFunction extends MultiOperandNumericFunction { - - private static final class LargeSmall extends Fixed2ArgFunction { - private final boolean _isLarge; - protected LargeSmall(boolean isLarge) { - _isLarge = isLarge; - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, - ValueEval arg1) { - double dn; - try { - ValueEval ve1 = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex); - dn = OperandResolver.coerceValueToDouble(ve1); - } catch (EvaluationException e1) { - // all errors in the second arg translate to #VALUE! - return ErrorEval.VALUE_INVALID; - } - // weird Excel behaviour on second arg - if (dn < 1.0) { - // values between 0.0 and 1.0 result in #NUM! - return ErrorEval.NUM_ERROR; - } - // all other values are rounded up to the next integer - int k = (int) Math.ceil(dn); - - double result; - try { - double[] ds = ValueCollector.collectValues(arg0); - if (k > ds.length) { - return ErrorEval.NUM_ERROR; - } - result = _isLarge ? StatsLib.kthLargest(ds, k) : StatsLib.kthSmallest(ds, k); - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - return new NumberEval(result); - } - } - private static final class ValueCollector extends MultiOperandNumericFunction { - private static final ValueCollector instance = new ValueCollector(); - public ValueCollector() { - super(false, false); - } - public static double[] collectValues(ValueEval...operands) throws EvaluationException { - return instance.getNumberArray(operands); - } - protected double evaluate(double[] values) { - throw new IllegalStateException("should not be called"); - } - } - - protected AggregateFunction() { - super(false, false); - } - - public static final Function AVEDEV = new AggregateFunction() { - protected double evaluate(double[] values) { - return StatsLib.avedev(values); - } - }; - public static final Function AVERAGE = new AggregateFunction() { - protected double evaluate(double[] values) throws EvaluationException { - if (values.length < 1) { - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - return MathX.average(values); - } - }; - public static final Function DEVSQ = new AggregateFunction() { - protected double evaluate(double[] values) { - return StatsLib.devsq(values); - } - }; - public static final Function LARGE = new LargeSmall(true); - public static final Function MAX = new AggregateFunction() { - protected double evaluate(double[] values) { - return values.length > 0 ? MathX.max(values) : 0; - } - }; - public static final Function MEDIAN = new AggregateFunction() { - protected double evaluate(double[] values) { - return StatsLib.median(values); - } - }; - public static final Function MIN = new AggregateFunction() { - protected double evaluate(double[] values) { - return values.length > 0 ? MathX.min(values) : 0; - } - }; - public static final Function PRODUCT = new AggregateFunction() { - protected double evaluate(double[] values) { - return MathX.product(values); - } - }; - public static final Function SMALL = new LargeSmall(false); - public static final Function STDEV = new AggregateFunction() { - protected double evaluate(double[] values) throws EvaluationException { - if (values.length < 1) { - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - return StatsLib.stdev(values); - } - }; - public static final Function SUM = new AggregateFunction() { - protected double evaluate(double[] values) { - return MathX.sum(values); - } - }; - public static final Function SUMSQ = new AggregateFunction() { - protected double evaluate(double[] values) { - return MathX.sumsq(values); - } - }; -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/BooleanFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/BooleanFunction.java deleted file mode 100644 index e3381a0ae9..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/BooleanFunction.java +++ /dev/null @@ -1,146 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * Here are the general rules concerning Boolean functions: - * <ol> - * <li> Blanks are ignored (not either true or false) </li> - * <li> Strings are ignored if part of an area ref or cell ref, otherwise they must be 'true' or 'false'</li> - * <li> Numbers: 0 is false. Any other number is TRUE </li> - * <li> Areas: *all* cells in area are evaluated according to the above rules</li> - * </ol> - * - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public abstract class BooleanFunction implements Function { - - public final ValueEval evaluate(ValueEval[] args, int srcRow, int srcCol) { - if (args.length < 1) { - return ErrorEval.VALUE_INVALID; - } - boolean boolResult; - try { - boolResult = calculate(args); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return BoolEval.valueOf(boolResult); - } - - private boolean calculate(ValueEval[] args) throws EvaluationException { - - boolean result = getInitialResultValue(); - boolean atleastOneNonBlank = false; - - /* - * Note: no short-circuit boolean loop exit because any ErrorEvals will override the result - */ - for (int i=0, iSize=args.length; i<iSize; i++) { - ValueEval arg = args[i]; - if (arg instanceof TwoDEval) { - TwoDEval ae = (TwoDEval) arg; - int height = ae.getHeight(); - int width = ae.getWidth(); - for (int rrIx=0; rrIx<height; rrIx++) { - for (int rcIx=0; rcIx<width; rcIx++) { - ValueEval ve = ae.getValue(rrIx, rcIx); - Boolean tempVe = OperandResolver.coerceValueToBoolean(ve, true); - if (tempVe != null) { - result = partialEvaluate(result, tempVe.booleanValue()); - atleastOneNonBlank = true; - } - } - } - continue; - } - Boolean tempVe; - if (arg instanceof RefEval) { - ValueEval ve = ((RefEval) arg).getInnerValueEval(); - tempVe = OperandResolver.coerceValueToBoolean(ve, true); - } else { - tempVe = OperandResolver.coerceValueToBoolean(arg, false); - } - - - if (tempVe != null) { - result = partialEvaluate(result, tempVe.booleanValue()); - atleastOneNonBlank = true; - } - } - - if (!atleastOneNonBlank) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - return result; - } - - - protected abstract boolean getInitialResultValue(); - protected abstract boolean partialEvaluate(boolean cumulativeResult, boolean currentValue); - - - public static final Function AND = new BooleanFunction() { - protected boolean getInitialResultValue() { - return true; - } - protected boolean partialEvaluate(boolean cumulativeResult, boolean currentValue) { - return cumulativeResult && currentValue; - } - }; - public static final Function OR = new BooleanFunction() { - protected boolean getInitialResultValue() { - return false; - } - protected boolean partialEvaluate(boolean cumulativeResult, boolean currentValue) { - return cumulativeResult || currentValue; - } - }; - public static final Function FALSE = new Fixed0ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return BoolEval.FALSE; - } - }; - public static final Function TRUE = new Fixed0ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return BoolEval.TRUE; - } - }; - public static final Function NOT = new Fixed1ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - boolean boolArgVal; - try { - ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - Boolean b = OperandResolver.coerceValueToBoolean(ve, false); - boolArgVal = b == null ? false : b.booleanValue(); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - return BoolEval.valueOf(!boolArgVal); - } - }; -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/CalendarFieldFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/CalendarFieldFunction.java deleted file mode 100644 index 48d3a16215..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/CalendarFieldFunction.java +++ /dev/null @@ -1,87 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.usermodel.DateUtil; - -/** - * Implementation of Excel functions DAY, MONTH and YEAR - * - * - * @author Guenter Kickinger g.kickinger@gmx.net - */ -public final class CalendarFieldFunction extends Fixed1ArgFunction { - - public static final Function YEAR = new CalendarFieldFunction(Calendar.YEAR, false); - public static final Function MONTH = new CalendarFieldFunction(Calendar.MONTH, true); - public static final Function DAY = new CalendarFieldFunction(Calendar.DAY_OF_MONTH, false); - - private final int _dateFieldId; - private final boolean _needsOneBaseAdjustment; - - private CalendarFieldFunction(int dateFieldId, boolean needsOneBaseAdjustment) { - _dateFieldId = dateFieldId; - _needsOneBaseAdjustment = needsOneBaseAdjustment; - } - - public final ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - int val; - try { - ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - val = OperandResolver.coerceValueToInt(ve); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - if (val < 0) { - return ErrorEval.NUM_ERROR; - } - return new NumberEval(getCalField(val)); - } - - private int getCalField(int serialDay) { - if (serialDay == 0) { - // Special weird case - // day zero should be 31-Dec-1899, but Excel seems to think it is 0-Jan-1900 - switch (_dateFieldId) { - case Calendar.YEAR: return 1900; - case Calendar.MONTH: return 1; - case Calendar.DAY_OF_MONTH: return 0; - } - throw new IllegalStateException("bad date field " + _dateFieldId); - } - Date d = DateUtil.getJavaDate(serialDay, false); // TODO fix 1900/1904 problem - - Calendar c = new GregorianCalendar(); - c.setTime(d); - - int result = c.get(_dateFieldId); - if (_needsOneBaseAdjustment) { - result++; - } - return result; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Choose.java b/src/java/org/apache/poi/hssf/record/formula/functions/Choose.java deleted file mode 100644 index cf6e4fd4a0..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Choose.java +++ /dev/null @@ -1,57 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.MissingArgEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * @author Josh Micich - */ -public final class Choose implements Function { - - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - if (args.length < 2) { - return ErrorEval.VALUE_INVALID; - } - - try { - int ix = evaluateFirstArg(args[0], srcRowIndex, srcColumnIndex); - if (ix < 1 || ix >= args.length) { - return ErrorEval.VALUE_INVALID; - } - ValueEval result = OperandResolver.getSingleValue(args[ix], srcRowIndex, srcColumnIndex); - if (result == MissingArgEval.instance) { - return BlankEval.instance; - } - return result; - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - - public static int evaluateFirstArg(ValueEval arg0, int srcRowIndex, int srcColumnIndex) - throws EvaluationException { - ValueEval ev = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - return OperandResolver.coerceValueToInt(ev); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Column.java b/src/java/org/apache/poi/hssf/record/formula/functions/Column.java deleted file mode 100644 index 02a34b4e27..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Column.java +++ /dev/null @@ -1,54 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.AreaEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -public final class Column implements Function0Arg, Function1Arg { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return new NumberEval(srcColumnIndex+1); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - int rnum; - - if (arg0 instanceof AreaEval) { - rnum = ((AreaEval) arg0).getFirstColumn(); - } else if (arg0 instanceof RefEval) { - rnum = ((RefEval) arg0).getColumn(); - } else { - // anything else is not valid argument - return ErrorEval.VALUE_INVALID; - } - - return new NumberEval(rnum + 1); - } - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - switch (args.length) { - case 1: - return evaluate(srcRowIndex, srcColumnIndex, args[0]); - case 0: - return new NumberEval(srcColumnIndex+1); - } - return ErrorEval.VALUE_INVALID; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Columns.java b/src/java/org/apache/poi/hssf/record/formula/functions/Columns.java deleted file mode 100644 index 83880e497b..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Columns.java +++ /dev/null @@ -1,45 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * Implementation for Excel COLUMNS function. - * - * @author Josh Micich - */ -public final class Columns extends Fixed1ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - - int result; - if (arg0 instanceof TwoDEval) { - result = ((TwoDEval) arg0).getWidth(); - } else if (arg0 instanceof RefEval) { - result = 1; - } else { // anything else is not valid argument - return ErrorEval.VALUE_INVALID; - } - return new NumberEval(result); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Count.java b/src/java/org/apache/poi/hssf/record/formula/functions/Count.java deleted file mode 100644 index 1c31d28b76..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Count.java +++ /dev/null @@ -1,77 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.MissingArgEval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate; - -/** - * Counts the number of cells that contain numeric data within - * the list of arguments. - * - * Excel Syntax - * COUNT(value1,value2,...) - * Value1, value2, ... are 1 to 30 arguments representing the values or ranges to be counted. - * - * TODO: Check this properly matches excel on edge cases - * like formula cells, error cells etc - */ -public final class Count implements Function { - - public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { - int nArgs = args.length; - if (nArgs < 1) { - // too few arguments - return ErrorEval.VALUE_INVALID; - } - - if (nArgs > 30) { - // too many arguments - return ErrorEval.VALUE_INVALID; - } - - int temp = 0; - - for(int i=0; i<nArgs; i++) { - temp += CountUtils.countArg(args[i], predicate); - - } - return new NumberEval(temp); - } - - private static final I_MatchPredicate predicate = new I_MatchPredicate() { - - public boolean matches(ValueEval valueEval) { - - if(valueEval instanceof NumberEval) { - // only numbers are counted - return true; - } - if(valueEval == MissingArgEval.instance) { - // oh yeah, and missing arguments - return true; - } - - // error values and string values not counted - return false; - } - }; -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/CountUtils.java b/src/java/org/apache/poi/hssf/record/formula/functions/CountUtils.java deleted file mode 100644 index 592fb985cc..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/CountUtils.java +++ /dev/null @@ -1,80 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * Common logic for COUNT, COUNTA and COUNTIF - * - * @author Josh Micich - */ -final class CountUtils { - - private CountUtils() { - // no instances of this class - } - - /** - * Common interface for the matching criteria. - */ - public interface I_MatchPredicate { - boolean matches(ValueEval x); - } - /** - * @return the number of evaluated cells in the range that match the specified criteria - */ - public static int countMatchingCellsInArea(TwoDEval areaEval, I_MatchPredicate criteriaPredicate) { - int result = 0; - - int height = areaEval.getHeight(); - int width = areaEval.getWidth(); - for (int rrIx=0; rrIx<height; rrIx++) { - for (int rcIx=0; rcIx<width; rcIx++) { - ValueEval ve = areaEval.getValue(rrIx, rcIx); - if(criteriaPredicate.matches(ve)) { - result++; - } - } - } - return result; - } - /** - * @return 1 if the evaluated cell matches the specified criteria - */ - public static int countMatchingCell(RefEval refEval, I_MatchPredicate criteriaPredicate) { - if(criteriaPredicate.matches(refEval.getInnerValueEval())) { - return 1; - } - return 0; - } - public static int countArg(ValueEval eval, I_MatchPredicate criteriaPredicate) { - if (eval == null) { - throw new IllegalArgumentException("eval must not be null"); - } - if (eval instanceof TwoDEval) { - return countMatchingCellsInArea((TwoDEval) eval, criteriaPredicate); - } - if (eval instanceof RefEval) { - return CountUtils.countMatchingCell((RefEval) eval, criteriaPredicate); - } - return criteriaPredicate.matches(eval) ? 1 : 0; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Counta.java b/src/java/org/apache/poi/hssf/record/formula/functions/Counta.java deleted file mode 100644 index ee289e2746..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Counta.java +++ /dev/null @@ -1,72 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate; - -/** - * Counts the number of cells that contain data within the list of arguments. - * - * Excel Syntax - * COUNTA(value1,value2,...) - * Value1, value2, ... are 1 to 30 arguments representing the values or ranges to be counted. - * - * @author Josh Micich - */ -public final class Counta implements Function { - - public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { - int nArgs = args.length; - if (nArgs < 1) { - // too few arguments - return ErrorEval.VALUE_INVALID; - } - - if (nArgs > 30) { - // too many arguments - return ErrorEval.VALUE_INVALID; - } - - int temp = 0; - - for(int i=0; i<nArgs; i++) { - temp += CountUtils.countArg(args[i], predicate); - - } - return new NumberEval(temp); - } - - private static final I_MatchPredicate predicate = new I_MatchPredicate() { - - public boolean matches(ValueEval valueEval) { - // Note - observed behavior of Excel: - // Error values like #VALUE!, #REF!, #DIV/0!, #NAME? etc don't cause this COUNTA to return an error - // in fact, they seem to get counted - - if(valueEval == BlankEval.instance) { - return false; - } - // Note - everything but BlankEval counts - return true; - } - }; -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Countblank.java b/src/java/org/apache/poi/hssf/record/formula/functions/Countblank.java deleted file mode 100644 index b155b84d86..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Countblank.java +++ /dev/null @@ -1,60 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * Implementation for the function COUNTBLANK - * <p> - * Syntax: COUNTBLANK ( range ) - * <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions"> - * <tr><th>range </th><td>is the range of cells to count blanks</td></tr> - * </table> - * </p> - * - * @author Mads Mohr Christensen - */ -public final class Countblank extends Fixed1ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - - double result; - if (arg0 instanceof RefEval) { - result = CountUtils.countMatchingCell((RefEval) arg0, predicate); - } else if (arg0 instanceof TwoDEval) { - result = CountUtils.countMatchingCellsInArea((TwoDEval) arg0, predicate); - } else { - throw new IllegalArgumentException("Bad range arg type (" + arg0.getClass().getName() + ")"); - } - return new NumberEval(result); - } - - private static final I_MatchPredicate predicate = new I_MatchPredicate() { - - public boolean matches(ValueEval valueEval) { - // Note - only BlankEval counts - return valueEval == BlankEval.instance; - } - }; -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Countif.java b/src/java/org/apache/poi/hssf/record/formula/functions/Countif.java deleted file mode 100644 index 93b2ea8f0c..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Countif.java +++ /dev/null @@ -1,528 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import java.util.regex.Pattern; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate; -import org.apache.poi.ss.formula.TwoDEval; -import org.apache.poi.ss.usermodel.ErrorConstants; - -/** - * Implementation for the function COUNTIF - * <p> - * Syntax: COUNTIF ( range, criteria ) - * <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions"> - * <tr><th>range </th><td>is the range of cells to be counted based on the criteria</td></tr> - * <tr><th>criteria</th><td>is used to determine which cells to count</td></tr> - * </table> - * </p> - * - * @author Josh Micich - */ -public final class Countif extends Fixed2ArgFunction { - - private static final class CmpOp { - public static final int NONE = 0; - public static final int EQ = 1; - public static final int NE = 2; - public static final int LE = 3; - public static final int LT = 4; - public static final int GT = 5; - public static final int GE = 6; - - public static final CmpOp OP_NONE = op("", NONE); - public static final CmpOp OP_EQ = op("=", EQ); - public static final CmpOp OP_NE = op("<>", NE); - public static final CmpOp OP_LE = op("<=", LE); - public static final CmpOp OP_LT = op("<", LT); - public static final CmpOp OP_GT = op(">", GT); - public static final CmpOp OP_GE = op(">=", GE); - private final String _representation; - private final int _code; - - private static CmpOp op(String rep, int code) { - return new CmpOp(rep, code); - } - private CmpOp(String representation, int code) { - _representation = representation; - _code = code; - } - /** - * @return number of characters used to represent this operator - */ - public int getLength() { - return _representation.length(); - } - public int getCode() { - return _code; - } - public static CmpOp getOperator(String value) { - int len = value.length(); - if (len < 1) { - return OP_NONE; - } - - char firstChar = value.charAt(0); - - switch(firstChar) { - case '=': - return OP_EQ; - case '>': - if (len > 1) { - switch(value.charAt(1)) { - case '=': - return OP_GE; - } - } - return OP_GT; - case '<': - if (len > 1) { - switch(value.charAt(1)) { - case '=': - return OP_LE; - case '>': - return OP_NE; - } - } - return OP_LT; - } - return OP_NONE; - } - public boolean evaluate(boolean cmpResult) { - switch (_code) { - case NONE: - case EQ: - return cmpResult; - case NE: - return !cmpResult; - } - throw new RuntimeException("Cannot call boolean evaluate on non-equality operator '" - + _representation + "'"); - } - public boolean evaluate(int cmpResult) { - switch (_code) { - case NONE: - case EQ: - return cmpResult == 0; - case NE: return cmpResult != 0; - case LT: return cmpResult < 0; - case LE: return cmpResult <= 0; - case GT: return cmpResult > 0; - case GE: return cmpResult <= 0; - } - throw new RuntimeException("Cannot call boolean evaluate on non-equality operator '" - + _representation + "'"); - } - public String toString() { - StringBuffer sb = new StringBuffer(64); - sb.append(getClass().getName()); - sb.append(" [").append(_representation).append("]"); - return sb.toString(); - } - public String getRepresentation() { - return _representation; - } - } - - private static abstract class MatcherBase implements I_MatchPredicate { - private final CmpOp _operator; - - MatcherBase(CmpOp operator) { - _operator = operator; - } - protected final int getCode() { - return _operator.getCode(); - } - protected final boolean evaluate(int cmpResult) { - return _operator.evaluate(cmpResult); - } - protected final boolean evaluate(boolean cmpResult) { - return _operator.evaluate(cmpResult); - } - @Override - public final String toString() { - StringBuffer sb = new StringBuffer(64); - sb.append(getClass().getName()).append(" ["); - sb.append(_operator.getRepresentation()); - sb.append(getValueText()); - sb.append("]"); - return sb.toString(); - } - protected abstract String getValueText(); - } - - private static final class NumberMatcher extends MatcherBase { - - private final double _value; - - public NumberMatcher(double value, CmpOp operator) { - super(operator); - _value = value; - } - @Override - protected String getValueText() { - return String.valueOf(_value); - } - - public boolean matches(ValueEval x) { - double testValue; - if(x instanceof StringEval) { - // if the target(x) is a string, but parses as a number - // it may still count as a match, only for the equality operator - switch (getCode()) { - case CmpOp.EQ: - case CmpOp.NONE: - break; - case CmpOp.NE: - // Always matches (inconsistent with above two cases). - // for example '<>123' matches '123', '4', 'abc', etc - return true; - default: - // never matches (also inconsistent with above three cases). - // for example '>5' does not match '6', - return false; - } - StringEval se = (StringEval)x; - Double val = OperandResolver.parseDouble(se.getStringValue()); - if(val == null) { - // x is text that is not a number - return false; - } - return _value == val.doubleValue(); - } else if((x instanceof NumberEval)) { - NumberEval ne = (NumberEval) x; - testValue = ne.getNumberValue(); - } else { - return false; - } - return evaluate(Double.compare(testValue, _value)); - } - } - private static final class BooleanMatcher extends MatcherBase { - - private final int _value; - - public BooleanMatcher(boolean value, CmpOp operator) { - super(operator); - _value = boolToInt(value); - } - @Override - protected String getValueText() { - return _value == 1 ? "TRUE" : "FALSE"; - } - - private static int boolToInt(boolean value) { - return value ? 1 : 0; - } - - public boolean matches(ValueEval x) { - int testValue; - if(x instanceof StringEval) { - if (true) { // change to false to observe more intuitive behaviour - // Note - Unlike with numbers, it seems that COUNTIF never matches - // boolean values when the target(x) is a string - return false; - } - StringEval se = (StringEval)x; - Boolean val = parseBoolean(se.getStringValue()); - if(val == null) { - // x is text that is not a boolean - return false; - } - testValue = boolToInt(val.booleanValue()); - } else if((x instanceof BoolEval)) { - BoolEval be = (BoolEval) x; - testValue = boolToInt(be.getBooleanValue()); - } else { - return false; - } - return evaluate(testValue - _value); - } - } - private static final class ErrorMatcher extends MatcherBase { - - private final int _value; - - public ErrorMatcher(int errorCode, CmpOp operator) { - super(operator); - _value = errorCode; - } - @Override - protected String getValueText() { - return ErrorConstants.getText(_value); - } - - public boolean matches(ValueEval x) { - if(x instanceof ErrorEval) { - int testValue = ((ErrorEval)x).getErrorCode(); - return evaluate(testValue - _value); - } - return false; - } - } - private static final class StringMatcher extends MatcherBase { - - private final String _value; - private final Pattern _pattern; - - public StringMatcher(String value, CmpOp operator) { - super(operator); - _value = value; - switch(operator.getCode()) { - case CmpOp.NONE: - case CmpOp.EQ: - case CmpOp.NE: - _pattern = getWildCardPattern(value); - break; - default: - // pattern matching is never used for < > <= => - _pattern = null; - } - } - @Override - protected String getValueText() { - if (_pattern == null) { - return _value; - } - return _pattern.pattern(); - } - - public boolean matches(ValueEval x) { - if (x instanceof BlankEval) { - switch(getCode()) { - case CmpOp.NONE: - case CmpOp.EQ: - return _value.length() == 0; - } - // no other criteria matches a blank cell - return false; - } - if(!(x instanceof StringEval)) { - // must always be string - // even if match str is wild, but contains only digits - // e.g. '4*7', NumberEval(4567) does not match - return false; - } - String testedValue = ((StringEval) x).getStringValue(); - if (testedValue.length() < 1 && _value.length() < 1) { - // odd case: criteria '=' behaves differently to criteria '' - - switch(getCode()) { - case CmpOp.NONE: return true; - case CmpOp.EQ: return false; - case CmpOp.NE: return true; - } - return false; - } - if (_pattern != null) { - return evaluate(_pattern.matcher(testedValue).matches()); - } - return evaluate(testedValue.compareTo(_value)); - } - /** - * Translates Excel countif wildcard strings into java regex strings - * @return <code>null</code> if the specified value contains no special wildcard characters. - */ - private static Pattern getWildCardPattern(String value) { - int len = value.length(); - StringBuffer sb = new StringBuffer(len); - boolean hasWildCard = false; - for(int i=0; i<len; i++) { - char ch = value.charAt(i); - switch(ch) { - case '?': - hasWildCard = true; - // match exactly one character - sb.append('.'); - continue; - case '*': - hasWildCard = true; - // match one or more occurrences of any character - sb.append(".*"); - continue; - case '~': - if (i+1<len) { - ch = value.charAt(i+1); - switch (ch) { - case '?': - case '*': - hasWildCard = true; - sb.append('[').append(ch).append(']'); - i++; // Note - incrementing loop variable here - continue; - } - } - // else not '~?' or '~*' - sb.append('~'); // just plain '~' - continue; - case '.': - case '$': - case '^': - case '[': - case ']': - case '(': - case ')': - // escape literal characters that would have special meaning in regex - sb.append("\\").append(ch); - continue; - } - sb.append(ch); - } - if (hasWildCard) { - return Pattern.compile(sb.toString()); - } - return null; - } - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - - I_MatchPredicate mp = createCriteriaPredicate(arg1, srcRowIndex, srcColumnIndex); - if(mp == null) { - // If the criteria arg is a reference to a blank cell, countif always returns zero. - return NumberEval.ZERO; - } - double result = countMatchingCellsInArea(arg0, mp); - return new NumberEval(result); - } - /** - * @return the number of evaluated cells in the range that match the specified criteria - */ - private double countMatchingCellsInArea(ValueEval rangeArg, I_MatchPredicate criteriaPredicate) { - - if (rangeArg instanceof RefEval) { - return CountUtils.countMatchingCell((RefEval) rangeArg, criteriaPredicate); - } else if (rangeArg instanceof TwoDEval) { - return CountUtils.countMatchingCellsInArea((TwoDEval) rangeArg, criteriaPredicate); - } else { - throw new IllegalArgumentException("Bad range arg type (" + rangeArg.getClass().getName() + ")"); - } - } - - /** - * Creates a criteria predicate object for the supplied criteria arg - * @return <code>null</code> if the arg evaluates to blank. - */ - /* package */ static I_MatchPredicate createCriteriaPredicate(ValueEval arg, int srcRowIndex, int srcColumnIndex) { - - ValueEval evaluatedCriteriaArg = evaluateCriteriaArg(arg, srcRowIndex, srcColumnIndex); - - if(evaluatedCriteriaArg instanceof NumberEval) { - return new NumberMatcher(((NumberEval)evaluatedCriteriaArg).getNumberValue(), CmpOp.OP_NONE); - } - if(evaluatedCriteriaArg instanceof BoolEval) { - return new BooleanMatcher(((BoolEval)evaluatedCriteriaArg).getBooleanValue(), CmpOp.OP_NONE); - } - - if(evaluatedCriteriaArg instanceof StringEval) { - return createGeneralMatchPredicate((StringEval)evaluatedCriteriaArg); - } - if(evaluatedCriteriaArg instanceof ErrorEval) { - return new ErrorMatcher(((ErrorEval)evaluatedCriteriaArg).getErrorCode(), CmpOp.OP_NONE); - } - if(evaluatedCriteriaArg == BlankEval.instance) { - return null; - } - throw new RuntimeException("Unexpected type for criteria (" - + evaluatedCriteriaArg.getClass().getName() + ")"); - } - - /** - * - * @return the de-referenced criteria arg (possibly {@link ErrorEval}) - */ - private static ValueEval evaluateCriteriaArg(ValueEval arg, int srcRowIndex, int srcColumnIndex) { - try { - return OperandResolver.getSingleValue(arg, srcRowIndex, (short)srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - /** - * When the second argument is a string, many things are possible - */ - private static I_MatchPredicate createGeneralMatchPredicate(StringEval stringEval) { - String value = stringEval.getStringValue(); - CmpOp operator = CmpOp.getOperator(value); - value = value.substring(operator.getLength()); - - Boolean booleanVal = parseBoolean(value); - if(booleanVal != null) { - return new BooleanMatcher(booleanVal.booleanValue(), operator); - } - - Double doubleVal = OperandResolver.parseDouble(value); - if(doubleVal != null) { - return new NumberMatcher(doubleVal.doubleValue(), operator); - } - ErrorEval ee = parseError(value); - if (ee != null) { - return new ErrorMatcher(ee.getErrorCode(), operator); - } - - //else - just a plain string with no interpretation. - return new StringMatcher(value, operator); - } - private static ErrorEval parseError(String value) { - if (value.length() < 4 || value.charAt(0) != '#') { - return null; - } - if (value.equals("#NULL!")) return ErrorEval.NULL_INTERSECTION; - if (value.equals("#DIV/0!")) return ErrorEval.DIV_ZERO; - if (value.equals("#VALUE!")) return ErrorEval.VALUE_INVALID; - if (value.equals("#REF!")) return ErrorEval.REF_INVALID; - if (value.equals("#NAME?")) return ErrorEval.NAME_INVALID; - if (value.equals("#NUM!")) return ErrorEval.NUM_ERROR; - if (value.equals("#N/A")) return ErrorEval.NA; - - return null; - } - /** - * Boolean literals ('TRUE', 'FALSE') treated similarly but NOT same as numbers. - */ - /* package */ static Boolean parseBoolean(String strRep) { - if (strRep.length() < 1) { - return null; - } - switch(strRep.charAt(0)) { - case 't': - case 'T': - if("TRUE".equalsIgnoreCase(strRep)) { - return Boolean.TRUE; - } - break; - case 'f': - case 'F': - if("FALSE".equalsIgnoreCase(strRep)) { - return Boolean.FALSE; - } - break; - } - return null; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/DateFunc.java b/src/java/org/apache/poi/hssf/record/formula/functions/DateFunc.java deleted file mode 100644 index 55bc0825fd..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/DateFunc.java +++ /dev/null @@ -1,92 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import java.util.Calendar; -import java.util.GregorianCalendar; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.usermodel.DateUtil; - - -/** - * Implementation for the Excel function DATE - * - * @author Pavel Krupets (pkrupets at palmtreebusiness dot com) - */ -public final class DateFunc extends Fixed3ArgFunction { - - public static final Function instance = new DateFunc(); - - private DateFunc() { - // no fields to initialise - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - double result; - try { - double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - double d2 = NumericFunction.singleOperandEvaluate(arg2, srcRowIndex, srcColumnIndex); - result = evaluate(getYear(d0), (int) (d1 - 1), (int) d2); - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - - private static double evaluate(int year, int month, int pDay) throws EvaluationException { - - if (year < 0 || month < 0 || pDay < 0) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - - if (year == 1900 && month == Calendar.FEBRUARY && pDay == 29) { - return 60.0; - } - - int day = pDay; - if (year == 1900) { - if ((month == Calendar.JANUARY && day >= 60) || - (month == Calendar.FEBRUARY && day >= 30)) { - day--; - } - } - - Calendar c = new GregorianCalendar(); - - c.set(year, month, day, 0, 0, 0); - c.set(Calendar.MILLISECOND, 0); - - return DateUtil.getExcelDate(c.getTime(), false); // TODO - fix 1900/1904 problem - } - - private static int getYear(double d) { - int year = (int)d; - - if (year < 0) { - return -1; - } - - return year < 1900 ? 1900 + year : year; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Days360.java b/src/java/org/apache/poi/hssf/record/formula/functions/Days360.java deleted file mode 100644 index 66f95fbc92..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Days360.java +++ /dev/null @@ -1,118 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hssf.record.formula.functions; - -import java.util.Calendar; -import java.util.GregorianCalendar; - -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.usermodel.DateUtil; - -/** - * Calculates the number of days between two dates based on a 360-day year - * (twelve 30-day months), which is used in some accounting calculations. Use - * this function to help compute payments if your accounting system is based on - * twelve 30-day months. - * - * @author PUdalau - */ -public class Days360 extends Var2or3ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - double result; - try { - double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - result = evaluate(d0, d1, false); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - double result; - try { - double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - ValueEval ve = OperandResolver.getSingleValue(arg2, srcRowIndex, srcColumnIndex); - Boolean method = OperandResolver.coerceValueToBoolean(ve, false); - result = evaluate(d0, d1, method == null ? false : method.booleanValue()); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - - private static double evaluate(double d0, double d1, boolean method) { - Calendar startingDate = getStartingDate(d0); - Calendar endingDate = getEndingDateAccordingToStartingDate(d1, startingDate); - long startingDay = startingDate.get(Calendar.MONTH) * 30 + startingDate.get(Calendar.DAY_OF_MONTH); - long endingDay = (endingDate.get(Calendar.YEAR) - startingDate.get(Calendar.YEAR)) * 360 - + endingDate.get(Calendar.MONTH) * 30 + endingDate.get(Calendar.DAY_OF_MONTH); - return endingDay - startingDay; - } - - private static Calendar getDate(double date) { - Calendar processedDate = new GregorianCalendar(); - processedDate.setTime(DateUtil.getJavaDate(date, false)); - return processedDate; - } - - private static Calendar getStartingDate(double date) { - Calendar startingDate = getDate(date); - if (isLastDayOfMonth(startingDate)) { - startingDate.set(Calendar.DAY_OF_MONTH, 30); - } - return startingDate; - } - - private static Calendar getEndingDateAccordingToStartingDate(double date, Calendar startingDate) { - Calendar endingDate = getDate(date); - endingDate.setTime(DateUtil.getJavaDate(date, false)); - if (isLastDayOfMonth(endingDate)) { - if (startingDate.get(Calendar.DATE) < 30) { - endingDate = getFirstDayOfNextMonth(endingDate); - } - } - return endingDate; - } - - private static boolean isLastDayOfMonth(Calendar date) { - Calendar clone = (Calendar) date.clone(); - clone.add(java.util.Calendar.MONTH, 1); - clone.add(java.util.Calendar.DAY_OF_MONTH, -1); - int lastDayOfMonth = clone.get(Calendar.DAY_OF_MONTH); - return date.get(Calendar.DAY_OF_MONTH) == lastDayOfMonth; - } - - private static Calendar getFirstDayOfNextMonth(Calendar date) { - Calendar newDate = (Calendar) date.clone(); - if (date.get(Calendar.MONTH) < Calendar.DECEMBER) { - newDate.set(Calendar.MONTH, date.get(Calendar.MONTH) + 1); - } else { - newDate.set(Calendar.MONTH, 1); - newDate.set(Calendar.YEAR, date.get(Calendar.YEAR) + 1); - } - newDate.set(Calendar.DATE, 1); - return newDate; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Errortype.java b/src/java/org/apache/poi/hssf/record/formula/functions/Errortype.java deleted file mode 100644 index 25dda0a1b3..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Errortype.java +++ /dev/null @@ -1,79 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.usermodel.ErrorConstants; - -/** - * Implementation for the ERROR.TYPE() Excel function. - * <p> - * <b>Syntax:</b><br/> - * <b>ERROR.TYPE</b>(<b>errorValue</b>)</p> - * <p> - * Returns a number corresponding to the error type of the supplied argument.<p/> - * <p> - * <table border="1" cellpadding="1" cellspacing="1" summary="Return values for ERROR.TYPE()"> - * <tr><td>errorValue</td><td>Return Value</td></tr> - * <tr><td>#NULL!</td><td>1</td></tr> - * <tr><td>#DIV/0!</td><td>2</td></tr> - * <tr><td>#VALUE!</td><td>3</td></tr> - * <tr><td>#REF!</td><td>4</td></tr> - * <tr><td>#NAME?</td><td>5</td></tr> - * <tr><td>#NUM!</td><td>6</td></tr> - * <tr><td>#N/A!</td><td>7</td></tr> - * <tr><td>everything else</td><td>#N/A!</td></tr> - * </table> - * - * Note - the results of ERROR.TYPE() are different to the constants defined in - * <tt>ErrorConstants</tt>. - * </p> - * - * @author Josh Micich - */ -public final class Errortype extends Fixed1ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - - try { - OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - return ErrorEval.NA; - } catch (EvaluationException e) { - int result = translateErrorCodeToErrorTypeValue(e.getErrorEval().getErrorCode()); - return new NumberEval(result); - } - } - - private int translateErrorCodeToErrorTypeValue(int errorCode) { - switch (errorCode) { - case ErrorConstants.ERROR_NULL: return 1; - case ErrorConstants.ERROR_DIV_0: return 2; - case ErrorConstants.ERROR_VALUE: return 3; - case ErrorConstants.ERROR_REF: return 4; - case ErrorConstants.ERROR_NAME: return 5; - case ErrorConstants.ERROR_NUM: return 6; - case ErrorConstants.ERROR_NA : return 7; - } - throw new IllegalArgumentException("Invalid error code (" + errorCode + ")"); - } - -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Even.java b/src/java/org/apache/poi/hssf/record/formula/functions/Even.java deleted file mode 100644 index 8426416d42..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Even.java +++ /dev/null @@ -1,49 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public final class Even extends NumericFunction.OneArg { - - private static final long PARITY_MASK = 0xFFFFFFFFFFFFFFFEL; - - protected double evaluate(double d) { - if (d==0) { - return 0; - } - long result; - if (d>0) { - result = calcEven(d); - } else { - result = -calcEven(-d); - } - return result; - } - - private static long calcEven(double d) { - long x = ((long) d) & PARITY_MASK; - if (x == d) { - return x; - } - return x + 2; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java deleted file mode 100644 index c101f2dc9e..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java +++ /dev/null @@ -1,118 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public abstract class FinanceFunction implements Function3Arg, Function4Arg { - private static final ValueEval DEFAULT_ARG3 = NumberEval.ZERO; - private static final ValueEval DEFAULT_ARG4 = BoolEval.FALSE; - - - protected FinanceFunction() { - // no instance fields - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - return evaluate(srcRowIndex, srcColumnIndex, arg0, arg1, arg2, DEFAULT_ARG3); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2, ValueEval arg3) { - return evaluate(srcRowIndex, srcColumnIndex, arg0, arg1, arg2, arg3, DEFAULT_ARG4); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2, ValueEval arg3, ValueEval arg4) { - double result; - try { - double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - double d2 = NumericFunction.singleOperandEvaluate(arg2, srcRowIndex, srcColumnIndex); - double d3 = NumericFunction.singleOperandEvaluate(arg3, srcRowIndex, srcColumnIndex); - double d4 = NumericFunction.singleOperandEvaluate(arg4, srcRowIndex, srcColumnIndex); - result = evaluate(d0, d1, d2, d3, d4 != 0.0); - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - switch (args.length) { - case 3: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], DEFAULT_ARG3, DEFAULT_ARG4); - case 4: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], args[3], DEFAULT_ARG4); - case 5: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], args[3], args[4]); - } - return ErrorEval.VALUE_INVALID; - } - - protected double evaluate(double[] ds) throws EvaluationException { - // All finance functions have 3 to 5 args, first 4 are numbers, last is boolean - // default for last 2 args are 0.0 and false - // Text boolean literals are not valid for the last arg - - double arg3 = 0.0; - double arg4 = 0.0; - - switch(ds.length) { - case 5: - arg4 = ds[4]; - case 4: - arg3 = ds[3]; - case 3: - break; - default: - throw new IllegalStateException("Wrong number of arguments"); - } - return evaluate(ds[0], ds[1], ds[2], arg3, arg4!=0.0); - } - - protected abstract double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) throws EvaluationException ; - - - public static final Function FV = new FinanceFunction() { - protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) { - return FinanceLib.fv(rate, arg1, arg2, arg3, type); - } - }; - public static final Function NPER = new FinanceFunction() { - protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) { - return FinanceLib.nper(rate, arg1, arg2, arg3, type); - } - }; - public static final Function PMT = new FinanceFunction() { - protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) { - return FinanceLib.pmt(rate, arg1, arg2, arg3, type); - } - }; - public static final Function PV = new FinanceFunction() { - protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) { - return FinanceLib.pv(rate, arg1, arg2, arg3, type); - } - }; -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/FinanceLib.java b/src/java/org/apache/poi/hssf/record/formula/functions/FinanceLib.java deleted file mode 100644 index d811116c10..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/FinanceLib.java +++ /dev/null @@ -1,185 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - * - * This class is a functon library for common fiscal functions. - * <b>Glossary of terms/abbreviations:</b> - * <br/> - * <ul> - * <li><em>FV:</em> Future Value</li> - * <li><em>PV:</em> Present Value</li> - * <li><em>NPV:</em> Net Present Value</li> - * <li><em>PMT:</em> (Periodic) Payment</li> - * - * </ul> - * For more info on the terms/abbreviations please use the references below - * (hyperlinks are subject to change): - * </br>Online References: - * <ol> - * <li>GNU Emacs Calc 2.02 Manual: http://theory.uwinnipeg.ca/gnu/calc/calc_203.html</li> - * <li>Yahoo Financial Glossary: http://biz.yahoo.com/f/g/nn.html#y</li> - * <li>MS Excel function reference: http://office.microsoft.com/en-us/assistance/CH062528251033.aspx</li> - * </ol> - * <h3>Implementation Notes:</h3> - * Symbols used in the formulae that follow:<br/> - * <ul> - * <li>p: present value</li> - * <li>f: future value</li> - * <li>n: number of periods</li> - * <li>y: payment (in each period)</li> - * <li>r: rate</li> - * <li>^: the power operator (NOT the java bitwise XOR operator!)</li> - * </ul> - * [From MS Excel function reference] Following are some of the key formulas - * that are used in this implementation: - * <pre> - * p(1+r)^n + y(1+rt)((1+r)^n-1)/r + f=0 ...{when r!=0} - * ny + p + f=0 ...{when r=0} - * </pre> - */ -final class FinanceLib { - - private FinanceLib() { - // no instances of this class - } - - /** - * Future value of an amount given the number of payments, rate, amount - * of individual payment, present value and boolean value indicating whether - * payments are due at the beginning of period - * (false => payments are due at end of period) - * @param r rate - * @param n num of periods - * @param y pmt per period - * @param p future value - * @param t type (true=pmt at end of period, false=pmt at begining of period) - */ - public static double fv(double r, double n, double y, double p, boolean t) { - double retval = 0; - if (r == 0) { - retval = -1*(p+(n*y)); - } - else { - double r1 = r + 1; - retval =((1-Math.pow(r1, n)) * (t ? r1 : 1) * y ) / r - - - p*Math.pow(r1, n); - } - return retval; - } - - /** - * Present value of an amount given the number of future payments, rate, amount - * of individual payment, future value and boolean value indicating whether - * payments are due at the beginning of period - * (false => payments are due at end of period) - * @param r - * @param n - * @param y - * @param f - * @param t - */ - public static double pv(double r, double n, double y, double f, boolean t) { - double retval = 0; - if (r == 0) { - retval = -1*((n*y)+f); - } - else { - double r1 = r + 1; - retval =(( ( 1 - Math.pow(r1, n) ) / r ) * (t ? r1 : 1) * y - f) - / - Math.pow(r1, n); - } - return retval; - } - - /** - * calculates the Net Present Value of a principal amount - * given the discount rate and a sequence of cash flows - * (supplied as an array). If the amounts are income the value should - * be positive, else if they are payments and not income, the - * value should be negative. - * @param r - * @param cfs cashflow amounts - */ - public static double npv(double r, double[] cfs) { - double npv = 0; - double r1 = r + 1; - double trate = r1; - for (int i=0, iSize=cfs.length; i<iSize; i++) { - npv += cfs[i] / trate; - trate *= r1; - } - return npv; - } - - /** - * - * @param r - * @param n - * @param p - * @param f - * @param t - */ - public static double pmt(double r, double n, double p, double f, boolean t) { - double retval = 0; - if (r == 0) { - retval = -1*(f+p)/n; - } - else { - double r1 = r + 1; - retval = ( f + p * Math.pow(r1, n) ) * r - / - ((t ? r1 : 1) * (1 - Math.pow(r1, n))); - } - return retval; - } - - /** - * - * @param r - * @param y - * @param p - * @param f - * @param t - */ - public static double nper(double r, double y, double p, double f, boolean t) { - double retval = 0; - if (r == 0) { - retval = -1 * (f + p) / y; - } else { - double r1 = r + 1; - double ryr = (t ? r1 : 1) * y / r; - double a1 = ((ryr - f) < 0) - ? Math.log(f - ryr) - : Math.log(ryr - f); - double a2 = ((ryr - f) < 0) - ? Math.log(-p - ryr) - : Math.log(p + ryr); - double a3 = Math.log(r1); - retval = (a1 - a2) / a3; - } - return retval; - } - - -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed0ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed0ArgFunction.java deleted file mode 100644 index ff3207b319..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed0ArgFunction.java +++ /dev/null @@ -1,35 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Convenience base class for functions that only take zero arguments. - * - * @author Josh Micich - */ -public abstract class Fixed0ArgFunction implements Function0Arg { - public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - if (args.length != 0) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(srcRowIndex, srcColumnIndex); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed1ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed1ArgFunction.java deleted file mode 100644 index 6a12d9efc8..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed1ArgFunction.java +++ /dev/null @@ -1,35 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Convenience base class for functions that must take exactly one argument. - * - * @author Josh Micich - */ -public abstract class Fixed1ArgFunction implements Function1Arg { - public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - if (args.length != 1) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(srcRowIndex, srcColumnIndex, args[0]); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed2ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed2ArgFunction.java deleted file mode 100644 index 7695920b97..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed2ArgFunction.java +++ /dev/null @@ -1,35 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Convenience base class for functions that must take exactly two arguments. - * - * @author Josh Micich - */ -public abstract class Fixed2ArgFunction implements Function2Arg { - public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - if (args.length != 2) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1]); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed3ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed3ArgFunction.java deleted file mode 100644 index d4488ab7b7..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed3ArgFunction.java +++ /dev/null @@ -1,35 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Convenience base class for functions that must take exactly three arguments. - * - * @author Josh Micich - */ -public abstract class Fixed3ArgFunction implements Function3Arg { - public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - if (args.length != 3) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2]); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed4ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed4ArgFunction.java deleted file mode 100644 index 5588714972..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed4ArgFunction.java +++ /dev/null @@ -1,35 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Convenience base class for functions that must take exactly four arguments. - * - * @author Josh Micich - */ -public abstract class Fixed4ArgFunction implements Function4Arg { - public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - if (args.length != 4) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], args[3]); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/FreeRefFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/FreeRefFunction.java deleted file mode 100644 index 119592101d..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/FreeRefFunction.java +++ /dev/null @@ -1,51 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.OperationEvaluationContext; - - -/** - * For most Excel functions, involving references ((cell, area), (2d, 3d)), the references are - * passed in as arguments, and the exact location remains fixed. However, a select few Excel - * functions have the ability to access cells that were not part of any reference passed as an - * argument.<br/> - * Two important functions with this feature are <b>INDIRECT</b> and <b>OFFSET</b><p/> - * - * When POI evaluates formulas, each reference argument is capable of evaluating any cell inside - * its range. Actually, even cells outside the reference range but on the same sheet can be - * evaluated. This allows <b>OFFSET</b> to be implemented like most other functions - taking only - * the arguments, and source cell coordinates. - * - * For the moment this interface only exists to serve the <b>INDIRECT</b> which can decode - * arbitrary text into cell references, and evaluate them.. - * - * @author Josh Micich - */ -public interface FreeRefFunction { - /** - * @param args the pre-evaluated arguments for this function. args is never <code>null</code>, - * nor are any of its elements. - * @param ec primarily used to identify the source cell containing the formula being evaluated. - * may also be used to dynamically create reference evals. - * @return never <code>null</code>. Possibly an instance of <tt>ErrorEval</tt> in the case of - * a specified Excel error (Exceptions are never thrown to represent Excel errors). - */ - ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function.java deleted file mode 100644 index 92505ecd03..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Function.java +++ /dev/null @@ -1,43 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.MissingArgEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Common interface for all implementations of Excel built-in functions. - * - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public interface Function { - - /** - * @param args the evaluated function arguments. Empty values are represented with - * {@link BlankEval} or {@link MissingArgEval}, never <code>null</code>. - * @param srcRowIndex row index of the cell containing the formula under evaluation - * @param srcColumnIndex column index of the cell containing the formula under evaluation - * @return The evaluated result, possibly an {@link ErrorEval}, never <code>null</code>. - * <b>Note</b> - Excel uses the error code <i>#NUM!</i> instead of IEEE <i>NaN</i>, so when - * numeric functions evaluate to {@link Double#NaN} be sure to translate the result to {@link - * ErrorEval#NUM_ERROR}. - */ - ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function0Arg.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function0Arg.java deleted file mode 100644 index c61a87e0a2..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Function0Arg.java +++ /dev/null @@ -1,32 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implemented by all functions that can be called with zero arguments - * - * @author Josh Micich - */ -public interface Function0Arg extends Function { - /** - * see {@link Function#evaluate(ValueEval[], int, int)} - */ - ValueEval evaluate(int srcRowIndex, int srcColumnIndex); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function1Arg.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function1Arg.java deleted file mode 100644 index 42007fa4cc..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Function1Arg.java +++ /dev/null @@ -1,32 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implemented by all functions that can be called with one argument - * - * @author Josh Micich - */ -public interface Function1Arg extends Function { - /** - * see {@link Function#evaluate(ValueEval[], int, int)} - */ - ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function2Arg.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function2Arg.java deleted file mode 100644 index b0ef472859..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Function2Arg.java +++ /dev/null @@ -1,32 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implemented by all functions that can be called with two arguments - * - * @author Josh Micich - */ -public interface Function2Arg extends Function { - /** - * see {@link Function#evaluate(ValueEval[], int, int)} - */ - ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function3Arg.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function3Arg.java deleted file mode 100644 index 7ee32b81c2..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Function3Arg.java +++ /dev/null @@ -1,32 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implemented by all functions that can be called with three arguments - * - * @author Josh Micich - */ -public interface Function3Arg extends Function { - /** - * see {@link Function#evaluate(ValueEval[], int, int)} - */ - ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, ValueEval arg2); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function4Arg.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function4Arg.java deleted file mode 100644 index 7089432f75..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Function4Arg.java +++ /dev/null @@ -1,32 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implemented by all functions that can be called with four arguments - * - * @author Josh Micich - */ -public interface Function4Arg extends Function { - /** - * see {@link Function#evaluate(ValueEval[], int, int)} - */ - ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, ValueEval arg2, ValueEval arg3); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Hlookup.java b/src/java/org/apache/poi/hssf/record/formula/functions/Hlookup.java deleted file mode 100644 index df5ecad6ef..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Hlookup.java +++ /dev/null @@ -1,80 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; -import org.apache.poi.ss.formula.TwoDEval; -/** - * Implementation of the HLOOKUP() function.<p/> - * - * HLOOKUP finds a column in a lookup table by the first row value and returns the value from another row.<br/> - * - * <b>Syntax</b>:<br/> - * <b>HLOOKUP</b>(<b>lookup_value</b>, <b>table_array</b>, <b>row_index_num</b>, range_lookup)<p/> - * - * <b>lookup_value</b> The value to be found in the first column of the table array.<br/> - * <b>table_array</b> An area reference for the lookup data. <br/> - * <b>row_index_num</b> a 1 based index specifying which row value of the lookup data will be returned.<br/> - * <b>range_lookup</b> If TRUE (default), HLOOKUP finds the largest value less than or equal to - * the lookup_value. If FALSE, only exact matches will be considered<br/> - * - * @author Josh Micich - */ -public final class Hlookup extends Var3or4ArgFunction { - private static final ValueEval DEFAULT_ARG3 = BoolEval.TRUE; - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - return evaluate(srcRowIndex, srcColumnIndex, arg0, arg1, arg2, DEFAULT_ARG3); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2, ValueEval arg3) { - try { - // Evaluation order: - // arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 row_index, fetch result - ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - TwoDEval tableArray = LookupUtils.resolveTableArrayArg(arg1); - boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex); - int colIndex = LookupUtils.lookupIndexOfValue(lookupValue, LookupUtils.createRowVector(tableArray, 0), isRangeLookup); - int rowIndex = LookupUtils.resolveRowOrColIndexArg(arg2, srcRowIndex, srcColumnIndex); - ValueVector resultCol = createResultColumnVector(tableArray, rowIndex); - return resultCol.getItem(colIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - - /** - * Returns one column from an <tt>AreaEval</tt> - * - * @param rowIndex assumed to be non-negative - * - * @throws EvaluationException (#REF!) if colIndex is too high - */ - private ValueVector createResultColumnVector(TwoDEval tableArray, int rowIndex) throws EvaluationException { - if(rowIndex >= tableArray.getHeight()) { - throw EvaluationException.invalidRef(); - } - return LookupUtils.createRowVector(tableArray, rowIndex); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Hyperlink.java b/src/java/org/apache/poi/hssf/record/formula/functions/Hyperlink.java deleted file mode 100644 index 761c5f3a63..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Hyperlink.java +++ /dev/null @@ -1,49 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implementation of Excel HYPERLINK function.<p/> - * - * In Excel this function has special behaviour - it causes the displayed cell value to behave like - * a hyperlink in the GUI. From an evaluation perspective however, it is very simple.<p/> - * - * <b>Syntax</b>:<br/> - * <b>HYPERLINK</b>(<b>link_location</b>, friendly_name)<p/> - * - * <b>link_location</b> The URL of the hyperlink <br/> - * <b>friendly_name</b> (optional) the value to display<p/> - * - * Returns last argument. Leaves type unchanged (does not convert to {@link StringEval}). - * - * @author Wayne Clingingsmith - */ -public final class Hyperlink extends Var1or2ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - return arg0; - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - // note - if last arg is MissingArgEval, result will be NumberEval.ZERO, - // but WorkbookEvaluator does that translation - return arg1; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/IfFunc.java b/src/java/org/apache/poi/hssf/record/formula/functions/IfFunc.java deleted file mode 100644 index 77e304044b..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/IfFunc.java +++ /dev/null @@ -1,79 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.MissingArgEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implementation for the Excel function IF - * - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public final class IfFunc extends Var2or3ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - boolean b; - try { - b = evaluateFirstArg(arg0, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - if (b) { - if (arg1 == MissingArgEval.instance) { - return BlankEval.instance; - } - return arg1; - } - return BoolEval.FALSE; - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - boolean b; - try { - b = evaluateFirstArg(arg0, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - if (b) { - if (arg1 == MissingArgEval.instance) { - return BlankEval.instance; - } - return arg1; - } - if (arg2 == MissingArgEval.instance) { - return BlankEval.instance; - } - return arg2; - } - - public static boolean evaluateFirstArg(ValueEval arg, int srcCellRow, int srcCellCol) - throws EvaluationException { - ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); - Boolean b = OperandResolver.coerceValueToBoolean(ve, false); - if (b == null) { - return false; - } - return b.booleanValue(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Index.java b/src/java/org/apache/poi/hssf/record/formula/functions/Index.java deleted file mode 100644 index fd3816b994..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Index.java +++ /dev/null @@ -1,171 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.MissingArgEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * Implementation for the Excel function INDEX - * <p> - * - * Syntax : <br/> - * INDEX ( reference, row_num[, column_num [, area_num]])</br> - * INDEX ( array, row_num[, column_num]) - * <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions"> - * <tr><th>reference</th><td>typically an area reference, possibly a union of areas</td></tr> - * <tr><th>array</th><td>a literal array value (currently not supported)</td></tr> - * <tr><th>row_num</th><td>selects the row within the array or area reference</td></tr> - * <tr><th>column_num</th><td>selects column within the array or area reference. default is 1</td></tr> - * <tr><th>area_num</th><td>used when reference is a union of areas</td></tr> - * </table> - * </p> - * - * @author Josh Micich - */ -public final class Index implements Function2Arg, Function3Arg, Function4Arg { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - TwoDEval reference = convertFirstArg(arg0); - - int columnIx = 0; - try { - int rowIx = resolveIndexArg(arg1, srcRowIndex, srcColumnIndex); - - if (!reference.isColumn()) { - if (!reference.isRow()) { - // always an error with 2-D area refs - // Note - the type of error changes if the pRowArg is negative - return ErrorEval.REF_INVALID; - } - // When the two-arg version of INDEX() has been invoked and the reference - // is a single column ref, the row arg seems to get used as the column index - columnIx = rowIx; - rowIx = 0; - } - - return getValueFromArea(reference, rowIx, columnIx); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - TwoDEval reference = convertFirstArg(arg0); - - try { - int columnIx = resolveIndexArg(arg2, srcRowIndex, srcColumnIndex); - int rowIx = resolveIndexArg(arg1, srcRowIndex, srcColumnIndex); - return getValueFromArea(reference, rowIx, columnIx); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2, ValueEval arg3) { - throw new RuntimeException("Incomplete code" - + " - don't know how to support the 'area_num' parameter yet)"); - // Excel expression might look like this "INDEX( (A1:B4, C3:D6, D2:E5 ), 1, 2, 3) - // In this example, the 3rd area would be used i.e. D2:E5, and the overall result would be E2 - // Token array might be encoded like this: MemAreaPtg, AreaPtg, AreaPtg, UnionPtg, UnionPtg, ParenthesesPtg - // The formula parser doesn't seem to support this yet. Not sure if the evaluator does either - } - - private static TwoDEval convertFirstArg(ValueEval arg0) { - ValueEval firstArg = arg0; - if (firstArg instanceof RefEval) { - // convert to area ref for simpler code in getValueFromArea() - return ((RefEval)firstArg).offset(0, 0, 0, 0); - } - if((firstArg instanceof TwoDEval)) { - return (TwoDEval) firstArg; - } - // else the other variation of this function takes an array as the first argument - // it seems like interface 'ArrayEval' does not even exist yet - throw new RuntimeException("Incomplete code - cannot handle first arg of type (" - + firstArg.getClass().getName() + ")"); - - } - - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - switch (args.length) { - case 2: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1]); - case 3: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2]); - case 4: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], args[3]); - } - return ErrorEval.VALUE_INVALID; - } - - private static ValueEval getValueFromArea(TwoDEval ae, int pRowIx, int pColumnIx) - throws EvaluationException { - assert pRowIx >= 0; - assert pColumnIx >= 0; - - TwoDEval result = ae; - - if (pRowIx != 0) { - // Slightly irregular logic for bounds checking errors - if (pRowIx > ae.getHeight()) { - // high bounds check fail gives #REF! if arg was explicitly passed - throw new EvaluationException(ErrorEval.REF_INVALID); - } - result = result.getRow(pRowIx-1); - } - - if (pColumnIx != 0) { - // Slightly irregular logic for bounds checking errors - if (pColumnIx > ae.getWidth()) { - // high bounds check fail gives #REF! if arg was explicitly passed - throw new EvaluationException(ErrorEval.REF_INVALID); - } - result = result.getColumn(pColumnIx-1); - } - return result; - } - - - /** - * @param arg a 1-based index. - * @return the resolved 1-based index. Zero if the arg was missing or blank - * @throws EvaluationException if the arg is an error value evaluates to a negative numeric value - */ - private static int resolveIndexArg(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException { - - ValueEval ev = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); - if (ev == MissingArgEval.instance) { - return 0; - } - if (ev == BlankEval.instance) { - return 0; - } - int result = OperandResolver.coerceValueToInt(ev); - if (result < 0) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - return result; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java b/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java deleted file mode 100644 index 8a4fba3dd3..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java +++ /dev/null @@ -1,239 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.MissingArgEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.OperationEvaluationContext; - -/** - * Implementation for Excel function INDIRECT<p/> - * - * INDIRECT() returns the cell or area reference denoted by the text argument.<p/> - * - * <b>Syntax</b>:</br> - * <b>INDIRECT</b>(<b>ref_text</b>,isA1Style)<p/> - * - * <b>ref_text</b> a string representation of the desired reference as it would - * normally be written in a cell formula.<br/> - * <b>isA1Style</b> (default TRUE) specifies whether the ref_text should be - * interpreted as A1-style or R1C1-style. - * - * @author Josh Micich - */ -public final class Indirect implements FreeRefFunction { - - public static final FreeRefFunction instance = new Indirect(); - - private Indirect() { - // enforce singleton - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length < 1) { - return ErrorEval.VALUE_INVALID; - } - - boolean isA1style; - String text; - try { - ValueEval ve = OperandResolver.getSingleValue(args[0], ec.getRowIndex(), ec - .getColumnIndex()); - text = OperandResolver.coerceValueToString(ve); - switch (args.length) { - case 1: - isA1style = true; - break; - case 2: - isA1style = evaluateBooleanArg(args[1], ec); - break; - default: - return ErrorEval.VALUE_INVALID; - } - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - return evaluateIndirect(ec, text, isA1style); - } - - private static boolean evaluateBooleanArg(ValueEval arg, OperationEvaluationContext ec) - throws EvaluationException { - ValueEval ve = OperandResolver.getSingleValue(arg, ec.getRowIndex(), ec.getColumnIndex()); - - if (ve == BlankEval.instance || ve == MissingArgEval.instance) { - return false; - } - // numeric quantities follow standard boolean conversion rules - // for strings, only "TRUE" and "FALSE" (case insensitive) are valid - return OperandResolver.coerceValueToBoolean(ve, false).booleanValue(); - } - - private static ValueEval evaluateIndirect(OperationEvaluationContext ec, String text, - boolean isA1style) { - // Search backwards for '!' because sheet names can contain '!' - int plingPos = text.lastIndexOf('!'); - - String workbookName; - String sheetName; - String refText; // whitespace around this gets trimmed OK - if (plingPos < 0) { - workbookName = null; - sheetName = null; - refText = text; - } else { - String[] parts = parseWorkbookAndSheetName(text.subSequence(0, plingPos)); - if (parts == null) { - return ErrorEval.REF_INVALID; - } - workbookName = parts[0]; - sheetName = parts[1]; - refText = text.substring(plingPos + 1); - } - - String refStrPart1; - String refStrPart2; - - int colonPos = refText.indexOf(':'); - if (colonPos < 0) { - refStrPart1 = refText.trim(); - refStrPart2 = null; - } else { - refStrPart1 = refText.substring(0, colonPos).trim(); - refStrPart2 = refText.substring(colonPos + 1).trim(); - } - return ec.getDynamicReference(workbookName, sheetName, refStrPart1, refStrPart2, isA1style); - } - - /** - * @return array of length 2: {workbookName, sheetName,}. Second element will always be - * present. First element may be null if sheetName is unqualified. - * Returns <code>null</code> if text cannot be parsed. - */ - private static String[] parseWorkbookAndSheetName(CharSequence text) { - int lastIx = text.length() - 1; - if (lastIx < 0) { - return null; - } - if (canTrim(text)) { - return null; - } - char firstChar = text.charAt(0); - if (Character.isWhitespace(firstChar)) { - return null; - } - if (firstChar == '\'') { - // workbookName or sheetName needs quoting - // quotes go around both - if (text.charAt(lastIx) != '\'') { - return null; - } - firstChar = text.charAt(1); - if (Character.isWhitespace(firstChar)) { - return null; - } - String wbName; - int sheetStartPos; - if (firstChar == '[') { - int rbPos = text.toString().lastIndexOf(']'); - if (rbPos < 0) { - return null; - } - wbName = unescapeString(text.subSequence(2, rbPos)); - if (wbName == null || canTrim(wbName)) { - return null; - } - sheetStartPos = rbPos + 1; - } else { - wbName = null; - sheetStartPos = 1; - } - - // else - just sheet name - String sheetName = unescapeString(text.subSequence(sheetStartPos, lastIx)); - if (sheetName == null) { // note - when quoted, sheetName can - // start/end with whitespace - return null; - } - return new String[] { wbName, sheetName, }; - } - - if (firstChar == '[') { - int rbPos = text.toString().lastIndexOf(']'); - if (rbPos < 0) { - return null; - } - CharSequence wbName = text.subSequence(1, rbPos); - if (canTrim(wbName)) { - return null; - } - CharSequence sheetName = text.subSequence(rbPos + 1, text.length()); - if (canTrim(sheetName)) { - return null; - } - return new String[] { wbName.toString(), sheetName.toString(), }; - } - // else - just sheet name - return new String[] { null, text.toString(), }; - } - - /** - * @return <code>null</code> if there is a syntax error in any escape sequence - * (the typical syntax error is a single quote character not followed by another). - */ - private static String unescapeString(CharSequence text) { - int len = text.length(); - StringBuilder sb = new StringBuilder(len); - int i = 0; - while (i < len) { - char ch = text.charAt(i); - if (ch == '\'') { - // every quote must be followed by another - i++; - if (i >= len) { - return null; - } - ch = text.charAt(i); - if (ch != '\'') { - return null; - } - } - sb.append(ch); - i++; - } - return sb.toString(); - } - - private static boolean canTrim(CharSequence text) { - int lastIx = text.length() - 1; - if (lastIx < 0) { - return false; - } - if (Character.isWhitespace(text.charAt(0))) { - return true; - } - if (Character.isWhitespace(text.charAt(lastIx))) { - return true; - } - return false; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/LogicalFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/LogicalFunction.java deleted file mode 100644 index 206dd41b68..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/LogicalFunction.java +++ /dev/null @@ -1,119 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.AreaEval; -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * @author Josh Micich - */ -public abstract class LogicalFunction extends Fixed1ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - ValueEval ve; - try { - ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - if (false) { - // Note - it is more usual to propagate error codes straight to the result like this: - return e.getErrorEval(); - // but logical functions behave a little differently - } - // this will usually cause a 'FALSE' result except for ISNONTEXT() - ve = e.getErrorEval(); - } - return BoolEval.valueOf(evaluate(ve)); - - } - /** - * @param arg any {@link ValueEval}, potentially {@link BlankEval} or {@link ErrorEval}. - */ - protected abstract boolean evaluate(ValueEval arg); - - public static final Function ISLOGICAL = new LogicalFunction() { - protected boolean evaluate(ValueEval arg) { - return arg instanceof BoolEval; - } - }; - public static final Function ISNONTEXT = new LogicalFunction() { - protected boolean evaluate(ValueEval arg) { - return !(arg instanceof StringEval); - } - }; - public static final Function ISNUMBER = new LogicalFunction() { - protected boolean evaluate(ValueEval arg) { - return arg instanceof NumberEval; - } - }; - public static final Function ISTEXT = new LogicalFunction() { - protected boolean evaluate(ValueEval arg) { - return arg instanceof StringEval; - } - }; - - public static final Function ISBLANK = new LogicalFunction() { - - protected boolean evaluate(ValueEval arg) { - return arg instanceof BlankEval; - } - }; - - public static final Function ISERROR = new LogicalFunction() { - - protected boolean evaluate(ValueEval arg) { - return arg instanceof ErrorEval; - } - }; - - /** - * Implementation for Excel ISNA() function.<p/> - * - * <b>Syntax</b>:<br/> - * <b>ISNA</b>(<b>value</b>)<p/> - * - * <b>value</b> The value to be tested<br/> - * <br/> - * Returns <tt>TRUE</tt> if the specified value is '#N/A', <tt>FALSE</tt> otherwise. - */ - public static final Function ISNA = new LogicalFunction() { - - protected boolean evaluate(ValueEval arg) { - return arg == ErrorEval.NA; - } - }; - - public static final Function ISREF = new Fixed1ArgFunction() { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - if (arg0 instanceof RefEval || arg0 instanceof AreaEval) { - return BoolEval.TRUE; - } - return BoolEval.FALSE; - } - }; -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Lookup.java b/src/java/org/apache/poi/hssf/record/formula/functions/Lookup.java deleted file mode 100644 index 09baff5dbb..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Lookup.java +++ /dev/null @@ -1,76 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * Implementation of Excel function LOOKUP.<p/> - * - * LOOKUP finds an index row in a lookup table by the first column value and returns the value from another column. - * - * <b>Syntax</b>:<br/> - * <b>VLOOKUP</b>(<b>lookup_value</b>, <b>lookup_vector</b>, result_vector)<p/> - * - * <b>lookup_value</b> The value to be found in the lookup vector.<br/> - * <b>lookup_vector</> An area reference for the lookup data. <br/> - * <b>result_vector</b> Single row or single column area reference from which the result value is chosen.<br/> - * - * @author Josh Micich - */ -public final class Lookup extends Var2or3ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - // complex rules to choose lookupVector and resultVector from the single area ref - throw new RuntimeException("Two arg version of LOOKUP not supported yet"); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - try { - ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - TwoDEval aeLookupVector = LookupUtils.resolveTableArrayArg(arg1); - TwoDEval aeResultVector = LookupUtils.resolveTableArrayArg(arg2); - - ValueVector lookupVector = createVector(aeLookupVector); - ValueVector resultVector = createVector(aeResultVector); - if(lookupVector.getSize() > resultVector.getSize()) { - // Excel seems to handle this by accessing past the end of the result vector. - throw new RuntimeException("Lookup vector and result vector of differing sizes not supported yet"); - } - int index = LookupUtils.lookupIndexOfValue(lookupValue, lookupVector, true); - - return resultVector.getItem(index); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - - private static ValueVector createVector(TwoDEval ae) { - ValueVector result = LookupUtils.createVector(ae); - if (result != null) { - return result; - } - // extra complexity required to emulate the way LOOKUP can handles these abnormal cases. - throw new RuntimeException("non-vector lookup or result areas not supported yet"); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/LookupUtils.java b/src/java/org/apache/poi/hssf/record/formula/functions/LookupUtils.java deleted file mode 100644 index 430565c597..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/LookupUtils.java +++ /dev/null @@ -1,603 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.NumericValueEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * Common functionality used by VLOOKUP, HLOOKUP, LOOKUP and MATCH - * - * @author Josh Micich - */ -final class LookupUtils { - - /** - * Represents a single row or column within an <tt>AreaEval</tt>. - */ - public interface ValueVector { - ValueEval getItem(int index); - int getSize(); - } - - - private static final class RowVector implements ValueVector { - - private final TwoDEval _tableArray; - private final int _size; - private final int _rowIndex; - - public RowVector(TwoDEval tableArray, int rowIndex) { - _rowIndex = rowIndex; - int lastRowIx = tableArray.getHeight() - 1; - if(rowIndex < 0 || rowIndex > lastRowIx) { - throw new IllegalArgumentException("Specified row index (" + rowIndex - + ") is outside the allowed range (0.." + lastRowIx + ")"); - } - _tableArray = tableArray; - _size = tableArray.getWidth(); - } - - public ValueEval getItem(int index) { - if(index > _size) { - throw new ArrayIndexOutOfBoundsException("Specified index (" + index - + ") is outside the allowed range (0.." + (_size-1) + ")"); - } - return _tableArray.getValue(_rowIndex, index); - } - public int getSize() { - return _size; - } - } - - private static final class ColumnVector implements ValueVector { - - private final TwoDEval _tableArray; - private final int _size; - private final int _columnIndex; - - public ColumnVector(TwoDEval tableArray, int columnIndex) { - _columnIndex = columnIndex; - int lastColIx = tableArray.getWidth()-1; - if(columnIndex < 0 || columnIndex > lastColIx) { - throw new IllegalArgumentException("Specified column index (" + columnIndex - + ") is outside the allowed range (0.." + lastColIx + ")"); - } - _tableArray = tableArray; - _size = _tableArray.getHeight(); - } - - public ValueEval getItem(int index) { - if(index > _size) { - throw new ArrayIndexOutOfBoundsException("Specified index (" + index - + ") is outside the allowed range (0.." + (_size-1) + ")"); - } - return _tableArray.getValue(index, _columnIndex); - } - public int getSize() { - return _size; - } - } - - public static ValueVector createRowVector(TwoDEval tableArray, int relativeRowIndex) { - return new RowVector(tableArray, relativeRowIndex); - } - public static ValueVector createColumnVector(TwoDEval tableArray, int relativeColumnIndex) { - return new ColumnVector(tableArray, relativeColumnIndex); - } - /** - * @return <code>null</code> if the supplied area is neither a single row nor a single colum - */ - public static ValueVector createVector(TwoDEval ae) { - if (ae.isColumn()) { - return createColumnVector(ae, 0); - } - if (ae.isRow()) { - return createRowVector(ae, 0); - } - return null; - } - - /** - * Enumeration to support <b>4</b> valued comparison results.<p/> - * Excel lookup functions have complex behaviour in the case where the lookup array has mixed - * types, and/or is unordered. Contrary to suggestions in some Excel documentation, there - * does not appear to be a universal ordering across types. The binary search algorithm used - * changes behaviour when the evaluated 'mid' value has a different type to the lookup value.<p/> - * - * A simple int might have done the same job, but there is risk in confusion with the well - * known <tt>Comparable.compareTo()</tt> and <tt>Comparator.compare()</tt> which both use - * a ubiquitous 3 value result encoding. - */ - public static final class CompareResult { - private final boolean _isTypeMismatch; - private final boolean _isLessThan; - private final boolean _isEqual; - private final boolean _isGreaterThan; - - private CompareResult(boolean isTypeMismatch, int simpleCompareResult) { - if(isTypeMismatch) { - _isTypeMismatch = true; - _isLessThan = false; - _isEqual = false; - _isGreaterThan = false; - } else { - _isTypeMismatch = false; - _isLessThan = simpleCompareResult < 0; - _isEqual = simpleCompareResult == 0; - _isGreaterThan = simpleCompareResult > 0; - } - } - public static final CompareResult TYPE_MISMATCH = new CompareResult(true, 0); - public static final CompareResult LESS_THAN = new CompareResult(false, -1); - public static final CompareResult EQUAL = new CompareResult(false, 0); - public static final CompareResult GREATER_THAN = new CompareResult(false, +1); - - public static final CompareResult valueOf(int simpleCompareResult) { - if(simpleCompareResult < 0) { - return LESS_THAN; - } - if(simpleCompareResult > 0) { - return GREATER_THAN; - } - return EQUAL; - } - - public boolean isTypeMismatch() { - return _isTypeMismatch; - } - public boolean isLessThan() { - return _isLessThan; - } - public boolean isEqual() { - return _isEqual; - } - public boolean isGreaterThan() { - return _isGreaterThan; - } - public String toString() { - StringBuffer sb = new StringBuffer(64); - sb.append(getClass().getName()).append(" ["); - sb.append(formatAsString()); - sb.append("]"); - return sb.toString(); - } - - private String formatAsString() { - if(_isTypeMismatch) { - return "TYPE_MISMATCH"; - } - if(_isLessThan) { - return "LESS_THAN"; - } - if(_isEqual) { - return "EQUAL"; - } - if(_isGreaterThan) { - return "GREATER_THAN"; - } - // toString must be reliable - return "??error??"; - } - } - - public interface LookupValueComparer { - /** - * @return one of 4 instances or <tt>CompareResult</tt>: <tt>LESS_THAN</tt>, <tt>EQUAL</tt>, - * <tt>GREATER_THAN</tt> or <tt>TYPE_MISMATCH</tt> - */ - CompareResult compareTo(ValueEval other); - } - - private static abstract class LookupValueComparerBase implements LookupValueComparer { - - private final Class<? extends ValueEval> _targetClass; - protected LookupValueComparerBase(ValueEval targetValue) { - if(targetValue == null) { - throw new RuntimeException("targetValue cannot be null"); - } - _targetClass = targetValue.getClass(); - } - public final CompareResult compareTo(ValueEval other) { - if (other == null) { - throw new RuntimeException("compare to value cannot be null"); - } - if (_targetClass != other.getClass()) { - return CompareResult.TYPE_MISMATCH; - } - return compareSameType(other); - } - public String toString() { - StringBuffer sb = new StringBuffer(64); - sb.append(getClass().getName()).append(" ["); - sb.append(getValueAsString()); - sb.append("]"); - return sb.toString(); - } - protected abstract CompareResult compareSameType(ValueEval other); - /** used only for debug purposes */ - protected abstract String getValueAsString(); - } - - private static final class StringLookupComparer extends LookupValueComparerBase { - private String _value; - - protected StringLookupComparer(StringEval se) { - super(se); - _value = se.getStringValue(); - } - protected CompareResult compareSameType(ValueEval other) { - StringEval se = (StringEval) other; - return CompareResult.valueOf(_value.compareToIgnoreCase(se.getStringValue())); - } - protected String getValueAsString() { - return _value; - } - } - private static final class NumberLookupComparer extends LookupValueComparerBase { - private double _value; - - protected NumberLookupComparer(NumberEval ne) { - super(ne); - _value = ne.getNumberValue(); - } - protected CompareResult compareSameType(ValueEval other) { - NumberEval ne = (NumberEval) other; - return CompareResult.valueOf(Double.compare(_value, ne.getNumberValue())); - } - protected String getValueAsString() { - return String.valueOf(_value); - } - } - private static final class BooleanLookupComparer extends LookupValueComparerBase { - private boolean _value; - - protected BooleanLookupComparer(BoolEval be) { - super(be); - _value = be.getBooleanValue(); - } - protected CompareResult compareSameType(ValueEval other) { - BoolEval be = (BoolEval) other; - boolean otherVal = be.getBooleanValue(); - if(_value == otherVal) { - return CompareResult.EQUAL; - } - // TRUE > FALSE - if(_value) { - return CompareResult.GREATER_THAN; - } - return CompareResult.LESS_THAN; - } - protected String getValueAsString() { - return String.valueOf(_value); - } - } - - /** - * Processes the third argument to VLOOKUP, or HLOOKUP (<b>col_index_num</b> - * or <b>row_index_num</b> respectively).<br> - * Sample behaviour: - * <table border="0" cellpadding="1" cellspacing="2" summary="Sample behaviour"> - * <tr><th>Input Return</th><th>Value </th><th>Thrown Error</th></tr> - * <tr><td>5</td><td>4</td><td> </td></tr> - * <tr><td>2.9</td><td>2</td><td> </td></tr> - * <tr><td>"5"</td><td>4</td><td> </td></tr> - * <tr><td>"2.18e1"</td><td>21</td><td> </td></tr> - * <tr><td>"-$2"</td><td>-3</td><td>*</td></tr> - * <tr><td>FALSE</td><td>-1</td><td>*</td></tr> - * <tr><td>TRUE</td><td>0</td><td> </td></tr> - * <tr><td>"TRUE"</td><td> </td><td>#REF!</td></tr> - * <tr><td>"abc"</td><td> </td><td>#REF!</td></tr> - * <tr><td>""</td><td> </td><td>#REF!</td></tr> - * <tr><td><blank></td><td> </td><td>#VALUE!</td></tr> - * </table><br/> - * - * Note - out of range errors (result index too high) are handled by the caller. - * @return column or row index as a zero-based value, never negative. - * @throws EvaluationException when the specified arg cannot be coerced to a non-negative integer - */ - public static int resolveRowOrColIndexArg(ValueEval rowColIndexArg, int srcCellRow, int srcCellCol) throws EvaluationException { - if(rowColIndexArg == null) { - throw new IllegalArgumentException("argument must not be null"); - } - - ValueEval veRowColIndexArg; - try { - veRowColIndexArg = OperandResolver.getSingleValue(rowColIndexArg, srcCellRow, (short)srcCellCol); - } catch (EvaluationException e) { - // All errors get translated to #REF! - throw EvaluationException.invalidRef(); - } - int oneBasedIndex; - if(veRowColIndexArg instanceof StringEval) { - StringEval se = (StringEval) veRowColIndexArg; - String strVal = se.getStringValue(); - Double dVal = OperandResolver.parseDouble(strVal); - if(dVal == null) { - // String does not resolve to a number. Raise #REF! error. - throw EvaluationException.invalidRef(); - // This includes text booleans "TRUE" and "FALSE". They are not valid. - } - // else - numeric value parses OK - } - // actual BoolEval values get interpreted as FALSE->0 and TRUE->1 - oneBasedIndex = OperandResolver.coerceValueToInt(veRowColIndexArg); - if (oneBasedIndex < 1) { - // note this is asymmetric with the errors when the index is too large (#REF!) - throw EvaluationException.invalidValue(); - } - return oneBasedIndex - 1; // convert to zero based - } - - - - /** - * The second argument (table_array) should be an area ref, but can actually be a cell ref, in - * which case it is interpreted as a 1x1 area ref. Other scalar values cause #VALUE! error. - */ - public static TwoDEval resolveTableArrayArg(ValueEval eval) throws EvaluationException { - if (eval instanceof TwoDEval) { - return (TwoDEval) eval; - } - - if(eval instanceof RefEval) { - RefEval refEval = (RefEval) eval; - // Make this cell ref look like a 1x1 area ref. - - // It doesn't matter if eval is a 2D or 3D ref, because that detail is never asked of AreaEval. - return refEval.offset(0, 0, 0, 0); - } - throw EvaluationException.invalidValue(); - } - - - /** - * Resolves the last (optional) parameter (<b>range_lookup</b>) to the VLOOKUP and HLOOKUP functions. - * @param rangeLookupArg must not be <code>null</code> - */ - public static boolean resolveRangeLookupArg(ValueEval rangeLookupArg, int srcCellRow, int srcCellCol) throws EvaluationException { - - ValueEval valEval = OperandResolver.getSingleValue(rangeLookupArg, srcCellRow, srcCellCol); - if(valEval instanceof BlankEval) { - // Tricky: - // fourth arg supplied but evaluates to blank - // this does not get the default value - return false; - } - if(valEval instanceof BoolEval) { - // Happy day flow - BoolEval boolEval = (BoolEval) valEval; - return boolEval.getBooleanValue(); - } - - if (valEval instanceof StringEval) { - String stringValue = ((StringEval) valEval).getStringValue(); - if(stringValue.length() < 1) { - // More trickiness: - // Empty string is not the same as BlankEval. It causes #VALUE! error - throw EvaluationException.invalidValue(); - } - // TODO move parseBoolean to OperandResolver - Boolean b = Countif.parseBoolean(stringValue); - if(b != null) { - // string converted to boolean OK - return b.booleanValue(); - } - // Even more trickiness: - // Note - even if the StringEval represents a number value (for example "1"), - // Excel does not resolve it to a boolean. - throw EvaluationException.invalidValue(); - // This is in contrast to the code below,, where NumberEvals values (for - // example 0.01) *do* resolve to equivalent boolean values. - } - if (valEval instanceof NumericValueEval) { - NumericValueEval nve = (NumericValueEval) valEval; - // zero is FALSE, everything else is TRUE - return 0.0 != nve.getNumberValue(); - } - throw new RuntimeException("Unexpected eval type (" + valEval.getClass().getName() + ")"); - } - - public static int lookupIndexOfValue(ValueEval lookupValue, ValueVector vector, boolean isRangeLookup) throws EvaluationException { - LookupValueComparer lookupComparer = createLookupComparer(lookupValue); - int result; - if(isRangeLookup) { - result = performBinarySearch(vector, lookupComparer); - } else { - result = lookupIndexOfExactValue(lookupComparer, vector); - } - if(result < 0) { - throw new EvaluationException(ErrorEval.NA); - } - return result; - } - - - /** - * Finds first (lowest index) exact occurrence of specified value. - * @param lookupValue the value to be found in column or row vector - * @param vector the values to be searched. For VLOOKUP this is the first column of the - * tableArray. For HLOOKUP this is the first row of the tableArray. - * @return zero based index into the vector, -1 if value cannot be found - */ - private static int lookupIndexOfExactValue(LookupValueComparer lookupComparer, ValueVector vector) { - - // find first occurrence of lookup value - int size = vector.getSize(); - for (int i = 0; i < size; i++) { - if(lookupComparer.compareTo(vector.getItem(i)).isEqual()) { - return i; - } - } - return -1; - } - - - /** - * Encapsulates some standard binary search functionality so the unusual Excel behaviour can - * be clearly distinguished. - */ - private static final class BinarySearchIndexes { - - private int _lowIx; - private int _highIx; - - public BinarySearchIndexes(int highIx) { - _lowIx = -1; - _highIx = highIx; - } - - /** - * @return -1 if the search range is empty - */ - public int getMidIx() { - int ixDiff = _highIx - _lowIx; - if(ixDiff < 2) { - return -1; - } - return _lowIx + (ixDiff / 2); - } - - public int getLowIx() { - return _lowIx; - } - public int getHighIx() { - return _highIx; - } - public void narrowSearch(int midIx, boolean isLessThan) { - if(isLessThan) { - _highIx = midIx; - } else { - _lowIx = midIx; - } - } - } - /** - * Excel has funny behaviour when the some elements in the search vector are the wrong type. - * - */ - private static int performBinarySearch(ValueVector vector, LookupValueComparer lookupComparer) { - // both low and high indexes point to values assumed too low and too high. - BinarySearchIndexes bsi = new BinarySearchIndexes(vector.getSize()); - - while(true) { - int midIx = bsi.getMidIx(); - - if(midIx < 0) { - return bsi.getLowIx(); - } - CompareResult cr = lookupComparer.compareTo(vector.getItem(midIx)); - if(cr.isTypeMismatch()) { - int newMidIx = handleMidValueTypeMismatch(lookupComparer, vector, bsi, midIx); - if(newMidIx < 0) { - continue; - } - midIx = newMidIx; - cr = lookupComparer.compareTo(vector.getItem(midIx)); - } - if(cr.isEqual()) { - return findLastIndexInRunOfEqualValues(lookupComparer, vector, midIx, bsi.getHighIx()); - } - bsi.narrowSearch(midIx, cr.isLessThan()); - } - } - /** - * Excel seems to handle mismatched types initially by just stepping 'mid' ix forward to the - * first compatible value. - * @param midIx 'mid' index (value which has the wrong type) - * @return usually -1, signifying that the BinarySearchIndex has been narrowed to the new mid - * index. Zero or greater signifies that an exact match for the lookup value was found - */ - private static int handleMidValueTypeMismatch(LookupValueComparer lookupComparer, ValueVector vector, - BinarySearchIndexes bsi, int midIx) { - int newMid = midIx; - int highIx = bsi.getHighIx(); - - while(true) { - newMid++; - if(newMid == highIx) { - // every element from midIx to highIx was the wrong type - // move highIx down to the low end of the mid values - bsi.narrowSearch(midIx, true); - return -1; - } - CompareResult cr = lookupComparer.compareTo(vector.getItem(newMid)); - if(cr.isLessThan() && newMid == highIx-1) { - // move highIx down to the low end of the mid values - bsi.narrowSearch(midIx, true); - return -1; - // but only when "newMid == highIx-1"? slightly weird. - // It would seem more efficient to always do this. - } - if(cr.isTypeMismatch()) { - // keep stepping over values until the right type is found - continue; - } - if(cr.isEqual()) { - return newMid; - } - // Note - if moving highIx down (due to lookup<vector[newMid]), - // this execution path only moves highIx it down as far as newMid, not midIx, - // which would be more efficient. - bsi.narrowSearch(newMid, cr.isLessThan()); - return -1; - } - } - /** - * Once the binary search has found a single match, (V/H)LOOKUP steps one by one over subsequent - * values to choose the last matching item. - */ - private static int findLastIndexInRunOfEqualValues(LookupValueComparer lookupComparer, ValueVector vector, - int firstFoundIndex, int maxIx) { - for(int i=firstFoundIndex+1; i<maxIx; i++) { - if(!lookupComparer.compareTo(vector.getItem(i)).isEqual()) { - return i-1; - } - } - return maxIx - 1; - } - - public static LookupValueComparer createLookupComparer(ValueEval lookupValue) { - - if (lookupValue == BlankEval.instance) { - // blank eval translates to zero - // Note - a blank eval in the lookup column/row never matches anything - // empty string in the lookup column/row can only be matched by explicit empty string - return new NumberLookupComparer(NumberEval.ZERO); - } - if (lookupValue instanceof StringEval) { - return new StringLookupComparer((StringEval) lookupValue); - } - if (lookupValue instanceof NumberEval) { - return new NumberLookupComparer((NumberEval) lookupValue); - } - if (lookupValue instanceof BoolEval) { - return new BooleanLookupComparer((BoolEval) lookupValue); - } - throw new IllegalArgumentException("Bad lookup value type (" + lookupValue.getClass().getName() + ")"); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Match.java b/src/java/org/apache/poi/hssf/record/formula/functions/Match.java deleted file mode 100644 index d774c67bc1..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Match.java +++ /dev/null @@ -1,251 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.NumericValueEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.LookupUtils.CompareResult; -import org.apache.poi.hssf.record.formula.functions.LookupUtils.LookupValueComparer; -import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * Implementation for the MATCH() Excel function.<p/> - * - * <b>Syntax:</b><br/> - * <b>MATCH</b>(<b>lookup_value</b>, <b>lookup_array</b>, match_type)<p/> - * - * Returns a 1-based index specifying at what position in the <b>lookup_array</b> the specified - * <b>lookup_value</b> is found.<p/> - * - * Specific matching behaviour can be modified with the optional <b>match_type</b> parameter. - * - * <table border="0" cellpadding="1" cellspacing="0" summary="match_type parameter description"> - * <tr><th>Value</th><th>Matching Behaviour</th></tr> - * <tr><td>1</td><td>(default) find the largest value that is less than or equal to lookup_value. - * The lookup_array must be in ascending <i>order</i>*.</td></tr> - * <tr><td>0</td><td>find the first value that is exactly equal to lookup_value. - * The lookup_array can be in any order.</td></tr> - * <tr><td>-1</td><td>find the smallest value that is greater than or equal to lookup_value. - * The lookup_array must be in descending <i>order</i>*.</td></tr> - * </table> - * - * * Note regarding <i>order</i> - For the <b>match_type</b> cases that require the lookup_array to - * be ordered, MATCH() can produce incorrect results if this requirement is not met. Observed - * behaviour in Excel is to return the lowest index value for which every item after that index - * breaks the match rule.<br> - * The (ascending) sort order expected by MATCH() is:<br/> - * numbers (low to high), strings (A to Z), boolean (FALSE to TRUE)<br/> - * MATCH() ignores all elements in the lookup_array with a different type to the lookup_value. - * Type conversion of the lookup_array elements is never performed. - * - * - * @author Josh Micich - */ -public final class Match extends Var2or3ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - // default match_type is 1.0 - return eval(srcRowIndex, srcColumnIndex, arg0, arg1, 1.0); - } - - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - - double match_type; - - try { - match_type = evaluateMatchTypeArg(arg2, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - // Excel/MATCH() seems to have slightly abnormal handling of errors with - // the last parameter. Errors do not propagate up. Every error gets - // translated into #REF! - return ErrorEval.REF_INVALID; - } - - return eval(srcRowIndex, srcColumnIndex, arg0, arg1, match_type); - } - - private static ValueEval eval(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - double match_type) { - boolean matchExact = match_type == 0; - // Note - Excel does not strictly require -1 and +1 - boolean findLargestLessThanOrEqual = match_type > 0; - - try { - ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - ValueVector lookupRange = evaluateLookupRange(arg1); - int index = findIndexOfValue(lookupValue, lookupRange, matchExact, findLargestLessThanOrEqual); - return new NumberEval(index + 1); // +1 to convert to 1-based - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - - private static final class SingleValueVector implements ValueVector { - - private final ValueEval _value; - - public SingleValueVector(ValueEval value) { - _value = value; - } - - public ValueEval getItem(int index) { - if (index != 0) { - throw new RuntimeException("Invalid index (" - + index + ") only zero is allowed"); - } - return _value; - } - - public int getSize() { - return 1; - } - } - - private static ValueVector evaluateLookupRange(ValueEval eval) throws EvaluationException { - if (eval instanceof RefEval) { - RefEval re = (RefEval) eval; - return new SingleValueVector(re.getInnerValueEval()); - } - if (eval instanceof TwoDEval) { - ValueVector result = LookupUtils.createVector((TwoDEval)eval); - if (result == null) { - throw new EvaluationException(ErrorEval.NA); - } - return result; - } - - // Error handling for lookup_range arg is also unusual - if(eval instanceof NumericValueEval) { - throw new EvaluationException(ErrorEval.NA); - } - if (eval instanceof StringEval) { - StringEval se = (StringEval) eval; - Double d = OperandResolver.parseDouble(se.getStringValue()); - if(d == null) { - // plain string - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - // else looks like a number - throw new EvaluationException(ErrorEval.NA); - } - throw new RuntimeException("Unexpected eval type (" + eval.getClass().getName() + ")"); - } - - - - private static double evaluateMatchTypeArg(ValueEval arg, int srcCellRow, int srcCellCol) - throws EvaluationException { - ValueEval match_type = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); - - if(match_type instanceof ErrorEval) { - throw new EvaluationException((ErrorEval)match_type); - } - if(match_type instanceof NumericValueEval) { - NumericValueEval ne = (NumericValueEval) match_type; - return ne.getNumberValue(); - } - if (match_type instanceof StringEval) { - StringEval se = (StringEval) match_type; - Double d = OperandResolver.parseDouble(se.getStringValue()); - if(d == null) { - // plain string - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - // if the string parses as a number, it is OK - return d.doubleValue(); - } - throw new RuntimeException("Unexpected match_type type (" + match_type.getClass().getName() + ")"); - } - - /** - * @return zero based index - */ - private static int findIndexOfValue(ValueEval lookupValue, ValueVector lookupRange, - boolean matchExact, boolean findLargestLessThanOrEqual) throws EvaluationException { - - LookupValueComparer lookupComparer = createLookupComparer(lookupValue, matchExact); - - int size = lookupRange.getSize(); - if(matchExact) { - for (int i = 0; i < size; i++) { - if(lookupComparer.compareTo(lookupRange.getItem(i)).isEqual()) { - return i; - } - } - throw new EvaluationException(ErrorEval.NA); - } - - if(findLargestLessThanOrEqual) { - // Note - backward iteration - for (int i = size - 1; i>=0; i--) { - CompareResult cmp = lookupComparer.compareTo(lookupRange.getItem(i)); - if(cmp.isTypeMismatch()) { - continue; - } - if(!cmp.isLessThan()) { - return i; - } - } - throw new EvaluationException(ErrorEval.NA); - } - - // else - find smallest greater than or equal to - // TODO - is binary search used for (match_type==+1) ? - for (int i = 0; i<size; i++) { - CompareResult cmp = lookupComparer.compareTo(lookupRange.getItem(i)); - if(cmp.isEqual()) { - return i; - } - if(cmp.isGreaterThan()) { - if(i<1) { - throw new EvaluationException(ErrorEval.NA); - } - return i-1; - } - } - - throw new EvaluationException(ErrorEval.NA); - } - - private static LookupValueComparer createLookupComparer(ValueEval lookupValue, boolean matchExact) { - if (matchExact && lookupValue instanceof StringEval) { - String stringValue = ((StringEval) lookupValue).getStringValue(); - if(isLookupValueWild(stringValue)) { - throw new RuntimeException("Wildcard lookup values '" + stringValue + "' not supported yet"); - } - - } - return LookupUtils.createLookupComparer(lookupValue); - } - - private static boolean isLookupValueWild(String stringValue) { - if(stringValue.indexOf('?') >=0 || stringValue.indexOf('*') >=0) { - return true; - } - return false; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/MathX.java b/src/java/org/apache/poi/hssf/record/formula/functions/MathX.java deleted file mode 100644 index 600214662b..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/MathX.java +++ /dev/null @@ -1,444 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * This class is an extension to the standard math library - * provided by java.lang.Math class. It follows the Math class - * in that it has a private constructor and all static methods. - */ -final class MathX { - - private MathX() { - // no instances of this class - } - - - /** - * Returns a value rounded to p digits after decimal. - * If p is negative, then the number is rounded to - * places to the left of the decimal point. eg. - * 10.23 rounded to -1 will give: 10. If p is zero, - * the returned value is rounded to the nearest integral - * value. - * <p>If n is negative, the resulting value is obtained - * as the round value of absolute value of n multiplied - * by the sign value of n (@see MathX.sign(double d)). - * Thus, -0.6666666 rounded to p=0 will give -1 not 0. - * <p>If n is NaN, returned value is NaN. - * @param n - * @param p - */ - public static double round(double n, int p) { - double retval; - - if (Double.isNaN(n) || Double.isInfinite(n)) { - retval = Double.NaN; - } - else { - if (p != 0) { - double temp = Math.pow(10, p); - retval = Math.round(n*temp)/temp; - } - else { - retval = Math.round(n); - } - } - - return retval; - } - - /** - * Returns a value rounded-up to p digits after decimal. - * If p is negative, then the number is rounded to - * places to the left of the decimal point. eg. - * 10.23 rounded to -1 will give: 20. If p is zero, - * the returned value is rounded to the nearest integral - * value. - * <p>If n is negative, the resulting value is obtained - * as the round-up value of absolute value of n multiplied - * by the sign value of n (@see MathX.sign(double d)). - * Thus, -0.2 rounded-up to p=0 will give -1 not 0. - * <p>If n is NaN, returned value is NaN. - * @param n - * @param p - */ - public static double roundUp(double n, int p) { - double retval; - - if (Double.isNaN(n) || Double.isInfinite(n)) { - retval = Double.NaN; - } - else { - if (p != 0) { - double temp = Math.pow(10, p); - double nat = Math.abs(n*temp); - - retval = sign(n) * - ((nat == (long) nat) - ? nat / temp - : Math.round(nat + 0.5) / temp); - } - else { - double na = Math.abs(n); - retval = sign(n) * - ((na == (long) na) - ? na - : (long) na + 1); - } - } - - return retval; - } - - /** - * Returns a value rounded to p digits after decimal. - * If p is negative, then the number is rounded to - * places to the left of the decimal point. eg. - * 10.23 rounded to -1 will give: 10. If p is zero, - * the returned value is rounded to the nearest integral - * value. - * <p>If n is negative, the resulting value is obtained - * as the round-up value of absolute value of n multiplied - * by the sign value of n (@see MathX.sign(double d)). - * Thus, -0.8 rounded-down to p=0 will give 0 not -1. - * <p>If n is NaN, returned value is NaN. - * @param n - * @param p - */ - public static double roundDown(double n, int p) { - double retval; - - if (Double.isNaN(n) || Double.isInfinite(n)) { - retval = Double.NaN; - } - else { - if (p != 0) { - double temp = Math.pow(10, p); - retval = sign(n) * Math.round((Math.abs(n)*temp) - 0.5)/temp; - } - else { - retval = (long) n; - } - } - - return retval; - } - - - /** - * If d < 0, returns short -1 - * <br/> - * If d > 0, returns short 1 - * <br/> - * If d == 0, returns short 0 - * <p> If d is NaN, then 1 will be returned. It is the responsibility - * of caller to check for d isNaN if some other value is desired. - * @param d - */ - public static short sign(double d) { - return (short) ((d == 0) - ? 0 - : (d < 0) - ? -1 - : 1); - } - - /** - * average of all values - * @param values - */ - public static double average(double[] values) { - double ave = 0; - double sum = 0; - for (int i=0, iSize=values.length; i<iSize; i++) { - sum += values[i]; - } - ave = sum / values.length; - return ave; - } - - - /** - * sum of all values - * @param values - */ - public static double sum(double[] values) { - double sum = 0; - for (int i=0, iSize=values.length; i<iSize; i++) { - sum += values[i]; - } - return sum; - } - - /** - * sum of squares of all values - * @param values - */ - public static double sumsq(double[] values) { - double sumsq = 0; - for (int i=0, iSize=values.length; i<iSize; i++) { - sumsq += values[i]*values[i]; - } - return sumsq; - } - - - /** - * product of all values - * @param values - */ - public static double product(double[] values) { - double product = 0; - if (values!=null && values.length > 0) { - product = 1; - for (int i=0, iSize=values.length; i<iSize; i++) { - product *= values[i]; - } - } - return product; - } - - /** - * min of all values. If supplied array is zero length, - * Double.POSITIVE_INFINITY is returned. - * @param values - */ - public static double min(double[] values) { - double min = Double.POSITIVE_INFINITY; - for (int i=0, iSize=values.length; i<iSize; i++) { - min = Math.min(min, values[i]); - } - return min; - } - - /** - * min of all values. If supplied array is zero length, - * Double.NEGATIVE_INFINITY is returned. - * @param values - */ - public static double max(double[] values) { - double max = Double.NEGATIVE_INFINITY; - for (int i=0, iSize=values.length; i<iSize; i++) { - max = Math.max(max, values[i]); - } - return max; - } - - /** - * Note: this function is different from java.lang.Math.floor(..). - * <p> - * When n and s are "valid" arguments, the returned value is: Math.floor(n/s) * s; - * <br/> - * n and s are invalid if any of following conditions are true: - * <ul> - * <li>s is zero</li> - * <li>n is negative and s is positive</li> - * <li>n is positive and s is negative</li> - * </ul> - * In all such cases, Double.NaN is returned. - * @param n - * @param s - */ - public static double floor(double n, double s) { - double f; - - if ((n<0 && s>0) || (n>0 && s<0) || (s==0 && n!=0)) { - f = Double.NaN; - } - else { - f = (n==0 || s==0) ? 0 : Math.floor(n/s) * s; - } - - return f; - } - - /** - * Note: this function is different from java.lang.Math.ceil(..). - * <p> - * When n and s are "valid" arguments, the returned value is: Math.ceiling(n/s) * s; - * <br/> - * n and s are invalid if any of following conditions are true: - * <ul> - * <li>s is zero</li> - * <li>n is negative and s is positive</li> - * <li>n is positive and s is negative</li> - * </ul> - * In all such cases, Double.NaN is returned. - * @param n - * @param s - */ - public static double ceiling(double n, double s) { - double c; - - if ((n<0 && s>0) || (n>0 && s<0)) { - c = Double.NaN; - } - else { - c = (n == 0 || s == 0) ? 0 : Math.ceil(n/s) * s; - } - - return c; - } - - /** - * <br/> for all n >= 1; factorial n = n * (n-1) * (n-2) * ... * 1 - * <br/> else if n == 0; factorial n = 1 - * <br/> else if n < 0; factorial n = Double.NaN - * <br/> Loss of precision can occur if n is large enough. - * If n is large so that the resulting value would be greater - * than Double.MAX_VALUE; Double.POSITIVE_INFINITY is returned. - * If n < 0, Double.NaN is returned. - * @param n - */ - public static double factorial(int n) { - double d = 1; - - if (n >= 0) { - if (n <= 170) { - for (int i=1; i<=n; i++) { - d *= i; - } - } - else { - d = Double.POSITIVE_INFINITY; - } - } - else { - d = Double.NaN; - } - return d; - } - - - /** - * returns the remainder resulting from operation: - * n / d. - * <br/> The result has the sign of the divisor. - * <br/> Examples: - * <ul> - * <li>mod(3.4, 2) = 1.4</li> - * <li>mod(-3.4, 2) = 0.6</li> - * <li>mod(-3.4, -2) = -1.4</li> - * <li>mod(3.4, -2) = -0.6</li> - * </ul> - * If d == 0, result is NaN - * @param n - * @param d - */ - public static double mod(double n, double d) { - double result = 0; - - if (d == 0) { - result = Double.NaN; - } - else if (sign(n) == sign(d)) { - result = n % d; - } - else { - result = ((n % d) + d) % d; - } - - return result; - } - - /** - * inverse hyperbolic cosine - * @param d - */ - public static double acosh(double d) { - return Math.log(Math.sqrt(Math.pow(d, 2) - 1) + d); - } - - /** - * inverse hyperbolic sine - * @param d - */ - public static double asinh(double d) { - return Math.log(Math.sqrt(d*d + 1) + d); - } - - /** - * inverse hyperbolic tangent - * @param d - */ - public static double atanh(double d) { - return Math.log((1 + d)/(1 - d)) / 2; - } - - /** - * hyperbolic cosine - * @param d - */ - public static double cosh(double d) { - double ePowX = Math.pow(Math.E, d); - double ePowNegX = Math.pow(Math.E, -d); - return (ePowX + ePowNegX) / 2; - } - - /** - * hyperbolic sine - * @param d - */ - public static double sinh(double d) { - double ePowX = Math.pow(Math.E, d); - double ePowNegX = Math.pow(Math.E, -d); - return (ePowX - ePowNegX) / 2; - } - - /** - * hyperbolic tangent - * @param d - */ - public static double tanh(double d) { - double ePowX = Math.pow(Math.E, d); - double ePowNegX = Math.pow(Math.E, -d); - return (ePowX - ePowNegX) / (ePowX + ePowNegX); - } - - - /** - * returns the total number of combinations possible when - * k items are chosen out of total of n items. If the number - * is too large, loss of precision may occur (since returned - * value is double). If the returned value is larger than - * Double.MAX_VALUE, Double.POSITIVE_INFINITY is returned. - * If either of the parameters is negative, Double.NaN is returned. - * @param n - * @param k - */ - public static double nChooseK(int n, int k) { - double d = 1; - if (n<0 || k<0 || n<k) { - d= Double.NaN; - } - else { - int minnk = Math.min(n-k, k); - int maxnk = Math.max(n-k, k); - for (int i=maxnk; i<n; i++) { - d *= i+1; - } - d /= factorial(minnk); - } - - return d; - } - -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/MinaMaxa.java b/src/java/org/apache/poi/hssf/record/formula/functions/MinaMaxa.java deleted file mode 100644 index cc0d35e14a..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/MinaMaxa.java +++ /dev/null @@ -1,40 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public abstract class MinaMaxa extends MultiOperandNumericFunction { - - protected MinaMaxa() { - super(true, true); - } - - public static final Function MAXA = new MinaMaxa() { - protected double evaluate(double[] values) { - return values.length > 0 ? MathX.max(values) : 0; - } - }; - public static final Function MINA = new MinaMaxa() { - protected double evaluate(double[] values) { - return values.length > 0 ? MathX.min(values) : 0; - } - }; -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java b/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java deleted file mode 100644 index 4ede174d21..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java +++ /dev/null @@ -1,133 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public final class Mode implements Function { - - /** - * if v is zero length or contains no duplicates, return value is - * Double.NaN. Else returns the value that occurs most times and if there is - * a tie, returns the first such value. - * - * @param v - */ - public static double evaluate(double[] v) throws EvaluationException { - if (v.length < 2) { - throw new EvaluationException(ErrorEval.NA); - } - - // very naive impl, may need to be optimized - int[] counts = new int[v.length]; - Arrays.fill(counts, 1); - for (int i = 0, iSize = v.length; i < iSize; i++) { - for (int j = i + 1, jSize = v.length; j < jSize; j++) { - if (v[i] == v[j]) - counts[i]++; - } - } - double maxv = 0; - int maxc = 0; - for (int i = 0, iSize = counts.length; i < iSize; i++) { - if (counts[i] > maxc) { - maxv = v[i]; - maxc = counts[i]; - } - } - if (maxc > 1) { - return maxv; - } - throw new EvaluationException(ErrorEval.NA); - - } - - public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { - double result; - try { - List<Double> temp = new ArrayList<Double>(); - for (int i = 0; i < args.length; i++) { - collectValues(args[i], temp); - } - double[] values = new double[temp.size()]; - for (int i = 0; i < values.length; i++) { - values[i] = temp.get(i).doubleValue(); - } - result = evaluate(values); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - - private static void collectValues(ValueEval arg, List<Double> temp) throws EvaluationException { - if (arg instanceof TwoDEval) { - TwoDEval ae = (TwoDEval) arg; - int width = ae.getWidth(); - int height = ae.getHeight(); - for (int rrIx = 0; rrIx < height; rrIx++) { - for (int rcIx = 0; rcIx < width; rcIx++) { - ValueEval ve1 = ae.getValue(rrIx, rcIx); - collectValue(ve1, temp, false); - } - } - return; - } - if (arg instanceof RefEval) { - RefEval re = (RefEval) arg; - collectValue(re.getInnerValueEval(), temp, true); - return; - } - collectValue(arg, temp, true); - - } - - private static void collectValue(ValueEval arg, List<Double> temp, boolean mustBeNumber) - throws EvaluationException { - if (arg instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) arg); - } - if (arg == BlankEval.instance || arg instanceof BoolEval || arg instanceof StringEval) { - if (mustBeNumber) { - throw EvaluationException.invalidValue(); - } - return; - } - if (arg instanceof NumberEval) { - temp.add(new Double(((NumberEval) arg).getNumberValue())); - return; - } - throw new RuntimeException("Unexpected value type (" + arg.getClass().getName() + ")"); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java deleted file mode 100644 index cac7ca6e35..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java +++ /dev/null @@ -1,197 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * This is the super class for all excel function evaluator - * classes that take variable number of operands, and - * where the order of operands does not matter - */ -public abstract class MultiOperandNumericFunction implements Function { - - private final boolean _isReferenceBoolCounted; - private final boolean _isBlankCounted; - - protected MultiOperandNumericFunction(boolean isReferenceBoolCounted, boolean isBlankCounted) { - _isReferenceBoolCounted = isReferenceBoolCounted; - _isBlankCounted = isBlankCounted; - } - - static final double[] EMPTY_DOUBLE_ARRAY = { }; - - private static class DoubleList { - private double[] _array; - private int _count; - - public DoubleList() { - _array = new double[8]; - _count = 0; - } - - public double[] toArray() { - if(_count < 1) { - return EMPTY_DOUBLE_ARRAY; - } - double[] result = new double[_count]; - System.arraycopy(_array, 0, result, 0, _count); - return result; - } - - private void ensureCapacity(int reqSize) { - if(reqSize > _array.length) { - int newSize = reqSize * 3 / 2; // grow with 50% extra - double[] newArr = new double[newSize]; - System.arraycopy(_array, 0, newArr, 0, _count); - _array = newArr; - } - } - - public void add(double value) { - ensureCapacity(_count + 1); - _array[_count] = value; - _count++; - } - } - - private static final int DEFAULT_MAX_NUM_OPERANDS = 30; - - public final ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { - - double d; - try { - double[] values = getNumberArray(args); - d = evaluate(values); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - if (Double.isNaN(d) || Double.isInfinite(d)) - return ErrorEval.NUM_ERROR; - - return new NumberEval(d); - } - - protected abstract double evaluate(double[] values) throws EvaluationException; - - /** - * Maximum number of operands accepted by this function. - * Subclasses may override to change default value. - */ - protected int getMaxNumOperands() { - return DEFAULT_MAX_NUM_OPERANDS; - } - - /** - * Returns a double array that contains values for the numeric cells - * from among the list of operands. Blanks and Blank equivalent cells - * are ignored. Error operands or cells containing operands of type - * that are considered invalid and would result in #VALUE! error in - * excel cause this function to return <code>null</code>. - * - * @return never <code>null</code> - */ - protected final double[] getNumberArray(ValueEval[] operands) throws EvaluationException { - if (operands.length > getMaxNumOperands()) { - throw EvaluationException.invalidValue(); - } - DoubleList retval = new DoubleList(); - - for (int i=0, iSize=operands.length; i<iSize; i++) { - collectValues(operands[i], retval); - } - return retval.toArray(); - } - - /** - * Collects values from a single argument - */ - private void collectValues(ValueEval operand, DoubleList temp) throws EvaluationException { - - if (operand instanceof TwoDEval) { - TwoDEval ae = (TwoDEval) operand; - int width = ae.getWidth(); - int height = ae.getHeight(); - for (int rrIx=0; rrIx<height; rrIx++) { - for (int rcIx=0; rcIx<width; rcIx++) { - ValueEval ve = ae.getValue(rrIx, rcIx); - collectValue(ve, true, temp); - } - } - return; - } - if (operand instanceof RefEval) { - RefEval re = (RefEval) operand; - collectValue(re.getInnerValueEval(), true, temp); - return; - } - collectValue(operand, false, temp); - } - private void collectValue(ValueEval ve, boolean isViaReference, DoubleList temp) throws EvaluationException { - if (ve == null) { - throw new IllegalArgumentException("ve must not be null"); - } - if (ve instanceof NumberEval) { - NumberEval ne = (NumberEval) ve; - temp.add(ne.getNumberValue()); - return; - } - if (ve instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) ve); - } - if (ve instanceof StringEval) { - if (isViaReference) { - // ignore all ref strings - return; - } - String s = ((StringEval) ve).getStringValue(); - Double d = OperandResolver.parseDouble(s); - if(d == null) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - temp.add(d.doubleValue()); - return; - } - if (ve instanceof BoolEval) { - if (!isViaReference || _isReferenceBoolCounted) { - BoolEval boolEval = (BoolEval) ve; - temp.add(boolEval.getNumberValue()); - } - return; - } - if (ve == BlankEval.instance) { - if (_isBlankCounted) { - temp.add(0.0); - } - return; - } - throw new RuntimeException("Invalid ValueEval type passed for conversion: (" - + ve.getClass() + ")"); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Na.java b/src/java/org/apache/poi/hssf/record/formula/functions/Na.java deleted file mode 100644 index c66080b9d5..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Na.java +++ /dev/null @@ -1,33 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implementation of Excel function NA() - * - * @author Josh Micich - */ -public final class Na extends Fixed0ArgFunction { - - public ValueEval evaluate(int srcCellRow, int srcCellCol) { - return ErrorEval.NA; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/NotImplementedFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/NotImplementedFunction.java deleted file mode 100644 index 6815ed312f..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/NotImplementedFunction.java +++ /dev/null @@ -1,47 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.eval.NotImplementedException; - -/** - * - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * This is the default implementation of a Function class. - * The default behaviour is to raise a POI internal error - * ({@link NotImplementedException}). This error should alert - * the user that the formula contained a function that is not - * yet implemented. - */ -public final class NotImplementedFunction implements Function { - private final String _functionName; - protected NotImplementedFunction() { - _functionName = getClass().getName(); - } - public NotImplementedFunction(String name) { - _functionName = name; - } - - public ValueEval evaluate(ValueEval[] operands, int srcRow, int srcCol) { - throw new NotImplementedException(_functionName); - } - public String getFunctionName() { - return _functionName; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Now.java b/src/java/org/apache/poi/hssf/record/formula/functions/Now.java deleted file mode 100644 index c6d7c236a9..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Now.java +++ /dev/null @@ -1,37 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import java.util.Date; - -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.usermodel.DateUtil; - -/** - * Implementation of Excel NOW() Function - * - * @author Frank Taffelt - */ -public final class Now extends Fixed0ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - Date now = new Date(System.currentTimeMillis()); - return new NumberEval(DateUtil.getExcelDate(now)); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Npv.java b/src/java/org/apache/poi/hssf/record/formula/functions/Npv.java deleted file mode 100644 index 99955301e7..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Npv.java +++ /dev/null @@ -1,107 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Calculates the net present value of an investment by using a discount rate - * and a series of future payments (negative values) and income (positive - * values). Minimum 2 arguments, first arg is the rate of discount over the - * length of one period others up to 254 arguments representing the payments and - * income. - * - * @author SPetrakovsky - */ -public final class Npv implements Function2Arg, Function3Arg, Function4Arg { - - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - double result; - try { - double rate = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - result = evaluate(rate, d1); - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - double result; - try { - double rate = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - double d2 = NumericFunction.singleOperandEvaluate(arg2, srcRowIndex, srcColumnIndex); - result = evaluate(rate, d1, d2); - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2, ValueEval arg3) { - double result; - try { - double rate = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - double d2 = NumericFunction.singleOperandEvaluate(arg2, srcRowIndex, srcColumnIndex); - double d3 = NumericFunction.singleOperandEvaluate(arg3, srcRowIndex, srcColumnIndex); - result = evaluate(rate, d1, d2, d3); - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - int nArgs = args.length; - if (nArgs<2) { - return ErrorEval.VALUE_INVALID; - } - int np = nArgs-1; - double[] ds = new double[np]; - double result; - try { - double rate = NumericFunction.singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex); - for (int i = 0; i < ds.length; i++) { - ds[i] = NumericFunction.singleOperandEvaluate(args[i+1], srcRowIndex, srcColumnIndex); - } - result = evaluate(rate, ds); - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - - private static double evaluate(double rate, double...ds) { - double sum = 0; - for (int i = 0; i < ds.length; i++) { - sum += ds[i] / Math.pow(rate + 1, i); - } - return sum; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/NumericFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/NumericFunction.java deleted file mode 100644 index 8315159be2..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/NumericFunction.java +++ /dev/null @@ -1,495 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.*; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * @author Josh Micich - * @author Stephen Wolke (smwolke at geistig.com) - */ -public abstract class NumericFunction implements Function { - - static final double ZERO = 0.0; - static final double TEN = 10.0; - static final double LOG_10_TO_BASE_e = Math.log(TEN); - - protected static final double singleOperandEvaluate(ValueEval arg, int srcRowIndex, int srcColumnIndex) throws EvaluationException { - if (arg == null) { - throw new IllegalArgumentException("arg must not be null"); - } - ValueEval ve = OperandResolver.getSingleValue(arg, srcRowIndex, srcColumnIndex); - double result = OperandResolver.coerceValueToDouble(ve); - checkValue(result); - return result; - } - - /** - * @throws EvaluationException (#NUM!) if <tt>result</tt> is <tt>NaN</> or <tt>Infinity</tt> - */ - static final void checkValue(double result) throws EvaluationException { - if (Double.isNaN(result) || Double.isInfinite(result)) { - throw new EvaluationException(ErrorEval.NUM_ERROR); - } - } - - public final ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { - double result; - try { - result = eval(args, srcCellRow, srcCellCol); - checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - - protected abstract double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException; - - /* -------------------------------------------------------------------------- */ - // intermediate sub-classes (one-arg, two-arg and multi-arg) - - public static abstract class OneArg extends Fixed1ArgFunction { - protected OneArg() { - // no fields to initialise - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - double result; - try { - double d = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - result = evaluate(d); - checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - protected final double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException { - if (args.length != 1) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - double d = singleOperandEvaluate(args[0], srcCellRow, srcCellCol); - return evaluate(d); - } - protected abstract double evaluate(double d) throws EvaluationException; - } - - public static abstract class TwoArg extends Fixed2ArgFunction { - protected TwoArg() { - // no fields to initialise - } - - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - double result; - try { - double d0 = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - result = evaluate(d0, d1); - checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - - protected abstract double evaluate(double d0, double d1) throws EvaluationException; - } - - /* -------------------------------------------------------------------------- */ - - public static final Function ABS = new OneArg() { - protected double evaluate(double d) { - return Math.abs(d); - } - }; - public static final Function ACOS = new OneArg() { - protected double evaluate(double d) { - return Math.acos(d); - } - }; - public static final Function ACOSH = new OneArg() { - protected double evaluate(double d) { - return MathX.acosh(d); - } - }; - public static final Function ASIN = new OneArg() { - protected double evaluate(double d) { - return Math.asin(d); - } - }; - public static final Function ASINH = new OneArg() { - protected double evaluate(double d) { - return MathX.asinh(d); - } - }; - public static final Function ATAN = new OneArg() { - protected double evaluate(double d) { - return Math.atan(d); - } - }; - public static final Function ATANH = new OneArg() { - protected double evaluate(double d) { - return MathX.atanh(d); - } - }; - public static final Function COS = new OneArg() { - protected double evaluate(double d) { - return Math.cos(d); - } - }; - public static final Function COSH = new OneArg() { - protected double evaluate(double d) { - return MathX.cosh(d); - } - }; - public static final Function DEGREES = new OneArg() { - protected double evaluate(double d) { - return Math.toDegrees(d); - } - }; - static final NumberEval DOLLAR_ARG2_DEFAULT = new NumberEval(2.0); - public static final Function DOLLAR = new Var1or2ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - return evaluate(srcRowIndex, srcColumnIndex, arg0, DOLLAR_ARG2_DEFAULT); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, - ValueEval arg1) { - double val; - double d1; - try { - val = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - // second arg converts to int by truncating toward zero - int nPlaces = (int)d1; - - if (nPlaces > 127) { - return ErrorEval.VALUE_INVALID; - } - - - // TODO - DOLLAR() function impl is NQR - // result should be StringEval, with leading '$' and thousands separators - // current junits are asserting incorrect behaviour - return new NumberEval(val); - } - }; - public static final Function EXP = new OneArg() { - protected double evaluate(double d) { - return Math.pow(Math.E, d); - } - }; - public static final Function FACT = new OneArg() { - protected double evaluate(double d) { - return MathX.factorial((int)d); - } - }; - public static final Function INT = new OneArg() { - protected double evaluate(double d) { - return Math.round(d-0.5); - } - }; - public static final Function LN = new OneArg() { - protected double evaluate(double d) { - return Math.log(d); - } - }; - public static final Function LOG10 = new OneArg() { - protected double evaluate(double d) { - return Math.log(d) / LOG_10_TO_BASE_e; - } - }; - public static final Function RADIANS = new OneArg() { - protected double evaluate(double d) { - return Math.toRadians(d); - } - }; - public static final Function SIGN = new OneArg() { - protected double evaluate(double d) { - return MathX.sign(d); - } - }; - public static final Function SIN = new OneArg() { - protected double evaluate(double d) { - return Math.sin(d); - } - }; - public static final Function SINH = new OneArg() { - protected double evaluate(double d) { - return MathX.sinh(d); - } - }; - public static final Function SQRT = new OneArg() { - protected double evaluate(double d) { - return Math.sqrt(d); - } - }; - - public static final Function TAN = new OneArg() { - protected double evaluate(double d) { - return Math.tan(d); - } - }; - public static final Function TANH = new OneArg() { - protected double evaluate(double d) { - return MathX.tanh(d); - } - }; - - /* -------------------------------------------------------------------------- */ - - public static final Function ATAN2 = new TwoArg() { - protected double evaluate(double d0, double d1) throws EvaluationException { - if (d0 == ZERO && d1 == ZERO) { - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - return Math.atan2(d1, d0); - } - }; - public static final Function CEILING = new TwoArg() { - protected double evaluate(double d0, double d1) { - return MathX.ceiling(d0, d1); - } - }; - public static final Function COMBIN = new TwoArg() { - protected double evaluate(double d0, double d1) throws EvaluationException { - if (d0 > Integer.MAX_VALUE || d1 > Integer.MAX_VALUE) { - throw new EvaluationException(ErrorEval.NUM_ERROR); - } - return MathX.nChooseK((int) d0, (int) d1); - } - }; - public static final Function FLOOR = new TwoArg() { - protected double evaluate(double d0, double d1) throws EvaluationException { - if (d1 == ZERO) { - if (d0 == ZERO) { - return ZERO; - } - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - return MathX.floor(d0, d1); - } - }; - public static final Function MOD = new TwoArg() { - protected double evaluate(double d0, double d1) throws EvaluationException { - if (d1 == ZERO) { - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - return MathX.mod(d0, d1); - } - }; - public static final Function POWER = new TwoArg() { - protected double evaluate(double d0, double d1) { - return Math.pow(d0, d1); - } - }; - public static final Function ROUND = new TwoArg() { - protected double evaluate(double d0, double d1) { - return MathX.round(d0, (int)d1); - } - }; - public static final Function ROUNDDOWN = new TwoArg() { - protected double evaluate(double d0, double d1) { - return MathX.roundDown(d0, (int)d1); - } - }; - public static final Function ROUNDUP = new TwoArg() { - protected double evaluate(double d0, double d1) { - return MathX.roundUp(d0, (int)d1); - } - }; - static final NumberEval TRUNC_ARG2_DEFAULT = new NumberEval(0); - public static final Function TRUNC = new Var1or2ArgFunction() { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - return evaluate(srcRowIndex, srcColumnIndex, arg0, TRUNC_ARG2_DEFAULT); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - double result; - try { - double d0 = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - double multi = Math.pow(10d,d1); - result = Math.floor(d0 * multi) / multi; - checkValue(result); - }catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - }; - - /* -------------------------------------------------------------------------- */ - - private static final class Log extends Var1or2ArgFunction { - public Log() { - // no instance fields - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - double result; - try { - double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - result = Math.log(d0) / LOG_10_TO_BASE_e; - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, - ValueEval arg1) { - double result; - try { - double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - double logE = Math.log(d0); - double base = d1; - if (base == Math.E) { - result = logE; - } else { - result = logE / Math.log(base); - } - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - } - - public static final Function LOG = new Log(); - - static final NumberEval PI_EVAL = new NumberEval(Math.PI); - public static final Function PI = new Fixed0ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return PI_EVAL; - } - }; - public static final Function RAND = new Fixed0ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return new NumberEval(Math.random()); - } - }; - public static final Function POISSON = new Fixed3ArgFunction() { - - private final static double DEFAULT_RETURN_RESULT =1; - - /** - * This checks is x = 0 and the mean = 0. - * Excel currently returns the value 1 where as the - * maths common implementation will error. - * @param x The number. - * @param mean The mean. - * @return If a default value should be returned. - */ - private boolean isDefaultResult(double x, double mean) { - - if ( x == 0 && mean == 0 ) { - return true; - } - return false; - } - - private boolean checkArgument(double aDouble) throws EvaluationException { - - NumericFunction.checkValue(aDouble); - - // make sure that the number is positive - if (aDouble < 0) { - throw new EvaluationException(ErrorEval.NUM_ERROR); - } - - return true; - } - - private double probability(int k, double lambda) { - return Math.pow(lambda, k) * Math.exp(-lambda) / factorial(k); - } - - private double cumulativeProbability(int x, double lambda) { - double result = 0; - for(int k = 0; k <= x; k++){ - result += probability(k, lambda); - } - return result; - } - - /** All long-representable factorials */ - private final long[] FACTORIALS = new long[] { - 1l, 1l, 2l, - 6l, 24l, 120l, - 720l, 5040l, 40320l, - 362880l, 3628800l, 39916800l, - 479001600l, 6227020800l, 87178291200l, - 1307674368000l, 20922789888000l, 355687428096000l, - 6402373705728000l, 121645100408832000l, 2432902008176640000l }; - - - public long factorial(final int n) { - if (n < 0 || n > 20) { - throw new IllegalArgumentException("Valid argument should be in the range [0..20]"); - } - return FACTORIALS[n]; - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, ValueEval arg2) { - - // arguments/result for this function - double mean=0; - double x=0; - boolean cumulative = ((BoolEval)arg2).getBooleanValue(); - double result=0; - - try { - x = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - mean = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - - // check for default result : excel implementation for 0,0 - // is different to Math Common. - if (isDefaultResult(x,mean)) { - return new NumberEval(DEFAULT_RETURN_RESULT); - } - // check the arguments : as per excel function def - checkArgument(x); - checkArgument(mean); - - // truncate x : as per excel function def - if ( cumulative ) { - result = cumulativeProbability((int)x, mean); - } else { - result = probability((int)x, mean); - } - - // check the result - NumericFunction.checkValue(result); - - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - return new NumberEval(result); - - } - }; -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Odd.java b/src/java/org/apache/poi/hssf/record/formula/functions/Odd.java deleted file mode 100644 index 4904c01d47..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Odd.java +++ /dev/null @@ -1,45 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public final class Odd extends NumericFunction.OneArg { - private static final long PARITY_MASK = 0xFFFFFFFFFFFFFFFEL; - - protected double evaluate(double d) { - if (d==0) { - return 1; - } - if (d>0) { - return calcOdd(d); - } - return -calcOdd(-d); - } - - private static long calcOdd(double d) { - double dpm1 = d+1; - long x = ((long) dpm1) & PARITY_MASK; - if (x == dpm1) { - return x-1; - } - return x + 1; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Offset.java b/src/java/org/apache/poi/hssf/record/formula/functions/Offset.java deleted file mode 100644 index be4a33e680..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Offset.java +++ /dev/null @@ -1,227 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.AreaEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -/** - * Implementation for Excel function OFFSET()<p/> - * - * OFFSET returns an area reference that is a specified number of rows and columns from a - * reference cell or area.<p/> - * - * <b>Syntax</b>:<br/> - * <b>OFFSET</b>(<b>reference</b>, <b>rows</b>, <b>cols</b>, height, width)<p/> - * <b>reference</b> is the base reference.<br/> - * <b>rows</b> is the number of rows up or down from the base reference.<br/> - * <b>cols</b> is the number of columns left or right from the base reference.<br/> - * <b>height</b> (default same height as base reference) is the row count for the returned area reference.<br/> - * <b>width</b> (default same width as base reference) is the column count for the returned area reference.<br/> - * - * @author Josh Micich - */ -public final class Offset implements Function { - // These values are specific to BIFF8 - private static final int LAST_VALID_ROW_INDEX = 0xFFFF; - private static final int LAST_VALID_COLUMN_INDEX = 0xFF; - - - /** - * A one dimensional base + offset. Represents either a row range or a column range. - * Two instances of this class together specify an area range. - */ - /* package */ static final class LinearOffsetRange { - - private final int _offset; - private final int _length; - - public LinearOffsetRange(int offset, int length) { - if(length == 0) { - // handled that condition much earlier - throw new RuntimeException("length may not be zero"); - } - _offset = offset; - _length = length; - } - - public short getFirstIndex() { - return (short) _offset; - } - public short getLastIndex() { - return (short) (_offset + _length - 1); - } - /** - * Moves the range by the specified translation amount.<p/> - * - * This method also 'normalises' the range: Excel specifies that the width and height - * parameters (length field here) cannot be negative. However, OFFSET() does produce - * sensible results in these cases. That behavior is replicated here. <p/> - * - * @param translationAmount may be zero negative or positive - * - * @return the equivalent <tt>LinearOffsetRange</tt> with a positive length, moved by the - * specified translationAmount. - */ - public LinearOffsetRange normaliseAndTranslate(int translationAmount) { - if (_length > 0) { - if(translationAmount == 0) { - return this; - } - return new LinearOffsetRange(translationAmount + _offset, _length); - } - return new LinearOffsetRange(translationAmount + _offset + _length + 1, -_length); - } - - public boolean isOutOfBounds(int lowValidIx, int highValidIx) { - if(_offset < lowValidIx) { - return true; - } - if(getLastIndex() > highValidIx) { - return true; - } - return false; - } - public String toString() { - StringBuffer sb = new StringBuffer(64); - sb.append(getClass().getName()).append(" ["); - sb.append(_offset).append("...").append(getLastIndex()); - sb.append("]"); - return sb.toString(); - } - } - - /** - * Encapsulates either an area or cell reference which may be 2d or 3d. - */ - private static final class BaseRef { - private final int _firstRowIndex; - private final int _firstColumnIndex; - private final int _width; - private final int _height; - private final RefEval _refEval; - private final AreaEval _areaEval; - - public BaseRef(RefEval re) { - _refEval = re; - _areaEval = null; - _firstRowIndex = re.getRow(); - _firstColumnIndex = re.getColumn(); - _height = 1; - _width = 1; - } - - public BaseRef(AreaEval ae) { - _refEval = null; - _areaEval = ae; - _firstRowIndex = ae.getFirstRow(); - _firstColumnIndex = ae.getFirstColumn(); - _height = ae.getLastRow() - ae.getFirstRow() + 1; - _width = ae.getLastColumn() - ae.getFirstColumn() + 1; - } - - public int getWidth() { - return _width; - } - public int getHeight() { - return _height; - } - public int getFirstRowIndex() { - return _firstRowIndex; - } - public int getFirstColumnIndex() { - return _firstColumnIndex; - } - - public AreaEval offset(int relFirstRowIx, int relLastRowIx, - int relFirstColIx, int relLastColIx) { - if (_refEval == null) { - return _areaEval.offset(relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx); - } - return _refEval.offset(relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx); - } - } - - public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { - if(args.length < 3 || args.length > 5) { - return ErrorEval.VALUE_INVALID; - } - - try { - BaseRef baseRef = evaluateBaseRef(args[0]); - int rowOffset = evaluateIntArg(args[1], srcCellRow, srcCellCol); - int columnOffset = evaluateIntArg(args[2], srcCellRow, srcCellCol); - int height = baseRef.getHeight(); - int width = baseRef.getWidth(); - switch(args.length) { - case 5: - width = evaluateIntArg(args[4], srcCellRow, srcCellCol); - case 4: - height = evaluateIntArg(args[3], srcCellRow, srcCellCol); - } - // Zero height or width raises #REF! error - if(height == 0 || width == 0) { - return ErrorEval.REF_INVALID; - } - LinearOffsetRange rowOffsetRange = new LinearOffsetRange(rowOffset, height); - LinearOffsetRange colOffsetRange = new LinearOffsetRange(columnOffset, width); - return createOffset(baseRef, rowOffsetRange, colOffsetRange); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - - private static AreaEval createOffset(BaseRef baseRef, - LinearOffsetRange orRow, LinearOffsetRange orCol) throws EvaluationException { - LinearOffsetRange absRows = orRow.normaliseAndTranslate(baseRef.getFirstRowIndex()); - LinearOffsetRange absCols = orCol.normaliseAndTranslate(baseRef.getFirstColumnIndex()); - - if(absRows.isOutOfBounds(0, LAST_VALID_ROW_INDEX)) { - throw new EvaluationException(ErrorEval.REF_INVALID); - } - if(absCols.isOutOfBounds(0, LAST_VALID_COLUMN_INDEX)) { - throw new EvaluationException(ErrorEval.REF_INVALID); - } - return baseRef.offset(orRow.getFirstIndex(), orRow.getLastIndex(), orCol.getFirstIndex(), orCol.getLastIndex()); - } - - private static BaseRef evaluateBaseRef(ValueEval eval) throws EvaluationException { - - if(eval instanceof RefEval) { - return new BaseRef((RefEval)eval); - } - if(eval instanceof AreaEval) { - return new BaseRef((AreaEval)eval); - } - if (eval instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) eval); - } - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - - /** - * OFFSET's numeric arguments (2..5) have similar processing rules - */ - static int evaluateIntArg(ValueEval eval, int srcCellRow, int srcCellCol) throws EvaluationException { - ValueEval ve = OperandResolver.getSingleValue(eval, srcCellRow, srcCellCol); - return OperandResolver.coerceValueToInt(ve); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Replace.java b/src/java/org/apache/poi/hssf/record/formula/functions/Replace.java deleted file mode 100644 index f2af838f91..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Replace.java +++ /dev/null @@ -1,74 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * An implementation of the Excel REPLACE() function:<p/> - * Replaces part of a text string based on the number of characters - * you specify, with another text string.<br/> - * - * <b>Syntax</b>:<br/> - * <b>REPLACE</b>(<b>oldText</b>, <b>startNum</b>, <b>numChars</b>, <b>newText</b>)<p/> - * - * <b>oldText</b> The text string containing characters to replace<br/> - * <b>startNum</b> The position of the first character to replace (1-based)<br/> - * <b>numChars</b> The number of characters to replace<br/> - * <b>newText</b> The new text value to replace the removed section<br/> - * - * @author Manda Wilson < wilson at c bio dot msk cc dot org > - */ -public final class Replace extends Fixed4ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2, ValueEval arg3) { - - String oldStr; - int startNum; - int numChars; - String newStr; - try { - oldStr = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex); - startNum = TextFunction.evaluateIntArg(arg1, srcRowIndex, srcColumnIndex); - numChars = TextFunction.evaluateIntArg(arg2, srcRowIndex, srcColumnIndex); - newStr = TextFunction.evaluateStringArg(arg3, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - if (startNum < 1 || numChars < 0) { - return ErrorEval.VALUE_INVALID; - } - StringBuffer strBuff = new StringBuffer(oldStr); - // remove any characters that should be replaced - if (startNum <= oldStr.length() && numChars != 0) { - strBuff.delete(startNum - 1, startNum - 1 + numChars); - } - // now insert (or append) newStr - if (startNum > strBuff.length()) { - strBuff.append(newStr); - } else { - strBuff.insert(startNum - 1, newStr); - } - return new StringEval(strBuff.toString()); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/RowFunc.java b/src/java/org/apache/poi/hssf/record/formula/functions/RowFunc.java deleted file mode 100644 index ea1aa3252f..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/RowFunc.java +++ /dev/null @@ -1,59 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.AreaEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implementation for the Excel function ROW - * - * @author Josh Micich - */ -public final class RowFunc implements Function0Arg, Function1Arg { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return new NumberEval(srcRowIndex+1); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - int rnum; - - if (arg0 instanceof AreaEval) { - rnum = ((AreaEval) arg0).getFirstRow(); - } else if (arg0 instanceof RefEval) { - rnum = ((RefEval) arg0).getRow(); - } else { - // anything else is not valid argument - return ErrorEval.VALUE_INVALID; - } - - return new NumberEval(rnum + 1); - } - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - switch (args.length) { - case 1: - return evaluate(srcRowIndex, srcColumnIndex, args[0]); - case 0: - return new NumberEval(srcRowIndex+1); - } - return ErrorEval.VALUE_INVALID; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Rows.java b/src/java/org/apache/poi/hssf/record/formula/functions/Rows.java deleted file mode 100644 index 91da8e157d..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Rows.java +++ /dev/null @@ -1,45 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * Implementation for Excel ROWS function. - * - * @author Josh Micich - */ -public final class Rows extends Fixed1ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - - int result; - if (arg0 instanceof TwoDEval) { - result = ((TwoDEval) arg0).getHeight(); - } else if (arg0 instanceof RefEval) { - result = 1; - } else { // anything else is not valid argument - return ErrorEval.VALUE_INVALID; - } - return new NumberEval(result); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/StatsLib.java b/src/java/org/apache/poi/hssf/record/formula/functions/StatsLib.java deleted file mode 100644 index 2cc4a78f37..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/StatsLib.java +++ /dev/null @@ -1,137 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import java.util.Arrays; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - * Library for common statistics functions - */ -final class StatsLib { - - private StatsLib() { - // no instances of this class - } - - - /** - * returns the mean of deviations from mean. - * @param v - */ - public static double avedev(double[] v) { - double r = 0; - double m = 0; - double s = 0; - for (int i=0, iSize=v.length; i<iSize; i++) { - s += v[i]; - } - m = s / v.length; - s = 0; - for (int i=0, iSize=v.length; i<iSize; i++) { - s += Math.abs(v[i]-m); - } - r = s / v.length; - return r; - } - - public static double stdev(double[] v) { - double r = Double.NaN; - if (v!=null && v.length > 1) { - r = Math.sqrt( devsq(v) / (v.length - 1) ); - } - return r; - } - - - public static double median(double[] v) { - double r = Double.NaN; - - if (v!=null && v.length >= 1) { - int n = v.length; - Arrays.sort(v); - r = (n % 2 == 0) - ? (v[n / 2] + v[n / 2 - 1]) / 2 - : v[n / 2]; - } - - return r; - } - - - public static double devsq(double[] v) { - double r = Double.NaN; - if (v!=null && v.length >= 1) { - double m = 0; - double s = 0; - int n = v.length; - for (int i=0; i<n; i++) { - s += v[i]; - } - m = s / n; - s = 0; - for (int i=0; i<n; i++) { - s += (v[i]- m) * (v[i] - m); - } - - r = (n == 1) - ? 0 - : s; - } - return r; - } - - /** - * returns the kth largest element in the array. Duplicates - * are considered as distinct values. Hence, eg. - * for array {1,2,4,3,3} & k=2, returned value is 3. - * <br/> - * k <= 0 & k >= v.length and null or empty arrays - * will result in return value Double.NaN - */ - public static double kthLargest(double[] v, int k) { - double r = Double.NaN; - int index = k-1; // since arrays are 0-based - if (v!=null && v.length > index && index >= 0) { - Arrays.sort(v); - r = v[v.length-index-1]; - } - return r; - } - - /** - * returns the kth smallest element in the array. Duplicates - * are considered as distinct values. Hence, eg. - * for array {1,1,2,4,3,3} & k=2, returned value is 1. - * <br/> - * k <= 0 & k >= v.length or null array or empty array - * will result in return value Double.NaN - * @param v - * @param k - */ - public static double kthSmallest(double[] v, int k) { - double r = Double.NaN; - int index = k-1; // since arrays are 0-based - if (v!=null && v.length > index && index >= 0) { - Arrays.sort(v); - r = v[index]; - } - return r; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Substitute.java b/src/java/org/apache/poi/hssf/record/formula/functions/Substitute.java deleted file mode 100644 index 558de6ba8f..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Substitute.java +++ /dev/null @@ -1,108 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * An implementation of the SUBSTITUTE function:<P/> - * Substitutes text in a text string with new text, some number of times. - * @author Manda Wilson < wilson at c bio dot msk cc dot org > - */ -public final class Substitute extends Var3or4ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - String result; - try { - String oldStr = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex); - String searchStr = TextFunction.evaluateStringArg(arg1, srcRowIndex, srcColumnIndex); - String newStr = TextFunction.evaluateStringArg(arg2, srcRowIndex, srcColumnIndex); - - result = replaceAllOccurrences(oldStr, searchStr, newStr); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new StringEval(result); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2, ValueEval arg3) { - String result; - try { - String oldStr = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex); - String searchStr = TextFunction.evaluateStringArg(arg1, srcRowIndex, srcColumnIndex); - String newStr = TextFunction.evaluateStringArg(arg2, srcRowIndex, srcColumnIndex); - - int instanceNumber = TextFunction.evaluateIntArg(arg3, srcRowIndex, srcColumnIndex); - if (instanceNumber < 1) { - return ErrorEval.VALUE_INVALID; - } - result = replaceOneOccurrence(oldStr, searchStr, newStr, instanceNumber); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new StringEval(result); - } - - private static String replaceAllOccurrences(String oldStr, String searchStr, String newStr) { - StringBuffer sb = new StringBuffer(); - int startIndex = 0; - int nextMatch = -1; - while (true) { - nextMatch = oldStr.indexOf(searchStr, startIndex); - if (nextMatch < 0) { - // store everything from end of last match to end of string - sb.append(oldStr.substring(startIndex)); - return sb.toString(); - } - // store everything from end of last match to start of this match - sb.append(oldStr.substring(startIndex, nextMatch)); - sb.append(newStr); - startIndex = nextMatch + searchStr.length(); - } - } - - private static String replaceOneOccurrence(String oldStr, String searchStr, String newStr, int instanceNumber) { - if (searchStr.length() < 1) { - return oldStr; - } - int startIndex = 0; - int nextMatch = -1; - int count=0; - while (true) { - nextMatch = oldStr.indexOf(searchStr, startIndex); - if (nextMatch < 0) { - // not enough occurrences found - leave unchanged - return oldStr; - } - count++; - if (count == instanceNumber) { - StringBuffer sb = new StringBuffer(oldStr.length() + newStr.length()); - sb.append(oldStr.substring(0, nextMatch)); - sb.append(newStr); - sb.append(oldStr.substring(nextMatch + searchStr.length())); - return sb.toString(); - } - startIndex = nextMatch + searchStr.length(); - } - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Subtotal.java b/src/java/org/apache/poi/hssf/record/formula/functions/Subtotal.java deleted file mode 100644 index cdf74f820f..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Subtotal.java +++ /dev/null @@ -1,100 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.eval.NotImplementedException; - -/** - * Implementation for the Excel function SUBTOTAL<p> - * - * <b>Syntax :</b> <br/> - * SUBTOTAL ( <b>functionCode</b>, <b>ref1</b>, ref2 ... ) <br/> - * <table border="1" cellpadding="1" cellspacing="0" summary="Parameter descriptions"> - * <tr><td><b>functionCode</b></td><td>(1-11) Selects the underlying aggregate function to be used (see table below)</td></tr> - * <tr><td><b>ref1</b>, ref2 ...</td><td>Arguments to be passed to the underlying aggregate function</td></tr> - * </table><br/> - * </p> - * - * <table border="1" cellpadding="1" cellspacing="0" summary="Parameter descriptions"> - * <tr><th>functionCode</th><th>Aggregate Function</th></tr> - * <tr align='center'><td>1</td><td>AVERAGE</td></tr> - * <tr align='center'><td>2</td><td>COUNT</td></tr> - * <tr align='center'><td>3</td><td>COUNTA</td></tr> - * <tr align='center'><td>4</td><td>MAX</td></tr> - * <tr align='center'><td>5</td><td>MIN</td></tr> - * <tr align='center'><td>6</td><td>PRODUCT</td></tr> - * <tr align='center'><td>7</td><td>STDEV</td></tr> - * <tr align='center'><td>8</td><td>STDEVP *</td></tr> - * <tr align='center'><td>9</td><td>AVERAGE</td></tr> - * <tr align='center'><td>10</td><td>VAR *</td></tr> - * <tr align='center'><td>11</td><td>VARP *</td></tr> - * <tr align='center'><td>101-111</td><td>*</td></tr> - * </table><br/> - * * Not implemented in POI yet. Functions 101-111 are the same as functions 1-11 but with - * the option 'ignore hidden values'. - * <p/> - * - * @author Paul Tomlin < pault at bulk sms dot com > - */ -public class Subtotal implements Function { - - private static Function findFunction(int functionCode) throws EvaluationException { - switch (functionCode) { - case 1: return AggregateFunction.AVERAGE; - case 2: return new Count(); - case 3: return new Counta(); - case 4: return AggregateFunction.MAX; - case 5: return AggregateFunction.MIN; - case 6: return AggregateFunction.PRODUCT; - case 7: return AggregateFunction.STDEV; - case 8: throw new NotImplementedException("STDEVP"); - case 9: return AggregateFunction.SUM; - case 10: throw new NotImplementedException("VAR"); - case 11: throw new NotImplementedException("VARP"); - } - if (functionCode > 100 && functionCode < 112) { - throw new NotImplementedException("SUBTOTAL - with 'exclude hidden values' option"); - } - throw EvaluationException.invalidValue(); - } - - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - int nInnerArgs = args.length-1; // -1: first arg is used to select from a basic aggregate function - if (nInnerArgs < 1) { - return ErrorEval.VALUE_INVALID; - } - - Function innerFunc; - try { - ValueEval ve = OperandResolver.getSingleValue(args[0], srcRowIndex, srcColumnIndex); - int functionCode = OperandResolver.coerceValueToInt(ve); - innerFunc = findFunction(functionCode); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - ValueEval[] innerArgs = new ValueEval[nInnerArgs]; - System.arraycopy(args, 1, innerArgs, 0, nInnerArgs); - - return innerFunc.evaluate(innerArgs, srcRowIndex, srcColumnIndex); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Sumif.java b/src/java/org/apache/poi/hssf/record/formula/functions/Sumif.java deleted file mode 100644 index 8bc36ffe24..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Sumif.java +++ /dev/null @@ -1,127 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.AreaEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate; - -/** - * Implementation for the Excel function SUMIF<p> - * - * Syntax : <br/> - * SUMIF ( <b>range</b>, <b>criteria</b>, sum_range ) <br/> - * <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions"> - * <tr><th>range</th><td>The range over which criteria is applied. Also used for addend values when the third parameter is not present</td></tr> - * <tr><th>criteria</th><td>The value or expression used to filter rows from <b>range</b></td></tr> - * <tr><th>sum_range</th><td>Locates the top-left corner of the corresponding range of addends - values to be added (after being selected by the criteria)</td></tr> - * </table><br/> - * </p> - * @author Josh Micich - */ -public final class Sumif extends Var2or3ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - - AreaEval aeRange; - try { - aeRange = convertRangeArg(arg0); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return eval(srcRowIndex, srcColumnIndex, arg1, aeRange, aeRange); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - - AreaEval aeRange; - AreaEval aeSum; - try { - aeRange = convertRangeArg(arg0); - aeSum = createSumRange(arg2, aeRange); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return eval(srcRowIndex, srcColumnIndex, arg1, aeRange, aeSum); - } - - private static ValueEval eval(int srcRowIndex, int srcColumnIndex, ValueEval arg1, AreaEval aeRange, - AreaEval aeSum) { - // TODO - junit to prove last arg must be srcColumnIndex and not srcRowIndex - I_MatchPredicate mp = Countif.createCriteriaPredicate(arg1, srcRowIndex, srcColumnIndex); - double result = sumMatchingCells(aeRange, mp, aeSum); - return new NumberEval(result); - } - - private static double sumMatchingCells(AreaEval aeRange, I_MatchPredicate mp, AreaEval aeSum) { - int height=aeRange.getHeight(); - int width= aeRange.getWidth(); - - double result = 0.0; - for (int r=0; r<height; r++) { - for (int c=0; c<width; c++) { - result += accumulate(aeRange, mp, aeSum, r, c); - } - } - return result; - } - - private static double accumulate(AreaEval aeRange, I_MatchPredicate mp, AreaEval aeSum, int relRowIndex, - int relColIndex) { - - if (!mp.matches(aeRange.getRelativeValue(relRowIndex, relColIndex))) { - return 0.0; - } - ValueEval addend = aeSum.getRelativeValue(relRowIndex, relColIndex); - if (addend instanceof NumberEval) { - return ((NumberEval)addend).getNumberValue(); - } - // everything else (including string and boolean values) counts as zero - return 0.0; - } - - /** - * @return a range of the same dimensions as aeRange using eval to define the top left corner. - * @throws EvaluationException if eval is not a reference - */ - private static AreaEval createSumRange(ValueEval eval, AreaEval aeRange) throws EvaluationException { - if (eval instanceof AreaEval) { - return ((AreaEval) eval).offset(0, aeRange.getHeight()-1, 0, aeRange.getWidth()-1); - } - if (eval instanceof RefEval) { - return ((RefEval)eval).offset(0, aeRange.getHeight()-1, 0, aeRange.getWidth()-1); - } - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - - private static AreaEval convertRangeArg(ValueEval eval) throws EvaluationException { - if (eval instanceof AreaEval) { - return (AreaEval) eval; - } - if (eval instanceof RefEval) { - return ((RefEval)eval).offset(0, 0, 0, 0); - } - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Sumproduct.java b/src/java/org/apache/poi/hssf/record/formula/functions/Sumproduct.java deleted file mode 100644 index 41de8ef392..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Sumproduct.java +++ /dev/null @@ -1,231 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.AreaEval; -import org.apache.poi.hssf.record.formula.eval.BlankEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.NumericValueEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.formula.TwoDEval; - - -/** - * Implementation for the Excel function SUMPRODUCT<p> - * - * Syntax : <br/> - * SUMPRODUCT ( array1[, array2[, array3[, ...]]]) - * <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions"> - * <tr><th>array1, ... arrayN </th><td>typically area references, - * possibly cell references or scalar values</td></tr> - * </table><br/> - * - * Let A<b>n</b><sub>(<b>i</b>,<b>j</b>)</sub> represent the element in the <b>i</b>th row <b>j</b>th column - * of the <b>n</b>th array<br/> - * Assuming each array has the same dimensions (W, H), the result is defined as:<br/> - * SUMPRODUCT = Σ<sub><b>i</b>: 1..H</sub> - * ( Σ<sub><b>j</b>: 1..W</sub> - * ( Π<sub><b>n</b>: 1..N</sub> - * A<b>n</b><sub>(<b>i</b>,<b>j</b>)</sub> - * ) - * ) - * </p> - * @author Josh Micich - */ -public final class Sumproduct implements Function { - - - public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { - - int maxN = args.length; - - if(maxN < 1) { - return ErrorEval.VALUE_INVALID; - } - ValueEval firstArg = args[0]; - try { - if(firstArg instanceof NumericValueEval) { - return evaluateSingleProduct(args); - } - if(firstArg instanceof RefEval) { - return evaluateSingleProduct(args); - } - if (firstArg instanceof TwoDEval) { - TwoDEval ae = (TwoDEval) firstArg; - if(ae.isRow() && ae.isColumn()) { - return evaluateSingleProduct(args); - } - return evaluateAreaSumProduct(args); - } - } catch (EvaluationException e) { - return e.getErrorEval(); - } - throw new RuntimeException("Invalid arg type for SUMPRODUCT: (" - + firstArg.getClass().getName() + ")"); - } - - private static ValueEval evaluateSingleProduct(ValueEval[] evalArgs) throws EvaluationException { - int maxN = evalArgs.length; - - double term = 1D; - for(int n=0; n<maxN; n++) { - double val = getScalarValue(evalArgs[n]); - term *= val; - } - return new NumberEval(term); - } - - private static double getScalarValue(ValueEval arg) throws EvaluationException { - - ValueEval eval; - if (arg instanceof RefEval) { - RefEval re = (RefEval) arg; - eval = re.getInnerValueEval(); - } else { - eval = arg; - } - - if (eval == null) { - throw new RuntimeException("parameter may not be null"); - } - if (eval instanceof AreaEval) { - AreaEval ae = (AreaEval) eval; - // an area ref can work as a scalar value if it is 1x1 - if(!ae.isColumn() || !ae.isRow()) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - eval = ae.getRelativeValue(0, 0); - } - - return getProductTerm(eval, true); - } - - private static ValueEval evaluateAreaSumProduct(ValueEval[] evalArgs) throws EvaluationException { - int maxN = evalArgs.length; - TwoDEval[] args = new TwoDEval[maxN]; - try { - System.arraycopy(evalArgs, 0, args, 0, maxN); - } catch (ArrayStoreException e) { - // one of the other args was not an AreaRef - return ErrorEval.VALUE_INVALID; - } - - - TwoDEval firstArg = args[0]; - - int height = firstArg.getHeight(); - int width = firstArg.getWidth(); // TODO - junit - - // first check dimensions - if (!areasAllSameSize(args, height, width)) { - // normally this results in #VALUE!, - // but errors in individual cells take precedence - for (int i = 1; i < args.length; i++) { - throwFirstError(args[i]); - } - return ErrorEval.VALUE_INVALID; - } - - double acc = 0; - - for (int rrIx=0; rrIx<height; rrIx++) { - for (int rcIx=0; rcIx<width; rcIx++) { - double term = 1D; - for(int n=0; n<maxN; n++) { - double val = getProductTerm(args[n].getValue(rrIx, rcIx), false); - term *= val; - } - acc += term; - } - } - - return new NumberEval(acc); - } - - private static void throwFirstError(TwoDEval areaEval) throws EvaluationException { - int height = areaEval.getHeight(); - int width = areaEval.getWidth(); - for (int rrIx=0; rrIx<height; rrIx++) { - for (int rcIx=0; rcIx<width; rcIx++) { - ValueEval ve = areaEval.getValue(rrIx, rcIx); - if (ve instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) ve); - } - } - } - } - - private static boolean areasAllSameSize(TwoDEval[] args, int height, int width) { - for (int i = 0; i < args.length; i++) { - TwoDEval areaEval = args[i]; - // check that height and width match - if(areaEval.getHeight() != height) { - return false; - } - if(areaEval.getWidth() != width) { - return false; - } - } - return true; - } - - - /** - * Determines a <code>double</code> value for the specified <code>ValueEval</code>. - * @param isScalarProduct <code>false</code> for SUMPRODUCTs over area refs. - * @throws EvaluationException if <code>ve</code> represents an error value. - * <p/> - * Note - string values and empty cells are interpreted differently depending on - * <code>isScalarProduct</code>. For scalar products, if any term is blank or a string, the - * error (#VALUE!) is raised. For area (sum)products, if any term is blank or a string, the - * result is zero. - */ - private static double getProductTerm(ValueEval ve, boolean isScalarProduct) throws EvaluationException { - - if(ve instanceof BlankEval || ve == null) { - // TODO - shouldn't BlankEval.INSTANCE be used always instead of null? - // null seems to occur when the blank cell is part of an area ref (but not reliably) - if(isScalarProduct) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - return 0; - } - - if(ve instanceof ErrorEval) { - throw new EvaluationException((ErrorEval)ve); - } - if(ve instanceof StringEval) { - if(isScalarProduct) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - // Note for area SUMPRODUCTs, string values are interpreted as zero - // even if they would parse as valid numeric values - return 0; - } - if(ve instanceof NumericValueEval) { - NumericValueEval nve = (NumericValueEval) ve; - return nve.getNumberValue(); - } - throw new RuntimeException("Unexpected value eval class (" - + ve.getClass().getName() + ")"); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2my2.java b/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2my2.java deleted file mode 100644 index b271169666..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2my2.java +++ /dev/null @@ -1,43 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - - -/** - * Implementation of Excel function SUMX2MY2()<p/> - * - * Calculates the sum of differences of squares in two arrays of the same size.<br/> - * <b>Syntax</b>:<br/> - * <b>SUMX2MY2</b>(<b>arrayX</b>, <b>arrayY</b>)<p/> - * - * result = Σ<sub>i: 0..n</sub>(x<sub>i</sub><sup>2</sup>-y<sub>i</sub><sup>2</sup>) - * - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public final class Sumx2my2 extends XYNumericFunction { - - private static final Accumulator XSquaredMinusYSquaredAccumulator = new Accumulator() { - public double accumulate(double x, double y) { - return x * x - y * y; - } - }; - - protected Accumulator createAccumulator() { - return XSquaredMinusYSquaredAccumulator; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java b/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java deleted file mode 100644 index 3cedca35e2..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java +++ /dev/null @@ -1,43 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - - -/** - * Implementation of Excel function SUMX2PY2()<p/> - * - * Calculates the sum of squares in two arrays of the same size.<br/> - * <b>Syntax</b>:<br/> - * <b>SUMX2PY2</b>(<b>arrayX</b>, <b>arrayY</b>)<p/> - * - * result = Σ<sub>i: 0..n</sub>(x<sub>i</sub><sup>2</sup>+y<sub>i</sub><sup>2</sup>) - * - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public final class Sumx2py2 extends XYNumericFunction { - - private static final Accumulator XSquaredPlusYSquaredAccumulator = new Accumulator() { - public double accumulate(double x, double y) { - return x * x + y * y; - } - }; - - protected Accumulator createAccumulator() { - return XSquaredPlusYSquaredAccumulator; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java b/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java deleted file mode 100644 index bb95c9fdf6..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java +++ /dev/null @@ -1,43 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -/** - * Implementation of Excel function SUMXMY2()<p/> - * - * Calculates the sum of squares of differences between two arrays of the same size.<br/> - * <b>Syntax</b>:<br/> - * <b>SUMXMY2</b>(<b>arrayX</b>, <b>arrayY</b>)<p/> - * - * result = Σ<sub>i: 0..n</sub>(x<sub>i</sub>-y<sub>i</sub>)<sup>2</sup> - * - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public final class Sumxmy2 extends XYNumericFunction { - - private static final Accumulator XMinusYSquaredAccumulator = new Accumulator() { - public double accumulate(double x, double y) { - double xmy = x - y; - return xmy * xmy; - } - }; - - protected Accumulator createAccumulator() { - return XMinusYSquaredAccumulator; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/T.java b/src/java/org/apache/poi/hssf/record/formula/functions/T.java deleted file mode 100644 index 70869e462e..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/T.java +++ /dev/null @@ -1,56 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.AreaEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implementation of Excel T() function - * <p/> - * If the argument is a text or error value it is returned unmodified. All other argument types - * cause an empty string result. If the argument is an area, the first (top-left) cell is used - * (regardless of the coordinates of the evaluating formula cell). - */ -public final class T extends Fixed1ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - ValueEval arg = arg0; - if (arg instanceof RefEval) { - arg = ((RefEval) arg).getInnerValueEval(); - } else if (arg instanceof AreaEval) { - // when the arg is an area, choose the top left cell - arg = ((AreaEval) arg).getRelativeValue(0, 0); - } - - if (arg instanceof StringEval) { - // Text values are returned unmodified - return arg; - } - - if (arg instanceof ErrorEval) { - // Error values also returned unmodified - return arg; - } - // for all other argument types the result is empty string - return StringEval.EMPTY_INSTANCE; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/TextFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/TextFunction.java deleted file mode 100644 index 6a2206f13e..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/TextFunction.java +++ /dev/null @@ -1,372 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.GregorianCalendar; -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * @author Josh Micich - * @author Stephen Wolke (smwolke at geistig.com) - */ -public abstract class TextFunction implements Function { - - protected static final String EMPTY_STRING = ""; - - protected static final String evaluateStringArg(ValueEval eval, int srcRow, int srcCol) throws EvaluationException { - ValueEval ve = OperandResolver.getSingleValue(eval, srcRow, srcCol); - return OperandResolver.coerceValueToString(ve); - } - protected static final int evaluateIntArg(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException { - ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); - return OperandResolver.coerceValueToInt(ve); - } - - protected static final double evaluateDoubleArg(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException { - ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); - return OperandResolver.coerceValueToDouble(ve); - } - - public final ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { - try { - return evaluateFunc(args, srcCellRow, srcCellCol); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - - protected abstract ValueEval evaluateFunc(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException; - - /* ---------------------------------------------------------------------- */ - - private static abstract class SingleArgTextFunc extends Fixed1ArgFunction { - - protected SingleArgTextFunc() { - // no fields to initialise - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - String arg; - try { - arg = evaluateStringArg(arg0, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return evaluate(arg); - } - protected abstract ValueEval evaluate(String arg); - } - - public static final Function LEN = new SingleArgTextFunc() { - protected ValueEval evaluate(String arg) { - return new NumberEval(arg.length()); - } - }; - public static final Function LOWER = new SingleArgTextFunc() { - protected ValueEval evaluate(String arg) { - return new StringEval(arg.toLowerCase()); - } - }; - public static final Function UPPER = new SingleArgTextFunc() { - protected ValueEval evaluate(String arg) { - return new StringEval(arg.toUpperCase()); - } - }; - /** - * An implementation of the TRIM function: - * Removes leading and trailing spaces from value if evaluated operand - * value is string. - * Author: Manda Wilson < wilson at c bio dot msk cc dot org > - */ - public static final Function TRIM = new SingleArgTextFunc() { - protected ValueEval evaluate(String arg) { - return new StringEval(arg.trim()); - } - }; - - /** - * An implementation of the MID function<br/> - * MID returns a specific number of - * characters from a text string, starting at the specified position.<p/> - * - * <b>Syntax<b>:<br/> <b>MID</b>(<b>text</b>, <b>start_num</b>, - * <b>num_chars</b>)<br/> - * - * Author: Manda Wilson < wilson at c bio dot msk cc dot org > - */ - public static final Function MID = new Fixed3ArgFunction() { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, - ValueEval arg1, ValueEval arg2) { - String text; - int startCharNum; - int numChars; - try { - text = evaluateStringArg(arg0, srcRowIndex, srcColumnIndex); - startCharNum = evaluateIntArg(arg1, srcRowIndex, srcColumnIndex); - numChars = evaluateIntArg(arg2, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - int startIx = startCharNum - 1; // convert to zero-based - - // Note - for start_num arg, blank/zero causes error(#VALUE!), - // but for num_chars causes empty string to be returned. - if (startIx < 0) { - return ErrorEval.VALUE_INVALID; - } - if (numChars < 0) { - return ErrorEval.VALUE_INVALID; - } - int len = text.length(); - if (numChars < 0 || startIx > len) { - return new StringEval(""); - } - int endIx = Math.min(startIx + numChars, len); - String result = text.substring(startIx, endIx); - return new StringEval(result); - } - }; - - private static final class LeftRight extends Var1or2ArgFunction { - private static final ValueEval DEFAULT_ARG1 = new NumberEval(1.0); - private final boolean _isLeft; - protected LeftRight(boolean isLeft) { - _isLeft = isLeft; - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - return evaluate(srcRowIndex, srcColumnIndex, arg0, DEFAULT_ARG1); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, - ValueEval arg1) { - String arg; - int index; - try { - arg = evaluateStringArg(arg0, srcRowIndex, srcColumnIndex); - index = evaluateIntArg(arg1, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - if(index < 0) { - return ErrorEval.VALUE_INVALID; - } - - String result; - if (_isLeft) { - result = arg.substring(0, Math.min(arg.length(), index)); - } else { - result = arg.substring(Math.max(0, arg.length()-index)); - } - return new StringEval(result); - } - } - - public static final Function LEFT = new LeftRight(true); - public static final Function RIGHT = new LeftRight(false); - - public static final Function CONCATENATE = new Function() { - - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - StringBuilder sb = new StringBuilder(); - for (int i=0, iSize=args.length; i<iSize; i++) { - try { - sb.append(evaluateStringArg(args[i], srcRowIndex, srcColumnIndex)); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - return new StringEval(sb.toString()); - } - }; - - public static final Function EXACT = new Fixed2ArgFunction() { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, - ValueEval arg1) { - String s0; - String s1; - try { - s0 = evaluateStringArg(arg0, srcRowIndex, srcColumnIndex); - s1 = evaluateStringArg(arg1, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return BoolEval.valueOf(s0.equals(s1)); - } - }; - - /** - * An implementation of the TEXT function<br/> - * TEXT returns a number value formatted with the given - * number formatting string. This function is not a complete implementation of - * the Excel function. This function implements decimal formatting - * with the Java class DecimalFormat. For date formatting this function uses - * the SimpleDateFormat class.<p/> - * - * <b>Syntax<b>:<br/> <b>TEXT</b>(<b>value</b>, <b>format_text</b>)<br/> - * - */ - public static final Function TEXT = new Fixed2ArgFunction() { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - double s0; - String s1; - try { - s0 = evaluateDoubleArg(arg0, srcRowIndex, srcColumnIndex); - s1 = evaluateStringArg(arg1, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - if (s1.matches("[\\d,\\#,\\.,\\$,\\,]+")) { - NumberFormat formatter = new DecimalFormat(s1); - return new StringEval(formatter.format(s0)); - } else if (s1.indexOf("/") == s1.lastIndexOf("/") && s1.indexOf("/") >=0 && !s1.contains("-")) { - double wholePart = Math.floor(s0); - double decPart = s0 - wholePart; - if (wholePart * decPart == 0) { - return new StringEval("0"); - } - String[] parts = s1.split(" "); - String[] fractParts; - if (parts.length == 2) { - fractParts = parts[1].split("/"); - } else { - fractParts = s1.split("/"); - } - - if (fractParts.length == 2) { - double minVal = 1.0; - double currDenom = Math.pow(10 , fractParts[1].length()) - 1d; - double currNeum = 0; - for (int i = (int)(Math.pow(10, fractParts[1].length())- 1d); i > 0; i--) { - for(int i2 = (int)(Math.pow(10, fractParts[1].length())- 1d); i2 > 0; i2--){ - if (minVal >= Math.abs((double)i2/(double)i - decPart)) { - currDenom = i; - currNeum = i2; - minVal = Math.abs((double)i2/(double)i - decPart); - } - } - } - NumberFormat neumFormatter = new DecimalFormat(fractParts[0]); - NumberFormat denomFormatter = new DecimalFormat(fractParts[1]); - if (parts.length == 2) { - NumberFormat wholeFormatter = new DecimalFormat(parts[0]); - String result = wholeFormatter.format(wholePart) + " " + neumFormatter.format(currNeum) + "/" + denomFormatter.format(currDenom); - return new StringEval(result); - } else { - String result = neumFormatter.format(currNeum + (currDenom * wholePart)) + "/" + denomFormatter.format(currDenom); - return new StringEval(result); - } - } else { - return ErrorEval.VALUE_INVALID; - } - } else { - try { - DateFormat dateFormatter = new SimpleDateFormat(s1); - Calendar cal = new GregorianCalendar(1899, 11, 30, 0, 0, 0); - cal.add(Calendar.DATE, (int)Math.floor(s0)); - double dayFraction = s0 - Math.floor(s0); - cal.add(Calendar.MILLISECOND, (int) Math.round(dayFraction * 24 * 60 * 60 * 1000)); - return new StringEval(dateFormatter.format(cal.getTime())); - } catch (Exception e) { - return ErrorEval.VALUE_INVALID; - } - } - } - }; - - private static final class SearchFind extends Var2or3ArgFunction { - - private final boolean _isCaseSensitive; - - public SearchFind(boolean isCaseSensitive) { - _isCaseSensitive = isCaseSensitive; - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - try { - String needle = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex); - String haystack = TextFunction.evaluateStringArg(arg1, srcRowIndex, srcColumnIndex); - return eval(haystack, needle, 0); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - try { - String needle = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex); - String haystack = TextFunction.evaluateStringArg(arg1, srcRowIndex, srcColumnIndex); - // evaluate third arg and convert from 1-based to 0-based index - int startpos = TextFunction.evaluateIntArg(arg2, srcRowIndex, srcColumnIndex) - 1; - if (startpos < 0) { - return ErrorEval.VALUE_INVALID; - } - return eval(haystack, needle, startpos); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - private ValueEval eval(String haystack, String needle, int startIndex) { - int result; - if (_isCaseSensitive) { - result = haystack.indexOf(needle, startIndex); - } else { - result = haystack.toUpperCase().indexOf(needle.toUpperCase(), startIndex); - } - if (result == -1) { - return ErrorEval.VALUE_INVALID; - } - return new NumberEval(result + 1); - } - } - /** - * Implementation of the FIND() function.<p/> - * - * <b>Syntax</b>:<br/> - * <b>FIND</b>(<b>find_text</b>, <b>within_text</b>, start_num)<p/> - * - * FIND returns the character position of the first (case sensitive) occurrence of - * <tt>find_text</tt> inside <tt>within_text</tt>. The third parameter, - * <tt>start_num</tt>, is optional (default=1) and specifies where to start searching - * from. Character positions are 1-based.<p/> - * - * Author: Torstein Tauno Svendsen (torstei@officenet.no) - */ - public static final Function FIND = new SearchFind(true); - /** - * Implementation of the FIND() function.<p/> - * - * <b>Syntax</b>:<br/> - * <b>SEARCH</b>(<b>find_text</b>, <b>within_text</b>, start_num)<p/> - * - * SEARCH is a case-insensitive version of FIND() - */ - public static final Function SEARCH = new SearchFind(false); -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/TimeFunc.java b/src/java/org/apache/poi/hssf/record/formula/functions/TimeFunc.java deleted file mode 100644 index 44f9a2be10..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/TimeFunc.java +++ /dev/null @@ -1,87 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.MissingArgEval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implementation for the Excel function TIME - * - * @author Steven Butler (sebutler @ gmail dot com) - * - * Based on POI {@link DateFunc} - */ -public final class TimeFunc extends Fixed3ArgFunction { - - private static final int SECONDS_PER_MINUTE = 60; - private static final int SECONDS_PER_HOUR = 3600; - private static final int HOURS_PER_DAY = 24; - private static final int SECONDS_PER_DAY = HOURS_PER_DAY * SECONDS_PER_HOUR; - - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - double result; - try { - result = evaluate(evalArg(arg0, srcRowIndex, srcColumnIndex), evalArg(arg1, srcRowIndex, srcColumnIndex), evalArg(arg2, srcRowIndex, srcColumnIndex)); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - private static int evalArg(ValueEval arg, int srcRowIndex, int srcColumnIndex) throws EvaluationException { - if (arg == MissingArgEval.instance) { - return 0; - } - ValueEval ev = OperandResolver.getSingleValue(arg, srcRowIndex, srcColumnIndex); - // Excel silently truncates double values to integers - return OperandResolver.coerceValueToInt(ev); - } - /** - * Converts the supplied hours, minutes and seconds to an Excel time value. - * - * - * @param ds array of 3 doubles containing hours, minutes and seconds. - * Non-integer inputs are truncated to an integer before further calculation - * of the time value. - * @return An Excel representation of a time of day. - * If the time value represents more than a day, the days are removed from - * the result, leaving only the time of day component. - * @throws org.apache.poi.hssf.record.formula.eval.EvaluationException - * If any of the arguments are greater than 32767 or the hours - * minutes and seconds when combined form a time value less than 0, the function - * evaluates to an error. - */ - private static double evaluate(int hours, int minutes, int seconds) throws EvaluationException { - - if (hours > 32767 || minutes > 32767 || seconds > 32767) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - int totalSeconds = hours * SECONDS_PER_HOUR + minutes * SECONDS_PER_MINUTE + seconds; - - if (totalSeconds < 0) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - return (totalSeconds % SECONDS_PER_DAY) / (double)SECONDS_PER_DAY; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Today.java b/src/java/org/apache/poi/hssf/record/formula/functions/Today.java deleted file mode 100644 index 9acbdbd332..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Today.java +++ /dev/null @@ -1,41 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import java.util.Calendar; -import java.util.GregorianCalendar; - -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.ss.usermodel.DateUtil; - -/** - * Implementation of Excel TODAY() Function<br/> - * - * @author Frank Taffelt - */ -public final class Today extends Fixed0ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - - Calendar now = new GregorianCalendar(); - now.set(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DATE),0,0,0); - now.set(Calendar.MILLISECOND, 0); - return new NumberEval(DateUtil.getExcelDate(now.getTime())); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Value.java b/src/java/org/apache/poi/hssf/record/formula/functions/Value.java deleted file mode 100644 index 951f19cb40..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Value.java +++ /dev/null @@ -1,184 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implementation for Excel VALUE() function.<p/> - * - * <b>Syntax</b>:<br/> <b>VALUE</b>(<b>text</b>)<br/> - * - * Converts the text argument to a number. Leading and/or trailing whitespace is - * ignored. Currency symbols and thousands separators are stripped out. - * Scientific notation is also supported. If the supplied text does not convert - * properly the result is <b>#VALUE!</b> error. Blank string converts to zero. - * - * @author Josh Micich - */ -public final class Value extends Fixed1ArgFunction { - - /** "1,0000" is valid, "1,00" is not */ - private static final int MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR = 4; - private static final Double ZERO = new Double(0.0); - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - ValueEval veText; - try { - veText = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - String strText = OperandResolver.coerceValueToString(veText); - Double result = convertTextToNumber(strText); - if (result == null) { - return ErrorEval.VALUE_INVALID; - } - return new NumberEval(result.doubleValue()); - } - - /** - * TODO see if the same functionality is needed in {@link OperandResolver#parseDouble(String)} - * - * @return <code>null</code> if there is any problem converting the text - */ - private static Double convertTextToNumber(String strText) { - boolean foundCurrency = false; - boolean foundUnaryPlus = false; - boolean foundUnaryMinus = false; - - int len = strText.length(); - int i; - for (i = 0; i < len; i++) { - char ch = strText.charAt(i); - if (Character.isDigit(ch) || ch == '.') { - break; - } - switch (ch) { - case ' ': - // intervening spaces between '$', '-', '+' are OK - continue; - case '$': - if (foundCurrency) { - // only one currency symbols is allowed - return null; - } - foundCurrency = true; - continue; - case '+': - if (foundUnaryMinus || foundUnaryPlus) { - return null; - } - foundUnaryPlus = true; - continue; - case '-': - if (foundUnaryMinus || foundUnaryPlus) { - return null; - } - foundUnaryMinus = true; - continue; - default: - // all other characters are illegal - return null; - } - } - if (i >= len) { - // didn't find digits or '.' - if (foundCurrency || foundUnaryMinus || foundUnaryPlus) { - return null; - } - return ZERO; - } - - // remove thousands separators - - boolean foundDecimalPoint = false; - int lastThousandsSeparatorIndex = Short.MIN_VALUE; - - StringBuffer sb = new StringBuffer(len); - for (; i < len; i++) { - char ch = strText.charAt(i); - if (Character.isDigit(ch)) { - sb.append(ch); - continue; - } - switch (ch) { - case ' ': - String remainingText = strText.substring(i); - if (remainingText.trim().length() > 0) { - // intervening spaces not allowed once the digits start - return null; - } - break; - case '.': - if (foundDecimalPoint) { - return null; - } - if (i - lastThousandsSeparatorIndex < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) { - return null; - } - foundDecimalPoint = true; - sb.append('.'); - continue; - case ',': - if (foundDecimalPoint) { - // thousands separators not allowed after '.' or 'E' - return null; - } - int distanceBetweenThousandsSeparators = i - lastThousandsSeparatorIndex; - // as long as there are 3 or more digits between - if (distanceBetweenThousandsSeparators < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) { - return null; - } - lastThousandsSeparatorIndex = i; - // don't append ',' - continue; - - case 'E': - case 'e': - if (i - lastThousandsSeparatorIndex < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) { - return null; - } - // append rest of strText and skip to end of loop - sb.append(strText.substring(i)); - i = len; - break; - default: - // all other characters are illegal - return null; - } - } - if (!foundDecimalPoint) { - if (i - lastThousandsSeparatorIndex < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) { - return null; - } - } - double d; - try { - d = Double.parseDouble(sb.toString()); - } catch (NumberFormatException e) { - // still a problem parsing the number - probably out of range - return null; - } - return new Double(foundUnaryMinus ? -d : d); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Var1or2ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Var1or2ArgFunction.java deleted file mode 100644 index d7310c41bf..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Var1or2ArgFunction.java +++ /dev/null @@ -1,40 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Convenience base class for any function which must take two or three - * arguments - * - * @author Josh Micich - */ -abstract class Var1or2ArgFunction implements Function1Arg, Function2Arg { - - public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - switch (args.length) { - case 1: - return evaluate(srcRowIndex, srcColumnIndex, args[0]); - case 2: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1]); - } - return ErrorEval.VALUE_INVALID; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Var2or3ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Var2or3ArgFunction.java deleted file mode 100644 index 4928425f99..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Var2or3ArgFunction.java +++ /dev/null @@ -1,40 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Convenience base class for any function which must take two or three - * arguments - * - * @author Josh Micich - */ -abstract class Var2or3ArgFunction implements Function2Arg, Function3Arg { - - public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - switch (args.length) { - case 2: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1]); - case 3: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2]); - } - return ErrorEval.VALUE_INVALID; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Var3or4ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Var3or4ArgFunction.java deleted file mode 100644 index c3cf9410a4..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Var3or4ArgFunction.java +++ /dev/null @@ -1,40 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Convenience base class for any function which must take three or four - * arguments - * - * @author Josh Micich - */ -abstract class Var3or4ArgFunction implements Function3Arg, Function4Arg { - - public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - switch (args.length) { - case 3: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2]); - case 4: - return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], args[3]); - } - return ErrorEval.VALUE_INVALID; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Vlookup.java b/src/java/org/apache/poi/hssf/record/formula/functions/Vlookup.java deleted file mode 100644 index 1e240eb886..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Vlookup.java +++ /dev/null @@ -1,81 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.OperandResolver; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; -import org.apache.poi.ss.formula.TwoDEval; -/** - * Implementation of the VLOOKUP() function.<p/> - * - * VLOOKUP finds a row in a lookup table by the first column value and returns the value from another column.<br/> - * - * <b>Syntax</b>:<br/> - * <b>VLOOKUP</b>(<b>lookup_value</b>, <b>table_array</b>, <b>col_index_num</b>, range_lookup)<p/> - * - * <b>lookup_value</b> The value to be found in the first column of the table array.<br/> - * <b>table_array</b> An area reference for the lookup data. <br/> - * <b>col_index_num</b> a 1 based index specifying which column value of the lookup data will be returned.<br/> - * <b>range_lookup</b> If TRUE (default), VLOOKUP finds the largest value less than or equal to - * the lookup_value. If FALSE, only exact matches will be considered<br/> - * - * @author Josh Micich - */ -public final class Vlookup extends Var3or4ArgFunction { - private static final ValueEval DEFAULT_ARG3 = BoolEval.TRUE; - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2) { - return evaluate(srcRowIndex, srcColumnIndex, arg0, arg1, arg2, DEFAULT_ARG3); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, - ValueEval arg2, ValueEval arg3) { - try { - // Evaluation order: - // arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 col_index, fetch result - ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - TwoDEval tableArray = LookupUtils.resolveTableArrayArg(arg1); - boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex); - int rowIndex = LookupUtils.lookupIndexOfValue(lookupValue, LookupUtils.createColumnVector(tableArray, 0), isRangeLookup); - int colIndex = LookupUtils.resolveRowOrColIndexArg(arg2, srcRowIndex, srcColumnIndex); - ValueVector resultCol = createResultColumnVector(tableArray, colIndex); - return resultCol.getItem(rowIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - - - /** - * Returns one column from an <tt>AreaEval</tt> - * - * @param colIndex assumed to be non-negative - * - * @throws EvaluationException (#REF!) if colIndex is too high - */ - private ValueVector createResultColumnVector(TwoDEval tableArray, int colIndex) throws EvaluationException { - if(colIndex >= tableArray.getWidth()) { - throw EvaluationException.invalidRef(); - } - return LookupUtils.createColumnVector(tableArray, colIndex); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java deleted file mode 100644 index 2c7a4d3939..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java +++ /dev/null @@ -1,177 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; -import org.apache.poi.ss.formula.TwoDEval; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - */ -public abstract class XYNumericFunction extends Fixed2ArgFunction { - - private static abstract class ValueArray implements ValueVector { - private final int _size; - protected ValueArray(int size) { - _size = size; - } - public ValueEval getItem(int index) { - if (index < 0 || index > _size) { - throw new IllegalArgumentException("Specified index " + index - + " is outside range (0.." + (_size - 1) + ")"); - } - return getItemInternal(index); - } - protected abstract ValueEval getItemInternal(int index); - public final int getSize() { - return _size; - } - } - - private static final class SingleCellValueArray extends ValueArray { - private final ValueEval _value; - public SingleCellValueArray(ValueEval value) { - super(1); - _value = value; - } - protected ValueEval getItemInternal(int index) { - return _value; - } - } - - private static final class RefValueArray extends ValueArray { - private final RefEval _ref; - public RefValueArray(RefEval ref) { - super(1); - _ref = ref; - } - protected ValueEval getItemInternal(int index) { - return _ref.getInnerValueEval(); - } - } - - private static final class AreaValueArray extends ValueArray { - private final TwoDEval _ae; - private final int _width; - - public AreaValueArray(TwoDEval ae) { - super(ae.getWidth() * ae.getHeight()); - _ae = ae; - _width = ae.getWidth(); - } - protected ValueEval getItemInternal(int index) { - int rowIx = index / _width; - int colIx = index % _width; - return _ae.getValue(rowIx, colIx); - } - } - - protected static interface Accumulator { - double accumulate(double x, double y); - } - - /** - * Constructs a new instance of the Accumulator used to calculated this function - */ - protected abstract Accumulator createAccumulator(); - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - - double result; - try { - ValueVector vvX = createValueVector(arg0); - ValueVector vvY = createValueVector(arg1); - int size = vvX.getSize(); - if (size == 0 || vvY.getSize() != size) { - return ErrorEval.NA; - } - result = evaluateInternal(vvX, vvY, size); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - if (Double.isNaN(result) || Double.isInfinite(result)) { - return ErrorEval.NUM_ERROR; - } - return new NumberEval(result); - } - - private double evaluateInternal(ValueVector x, ValueVector y, int size) - throws EvaluationException { - Accumulator acc = createAccumulator(); - - // error handling is as if the x is fully evaluated before y - ErrorEval firstXerr = null; - ErrorEval firstYerr = null; - boolean accumlatedSome = false; - double result = 0.0; - - for (int i = 0; i < size; i++) { - ValueEval vx = x.getItem(i); - ValueEval vy = y.getItem(i); - if (vx instanceof ErrorEval) { - if (firstXerr == null) { - firstXerr = (ErrorEval) vx; - continue; - } - } - if (vy instanceof ErrorEval) { - if (firstYerr == null) { - firstYerr = (ErrorEval) vy; - continue; - } - } - // only count pairs if both elements are numbers - if (vx instanceof NumberEval && vy instanceof NumberEval) { - accumlatedSome = true; - NumberEval nx = (NumberEval) vx; - NumberEval ny = (NumberEval) vy; - result += acc.accumulate(nx.getNumberValue(), ny.getNumberValue()); - } else { - // all other combinations of value types are silently ignored - } - } - if (firstXerr != null) { - throw new EvaluationException(firstXerr); - } - if (firstYerr != null) { - throw new EvaluationException(firstYerr); - } - if (!accumlatedSome) { - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - return result; - } - - private static ValueVector createValueVector(ValueEval arg) throws EvaluationException { - if (arg instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) arg); - } - if (arg instanceof TwoDEval) { - return new AreaValueArray((TwoDEval) arg); - } - if (arg instanceof RefEval) { - return new RefValueArray((RefEval) arg); - } - return new SingleCellValueArray(arg); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/udf/AggregatingUDFFinder.java b/src/java/org/apache/poi/hssf/record/formula/udf/AggregatingUDFFinder.java deleted file mode 100644 index 2dedf7b9d3..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/udf/AggregatingUDFFinder.java +++ /dev/null @@ -1,52 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.udf; - -import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; - -/** - * Collects add-in libraries and VB macro functions together into one UDF finder - * - * @author PUdalau - */ -public final class AggregatingUDFFinder implements UDFFinder { - - private final UDFFinder[] _usedToolPacks; - - public AggregatingUDFFinder(UDFFinder ... usedToolPacks) { - _usedToolPacks = usedToolPacks.clone(); - } - - /** - * Returns executor by specified name. Returns <code>null</code> if - * function isn't contained by any registered tool pack. - * - * @param name Name of function. - * @return Function executor. <code>null</code> if not found - */ - public FreeRefFunction findFunction(String name) { - FreeRefFunction evaluatorForFunction; - for (UDFFinder pack : _usedToolPacks) { - evaluatorForFunction = pack.findFunction(name); - if (evaluatorForFunction != null) { - return evaluatorForFunction; - } - } - return null; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/udf/DefaultUDFFinder.java b/src/java/org/apache/poi/hssf/record/formula/udf/DefaultUDFFinder.java deleted file mode 100644 index f87027aeb7..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/udf/DefaultUDFFinder.java +++ /dev/null @@ -1,49 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.udf; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; - -/** - * Default UDF finder - for adding your own user defined functions. - * - * @author PUdalau - */ -public final class DefaultUDFFinder implements UDFFinder { - private final Map<String, FreeRefFunction> _functionsByName; - - public DefaultUDFFinder(String[] functionNames, FreeRefFunction[] functionImpls) { - int nFuncs = functionNames.length; - if (functionImpls.length != nFuncs) { - throw new IllegalArgumentException( - "Mismatch in number of function names and implementations"); - } - HashMap<String, FreeRefFunction> m = new HashMap<String, FreeRefFunction>(nFuncs * 3 / 2); - for (int i = 0; i < functionImpls.length; i++) { - m.put(functionNames[i], functionImpls[i]); - } - _functionsByName = m; - } - - public FreeRefFunction findFunction(String name) { - return _functionsByName.get(name); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/udf/UDFFinder.java b/src/java/org/apache/poi/hssf/record/formula/udf/UDFFinder.java deleted file mode 100644 index ba2882664f..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/udf/UDFFinder.java +++ /dev/null @@ -1,38 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.formula.udf; - -import org.apache.poi.hssf.record.formula.atp.AnalysisToolPak; -import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; - -/** - * Common interface for "Add-in" libraries and user defined function libraries. - * - * @author PUdalau - */ -public interface UDFFinder { - public static final UDFFinder DEFAULT = new AggregatingUDFFinder(AnalysisToolPak.instance); - - /** - * Returns executor by specified name. Returns <code>null</code> if the function name is unknown. - * - * @param name Name of function. - * @return Function executor. - */ - FreeRefFunction findFunction(String name); -} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 2862a0d032..63d42a639e 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -29,7 +29,6 @@ import org.apache.poi.hssf.record.BoolErrRecord; import org.apache.poi.hssf.record.CellValueRecordInterface; import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.record.DrawingRecord; -import org.apache.poi.hssf.record.EOFRecord; import org.apache.poi.hssf.record.ExtendedFormatRecord; import org.apache.poi.hssf.record.FormulaRecord; import org.apache.poi.hssf.record.HyperlinkRecord; @@ -45,7 +44,7 @@ import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate; import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.record.formula.ExpPtg; import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellReference; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java index 4242602c66..0250619c3d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java @@ -19,12 +19,12 @@ package org.apache.poi.hssf.usermodel; import java.util.Iterator; -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.StringEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.udf.UDFFinder; +import org.apache.poi.ss.formula.eval.BoolEval; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.ss.formula.udf.UDFFinder; import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment; import org.apache.poi.ss.formula.IStabilityClassifier; import org.apache.poi.ss.formula.WorkbookEvaluator; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index 96166d6a4c..9b39c665a1 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -17,14 +17,7 @@ package org.apache.poi.hssf.usermodel; -import java.awt.font.FontRenderContext; -import java.awt.font.TextAttribute; -import java.awt.font.TextLayout; -import java.awt.geom.AffineTransform; import java.io.PrintWriter; -import java.text.AttributedString; -import java.text.DecimalFormat; -import java.text.NumberFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -38,7 +31,7 @@ import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.aggregates.DataValidityTable; import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate; import org.apache.poi.hssf.record.aggregates.WorksheetProtectionBlock; -import org.apache.poi.hssf.record.formula.FormulaShifter; +import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.Area3DPtg; import org.apache.poi.hssf.util.PaneInformation; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 7cedfecacd..b999512b22 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -61,7 +61,7 @@ import org.apache.poi.hssf.record.formula.NameXPtg; import org.apache.poi.hssf.record.formula.OperandPtg; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.Ref3DPtg; -import org.apache.poi.hssf.record.formula.SheetNameFormatter; +import org.apache.poi.ss.formula.SheetNameFormatter; import org.apache.poi.hssf.record.formula.UnionPtg; import org.apache.poi.hssf.util.CellReference; import org.apache.poi.poifs.filesystem.DirectoryNode; |