From af192955909b59077a692994b00ac2c6447a3231 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 4 Apr 2018 16:55:46 +0000 Subject: [PATCH] fix error message git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1828364 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/ss/formula/functions/Offset.java | 398 +++++++++--------- .../poi/ss/format/TestCellFormatPart.java | 2 +- 2 files changed, 200 insertions(+), 200 deletions(-) diff --git a/src/java/org/apache/poi/ss/formula/functions/Offset.java b/src/java/org/apache/poi/ss/formula/functions/Offset.java index 60409f6c65..75aac0e780 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Offset.java +++ b/src/java/org/apache/poi/ss/formula/functions/Offset.java @@ -41,203 +41,203 @@ import org.apache.poi.ss.formula.eval.ValueEval; * @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.

- * - * 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.

- * - * @param translationAmount may be zero negative or positive - * - * @return the equivalent LinearOffsetRange 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); - } - } - - @SuppressWarnings("fallthrough") - public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { - if(args.length < 1 || args.length > 5) { - return ErrorEval.VALUE_INVALID; - } - - try { - BaseRef baseRef = evaluateBaseRef(args[0]); - // optional arguments - // If offsets are omitted, it is assumed to be 0. - int rowOffset = (args[1] instanceof MissingArgEval) ? 0 : evaluateIntArg(args[1], srcCellRow, srcCellCol); - int columnOffset = (args[2] instanceof MissingArgEval) ? 0 : evaluateIntArg(args[2], srcCellRow, srcCellCol); - int height = baseRef.getHeight(); - int width = baseRef.getWidth(); - // optional arguments - // If height or width are omitted, it is assumed to be the same height or width as reference. - switch(args.length) { - case 5: - if(!(args[4] instanceof MissingArgEval)) { - width = evaluateIntArg(args[4], srcCellRow, srcCellCol); - } - // fall-through to pick up height - case 4: - if(!(args[3] instanceof MissingArgEval)) { - height = evaluateIntArg(args[3], srcCellRow, srcCellCol); - } - break; - //case 3: - // nothing to do - default: - break; - } - // 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); - } + // 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.

+ * + * 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.

+ * + * @param translationAmount may be zero negative or positive + * + * @return the equivalent LinearOffsetRange 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() { + StringBuilder sb = new StringBuilder(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); + } + } + + @SuppressWarnings("fallthrough") + public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { + if(args.length < 1 || args.length > 5) { + return ErrorEval.VALUE_INVALID; + } + + try { + BaseRef baseRef = evaluateBaseRef(args[0]); + // optional arguments + // If offsets are omitted, it is assumed to be 0. + int rowOffset = (args[1] instanceof MissingArgEval) ? 0 : evaluateIntArg(args[1], srcCellRow, srcCellCol); + int columnOffset = (args[2] instanceof MissingArgEval) ? 0 : evaluateIntArg(args[2], srcCellRow, srcCellCol); + int height = baseRef.getHeight(); + int width = baseRef.getWidth(); + // optional arguments + // If height or width are omitted, it is assumed to be the same height or width as reference. + switch(args.length) { + case 5: + if(!(args[4] instanceof MissingArgEval)) { + width = evaluateIntArg(args[4], srcCellRow, srcCellCol); + } + // fall-through to pick up height + case 4: + if(!(args[3] instanceof MissingArgEval)) { + height = evaluateIntArg(args[3], srcCellRow, srcCellCol); + } + break; + //case 3: + // nothing to do + default: + break; + } + // 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/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java b/src/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java index 0bccba83c9..baef082015 100644 --- a/src/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java +++ b/src/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java @@ -156,7 +156,7 @@ public class TestCellFormatPart extends CellFormatTestBase { Matcher m = NUMBER_EXTRACT_FMT.matcher(str); if (!m.find()) throw new IllegalArgumentException( - "Cannot find numer in \"" + str + "\""); + "Cannot find number in \"" + str + "\""); StringBuilder sb = new StringBuilder(); // The groups in the pattern are the parts of the number -- 2.39.5