From 5126999358e502c1d207313e772c272d36d3c4a1 Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Tue, 22 Dec 2009 03:00:21 +0000 Subject: [PATCH] Added getRow() and getColumn() functions to TwoDEval to simplify logic in INDEX implementation. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@893063 13f79535-47bb-0310-9956-ffa450edef68 --- .../hssf/record/formula/functions/Index.java | 41 +++++-------------- .../apache/poi/ss/formula/LazyAreaEval.java | 17 ++++++++ .../org/apache/poi/ss/formula/TwoDEval.java | 19 +++++++-- .../record/formula/eval/TestRangeEval.java | 18 ++++++++ .../record/formula/functions/EvalFactory.java | 25 ++++++++++- 5 files changed, 85 insertions(+), 35 deletions(-) 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 index badb84640b..fd3816b994 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Index.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Index.java @@ -17,7 +17,6 @@ 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; @@ -53,7 +52,7 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg { int columnIx = 0; try { int rowIx = resolveIndexArg(arg1, srcRowIndex, srcColumnIndex); - + if (!reference.isColumn()) { if (!reference.isRow()) { // always an error with 2-D area refs @@ -65,7 +64,7 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg { columnIx = rowIx; rowIx = 0; } - + return getValueFromArea(reference, rowIx, columnIx); } catch (EvaluationException e) { return e.getErrorEval(); @@ -125,45 +124,27 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg { 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; } diff --git a/src/java/org/apache/poi/ss/formula/LazyAreaEval.java b/src/java/org/apache/poi/ss/formula/LazyAreaEval.java index b8e186a7d7..5063d1e6e8 100644 --- a/src/java/org/apache/poi/ss/formula/LazyAreaEval.java +++ b/src/java/org/apache/poi/ss/formula/LazyAreaEval.java @@ -57,6 +57,23 @@ final class LazyAreaEval extends AreaEvalBase { 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()); diff --git a/src/java/org/apache/poi/ss/formula/TwoDEval.java b/src/java/org/apache/poi/ss/formula/TwoDEval.java index f2e51459a3..ff3b933f96 100644 --- a/src/java/org/apache/poi/ss/formula/TwoDEval.java +++ b/src/java/org/apache/poi/ss/formula/TwoDEval.java @@ -28,11 +28,11 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; 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(); @@ -48,4 +48,15 @@ public interface TwoDEval extends ValueEval { * 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); } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java index be456a7556..80af1b924b 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestRangeEval.java @@ -28,6 +28,7 @@ import org.apache.poi.hssf.usermodel.HSSFRow; 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; /** @@ -90,6 +91,9 @@ public final class TestRangeEval extends TestCase { 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"); } @@ -100,6 +104,20 @@ public final class TestRangeEval extends TestCase { 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() { diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java index 57d707262b..fb2091911a 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java @@ -27,6 +27,7 @@ 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.RefEvalBase; import org.apache.poi.hssf.record.formula.eval.ValueEval; +import org.apache.poi.ss.formula.TwoDEval; /** * Test helper class for creating mock Eval objects @@ -119,7 +120,7 @@ public final class EvalFactory { int width = relLastColIx - relFirstColIx + 1; ValueEval[] result = new ValueEval[height * width]; for (int r=0; r= 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 {