mirror of https://github.com/apache/poi.git
Support for Mid, Replace and Substitute excel functions (bug #s 44095, 44097, 44099)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@606172 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
dae37b8632
commit
d47c14c347
|
@ -36,6 +36,7 @@
|
|||
|
||||
<!-- Don't forget to update status.xml too! -->
|
||||
<release version="3.0.2-FINAL" date="2007-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="add">44095, 44097, 44099 - [PATCH] Support for Mid, Replace and Substitute excel functions</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">44055 - [PATCH] Support for getting the from field from HSMF messages</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">43551 - [PATCH] Support for 1904 date windowing in HSSF (previously only supported 1900 date windowing)</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">41064 - [PATCH] Support for String continue records</action>
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
<!-- Don't forget to update changes.xml too! -->
|
||||
<changes>
|
||||
<release version="3.0.2-FINAL" date="2007-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="add">44095, 44097, 44099 - [PATCH] Support for Mid, Replace and Substitute excel functions</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">44055 - [PATCH] Support for getting the from field from HSMF messages</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">43551 - [PATCH] Support for 1904 date windowing in HSSF (previously only supported 1900 date windowing)</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">41064 - [PATCH] Support for String continue records</action>
|
||||
|
|
|
@ -20,6 +20,80 @@
|
|||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
public class Mid extends NotImplementedFunction {
|
||||
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.Eval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* An implementation of the MID function:
|
||||
* Returns a specific number of characters from a text string,
|
||||
* starting at the position you specify, based on the number
|
||||
* of characters you specify.
|
||||
* @author Manda Wilson < wilson at c bio dot msk cc dot org >
|
||||
*/
|
||||
public class Mid extends TextFunction {
|
||||
/**
|
||||
* Returns a specific number of characters from a text string,
|
||||
* starting at the position you specify, based on the number
|
||||
* of characters you specify.
|
||||
*
|
||||
* @see org.apache.poi.hssf.record.formula.eval.Eval
|
||||
*/
|
||||
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
|
||||
Eval retval = null;
|
||||
String str = null;
|
||||
int startNum = 0;
|
||||
int numChars = 0;
|
||||
|
||||
switch (operands.length) {
|
||||
default:
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
case 3:
|
||||
// first operand is text string containing characters to extract
|
||||
// second operand is position of first character to extract
|
||||
// third operand is the number of characters to return
|
||||
ValueEval firstveval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
|
||||
ValueEval secondveval = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
|
||||
ValueEval thirdveval = singleOperandEvaluate(operands[2], srcCellRow, srcCellCol);
|
||||
if (firstveval instanceof StringValueEval
|
||||
&& secondveval instanceof NumericValueEval
|
||||
&& thirdveval instanceof NumericValueEval) {
|
||||
|
||||
StringValueEval strEval = (StringValueEval) firstveval;
|
||||
str = strEval.getStringValue();
|
||||
|
||||
NumericValueEval startNumEval = (NumericValueEval) secondveval;
|
||||
// NOTE: it is safe to cast to int here
|
||||
// because in Excel =MID("test", 1, 1.7) returns t
|
||||
// so 1.7 must be truncated to 1
|
||||
// and =MID("test", 1.9, 2) returns te
|
||||
// so 1.9 must be truncated to 1
|
||||
startNum = (int) startNumEval.getNumberValue();
|
||||
|
||||
NumericValueEval numCharsEval = (NumericValueEval) thirdveval;
|
||||
numChars = (int) numCharsEval.getNumberValue();
|
||||
|
||||
} else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == null) {
|
||||
if (startNum < 1 || numChars < 0) {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
} else if (startNum > str.length() || numChars == 0) {
|
||||
retval = BlankEval.INSTANCE;
|
||||
} else if (startNum + numChars > str.length()) {
|
||||
retval = new StringEval(str.substring(startNum - 1));
|
||||
} else {
|
||||
retval = new StringEval(str.substring(startNum - 1, numChars));
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,93 @@
|
|||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
public class Replace extends NotImplementedFunction {
|
||||
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.NumericValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* An implementation of the REPLACE function:
|
||||
* Replaces part of a text string based on the number of characters
|
||||
* you specify, with another text string.
|
||||
* @author Manda Wilson < wilson at c bio dot msk cc dot org >
|
||||
*/
|
||||
public class Replace extends TextFunction {
|
||||
|
||||
/**
|
||||
* Replaces part of a text string based on the number of characters
|
||||
* you specify, with another text string.
|
||||
*
|
||||
* @see org.apache.poi.hssf.record.formula.eval.Eval
|
||||
*/
|
||||
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
|
||||
Eval retval = null;
|
||||
String oldStr = null;
|
||||
String newStr = null;
|
||||
int startNum = 0;
|
||||
int numChars = 0;
|
||||
|
||||
switch (operands.length) {
|
||||
default:
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
case 4:
|
||||
// first operand is text string containing characters to replace
|
||||
// second operand is position of first character to replace
|
||||
// third operand is the number of characters in the old string
|
||||
// you want to replace with new string
|
||||
// fourth operand is the new string
|
||||
ValueEval firstveval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
|
||||
ValueEval secondveval = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
|
||||
ValueEval thirdveval = singleOperandEvaluate(operands[2], srcCellRow, srcCellCol);
|
||||
ValueEval fourthveval = singleOperandEvaluate(operands[3], srcCellRow, srcCellCol);
|
||||
if (firstveval instanceof StringValueEval
|
||||
&& secondveval instanceof NumericValueEval
|
||||
&& thirdveval instanceof NumericValueEval
|
||||
&& fourthveval instanceof StringValueEval) {
|
||||
|
||||
StringValueEval oldStrEval = (StringValueEval) firstveval;
|
||||
oldStr = oldStrEval.getStringValue();
|
||||
|
||||
NumericValueEval startNumEval = (NumericValueEval) secondveval;
|
||||
// NOTE: it is safe to cast to int here
|
||||
// because in Excel =REPLACE("task", 2.7, 3, "est")
|
||||
// returns test
|
||||
// so 2.7 must be truncated to 2
|
||||
// and =REPLACE("task", 1, 1.9, "") returns ask
|
||||
// so 1.9 must be truncated to 1
|
||||
startNum = (int) startNumEval.getNumberValue();
|
||||
|
||||
NumericValueEval numCharsEval = (NumericValueEval) thirdveval;
|
||||
numChars = (int) numCharsEval.getNumberValue();
|
||||
|
||||
StringValueEval newStrEval = (StringValueEval) fourthveval;
|
||||
newStr = newStrEval.getStringValue();
|
||||
} else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == null) {
|
||||
if (startNum < 1 || numChars < 0) {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
} else {
|
||||
StringBuffer strBuff = new StringBuffer(oldStr);
|
||||
// remove any characters that should be replaced
|
||||
if (startNum <= oldStr.length() && numChars != 0) {
|
||||
strBuff.delete(startNum - 1, startNum - 1 + numChars);
|
||||
}
|
||||
// now insert (or append) newStr
|
||||
if (startNum > strBuff.length()) {
|
||||
strBuff.append(newStr);
|
||||
} else {
|
||||
strBuff.insert(startNum - 1, newStr);
|
||||
}
|
||||
retval = new StringEval(strBuff.toString());
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,98 @@
|
|||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
public class Substitute extends NotImplementedFunction {
|
||||
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.NumericValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* An implementation of the SUBSTITUTE function:
|
||||
* Substitutes text in a text string with new text, some number of times.
|
||||
* @author Manda Wilson < wilson at c bio dot msk cc dot org >
|
||||
*/
|
||||
public class Substitute extends TextFunction {
|
||||
private static final int REPLACE_ALL = -1;
|
||||
|
||||
/**
|
||||
*Substitutes text in a text string with new text, some number of times.
|
||||
*
|
||||
* @see org.apache.poi.hssf.record.formula.eval.Eval
|
||||
*/
|
||||
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
|
||||
Eval retval = null;
|
||||
String oldStr = null;
|
||||
String searchStr = null;
|
||||
String newStr = null;
|
||||
int numToReplace = REPLACE_ALL;
|
||||
|
||||
switch (operands.length) {
|
||||
default:
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
case 4:
|
||||
ValueEval fourthveval = singleOperandEvaluate(operands[3], srcCellRow, srcCellCol);
|
||||
if (fourthveval instanceof NumericValueEval) {
|
||||
NumericValueEval numToReplaceEval = (NumericValueEval) fourthveval;
|
||||
// NOTE: it is safe to cast to int here
|
||||
// because in Excel =SUBSTITUTE("teststr","t","T",1.9)
|
||||
// returns Teststr
|
||||
// so 1.9 must be truncated to 1
|
||||
numToReplace = (int) numToReplaceEval.getNumberValue();
|
||||
} else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
case 3:
|
||||
// first operand is text string containing characters to replace
|
||||
// second operand is text to find
|
||||
// third operand is replacement text
|
||||
ValueEval firstveval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
|
||||
ValueEval secondveval = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
|
||||
ValueEval thirdveval = singleOperandEvaluate(operands[2], srcCellRow, srcCellCol);
|
||||
if (firstveval instanceof StringValueEval
|
||||
&& secondveval instanceof StringValueEval
|
||||
&& thirdveval instanceof StringValueEval) {
|
||||
|
||||
StringValueEval oldStrEval = (StringValueEval) firstveval;
|
||||
oldStr = oldStrEval.getStringValue();
|
||||
|
||||
StringValueEval searchStrEval = (StringValueEval) secondveval;
|
||||
searchStr = searchStrEval.getStringValue();
|
||||
|
||||
StringValueEval newStrEval = (StringValueEval) thirdveval;
|
||||
newStr = newStrEval.getStringValue();
|
||||
} else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == null) {
|
||||
if (numToReplace != REPLACE_ALL && numToReplace < 1) {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
} else if (searchStr.length() == 0) {
|
||||
retval = new StringEval(oldStr);
|
||||
} else {
|
||||
StringBuffer strBuff = new StringBuffer();
|
||||
int startIndex = 0;
|
||||
int nextMatch = -1;
|
||||
for (int leftToReplace = numToReplace;
|
||||
(leftToReplace > 0 || numToReplace == REPLACE_ALL)
|
||||
&& (nextMatch = oldStr.indexOf(searchStr, startIndex)) != -1;
|
||||
leftToReplace--) {
|
||||
// store everything from end of last match to start of this match
|
||||
strBuff.append(oldStr.substring(startIndex, nextMatch));
|
||||
strBuff.append(newStr);
|
||||
startIndex = nextMatch + searchStr.length();
|
||||
}
|
||||
// store everything from end of last match to end of string
|
||||
if (startIndex < oldStr.length()) {
|
||||
strBuff.append(oldStr.substring(startIndex));
|
||||
}
|
||||
retval = new StringEval(strBuff.toString());
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue