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;
int columnIx = 0;
try {
int rowIx = resolveIndexArg(arg1, srcRowIndex, srcColumnIndex);
-
+
if (!reference.isColumn()) {
if (!reference.isRow()) {
// always an error with 2-D area refs
columnIx = rowIx;
rowIx = 0;
}
-
+
return getValueFromArea(reference, rowIx, columnIx);
} catch (EvaluationException e) {
return e.getErrorEval();
throws EvaluationException {
assert pRowIx >= 0;
assert pColumnIx >= 0;
-
- int width = ae.getWidth();
- int height = ae.getHeight();
-
- int relFirstRowIx;
- int relLastRowIx;
-
- if ((pRowIx == 0)) {
- relFirstRowIx = 0;
- relLastRowIx = height-1;
- } else {
+
+ TwoDEval result = ae;
+
+ if (pRowIx != 0) {
// Slightly irregular logic for bounds checking errors
- if (pRowIx > height) {
+ if (pRowIx > ae.getHeight()) {
// high bounds check fail gives #REF! if arg was explicitly passed
throw new EvaluationException(ErrorEval.REF_INVALID);
}
- int rowIx = pRowIx-1;
- relFirstRowIx = rowIx;
- relLastRowIx = rowIx;
+ result = result.getRow(pRowIx-1);
}
- int relFirstColIx;
- int relLastColIx;
- if ((pColumnIx == 0)) {
- relFirstColIx = 0;
- relLastColIx = width-1;
- } else {
+ if (pColumnIx != 0) {
// Slightly irregular logic for bounds checking errors
- if (pColumnIx > width) {
+ if (pColumnIx > ae.getWidth()) {
// high bounds check fail gives #REF! if arg was explicitly passed
throw new EvaluationException(ErrorEval.REF_INVALID);
}
- int columnIx = pColumnIx-1;
- relFirstColIx = columnIx;
- relLastColIx = columnIx;
+ result = result.getColumn(pColumnIx-1);
}
-
- AreaEval x = ((AreaEval) ae);
- return x.offset(relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
+ return result;
}
return new LazyAreaEval(area, _evaluator);
}
+ public LazyAreaEval getRow(int rowIndex) {
+ if (rowIndex >= getHeight()) {
+ throw new IllegalArgumentException("Invalid rowIndex " + rowIndex
+ + ". Allowable range is (0.." + getHeight() + ").");
+ }
+ int absRowIx = getFirstRow() + rowIndex;
+ return new LazyAreaEval(absRowIx, getFirstColumn(), absRowIx, getLastColumn(), _evaluator);
+ }
+ public LazyAreaEval getColumn(int columnIndex) {
+ if (columnIndex >= getWidth()) {
+ throw new IllegalArgumentException("Invalid columnIndex " + columnIndex
+ + ". Allowable range is (0.." + getWidth() + ").");
+ }
+ int absColIx = getFirstColumn() + columnIndex;
+ return new LazyAreaEval(getFirstRow(), absColIx, getLastRow(), absColIx, _evaluator);
+ }
+
public String toString() {
CellReference crA = new CellReference(getFirstRow(), getFirstColumn());
CellReference crB = new CellReference(getLastRow(), getLastColumn());
public interface TwoDEval extends ValueEval {
/**
- * @param row relative row index (zero based)
- * @param col relative column index (zero based)
- * @return element at the specified row and col position
+ * @param rowIndex relative row index (zero based)
+ * @param columnIndex relative column index (zero based)
+ * @return element at the specified row and column position
*/
- public ValueEval getValue(int row, int col);
+ ValueEval getValue(int rowIndex, int columnIndex);
int getWidth();
int getHeight();
* the trivial case when the area has just a single cell.
*/
boolean isColumn();
+
+ /**
+ * @param rowIndex relative row index (zero based)
+ * @return a single row {@link TwoDEval}
+ */
+ TwoDEval getRow(int rowIndex);
+ /**
+ * @param columnIndex relative column index (zero based)
+ * @return a single column {@link TwoDEval}
+ */
+ TwoDEval getColumn(int columnIndex);
}
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.AreaReference;
import org.apache.poi.hssf.util.CellReference;
+import org.apache.poi.ss.formula.TwoDEval;
import org.apache.poi.ss.usermodel.CellValue;
/**
public MockAreaEval(AreaI ptg) {
super(ptg);
}
+ private MockAreaEval(int firstRow, int firstColumn, int lastRow, int lastColumn) {
+ super(firstRow, firstColumn, lastRow, lastColumn);
+ }
public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
throw new RuntimeException("not expected to be called during this test");
}
return new MockAreaEval(area);
}
+ public TwoDEval getRow(int rowIndex) {
+ if (rowIndex >= getHeight()) {
+ throw new IllegalArgumentException("Invalid rowIndex " + rowIndex
+ + ". Allowable range is (0.." + getHeight() + ").");
+ }
+ return new MockAreaEval(rowIndex, getFirstColumn(), rowIndex, getLastColumn());
+ }
+ public TwoDEval getColumn(int columnIndex) {
+ if (columnIndex >= getWidth()) {
+ throw new IllegalArgumentException("Invalid columnIndex " + columnIndex
+ + ". Allowable range is (0.." + getWidth() + ").");
+ }
+ return new MockAreaEval(getFirstRow(), columnIndex, getLastRow(), columnIndex);
+ }
}
public void testRangeUsingOffsetFunc_bug46948() {
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;
+import org.apache.poi.ss.formula.TwoDEval;
/**
* Test helper class for creating mock <code>Eval</code> objects
int width = relLastColIx - relFirstColIx + 1;
ValueEval[] result = new ValueEval[height * width];
for (int r=0; r<height; r++) {
- int srcRowIx = r + relFirstRowIx;
+ int srcRowIx = r + relFirstRowIx;
for (int c=0; c<width; c++) {
int srcColIx = c + relFirstColIx;
int destIx = r * width + c;
}
return result;
}
+ public TwoDEval getRow(int rowIndex) {
+ if (rowIndex >= getHeight()) {
+ throw new IllegalArgumentException("Invalid rowIndex " + rowIndex
+ + ". Allowable range is (0.." + getHeight() + ").");
+ }
+ ValueEval[] values = new ValueEval[getWidth()];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = getRelativeValue(rowIndex, i);
+ }
+ return new MockAreaEval(rowIndex, getFirstColumn(), rowIndex, getLastColumn(), values);
+ }
+ public TwoDEval getColumn(int columnIndex) {
+ if (columnIndex >= getWidth()) {
+ throw new IllegalArgumentException("Invalid columnIndex " + columnIndex
+ + ". Allowable range is (0.." + getWidth() + ").");
+ }
+ ValueEval[] values = new ValueEval[getHeight()];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = getRelativeValue(i, columnIndex);
+ }
+ return new MockAreaEval(getFirstRow(), columnIndex, getLastRow(), columnIndex, values);
+ }
}
private static final class MockRefEval extends RefEvalBase {