001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /*
018: * Created on May 15, 2005
019: *
020: */
021: package org.apache.poi.hssf.record.formula.functions;
022:
023: import org.apache.poi.hssf.record.formula.eval.ErrorEval;
024: import org.apache.poi.hssf.record.formula.eval.Eval;
025: import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
026: import org.apache.poi.hssf.record.formula.eval.StringEval;
027: import org.apache.poi.hssf.record.formula.eval.StringValueEval;
028: import org.apache.poi.hssf.record.formula.eval.ValueEval;
029:
030: /**
031: * An implementation of the SUBSTITUTE function:
032: * Substitutes text in a text string with new text, some number of times.
033: * @author Manda Wilson < wilson at c bio dot msk cc dot org >
034: */
035: public class Substitute extends TextFunction {
036: private static final int REPLACE_ALL = -1;
037:
038: /**
039: *Substitutes text in a text string with new text, some number of times.
040: *
041: * @see org.apache.poi.hssf.record.formula.eval.Eval
042: */
043: public Eval evaluate(Eval[] operands, int srcCellRow,
044: short srcCellCol) {
045: Eval retval = null;
046: String oldStr = null;
047: String searchStr = null;
048: String newStr = null;
049: int numToReplace = REPLACE_ALL;
050:
051: switch (operands.length) {
052: default:
053: retval = ErrorEval.VALUE_INVALID;
054: case 4:
055: ValueEval fourthveval = singleOperandEvaluate(operands[3],
056: srcCellRow, srcCellCol);
057: if (fourthveval instanceof NumericValueEval) {
058: NumericValueEval numToReplaceEval = (NumericValueEval) fourthveval;
059: // NOTE: it is safe to cast to int here
060: // because in Excel =SUBSTITUTE("teststr","t","T",1.9)
061: // returns Teststr
062: // so 1.9 must be truncated to 1
063: numToReplace = (int) numToReplaceEval.getNumberValue();
064: } else {
065: retval = ErrorEval.VALUE_INVALID;
066: }
067: case 3:
068: // first operand is text string containing characters to replace
069: // second operand is text to find
070: // third operand is replacement text
071: ValueEval firstveval = singleOperandEvaluate(operands[0],
072: srcCellRow, srcCellCol);
073: ValueEval secondveval = singleOperandEvaluate(operands[1],
074: srcCellRow, srcCellCol);
075: ValueEval thirdveval = singleOperandEvaluate(operands[2],
076: srcCellRow, srcCellCol);
077: if (firstveval instanceof StringValueEval
078: && secondveval instanceof StringValueEval
079: && thirdveval instanceof StringValueEval) {
080:
081: StringValueEval oldStrEval = (StringValueEval) firstveval;
082: oldStr = oldStrEval.getStringValue();
083:
084: StringValueEval searchStrEval = (StringValueEval) secondveval;
085: searchStr = searchStrEval.getStringValue();
086:
087: StringValueEval newStrEval = (StringValueEval) thirdveval;
088: newStr = newStrEval.getStringValue();
089: } else {
090: retval = ErrorEval.VALUE_INVALID;
091: }
092: }
093:
094: if (retval == null) {
095: if (numToReplace != REPLACE_ALL && numToReplace < 1) {
096: retval = ErrorEval.VALUE_INVALID;
097: } else if (searchStr.length() == 0) {
098: retval = new StringEval(oldStr);
099: } else {
100: StringBuffer strBuff = new StringBuffer();
101: int startIndex = 0;
102: int nextMatch = -1;
103: for (int leftToReplace = numToReplace; (leftToReplace > 0 || numToReplace == REPLACE_ALL)
104: && (nextMatch = oldStr.indexOf(searchStr,
105: startIndex)) != -1; leftToReplace--) {
106: // store everything from end of last match to start of this match
107: strBuff.append(oldStr.substring(startIndex,
108: nextMatch));
109: strBuff.append(newStr);
110: startIndex = nextMatch + searchStr.length();
111: }
112: // store everything from end of last match to end of string
113: if (startIndex < oldStr.length()) {
114: strBuff.append(oldStr.substring(startIndex));
115: }
116: retval = new StringEval(strBuff.toString());
117: }
118: }
119: return retval;
120: }
121:
122: }
|