mirror of https://github.com/apache/poi.git
Converted AreEval and RefEval to be lazy (part of fix for bug 45358)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@690835 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
020bde0d66
commit
30819e2f9b
|
@ -14,11 +14,11 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
/**
|
||||
* Common interface for AreaPtg and Area3DPtg, and their
|
||||
* child classes.
|
||||
* Common interface for AreaPtg and Area3DPtg, and their child classes.
|
||||
*/
|
||||
public interface AreaI {
|
||||
/**
|
||||
|
@ -40,4 +40,37 @@ public interface AreaI {
|
|||
* @return lastcolumn in the area
|
||||
*/
|
||||
public int getLastColumn();
|
||||
|
||||
class OffsetArea implements AreaI {
|
||||
|
||||
private final int _firstColumn;
|
||||
private final int _firstRow;
|
||||
private final int _lastColumn;
|
||||
private final int _lastRow;
|
||||
|
||||
public OffsetArea(int baseRow, int baseColumn, int relFirstRowIx, int relLastRowIx,
|
||||
int relFirstColIx, int relLastColIx) {
|
||||
_firstRow = baseRow + relFirstRowIx;
|
||||
_lastRow = baseRow + relLastRowIx;
|
||||
_firstColumn = baseColumn + relFirstColIx;
|
||||
_lastColumn = baseColumn + relLastColIx;
|
||||
}
|
||||
|
||||
public int getFirstColumn() {
|
||||
return _firstColumn;
|
||||
}
|
||||
|
||||
public int getFirstRow() {
|
||||
return _firstRow;
|
||||
}
|
||||
|
||||
public int getLastColumn() {
|
||||
return _lastColumn;
|
||||
}
|
||||
|
||||
public int getLastRow() {
|
||||
return _lastRow;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -131,14 +131,6 @@ public abstract class RefPtgBase extends OperandPtg {
|
|||
field_2_col=colRelative.setBoolean(field_2_col,rel);
|
||||
}
|
||||
|
||||
public final void setColumnRawX(int col) { // TODO
|
||||
field_2_col = col;
|
||||
}
|
||||
|
||||
public int getColumnRawX() { // TODO
|
||||
return field_2_col;
|
||||
}
|
||||
|
||||
public final void setColumn(int col) {
|
||||
if(col < 0 || col >= 0x100) {
|
||||
throw new IllegalArgumentException("Specified colIx (" + col + ") is out of range");
|
||||
|
|
|
@ -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.eval;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public final class Area2DEval extends AreaEvalBase {
|
||||
|
||||
public Area2DEval(Ptg ptg, ValueEval[] values) {
|
||||
super((AreaPtg) ptg, values);
|
||||
}
|
||||
}
|
|
@ -1,39 +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.Area3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public final class Area3DEval extends AreaEvalBase {
|
||||
|
||||
private final int _externSheetIndex;
|
||||
|
||||
public Area3DEval(Ptg ptg, ValueEval[] values) {
|
||||
super((Area3DPtg) ptg, values);
|
||||
_externSheetIndex = ((Area3DPtg) ptg).getExternSheetIndex();
|
||||
}
|
||||
|
||||
public int getExternSheetIndex() {
|
||||
return _externSheetIndex;
|
||||
}
|
||||
}
|
|
@ -97,4 +97,10 @@ public interface AreaEval extends ValueEval {
|
|||
* 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);
|
||||
}
|
||||
|
|
|
@ -22,20 +22,16 @@ import org.apache.poi.hssf.record.formula.AreaI;
|
|||
/**
|
||||
* @author Josh Micich
|
||||
*/
|
||||
abstract class AreaEvalBase implements AreaEval {
|
||||
public abstract class AreaEvalBase implements AreaEval {
|
||||
|
||||
private final int _firstColumn;
|
||||
private final int _firstRow;
|
||||
private final int _lastColumn;
|
||||
private final int _lastRow;
|
||||
private final ValueEval[] _values;
|
||||
private final int _nColumns;
|
||||
private final int _nRows;
|
||||
|
||||
protected AreaEvalBase(AreaI ptg, ValueEval[] values) {
|
||||
if (values == null) {
|
||||
throw new IllegalArgumentException("values must not be null");
|
||||
}
|
||||
protected AreaEvalBase(AreaI ptg) {
|
||||
_firstRow = ptg.getFirstRow();
|
||||
_firstColumn = ptg.getFirstColumn();
|
||||
_lastRow = ptg.getLastRow();
|
||||
|
@ -43,22 +39,6 @@ abstract class AreaEvalBase implements AreaEval {
|
|||
|
||||
_nColumns = _lastColumn - _firstColumn + 1;
|
||||
_nRows = _lastRow - _firstRow + 1;
|
||||
|
||||
int expectedItemCount = _nRows * _nColumns;
|
||||
if ((values.length != expectedItemCount)) {
|
||||
// Note - this math may need alteration when POI starts to support full column or full row refs
|
||||
throw new IllegalArgumentException("Array size should be (" + expectedItemCount
|
||||
+ ") but was (" + values.length + ")");
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int i = values.length - 1; i >= 0; i--) {
|
||||
if (values[i] == null) {
|
||||
throw new IllegalArgumentException("value array elements must not be null");
|
||||
}
|
||||
}
|
||||
_values = values;
|
||||
}
|
||||
|
||||
public final int getFirstColumn() {
|
||||
|
@ -116,14 +96,7 @@ abstract class AreaEvalBase implements AreaEval {
|
|||
return _lastRow-_firstRow+1;
|
||||
}
|
||||
|
||||
public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
|
||||
int index = relativeRowIndex * _nColumns + relativeColumnIndex;
|
||||
ValueEval result = _values[index];
|
||||
if (result == null) {
|
||||
return BlankEval.INSTANCE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public abstract ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex);
|
||||
|
||||
public int getWidth() {
|
||||
return _lastColumn-_firstColumn+1;
|
||||
|
|
|
@ -50,7 +50,6 @@ public abstract class FunctionEval implements OperationEval {
|
|||
|
||||
static {
|
||||
Map m = new HashMap();
|
||||
addMapping(m, ID.OFFSET, new Offset());
|
||||
addMapping(m, ID.INDIRECT, new Indirect());
|
||||
addMapping(m, ID.EXTERNAL_FUNC, new ExternalFunction());
|
||||
freeRefFunctionsByIdMap = m;
|
||||
|
@ -155,7 +154,7 @@ public abstract class FunctionEval implements OperationEval {
|
|||
retval[75] = new Areas(); // AREAS
|
||||
retval[76] = new Rows(); // ROWS
|
||||
retval[77] = new Columns(); // COLUMNS
|
||||
retval[ID.OFFSET] = null; // Offset.evaluate has a different signature
|
||||
retval[ID.OFFSET] = new Offset(); // OFFSET
|
||||
retval[79] = new Absref(); // ABSREF
|
||||
retval[80] = new Relref(); // RELREF
|
||||
retval[81] = new Argument(); // ARGUMENT
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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;
|
||||
import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public final class LazyAreaEval extends AreaEvalBase {
|
||||
|
||||
private final HSSFSheet _sheet;
|
||||
private HSSFWorkbook _workbook;
|
||||
|
||||
public LazyAreaEval(AreaI ptg, HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
super(ptg);
|
||||
_sheet = sheet;
|
||||
_workbook = workbook;
|
||||
}
|
||||
|
||||
public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
|
||||
|
||||
int rowIx = (relativeRowIndex + getFirstRow() ) & 0xFFFF;
|
||||
int colIx = (relativeColumnIndex + getFirstColumn() ) & 0x00FF;
|
||||
|
||||
HSSFRow row = _sheet.getRow(rowIx);
|
||||
if (row == null) {
|
||||
return BlankEval.INSTANCE;
|
||||
}
|
||||
HSSFCell cell = row.getCell(colIx);
|
||||
if (cell == null) {
|
||||
return BlankEval.INSTANCE;
|
||||
}
|
||||
return HSSFFormulaEvaluator.getEvalForCell(cell, _sheet, _workbook);
|
||||
}
|
||||
|
||||
public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
|
||||
AreaI area = new OffsetArea(getFirstRow(), getFirstColumn(),
|
||||
relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
|
||||
|
||||
return new LazyAreaEval(area, _sheet, _workbook);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package org.apache.poi.hssf.record.formula.eval;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaI;
|
||||
import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
|
||||
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
public final class LazyRefEval extends RefEvalBase {
|
||||
|
||||
private final HSSFSheet _sheet;
|
||||
private final HSSFWorkbook _workbook;
|
||||
|
||||
|
||||
public LazyRefEval(RefPtg ptg, HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
super(ptg.getRow(), ptg.getColumn());
|
||||
_sheet = sheet;
|
||||
_workbook = workbook;
|
||||
}
|
||||
public LazyRefEval(Ref3DPtg ptg, HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
super(ptg.getRow(), ptg.getColumn());
|
||||
_sheet = sheet;
|
||||
_workbook = workbook;
|
||||
}
|
||||
|
||||
public ValueEval getInnerValueEval() {
|
||||
int rowIx = getRow();
|
||||
int colIx = getColumn();
|
||||
|
||||
HSSFRow row = _sheet.getRow(rowIx);
|
||||
if (row == null) {
|
||||
return BlankEval.INSTANCE;
|
||||
}
|
||||
HSSFCell cell = row.getCell(colIx);
|
||||
if (cell == null) {
|
||||
return BlankEval.INSTANCE;
|
||||
}
|
||||
return HSSFFormulaEvaluator.getEvalForCell(cell, _sheet, _workbook);
|
||||
}
|
||||
|
||||
public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
|
||||
|
||||
AreaI area = new OffsetArea(getRow(), getColumn(),
|
||||
relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
|
||||
|
||||
return new LazyAreaEval(area, _sheet, _workbook);
|
||||
}
|
||||
}
|
|
@ -47,4 +47,7 @@ public final class Ref2DEval implements RefEval {
|
|||
public int getColumn() {
|
||||
return delegate.getColumn();
|
||||
}
|
||||
public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
|
||||
throw new RuntimeException("should not be called"); // TODO - delete this whole class
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,53 +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.Ref3DPtg;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh
|
||||
*
|
||||
*/
|
||||
public final class Ref3DEval implements RefEval {
|
||||
|
||||
private final ValueEval value;
|
||||
private final Ref3DPtg delegate;
|
||||
|
||||
public Ref3DEval(Ref3DPtg ptg, ValueEval ve) {
|
||||
if(ve == null) {
|
||||
throw new IllegalArgumentException("ve must not be null");
|
||||
}
|
||||
if(ptg == null) {
|
||||
throw new IllegalArgumentException("ptg must not be null");
|
||||
}
|
||||
value = ve;
|
||||
delegate = ptg;
|
||||
}
|
||||
public ValueEval getInnerValueEval() {
|
||||
return value;
|
||||
}
|
||||
public int getRow() {
|
||||
return delegate.getRow();
|
||||
}
|
||||
public int getColumn() {
|
||||
return delegate.getColumn();
|
||||
}
|
||||
public int getExternSheetIndex() {
|
||||
return delegate.getExternSheetIndex();
|
||||
}
|
||||
}
|
|
@ -1,19 +1,19 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
/* ====================================================================
|
||||
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;
|
||||
|
||||
|
@ -30,22 +30,22 @@ package org.apache.poi.hssf.record.formula.eval;
|
|||
public interface RefEval extends ValueEval {
|
||||
|
||||
/**
|
||||
* The (possibly evaluated) ValueEval contained
|
||||
* in this RefEval. eg. if cell A1 contains "test"
|
||||
* then in a formula referring to cell A1
|
||||
* the RefEval representing
|
||||
* A1 will return as the getInnerValueEval() the
|
||||
* object of concrete type StringEval
|
||||
* @return the evaluated value of the cell referred to by this RefEval.
|
||||
*/
|
||||
public ValueEval getInnerValueEval();
|
||||
ValueEval getInnerValueEval();
|
||||
|
||||
/**
|
||||
* returns the zero based column index.
|
||||
*/
|
||||
public int getColumn();
|
||||
int getColumn();
|
||||
|
||||
/**
|
||||
* returns the zero based row index.
|
||||
*/
|
||||
public int getRow();
|
||||
int getRow();
|
||||
|
||||
/**
|
||||
* Creates an {@link AreaEval} offset by a relative amount from this RefEval
|
||||
*/
|
||||
AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package org.apache.poi.hssf.record.formula.eval;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -67,6 +67,9 @@ final class CountUtils {
|
|||
return 0;
|
||||
}
|
||||
public static int countArg(Eval eval, I_MatchPredicate criteriaPredicate) {
|
||||
if (eval == null) {
|
||||
throw new IllegalArgumentException("eval must not be null");
|
||||
}
|
||||
if (eval instanceof AreaEval) {
|
||||
return CountUtils.countMatchingCellsInArea((AreaEval) eval, criteriaPredicate);
|
||||
}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
* 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 Nov 25, 2006
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
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.Eval;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
|
@ -37,8 +37,13 @@ public final class If implements Function {
|
|||
case 3:
|
||||
evalWhenFalse = args[2];
|
||||
case 2:
|
||||
BoolEval beval = (BoolEval) args[0]; // TODO - class cast exception
|
||||
if (beval.getBooleanValue()) {
|
||||
boolean b;
|
||||
try {
|
||||
b = evaluateFirstArg(args[0], srcCellRow, srcCellCol);
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
if (b) {
|
||||
return args[1];
|
||||
}
|
||||
return evalWhenFalse;
|
||||
|
@ -46,4 +51,13 @@ public final class If implements Function {
|
|||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean evaluateFirstArg(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
|
||||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
|
||||
Boolean b = OperandResolver.coerceValueToBoolean(ve, false);
|
||||
if (b == null) {
|
||||
return false;
|
||||
}
|
||||
return b.booleanValue();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.Area2DEval;
|
||||
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;
|
||||
|
@ -366,13 +364,7 @@ final class LookupUtils {
|
|||
// 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.
|
||||
// This code only requires the value array item.
|
||||
// anything would be ok for rowIx and colIx, but may as well get it right.
|
||||
int rowIx = refEval.getRow();
|
||||
int colIx = refEval.getColumn();
|
||||
AreaPtg ap = new AreaPtg(rowIx, rowIx, colIx, colIx, false, false, false, false);
|
||||
ValueEval value = refEval.getInnerValueEval();
|
||||
return new Area2DEval(ap, new ValueEval[] { value, });
|
||||
return refEval.offset(0, 0, 0, 0);
|
||||
}
|
||||
throw EvaluationException.invalidValue();
|
||||
}
|
||||
|
|
|
@ -455,85 +455,6 @@ public final class MathX {
|
|||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the sum of difference of squares of corresponding double
|
||||
* value in each subarray: ie. sigma (xarr[i]^2-yarr[i]^2)
|
||||
* <br/>
|
||||
* It is the responsibility of the caller
|
||||
* to ensure that the two subarrays are of equal length. If the
|
||||
* subarrays are not of equal length, the return value can be
|
||||
* unpredictable.
|
||||
* @param xarr
|
||||
* @param yarr
|
||||
*/
|
||||
public static double sumx2my2(double[] xarr, double[] yarr) {
|
||||
double d = 0;
|
||||
|
||||
try {
|
||||
for (int i=0, iSize=xarr.length; i<iSize; i++) {
|
||||
d += (xarr[i] + yarr[i]) * (xarr[i] - yarr[i]);
|
||||
}
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException ae) {
|
||||
d = Double.NaN;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the sum of sum of squares of corresponding double
|
||||
* value in each subarray: ie. sigma (xarr[i]^2 + yarr[i]^2)
|
||||
* <br/>
|
||||
* It is the responsibility of the caller
|
||||
* to ensure that the two subarrays are of equal length. If the
|
||||
* subarrays are not of equal length, the return value can be
|
||||
* unpredictable.
|
||||
* @param xarr
|
||||
* @param yarr
|
||||
*/
|
||||
public static double sumx2py2(double[] xarr, double[] yarr) {
|
||||
double d = 0;
|
||||
|
||||
try {
|
||||
for (int i=0, iSize=xarr.length; i<iSize; i++) {
|
||||
d += (xarr[i] * xarr[i]) + (yarr[i] * yarr[i]);
|
||||
}
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException ae) {
|
||||
d = Double.NaN;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns the sum of squares of difference of corresponding double
|
||||
* value in each subarray: ie. sigma ( (xarr[i]-yarr[i])^2 )
|
||||
* <br/>
|
||||
* It is the responsibility of the caller
|
||||
* to ensure that the two subarrays are of equal length. If the
|
||||
* subarrays are not of equal length, the return value can be
|
||||
* unpredictable.
|
||||
* @param xarr
|
||||
* @param yarr
|
||||
*/
|
||||
public static double sumxmy2(double[] xarr, double[] yarr) {
|
||||
double d = 0;
|
||||
|
||||
try {
|
||||
for (int i=0, iSize=xarr.length; i<iSize; i++) {
|
||||
double t = (xarr[i] - yarr[i]);
|
||||
d += t * t;
|
||||
}
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException ae) {
|
||||
d = Double.NaN;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the total number of combinations possible when
|
||||
|
|
|
@ -1,26 +1,22 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
/* ====================================================================
|
||||
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.Area3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.Area3DEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
|
@ -28,13 +24,9 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
|
|||
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
|
||||
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.Ref3DEval;
|
||||
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.usermodel.HSSFFormulaEvaluator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
/**
|
||||
* Implementation for Excel function OFFSET()<p/>
|
||||
*
|
||||
|
@ -51,7 +43,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class Offset implements FreeRefFunction {
|
||||
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;
|
||||
|
@ -125,37 +117,29 @@ public final class Offset implements FreeRefFunction {
|
|||
* Encapsulates either an area or cell reference which may be 2d or 3d.
|
||||
*/
|
||||
private static final class BaseRef {
|
||||
private static final int INVALID_SHEET_INDEX = -1;
|
||||
private final int _firstRowIndex;
|
||||
private final int _firstColumnIndex;
|
||||
private final int _width;
|
||||
private final int _height;
|
||||
private final int _externalSheetIndex;
|
||||
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;
|
||||
if (re instanceof Ref3DEval) {
|
||||
Ref3DEval r3e = (Ref3DEval) re;
|
||||
_externalSheetIndex = r3e.getExternSheetIndex();
|
||||
} else {
|
||||
_externalSheetIndex = INVALID_SHEET_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (ae instanceof Area3DEval) {
|
||||
Area3DEval a3e = (Area3DEval) ae;
|
||||
_externalSheetIndex = a3e.getExternSheetIndex();
|
||||
} else {
|
||||
_externalSheetIndex = INVALID_SHEET_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
|
@ -170,19 +154,17 @@ public final class Offset implements FreeRefFunction {
|
|||
public int getFirstColumnIndex() {
|
||||
return _firstColumnIndex;
|
||||
}
|
||||
public boolean isIs3d() {
|
||||
return _externalSheetIndex > 0;
|
||||
}
|
||||
|
||||
public short getExternalSheetIndex() {
|
||||
if(_externalSheetIndex < 0) {
|
||||
throw new IllegalStateException("external sheet index only available for 3d refs");
|
||||
public AreaEval offset(int relFirstRowIx, int relLastRowIx,
|
||||
int relFirstColIx, int relLastColIx) {
|
||||
if (_refEval == null) {
|
||||
return _areaEval.offset(relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
|
||||
}
|
||||
return (short) _externalSheetIndex;
|
||||
return _refEval.offset(relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
|
||||
}
|
||||
}
|
||||
|
||||
public ValueEval evaluate(Eval[] args, int srcCellRow, short srcCellCol, HSSFWorkbook workbook, HSSFSheet sheet) {
|
||||
public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
|
||||
|
||||
if(args.length < 3 || args.length > 5) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
|
@ -206,37 +188,25 @@ public final class Offset implements FreeRefFunction {
|
|||
}
|
||||
LinearOffsetRange rowOffsetRange = new LinearOffsetRange(rowOffset, height);
|
||||
LinearOffsetRange colOffsetRange = new LinearOffsetRange(columnOffset, width);
|
||||
return createOffset(baseRef, rowOffsetRange, colOffsetRange, workbook, sheet);
|
||||
return createOffset(baseRef, rowOffsetRange, colOffsetRange);
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
}
|
||||
|
||||
private static AreaEval createOffset(BaseRef baseRef,
|
||||
LinearOffsetRange rowOffsetRange, LinearOffsetRange colOffsetRange,
|
||||
HSSFWorkbook workbook, HSSFSheet sheet) throws EvaluationException {
|
||||
LinearOffsetRange orRow, LinearOffsetRange orCol) throws EvaluationException {
|
||||
|
||||
LinearOffsetRange rows = rowOffsetRange.normaliseAndTranslate(baseRef.getFirstRowIndex());
|
||||
LinearOffsetRange cols = colOffsetRange.normaliseAndTranslate(baseRef.getFirstColumnIndex());
|
||||
LinearOffsetRange absRows = orRow.normaliseAndTranslate(baseRef.getFirstRowIndex());
|
||||
LinearOffsetRange absCols = orCol.normaliseAndTranslate(baseRef.getFirstColumnIndex());
|
||||
|
||||
if(rows.isOutOfBounds(0, LAST_VALID_ROW_INDEX)) {
|
||||
if(absRows.isOutOfBounds(0, LAST_VALID_ROW_INDEX)) {
|
||||
throw new EvaluationException(ErrorEval.REF_INVALID);
|
||||
}
|
||||
if(cols.isOutOfBounds(0, LAST_VALID_COLUMN_INDEX)) {
|
||||
if(absCols.isOutOfBounds(0, LAST_VALID_COLUMN_INDEX)) {
|
||||
throw new EvaluationException(ErrorEval.REF_INVALID);
|
||||
}
|
||||
if(baseRef.isIs3d()) {
|
||||
Area3DPtg a3dp = new Area3DPtg(rows.getFirstIndex(), rows.getLastIndex(),
|
||||
cols.getFirstIndex(), cols.getLastIndex(),
|
||||
false, false, false, false,
|
||||
baseRef.getExternalSheetIndex());
|
||||
return HSSFFormulaEvaluator.evaluateArea3dPtg(workbook, a3dp);
|
||||
}
|
||||
|
||||
AreaPtg ap = new AreaPtg(rows.getFirstIndex(), rows.getLastIndex(),
|
||||
cols.getFirstIndex(), cols.getLastIndex(),
|
||||
false, false, false, false);
|
||||
return HSSFFormulaEvaluator.evaluateAreaPtg(sheet, workbook, ap);
|
||||
return baseRef.offset(orRow.getFirstIndex(), orRow.getLastIndex(), orCol.getFirstIndex(), orCol.getLastIndex());
|
||||
}
|
||||
|
||||
private static BaseRef evaluateBaseRef(Eval eval) throws EvaluationException {
|
||||
|
|
|
@ -17,10 +17,7 @@
|
|||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.poi.hssf.model.FormulaParser;
|
||||
|
@ -29,6 +26,7 @@ import org.apache.poi.hssf.record.formula.Area3DPtg;
|
|||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.BoolPtg;
|
||||
import org.apache.poi.hssf.record.formula.ControlPtg;
|
||||
import org.apache.poi.hssf.record.formula.ErrPtg;
|
||||
import org.apache.poi.hssf.record.formula.IntPtg;
|
||||
import org.apache.poi.hssf.record.formula.MemErrPtg;
|
||||
import org.apache.poi.hssf.record.formula.MissingArgPtg;
|
||||
|
@ -42,20 +40,18 @@ import org.apache.poi.hssf.record.formula.RefPtg;
|
|||
import org.apache.poi.hssf.record.formula.StringPtg;
|
||||
import org.apache.poi.hssf.record.formula.UnionPtg;
|
||||
import org.apache.poi.hssf.record.formula.UnknownPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.Area2DEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Area3DEval;
|
||||
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.Eval;
|
||||
import org.apache.poi.hssf.record.formula.eval.FunctionEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.LazyAreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.LazyRefEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NameEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NameXEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.OperationEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Ref2DEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Ref3DEval;
|
||||
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;
|
||||
|
@ -66,32 +62,6 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
|||
*/
|
||||
public class HSSFFormulaEvaluator {
|
||||
|
||||
// params to lookup the right constructor using reflection
|
||||
private static final Class[] VALUE_CONTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class };
|
||||
|
||||
private static final Class[] AREA3D_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class, ValueEval[].class };
|
||||
|
||||
private static final Class[] REFERENCE_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class, ValueEval.class };
|
||||
|
||||
private static final Class[] REF3D_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class, ValueEval.class };
|
||||
|
||||
// Maps for mapping *Eval to *Ptg
|
||||
private static final Map VALUE_EVALS_MAP = new HashMap();
|
||||
|
||||
/*
|
||||
* Following is the mapping between the Ptg tokens returned
|
||||
* by the FormulaParser and the *Eval classes that are used
|
||||
* by the FormulaEvaluator
|
||||
*/
|
||||
static {
|
||||
VALUE_EVALS_MAP.put(BoolPtg.class, BoolEval.class);
|
||||
VALUE_EVALS_MAP.put(IntPtg.class, NumberEval.class);
|
||||
VALUE_EVALS_MAP.put(NumberPtg.class, NumberEval.class);
|
||||
VALUE_EVALS_MAP.put(StringPtg.class, StringEval.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected HSSFSheet _sheet;
|
||||
protected HSSFWorkbook _workbook;
|
||||
|
||||
|
@ -287,7 +257,7 @@ public class HSSFFormulaEvaluator {
|
|||
* Returns a CellValue wrapper around the supplied ValueEval instance.
|
||||
* @param eval
|
||||
*/
|
||||
protected static CellValue getCellValueForEval(ValueEval eval) {
|
||||
private static CellValue getCellValueForEval(ValueEval eval) {
|
||||
CellValue retval = null;
|
||||
if (eval != null) {
|
||||
if (eval instanceof NumberEval) {
|
||||
|
@ -369,7 +339,7 @@ public class HSSFFormulaEvaluator {
|
|||
continue;
|
||||
}
|
||||
if (ptg instanceof UnknownPtg) { continue; }
|
||||
|
||||
Eval opResult;
|
||||
if (ptg instanceof OperationPtg) {
|
||||
OperationPtg optg = (OperationPtg) ptg;
|
||||
|
||||
|
@ -385,41 +355,11 @@ public class HSSFFormulaEvaluator {
|
|||
Eval p = (Eval) stack.pop();
|
||||
ops[j] = p;
|
||||
}
|
||||
Eval opresult = invokeOperation(operation, ops, srcRowNum, srcColNum, workbook, sheet);
|
||||
stack.push(opresult);
|
||||
}
|
||||
else if (ptg instanceof RefPtg) {
|
||||
RefPtg refPtg = (RefPtg) ptg;
|
||||
int colIx = refPtg.getColumn();
|
||||
int rowIx = refPtg.getRow();
|
||||
HSSFRow row = sheet.getRow(rowIx);
|
||||
HSSFCell cell = (row != null) ? row.getCell(colIx) : null;
|
||||
stack.push(createRef2DEval(refPtg, cell, sheet, workbook));
|
||||
}
|
||||
else if (ptg instanceof Ref3DPtg) {
|
||||
Ref3DPtg refPtg = (Ref3DPtg) ptg;
|
||||
int colIx = refPtg.getColumn();
|
||||
int rowIx = refPtg.getRow();
|
||||
Workbook wb = workbook.getWorkbook();
|
||||
HSSFSheet xsheet = workbook.getSheetAt(wb.getSheetIndexFromExternSheetIndex(refPtg.getExternSheetIndex()));
|
||||
HSSFRow row = xsheet.getRow(rowIx);
|
||||
HSSFCell cell = (row != null) ? row.getCell(colIx) : null;
|
||||
stack.push(createRef3DEval(refPtg, cell, xsheet, workbook));
|
||||
}
|
||||
else if (ptg instanceof AreaPtg) {
|
||||
AreaPtg ap = (AreaPtg) ptg;
|
||||
AreaEval ae = evaluateAreaPtg(sheet, workbook, ap);
|
||||
stack.push(ae);
|
||||
}
|
||||
else if (ptg instanceof Area3DPtg) {
|
||||
Area3DPtg a3dp = (Area3DPtg) ptg;
|
||||
AreaEval ae = evaluateArea3dPtg(workbook, a3dp);
|
||||
stack.push(ae);
|
||||
}
|
||||
else {
|
||||
Eval ptgEval = getEvalForPtg(ptg);
|
||||
stack.push(ptgEval);
|
||||
opResult = invokeOperation(operation, ops, srcRowNum, srcColNum, workbook, sheet);
|
||||
} else {
|
||||
opResult = getEvalForPtg(ptg, sheet, workbook);
|
||||
}
|
||||
stack.push(opResult);
|
||||
}
|
||||
|
||||
ValueEval value = ((ValueEval) stack.pop());
|
||||
|
@ -475,105 +415,49 @@ public class HSSFFormulaEvaluator {
|
|||
return operation.evaluate(ops, srcRowNum, srcColNum);
|
||||
}
|
||||
|
||||
public static AreaEval evaluateAreaPtg(HSSFSheet sheet, HSSFWorkbook workbook, AreaPtg ap) {
|
||||
int row0 = ap.getFirstRow();
|
||||
int col0 = ap.getFirstColumn();
|
||||
int row1 = ap.getLastRow();
|
||||
int col1 = ap.getLastColumn();
|
||||
|
||||
// If the last row is -1, then the
|
||||
// reference is for the rest of the column
|
||||
// (eg C:C)
|
||||
// TODO: Handle whole column ranges properly
|
||||
if(row1 == -1 && row0 >= 0) {
|
||||
row1 = (short)sheet.getLastRowNum();
|
||||
}
|
||||
ValueEval[] values = evalArea(workbook, sheet, row0, col0, row1, col1);
|
||||
return new Area2DEval(ap, values);
|
||||
}
|
||||
|
||||
public static AreaEval evaluateArea3dPtg(HSSFWorkbook workbook, Area3DPtg a3dp) {
|
||||
int row0 = a3dp.getFirstRow();
|
||||
int col0 = a3dp.getFirstColumn();
|
||||
int row1 = a3dp.getLastRow();
|
||||
int col1 = a3dp.getLastColumn();
|
||||
Workbook wb = workbook.getWorkbook();
|
||||
HSSFSheet xsheet = workbook.getSheetAt(wb.getSheetIndexFromExternSheetIndex(a3dp.getExternSheetIndex()));
|
||||
|
||||
// If the last row is -1, then the
|
||||
// reference is for the rest of the column
|
||||
// (eg C:C)
|
||||
// TODO: Handle whole column ranges properly
|
||||
if(row1 == -1 && row0 >= 0) {
|
||||
row1 = (short)xsheet.getLastRowNum();
|
||||
}
|
||||
|
||||
ValueEval[] values = evalArea(workbook, xsheet, row0, col0, row1, col1);
|
||||
return new Area3DEval(a3dp, values);
|
||||
}
|
||||
|
||||
private static ValueEval[] evalArea(HSSFWorkbook workbook, HSSFSheet sheet,
|
||||
int row0, int col0, int row1, int col1) {
|
||||
ValueEval[] values = new ValueEval[(row1 - row0 + 1) * (col1 - col0 + 1)];
|
||||
for (int x = row0; sheet != null && x < row1 + 1; x++) {
|
||||
HSSFRow row = sheet.getRow(x);
|
||||
for (int y = col0; y < col1 + 1; y++) {
|
||||
ValueEval cellEval;
|
||||
if(row == null) {
|
||||
cellEval = BlankEval.INSTANCE;
|
||||
} else {
|
||||
cellEval = getEvalForCell(row.getCell(y), row, sheet, workbook);
|
||||
}
|
||||
values[(x - row0) * (col1 - col0 + 1) + (y - col0)] = cellEval;
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an appropriate Eval impl instance for the Ptg. The Ptg must be
|
||||
* one of: Area3DPtg, AreaPtg, ReferencePtg, Ref3DPtg, IntPtg, NumberPtg,
|
||||
* StringPtg, BoolPtg <br/>special Note: OperationPtg subtypes cannot be
|
||||
* passed here!
|
||||
*
|
||||
* @param ptg
|
||||
*/
|
||||
protected static Eval getEvalForPtg(Ptg ptg) {
|
||||
Eval retval = null;
|
||||
|
||||
Class clazz = (Class) VALUE_EVALS_MAP.get(ptg.getClass());
|
||||
try {
|
||||
private static Eval getEvalForPtg(Ptg ptg, HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
if (ptg instanceof RefPtg) {
|
||||
return new LazyRefEval(((RefPtg) ptg), sheet, workbook);
|
||||
}
|
||||
if (ptg instanceof Ref3DPtg) {
|
||||
Ref3DPtg refPtg = (Ref3DPtg) ptg;
|
||||
Workbook wb = workbook.getWorkbook();
|
||||
HSSFSheet xsheet = workbook.getSheetAt(wb.getSheetIndexFromExternSheetIndex(refPtg.getExternSheetIndex()));
|
||||
return new LazyRefEval(refPtg, xsheet, workbook);
|
||||
}
|
||||
if (ptg instanceof AreaPtg) {
|
||||
return new LazyAreaEval(((AreaPtg) ptg), sheet, workbook);
|
||||
}
|
||||
if (ptg instanceof Area3DPtg) {
|
||||
Constructor constructor = clazz.getConstructor(AREA3D_CONSTRUCTOR_CLASS_ARRAY);
|
||||
retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg });
|
||||
}
|
||||
else if (ptg instanceof AreaPtg) {
|
||||
Constructor constructor = clazz.getConstructor(AREA3D_CONSTRUCTOR_CLASS_ARRAY);
|
||||
retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg });
|
||||
}
|
||||
else if (ptg instanceof RefPtg) {
|
||||
Constructor constructor = clazz.getConstructor(REFERENCE_CONSTRUCTOR_CLASS_ARRAY);
|
||||
retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg });
|
||||
}
|
||||
else if (ptg instanceof Ref3DPtg) {
|
||||
Constructor constructor = clazz.getConstructor(REF3D_CONSTRUCTOR_CLASS_ARRAY);
|
||||
retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg });
|
||||
}
|
||||
else {
|
||||
if (ptg instanceof IntPtg || ptg instanceof NumberPtg || ptg instanceof StringPtg
|
||||
|| ptg instanceof BoolPtg) {
|
||||
Constructor constructor = clazz.getConstructor(VALUE_CONTRUCTOR_CLASS_ARRAY);
|
||||
retval = (ValueEval) constructor.newInstance(new Ptg[] { ptg });
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Fatal Error: ", e);
|
||||
}
|
||||
return retval;
|
||||
|
||||
Area3DPtg a3dp = (Area3DPtg) ptg;
|
||||
Workbook wb = workbook.getWorkbook();
|
||||
HSSFSheet xsheet = workbook.getSheetAt(wb.getSheetIndexFromExternSheetIndex(a3dp.getExternSheetIndex()));
|
||||
return new LazyAreaEval(a3dp, xsheet, workbook);
|
||||
}
|
||||
|
||||
if (ptg instanceof IntPtg) {
|
||||
return new NumberEval(((IntPtg)ptg).getValue());
|
||||
}
|
||||
if (ptg instanceof NumberPtg) {
|
||||
return new NumberEval(((NumberPtg)ptg).getValue());
|
||||
}
|
||||
if (ptg instanceof StringPtg) {
|
||||
return new StringEval(((StringPtg) ptg).getValue());
|
||||
}
|
||||
if (ptg instanceof BoolPtg) {
|
||||
return BoolEval.valueOf(((BoolPtg) ptg).getValue());
|
||||
}
|
||||
if (ptg instanceof ErrPtg) {
|
||||
return ErrorEval.valueOf(((ErrPtg) ptg).getErrorCode());
|
||||
}
|
||||
throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")");
|
||||
}
|
||||
/**
|
||||
* Given a cell, find its type and from that create an appropriate ValueEval
|
||||
* impl instance and return that. Since the cell could be an external
|
||||
|
@ -583,7 +467,7 @@ public class HSSFFormulaEvaluator {
|
|||
* @param sheet
|
||||
* @param workbook
|
||||
*/
|
||||
protected static ValueEval getEvalForCell(HSSFCell cell, HSSFRow row, HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
public static ValueEval getEvalForCell(HSSFCell cell, HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
|
||||
if (cell == null) {
|
||||
return BlankEval.INSTANCE;
|
||||
|
@ -605,58 +489,6 @@ public class HSSFFormulaEvaluator {
|
|||
throw new RuntimeException("Unexpected cell type (" + cell.getCellType() + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Ref2DEval for ReferencePtg.
|
||||
* Non existent cells are treated as RefEvals containing BlankEval.
|
||||
*/
|
||||
private static Ref2DEval createRef2DEval(RefPtg ptg, HSSFCell cell,
|
||||
HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
if (cell == null) {
|
||||
return new Ref2DEval(ptg, BlankEval.INSTANCE);
|
||||
}
|
||||
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
return new Ref2DEval(ptg, new NumberEval(cell.getNumericCellValue()));
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
return new Ref2DEval(ptg, new StringEval(cell.getRichStringCellValue().getString()));
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
return new Ref2DEval(ptg, internalEvaluate(cell, sheet, workbook));
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
return new Ref2DEval(ptg, BoolEval.valueOf(cell.getBooleanCellValue()));
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
return new Ref2DEval(ptg, BlankEval.INSTANCE);
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
return new Ref2DEval(ptg, ErrorEval.valueOf(cell.getErrorCellValue()));
|
||||
}
|
||||
throw new RuntimeException("Unexpected cell type (" + cell.getCellType() + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* create a Ref3DEval for Ref3DPtg.
|
||||
*/
|
||||
private static Ref3DEval createRef3DEval(Ref3DPtg ptg, HSSFCell cell,
|
||||
HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
if (cell == null) {
|
||||
return new Ref3DEval(ptg, BlankEval.INSTANCE);
|
||||
}
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
return new Ref3DEval(ptg, new NumberEval(cell.getNumericCellValue()));
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
return new Ref3DEval(ptg, new StringEval(cell.getRichStringCellValue().getString()));
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
return new Ref3DEval(ptg, internalEvaluate(cell, sheet, workbook));
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
return new Ref3DEval(ptg, BoolEval.valueOf(cell.getBooleanCellValue()));
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
return new Ref3DEval(ptg, BlankEval.INSTANCE);
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
return new Ref3DEval(ptg, ErrorEval.valueOf(cell.getErrorCellValue()));
|
||||
}
|
||||
throw new RuntimeException("Unexpected cell type (" + cell.getCellType() + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Mimics the 'data view' of a cell. This allows formula evaluator
|
||||
* to return a CellValue instead of precasting the value to String
|
||||
|
@ -752,15 +584,9 @@ public class HSSFFormulaEvaluator {
|
|||
|
||||
/**
|
||||
* debug method
|
||||
*
|
||||
* @param formula
|
||||
* @param sheet
|
||||
* @param workbook
|
||||
*/
|
||||
void inspectPtgs(String formula) {
|
||||
FormulaParser fp = new FormulaParser(formula, _workbook);
|
||||
fp.parse();
|
||||
Ptg[] ptgs = fp.getRPNPtg();
|
||||
Ptg[] ptgs = FormulaParser.parse(formula, _workbook);
|
||||
System.out.println("<ptg-group>");
|
||||
for (int i = 0, iSize = ptgs.length; i < iSize; i++) {
|
||||
System.out.println("<ptg>");
|
||||
|
|
|
@ -20,7 +20,8 @@ package org.apache.poi.hssf.record.formula.eval;
|
|||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.functions.EvalFactory;
|
||||
|
||||
/**
|
||||
* Tests for <tt>AreaEval</tt>
|
||||
|
@ -30,8 +31,8 @@ import org.apache.poi.hssf.record.formula.Area3DPtg;
|
|||
public final class TestAreaEval extends TestCase {
|
||||
|
||||
public void testGetValue_bug44950() {
|
||||
|
||||
Area3DPtg ptg = new Area3DPtg("B2:D3", (short)0);
|
||||
// TODO - this test probably isn't testing much anymore
|
||||
AreaPtg ptg = new AreaPtg("B2:D3");
|
||||
NumberEval one = new NumberEval(1);
|
||||
ValueEval[] values = {
|
||||
one,
|
||||
|
@ -41,7 +42,7 @@ public final class TestAreaEval extends TestCase {
|
|||
new NumberEval(5),
|
||||
new NumberEval(6),
|
||||
};
|
||||
AreaEval ae = new Area3DEval(ptg, values);
|
||||
AreaEval ae = EvalFactory.createAreaEval(ptg, values);
|
||||
if (one == ae.getValueAt(1, 2)) {
|
||||
throw new AssertionFailedError("Identified bug 44950 a");
|
||||
}
|
||||
|
|
|
@ -18,12 +18,13 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula.eval;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
|
||||
import org.apache.poi.hssf.record.formula.functions.EvalFactory;
|
||||
import org.apache.poi.hssf.record.formula.functions.NumericFunctionInvoker;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Test for unary plus operator evaluator.
|
||||
*
|
||||
|
@ -48,9 +49,8 @@ public final class TestUnaryPlusEval extends TestCase {
|
|||
new NumberEval(37),
|
||||
new NumberEval(38),
|
||||
};
|
||||
Eval areaEval = new Area2DEval(areaPtg, values);
|
||||
Eval[] args = {
|
||||
areaEval,
|
||||
EvalFactory.createAreaEval(areaPtg, values),
|
||||
};
|
||||
|
||||
double result = NumericFunctionInvoker.invoke(new UnaryPlusEval(UnaryPlusPtg.instance), args, 10, (short)20);
|
||||
|
|
|
@ -15,16 +15,16 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.Area2DEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEvalBase;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Ref2DEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RefEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RefEvalBase;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,7 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
|||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
final class EvalFactory {
|
||||
public final class EvalFactory {
|
||||
|
||||
private EvalFactory() {
|
||||
// no instances of this class
|
||||
|
@ -44,6 +44,14 @@ final class EvalFactory {
|
|||
*/
|
||||
public static AreaEval createAreaEval(String areaRefStr, ValueEval[] values) {
|
||||
AreaPtg areaPtg = new AreaPtg(areaRefStr);
|
||||
return createAreaEval(areaPtg, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dummy AreaEval
|
||||
* @param values empty (<code>null</code>) entries in this array will be converted to NumberEval.ZERO
|
||||
*/
|
||||
public static AreaEval createAreaEval(AreaPtg areaPtg, ValueEval[] values) {
|
||||
int nCols = areaPtg.getLastColumn() - areaPtg.getFirstColumn() + 1;
|
||||
int nRows = areaPtg.getLastRow() - areaPtg.getFirstRow() + 1;
|
||||
int nExpected = nRows * nCols;
|
||||
|
@ -55,13 +63,57 @@ final class EvalFactory {
|
|||
values[i] = NumberEval.ZERO;
|
||||
}
|
||||
}
|
||||
return new Area2DEval(areaPtg, values);
|
||||
return new MockAreaEval(areaPtg, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single RefEval (with value zero)
|
||||
*/
|
||||
public static RefEval createRefEval(String refStr) {
|
||||
return new Ref2DEval(new RefPtg(refStr), NumberEval.ZERO);
|
||||
return createRefEval(refStr, NumberEval.ZERO);
|
||||
}
|
||||
public static RefEval createRefEval(String refStr, ValueEval value) {
|
||||
return new MockRefEval(new RefPtg(refStr), value);
|
||||
}
|
||||
|
||||
private static final class MockAreaEval extends AreaEvalBase {
|
||||
private final ValueEval[] _values;
|
||||
public MockAreaEval(AreaPtg areaPtg, ValueEval[] values) {
|
||||
super(areaPtg);
|
||||
_values = values;
|
||||
}
|
||||
public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
|
||||
if (relativeRowIndex < 0 || relativeRowIndex >=getHeight()) {
|
||||
throw new IllegalArgumentException("row index out of range");
|
||||
}
|
||||
int width = getWidth();
|
||||
if (relativeColumnIndex < 0 || relativeColumnIndex >=width) {
|
||||
throw new IllegalArgumentException("column index out of range");
|
||||
}
|
||||
int oneDimensionalIndex = relativeRowIndex * width + relativeColumnIndex;
|
||||
return _values[oneDimensionalIndex];
|
||||
}
|
||||
public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
|
||||
throw new RuntimeException("Operation not implemented on this mock object");
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MockRefEval extends RefEvalBase {
|
||||
private final ValueEval _value;
|
||||
public MockRefEval(RefPtg ptg, ValueEval value) {
|
||||
super(ptg.getRow(), ptg.getColumn());
|
||||
_value = value;
|
||||
}
|
||||
public MockRefEval(Ref3DPtg ptg, ValueEval value) {
|
||||
super(ptg.getRow(), ptg.getColumn());
|
||||
_value = value;
|
||||
}
|
||||
public ValueEval getInnerValueEval() {
|
||||
return _value;
|
||||
}
|
||||
public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
|
||||
throw new RuntimeException("Operation not implemented on this mock object");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,9 +21,7 @@ import junit.framework.AssertionFailedError;
|
|||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.Area2DEval;
|
||||
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;
|
||||
|
@ -91,7 +89,7 @@ public final class TestCountFuncs extends TestCase {
|
|||
BoolEval.TRUE,
|
||||
BlankEval.INSTANCE,
|
||||
};
|
||||
range = createAreaEval("A1:B3", values);
|
||||
range = EvalFactory.createAreaEval("A1:B3", values);
|
||||
confirmCountIf(2, range, BoolEval.TRUE);
|
||||
|
||||
// when criteria is numeric
|
||||
|
@ -103,7 +101,7 @@ public final class TestCountFuncs extends TestCase {
|
|||
new NumberEval(2),
|
||||
BoolEval.TRUE,
|
||||
};
|
||||
range = createAreaEval("A1:B3", values);
|
||||
range = EvalFactory.createAreaEval("A1:B3", values);
|
||||
confirmCountIf(3, range, new NumberEval(2));
|
||||
// note - same results when criteria is a string that parses as the number with the same value
|
||||
confirmCountIf(3, range, new StringEval("2.00"));
|
||||
|
@ -126,20 +124,15 @@ public final class TestCountFuncs extends TestCase {
|
|||
new NumberEval(25),
|
||||
new NumberEval(25),
|
||||
};
|
||||
Area2DEval arg0 = new Area2DEval(new AreaPtg("C1:C6"), values);
|
||||
AreaEval arg0 = EvalFactory.createAreaEval("C1:C6", values);
|
||||
|
||||
Ref2DEval criteriaArg = new Ref2DEval(new RefPtg("A1"), new NumberEval(25));
|
||||
ValueEval criteriaArg = EvalFactory.createRefEval("A1", new NumberEval(25));
|
||||
Eval[] args= { arg0, criteriaArg, };
|
||||
|
||||
double actual = NumericFunctionInvoker.invoke(new Countif(), args);
|
||||
assertEquals(4, actual, 0D);
|
||||
}
|
||||
|
||||
|
||||
private static AreaEval createAreaEval(String areaRefStr, ValueEval[] values) {
|
||||
return new Area2DEval(new AreaPtg(areaRefStr), values);
|
||||
}
|
||||
|
||||
private static void confirmCountA(int expected, Eval[] args) {
|
||||
double result = NumericFunctionInvoker.invoke(new Counta(), args);
|
||||
assertEquals(expected, result, 0);
|
||||
|
|
|
@ -19,8 +19,7 @@ package org.apache.poi.hssf.record.formula.functions;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.Area2DEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Eval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
@ -68,7 +67,7 @@ public final class TestIndex extends TestCase {
|
|||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = new NumberEval(dValues[i]);
|
||||
}
|
||||
Area2DEval arg0 = new Area2DEval(new AreaPtg(areaRefString), values);
|
||||
AreaEval arg0 = EvalFactory.createAreaEval(areaRefString, values);
|
||||
|
||||
Eval[] args;
|
||||
if (colNum > 0) {
|
||||
|
|
|
@ -19,8 +19,6 @@ package org.apache.poi.hssf.record.formula.functions;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.Area2DEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
|
@ -54,13 +52,6 @@ public final class TestMatch extends TestCase {
|
|||
NumericValueEval nve = (NumericValueEval)actualEval;
|
||||
assertEquals(expected, nve.getNumberValue(), 0);
|
||||
}
|
||||
/**
|
||||
* Convenience method
|
||||
* @return <code>new Area2DEval(new AreaPtg(ref), values)</code>
|
||||
*/
|
||||
private static AreaEval createAreaEval(String ref, ValueEval[] values) {
|
||||
return new Area2DEval(new AreaPtg(ref), values);
|
||||
}
|
||||
|
||||
public void testSimpleNumber() {
|
||||
|
||||
|
@ -72,7 +63,7 @@ public final class TestMatch extends TestCase {
|
|||
new NumberEval(25),
|
||||
};
|
||||
|
||||
AreaEval ae = createAreaEval("A1:A5", values);
|
||||
AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
|
||||
|
||||
confirmInt(2, invokeMatch(new NumberEval(5), ae, MATCH_LARGEST_LTE));
|
||||
confirmInt(2, invokeMatch(new NumberEval(5), ae, MATCH_EXACT));
|
||||
|
@ -92,7 +83,7 @@ public final class TestMatch extends TestCase {
|
|||
new NumberEval(4),
|
||||
};
|
||||
|
||||
AreaEval ae = createAreaEval("A1:A5", values);
|
||||
AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
|
||||
|
||||
confirmInt(2, invokeMatch(new NumberEval(10), ae, MATCH_SMALLEST_GTE));
|
||||
confirmInt(2, invokeMatch(new NumberEval(10), ae, MATCH_EXACT));
|
||||
|
@ -112,7 +103,7 @@ public final class TestMatch extends TestCase {
|
|||
new StringEval("Ian"),
|
||||
};
|
||||
|
||||
AreaEval ae = createAreaEval("A1:A5", values);
|
||||
AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
|
||||
|
||||
// Note String comparisons are case insensitive
|
||||
confirmInt(3, invokeMatch(new StringEval("Ed"), ae, MATCH_LARGEST_LTE));
|
||||
|
@ -132,7 +123,7 @@ public final class TestMatch extends TestCase {
|
|||
BoolEval.TRUE,
|
||||
};
|
||||
|
||||
AreaEval ae = createAreaEval("A1:A4", values);
|
||||
AreaEval ae = EvalFactory.createAreaEval("A1:A4", values);
|
||||
|
||||
// Note String comparisons are case insensitive
|
||||
confirmInt(2, invokeMatch(BoolEval.FALSE, ae, MATCH_LARGEST_LTE));
|
||||
|
@ -159,7 +150,7 @@ public final class TestMatch extends TestCase {
|
|||
new StringEval("Ed"),
|
||||
};
|
||||
|
||||
AreaEval ae = createAreaEval("A1:A13", values);
|
||||
AreaEval ae = EvalFactory.createAreaEval("A1:A13", values);
|
||||
|
||||
assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Aaron"), ae, MATCH_LARGEST_LTE));
|
||||
|
||||
|
@ -197,9 +188,9 @@ public final class TestMatch extends TestCase {
|
|||
new NumberEval(25),
|
||||
};
|
||||
|
||||
AreaEval ae = createAreaEval("A1:A5", values);
|
||||
AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
|
||||
|
||||
AreaEval matchAE = createAreaEval("C1:C1", new ValueEval[] { MATCH_LARGEST_LTE, });
|
||||
AreaEval matchAE = EvalFactory.createAreaEval("C1:C1", new ValueEval[] { MATCH_LARGEST_LTE, });
|
||||
|
||||
try {
|
||||
confirmInt(4, invokeMatch(new NumberEval(10), ae, matchAE));
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.functions.XYNumericFunction.Accumulator;
|
||||
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
|
@ -566,97 +568,97 @@ public class TestMathX extends AbstractNumericTestCase {
|
|||
}
|
||||
|
||||
public void testSumx2my2() {
|
||||
double d = 0;
|
||||
double[] xarr = null;
|
||||
double[] yarr = null;
|
||||
|
||||
xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
d = MathX.sumx2my2(xarr, yarr);
|
||||
assertEquals("sumx2my2 ", 100, d);
|
||||
confirmSumx2my2(xarr, yarr, 100);
|
||||
|
||||
xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
|
||||
yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
d = MathX.sumx2my2(xarr, yarr);
|
||||
assertEquals("sumx2my2 ", 100, d);
|
||||
confirmSumx2my2(xarr, yarr, 100);
|
||||
|
||||
xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
d = MathX.sumx2my2(xarr, yarr);
|
||||
assertEquals("sumx2my2 ", -100, d);
|
||||
confirmSumx2my2(xarr, yarr, -100);
|
||||
|
||||
xarr = new double[]{10};
|
||||
yarr = new double[]{9};
|
||||
d = MathX.sumx2my2(xarr, yarr);
|
||||
assertEquals("sumx2my2 ", 19, d);
|
||||
confirmSumx2my2(xarr, yarr, 19);
|
||||
|
||||
xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
d = MathX.sumx2my2(xarr, yarr);
|
||||
assertEquals("sumx2my2 ", 0, d);
|
||||
|
||||
confirmSumx2my2(xarr, yarr, 0);
|
||||
}
|
||||
|
||||
public void testSumx2py2() {
|
||||
double d = 0;
|
||||
double[] xarr = null;
|
||||
double[] yarr = null;
|
||||
|
||||
xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
d = MathX.sumx2py2(xarr, yarr);
|
||||
assertEquals("sumx2py2 ", 670, d);
|
||||
confirmSumx2py2(xarr, yarr, 670);
|
||||
|
||||
xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
|
||||
yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
d = MathX.sumx2py2(xarr, yarr);
|
||||
assertEquals("sumx2py2 ", 670, d);
|
||||
confirmSumx2py2(xarr, yarr, 670);
|
||||
|
||||
xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
d = MathX.sumx2py2(xarr, yarr);
|
||||
assertEquals("sumx2py2 ", 670, d);
|
||||
confirmSumx2py2(xarr, yarr, 670);
|
||||
|
||||
xarr = new double[]{10};
|
||||
yarr = new double[]{9};
|
||||
d = MathX.sumx2py2(xarr, yarr);
|
||||
assertEquals("sumx2py2 ", 181, d);
|
||||
confirmSumx2py2(xarr, yarr, 181);
|
||||
|
||||
xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
d = MathX.sumx2py2(xarr, yarr);
|
||||
assertEquals("sumx2py2 ", 770, d);
|
||||
confirmSumx2py2(xarr, yarr, 770);
|
||||
}
|
||||
|
||||
public void testSumxmy2() {
|
||||
double d = 0;
|
||||
double[] xarr = null;
|
||||
double[] yarr = null;
|
||||
|
||||
xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
d = MathX.sumxmy2(xarr, yarr);
|
||||
assertEquals("sumxmy2 ", 10, d);
|
||||
confirmSumxmy2(xarr, yarr, 10);
|
||||
|
||||
xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
|
||||
yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
d = MathX.sumxmy2(xarr, yarr);
|
||||
assertEquals("sumxmy2 ", 1330, d);
|
||||
confirmSumxmy2(xarr, yarr, 1330);
|
||||
|
||||
xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
d = MathX.sumxmy2(xarr, yarr);
|
||||
assertEquals("sumxmy2 ", 10, d);
|
||||
confirmSumxmy2(xarr, yarr, 10);
|
||||
|
||||
xarr = new double[]{10};
|
||||
yarr = new double[]{9};
|
||||
d = MathX.sumxmy2(xarr, yarr);
|
||||
assertEquals("sumxmy2 ", 1, d);
|
||||
confirmSumxmy2(xarr, yarr, 1);
|
||||
|
||||
xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
d = MathX.sumxmy2(xarr, yarr);
|
||||
assertEquals("sumxmy2 ", 0, d);
|
||||
confirmSumxmy2(xarr, yarr, 0);
|
||||
}
|
||||
|
||||
private static void confirmSumx2my2(double[] xarr, double[] yarr, double expectedResult) {
|
||||
confirmXY(new Sumx2my2().createAccumulator(), xarr, yarr, expectedResult);
|
||||
}
|
||||
private static void confirmSumx2py2(double[] xarr, double[] yarr, double expectedResult) {
|
||||
confirmXY(new Sumx2py2().createAccumulator(), xarr, yarr, expectedResult);
|
||||
}
|
||||
private static void confirmSumxmy2(double[] xarr, double[] yarr, double expectedResult) {
|
||||
confirmXY(new Sumxmy2().createAccumulator(), xarr, yarr, expectedResult);
|
||||
}
|
||||
|
||||
private static void confirmXY(Accumulator acc, double[] xarr, double[] yarr,
|
||||
double expectedResult) {
|
||||
double result = 0.0;
|
||||
for (int i = 0; i < xarr.length; i++) {
|
||||
result += acc.accumulate(xarr[i], yarr[i]);
|
||||
}
|
||||
assertEquals(expectedResult, result, 0.0);
|
||||
}
|
||||
|
||||
public void testRound() {
|
||||
|
|
|
@ -17,21 +17,17 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.Area2DEval;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
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.Eval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Ref2DEval;
|
||||
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 junit.framework.TestCase;
|
||||
/**
|
||||
* Tests for Excel function MID()
|
||||
*
|
||||
|
@ -76,8 +72,8 @@ public final class TestMid extends TestCase {
|
|||
confirmMid(new NumberEval(123456), new StringEval("3.1"), new StringEval("2.9"), "34");
|
||||
|
||||
// startPos is 1x1 area ref, numChars is cell ref
|
||||
AreaEval aeStart = new Area2DEval(new AreaPtg("A1:A1"), new ValueEval[] { new NumberEval(2), } );
|
||||
RefEval reNumChars = new Ref2DEval(new RefPtg("B1"), new NumberEval(3));
|
||||
AreaEval aeStart = EvalFactory.createAreaEval("A1:A1", new ValueEval[] { new NumberEval(2), } );
|
||||
RefEval reNumChars = EvalFactory.createRefEval("B1", new NumberEval(3));
|
||||
confirmMid(new StringEval("galactic"), aeStart, reNumChars, "ala");
|
||||
|
||||
confirmMid(new StringEval("galactic"), new NumberEval(3.1), BlankEval.INSTANCE, "");
|
||||
|
|
|
@ -17,18 +17,16 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
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.Eval;
|
||||
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.Ref2DEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RefEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Test cases for SUMPRODUCT()
|
||||
*
|
||||
|
@ -50,7 +48,7 @@ public final class TestSumproduct extends TestCase {
|
|||
|
||||
public void testScalarSimple() {
|
||||
|
||||
RefEval refEval = new Ref2DEval(new RefPtg("A1"), new NumberEval(3));
|
||||
RefEval refEval = EvalFactory.createRefEval("A1", new NumberEval(3));
|
||||
Eval[] args = {
|
||||
refEval,
|
||||
new NumberEval(2),
|
||||
|
|
|
@ -17,18 +17,16 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
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.Eval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Ref2DEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Test cases for Excel function T()
|
||||
*
|
||||
|
@ -50,7 +48,7 @@ public final class TestTFunc extends TestCase {
|
|||
* where cell A1 has the specified innerValue
|
||||
*/
|
||||
private Eval invokeTWithReference(ValueEval innerValue) {
|
||||
Eval arg = new Ref2DEval(new RefPtg((short)1, (short)1, false, false), innerValue);
|
||||
Eval arg = EvalFactory.createRefEval("$B$2", innerValue);
|
||||
return invokeT(arg);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@ package org.apache.poi.hssf.record.formula.functions;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.Area2DEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Eval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
|
@ -100,7 +98,7 @@ public final class TestXYNumericFunction extends TestCase {
|
|||
|
||||
private static ValueEval createAreaEval(ValueEval[] values) {
|
||||
String refStr = "A1:A" + values.length;
|
||||
return new Area2DEval(new AreaPtg(refStr), values);
|
||||
return EvalFactory.createAreaEval(refStr, values);
|
||||
}
|
||||
|
||||
public void testErrors() {
|
||||
|
|
Loading…
Reference in New Issue