Refactored TextFunctions. Some minor fixes - test cases added.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@694877 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
324d79a0ba
commit
a0769d4082
@ -44,7 +44,7 @@ public final class ConcatEval implements OperationEval {
|
||||
if (ve instanceof StringValueEval) {
|
||||
StringValueEval sve = (StringValueEval) ve;
|
||||
sb.append(sve.getStringValue());
|
||||
} else if (ve instanceof BlankEval) {
|
||||
} else if (ve == BlankEval.INSTANCE) {
|
||||
// do nothing
|
||||
} else { // must be an error eval
|
||||
throw new RuntimeException("Unexpected value type ("
|
||||
|
@ -105,8 +105,8 @@ public abstract class FunctionEval implements OperationEval {
|
||||
retval[28] = new Lookup(); // LOOKUP
|
||||
retval[29] = new Index(); // INDEX
|
||||
retval[30] = new Rept(); // REPT
|
||||
retval[31] = new Mid(); // MID
|
||||
retval[32] = new Len(); // LEN
|
||||
retval[31] = TextFunction.MID;
|
||||
retval[32] = TextFunction.LEN;
|
||||
retval[33] = new Value(); // VALUE
|
||||
retval[34] = new True(); // TRUE
|
||||
retval[35] = new False(); // FALSE
|
||||
@ -185,13 +185,13 @@ public abstract class FunctionEval implements OperationEval {
|
||||
retval[109] = NumericFunction.LOG;
|
||||
retval[110] = new Exec(); // EXEC
|
||||
retval[111] = new Char(); // CHAR
|
||||
retval[112] = new Lower(); // LOWER
|
||||
retval[113] = new Upper(); // UPPER
|
||||
retval[112] = TextFunction.LOWER;
|
||||
retval[113] = TextFunction.UPPER;
|
||||
retval[114] = new Proper(); // PROPER
|
||||
retval[115] = new Left(); // LEFT
|
||||
retval[116] = new Right(); // RIGHT
|
||||
retval[117] = new Exact(); // EXACT
|
||||
retval[118] = new Trim(); // TRIM
|
||||
retval[115] = TextFunction.LEFT;
|
||||
retval[116] = TextFunction.RIGHT;
|
||||
retval[117] = TextFunction.EXACT;
|
||||
retval[118] = TextFunction.TRIM;
|
||||
retval[119] = new Replace(); // REPLACE
|
||||
retval[120] = new Substitute(); // SUBSTITUTE
|
||||
retval[121] = new Code(); // CODE
|
||||
@ -394,7 +394,7 @@ public abstract class FunctionEval implements OperationEval {
|
||||
retval[332] = new Tinv(); // TINV
|
||||
retval[334] = new NotImplementedFunction(); // MOVIECOMMAND
|
||||
retval[335] = new NotImplementedFunction(); // GETMOVIE
|
||||
retval[336] = new Concatenate(); // CONCATENATE
|
||||
retval[336] = TextFunction.CONCATENATE;
|
||||
retval[337] = NumericFunction.POWER;
|
||||
retval[338] = new NotImplementedFunction(); // PIVOTADDDATA
|
||||
retval[339] = new NotImplementedFunction(); // GETPIVOTTABLE
|
||||
|
@ -272,12 +272,7 @@ public final class OperandResolver {
|
||||
StringValueEval sve = (StringValueEval) ve;
|
||||
return sve.getStringValue();
|
||||
}
|
||||
if (ve instanceof NumberEval) {
|
||||
NumberEval neval = (NumberEval) ve;
|
||||
return neval.getStringValue();
|
||||
}
|
||||
|
||||
if (ve instanceof BlankEval) {
|
||||
if (ve == BlankEval.INSTANCE) {
|
||||
return "";
|
||||
}
|
||||
throw new IllegalArgumentException("Unexpected eval class (" + ve.getClass().getName() + ")");
|
||||
@ -289,7 +284,7 @@ public final class OperandResolver {
|
||||
*/
|
||||
public static Boolean coerceValueToBoolean(ValueEval ve, boolean stringsAreBlanks) throws EvaluationException {
|
||||
|
||||
if (ve == null || ve instanceof BlankEval) {
|
||||
if (ve == null || ve == BlankEval.INSTANCE) {
|
||||
// TODO - remove 've == null' condition once AreaEval is fixed
|
||||
return null;
|
||||
}
|
||||
@ -297,7 +292,7 @@ public final class OperandResolver {
|
||||
return Boolean.valueOf(((BoolEval) ve).getBooleanValue());
|
||||
}
|
||||
|
||||
if (ve instanceof BlankEval) {
|
||||
if (ve == BlankEval.INSTANCE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Created on May 15, 2005
|
||||
*
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
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.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public class Concatenate extends TextFunction {
|
||||
|
||||
|
||||
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
|
||||
ValueEval retval = null;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
for (int i=0, iSize=operands.length; i<iSize; i++) {
|
||||
ValueEval ve = singleOperandEvaluate(operands[i], srcCellRow, srcCellCol);
|
||||
if (ve instanceof StringValueEval) {
|
||||
StringValueEval sve = (StringValueEval) ve;
|
||||
sb.append(sve.getStringValue());
|
||||
}
|
||||
else if (ve instanceof BlankEval) {}
|
||||
else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == null) {
|
||||
retval = new StringEval(sb.toString());
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Created on May 15, 2005
|
||||
*
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.BlankEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
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.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public class Exact extends TextFunction {
|
||||
|
||||
|
||||
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
|
||||
ValueEval retval = null;
|
||||
String s0 = null;
|
||||
String s1 = null;
|
||||
|
||||
switch (operands.length) {
|
||||
default:
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
break;
|
||||
case 2:
|
||||
ValueEval ve = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
|
||||
if (ve instanceof StringValueEval) {
|
||||
StringValueEval sve = (StringValueEval) ve;
|
||||
s0 = sve.getStringValue();
|
||||
}
|
||||
else if (ve instanceof BlankEval) {
|
||||
s0 = StringEval.EMPTY_INSTANCE.getStringValue();
|
||||
}
|
||||
else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (retval == null) {
|
||||
ve = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
|
||||
if (ve instanceof StringValueEval) {
|
||||
StringValueEval sve = (StringValueEval) ve;
|
||||
s1 = sve.getStringValue();
|
||||
}
|
||||
else if (ve instanceof BlankEval) {
|
||||
s1 = StringEval.EMPTY_INSTANCE.getStringValue();
|
||||
}
|
||||
else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == null) {
|
||||
boolean b = s0.equals(s1);
|
||||
retval = b ? BoolEval.TRUE : BoolEval.FALSE;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Created on May 15, 2005
|
||||
*
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
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.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RefEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public class Left extends TextFunction {
|
||||
|
||||
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
|
||||
Eval retval = ErrorEval.VALUE_INVALID;
|
||||
int index = 1;
|
||||
switch (operands.length) {
|
||||
default:
|
||||
break;
|
||||
case 2:
|
||||
Eval indexEval = operands[1];
|
||||
index = evaluateAsInteger(indexEval);
|
||||
if (index < 0) {
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
ValueEval veval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
|
||||
String str = null;
|
||||
if (veval instanceof StringEval) {
|
||||
StringEval stringEval = (StringEval) veval;
|
||||
str = stringEval.getStringValue();
|
||||
}
|
||||
else if (veval instanceof BoolEval) {
|
||||
BoolEval beval = (BoolEval) veval;
|
||||
str = beval.getBooleanValue() ? "TRUE" : "FALSE";
|
||||
}
|
||||
else if (veval instanceof NumberEval) {
|
||||
NumberEval neval = (NumberEval) veval;
|
||||
str = neval.getStringValue();
|
||||
}
|
||||
if (null != str) {
|
||||
str = str.substring(0, Math.min(str.length(), index));
|
||||
retval = new StringEval(str);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
protected int evaluateAsInteger(Eval eval) {
|
||||
int numval = -1;
|
||||
if (eval instanceof NumberEval) {
|
||||
NumberEval neval = (NumberEval) eval;
|
||||
double d = neval.getNumberValue();
|
||||
numval = (int) d;
|
||||
}
|
||||
else if (eval instanceof StringEval) {
|
||||
StringEval seval = (StringEval) eval;
|
||||
String s = seval.getStringValue();
|
||||
try {
|
||||
double d = Double.parseDouble(s);
|
||||
numval = (int) d;
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
else if (eval instanceof BoolEval) {
|
||||
BoolEval beval = (BoolEval) eval;
|
||||
numval = beval.getBooleanValue() ? 1 : 0;
|
||||
}
|
||||
else if (eval instanceof RefEval) {
|
||||
numval = evaluateAsInteger(xlateRefEval((RefEval) eval));
|
||||
}
|
||||
return numval;
|
||||
}
|
||||
|
||||
protected Eval xlateRefEval(RefEval reval) {
|
||||
Eval retval = reval.getInnerValueEval();
|
||||
|
||||
if (retval instanceof RefEval) {
|
||||
retval = xlateRefEval((RefEval) retval);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
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.EvaluationException;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.OperandResolver;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public final class Len extends TextFunction {
|
||||
|
||||
public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
|
||||
|
||||
if(args.length != 1) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
ValueEval veval = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
|
||||
|
||||
String str = OperandResolver.coerceValueToString(veval);
|
||||
|
||||
return new NumberEval(str.length());
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Created on May 15, 2005
|
||||
*
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
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.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public class Lower extends TextFunction {
|
||||
|
||||
|
||||
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
|
||||
ValueEval retval = null;
|
||||
String s = null;
|
||||
|
||||
switch (operands.length) {
|
||||
default:
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
break;
|
||||
case 1:
|
||||
ValueEval ve = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
|
||||
if (ve instanceof StringValueEval) {
|
||||
StringValueEval sve = (StringValueEval) ve;
|
||||
s = sve.getStringValue();
|
||||
}
|
||||
else if (ve instanceof BlankEval) {}
|
||||
else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == null) {
|
||||
s = (s == null) ? EMPTY_STRING : s;
|
||||
retval = new StringEval(s.toLowerCase());
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
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.EvaluationException;
|
||||
import org.apache.poi.hssf.record.formula.eval.OperandResolver;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* An implementation of the MID function<br/> MID returns a specific number of
|
||||
* characters from a text string, starting at the specified position.<p/>
|
||||
*
|
||||
* <b>Syntax<b>:<br/> <b>MID</b>(<b>text</b>, <b>start_num</b>,
|
||||
* <b>num_chars</b>)<br/>
|
||||
*
|
||||
* @author Manda Wilson < wilson at c bio dot msk cc dot org >
|
||||
*/
|
||||
public class Mid implements 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.
|
||||
*
|
||||
* @see org.apache.poi.hssf.record.formula.eval.Eval
|
||||
*/
|
||||
public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
|
||||
if (args.length != 3) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
String text;
|
||||
int startIx; // zero based
|
||||
int numChars;
|
||||
|
||||
try {
|
||||
ValueEval evText = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
|
||||
text = OperandResolver.coerceValueToString(evText);
|
||||
int startCharNum = evaluateNumberArg(args[1], srcCellRow, srcCellCol);
|
||||
numChars = evaluateNumberArg(args[2], srcCellRow, srcCellCol);
|
||||
startIx = startCharNum - 1; // convert to zero-based
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
|
||||
int len = text.length();
|
||||
if (startIx < 0) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
if (numChars < 0) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
if (numChars < 0 || startIx > len) {
|
||||
return new StringEval("");
|
||||
}
|
||||
int endIx = startIx + numChars;
|
||||
if (endIx > len) {
|
||||
endIx = len;
|
||||
}
|
||||
String result = text.substring(startIx, endIx);
|
||||
return new StringEval(result);
|
||||
|
||||
}
|
||||
|
||||
private static int evaluateNumberArg(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
|
||||
ValueEval ev = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
|
||||
// Note - for start_num arg, blank/zero causes error(#VALUE!),
|
||||
// but for num_chars causes empty string to be returned.
|
||||
return OperandResolver.coerceValueToInt(ev);
|
||||
}
|
||||
}
|
@ -1,112 +1,70 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Created on May 15, 2005
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
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.EvaluationException;
|
||||
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.
|
||||
* An implementation of the Excel REPLACE() function<p/>:
|
||||
* Replaces part of a text string based on the number of characters
|
||||
* you specify, with another text string.<br/>
|
||||
*
|
||||
* <b>Syntax</b>:<br/>
|
||||
* <b>REPLACE</b>(<b>oldText</b>, <b>startNum</b>, <b>numChars</b>, <b>newText</b>)<p/>
|
||||
*
|
||||
* <b>oldText</b> The text string containing characters to replace<br/>
|
||||
* <b>startNum</b> The position of the first character to replace (1-based)<br/>
|
||||
* <b>numChars</b> The number of characters to replace<br/>
|
||||
* <b>newText</b> The new text value to replace the removed section<br/>
|
||||
*
|
||||
* @author Manda Wilson < wilson at c bio dot msk cc dot org >
|
||||
*/
|
||||
public class Replace extends TextFunction {
|
||||
public final 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;
|
||||
}
|
||||
protected ValueEval evaluateFunc(Eval[] args, int srcCellRow, short srcCellCol)
|
||||
throws EvaluationException {
|
||||
if (args.length != 4) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
String oldStr = evaluateStringArg(args[0], srcCellRow, srcCellCol);
|
||||
int startNum = evaluateIntArg(args[1], srcCellRow, srcCellCol);
|
||||
int numChars = evaluateIntArg(args[2], srcCellRow, srcCellCol);
|
||||
String newStr = evaluateStringArg(args[3], srcCellRow, srcCellCol);
|
||||
|
||||
if (startNum < 1 || numChars < 0) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
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);
|
||||
}
|
||||
return new StringEval(strBuff.toString());
|
||||
}
|
||||
}
|
||||
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Created on May 15, 2005
|
||||
*
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
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.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RefEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public class Right extends TextFunction {
|
||||
|
||||
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
|
||||
Eval retval = ErrorEval.VALUE_INVALID;
|
||||
int index = 1;
|
||||
switch (operands.length) {
|
||||
default:
|
||||
break;
|
||||
case 2:
|
||||
Eval indexEval = operands[1];
|
||||
index = evaluateAsInteger(indexEval);
|
||||
if (index < 0) {
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
ValueEval veval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
|
||||
String str = null;
|
||||
if (veval instanceof StringEval) {
|
||||
StringEval stringEval = (StringEval) veval;
|
||||
str = stringEval.getStringValue();
|
||||
}
|
||||
else if (veval instanceof BoolEval) {
|
||||
BoolEval beval = (BoolEval) veval;
|
||||
str = beval.getBooleanValue() ? "TRUE" : "FALSE";
|
||||
}
|
||||
else if (veval instanceof NumberEval) {
|
||||
NumberEval neval = (NumberEval) veval;
|
||||
str = neval.getStringValue();
|
||||
}
|
||||
if (null != str) {
|
||||
int strlen = str.length();
|
||||
str = str.substring(Math.max(0, strlen-index));
|
||||
retval = new StringEval(str);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
protected int evaluateAsInteger(Eval eval) {
|
||||
int numval = -1;
|
||||
if (eval instanceof NumberEval) {
|
||||
NumberEval neval = (NumberEval) eval;
|
||||
double d = neval.getNumberValue();
|
||||
numval = (int) d;
|
||||
}
|
||||
else if (eval instanceof StringEval) {
|
||||
StringEval seval = (StringEval) eval;
|
||||
String s = seval.getStringValue();
|
||||
try {
|
||||
double d = Double.parseDouble(s);
|
||||
numval = (int) d;
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
else if (eval instanceof BoolEval) {
|
||||
BoolEval beval = (BoolEval) eval;
|
||||
numval = beval.getBooleanValue() ? 1 : 0;
|
||||
}
|
||||
else if (eval instanceof RefEval) {
|
||||
numval = evaluateAsInteger(xlateRefEval((RefEval) eval));
|
||||
}
|
||||
return numval;
|
||||
}
|
||||
|
||||
protected Eval xlateRefEval(RefEval reval) {
|
||||
Eval retval = reval.getInnerValueEval();
|
||||
|
||||
if (retval instanceof RefEval) {
|
||||
retval = xlateRefEval((RefEval) retval);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
@ -1,30 +1,26 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Created on May 15, 2005
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
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.EvaluationException;
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -32,86 +28,75 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
* 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();
|
||||
public final class Substitute extends TextFunction {
|
||||
|
||||
protected ValueEval evaluateFunc(Eval[] args, int srcCellRow, short srcCellCol)
|
||||
throws EvaluationException {
|
||||
if (args.length < 3 || args.length > 4) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
String oldStr = evaluateStringArg(args[0], srcCellRow, srcCellCol);
|
||||
String searchStr = evaluateStringArg(args[1], srcCellRow, srcCellCol);
|
||||
String newStr = evaluateStringArg(args[2], srcCellRow, srcCellCol);
|
||||
|
||||
String result;
|
||||
switch (args.length) {
|
||||
default:
|
||||
throw new IllegalStateException("Cannot happen");
|
||||
case 4:
|
||||
int instanceNumber = evaluateIntArg(args[3], srcCellRow, srcCellCol);
|
||||
if (instanceNumber < 1) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
result = replaceOneOccurrence(oldStr, searchStr, newStr, instanceNumber);
|
||||
break;
|
||||
case 3:
|
||||
result = replaceAllOccurrences(oldStr, searchStr, newStr);
|
||||
}
|
||||
return new StringEval(result);
|
||||
}
|
||||
|
||||
private static String replaceAllOccurrences(String oldStr, String searchStr, String newStr) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int startIndex = 0;
|
||||
int nextMatch = -1;
|
||||
while (true) {
|
||||
nextMatch = oldStr.indexOf(searchStr, startIndex);
|
||||
if (nextMatch < 0) {
|
||||
// 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());
|
||||
sb.append(oldStr.substring(startIndex));
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// store everything from end of last match to start of this match
|
||||
sb.append(oldStr.substring(startIndex, nextMatch));
|
||||
sb.append(newStr);
|
||||
startIndex = nextMatch + searchStr.length();
|
||||
}
|
||||
}
|
||||
|
||||
private static String replaceOneOccurrence(String oldStr, String searchStr, String newStr, int instanceNumber) {
|
||||
if (searchStr.length() < 1) {
|
||||
return oldStr;
|
||||
}
|
||||
int startIndex = 0;
|
||||
int nextMatch = -1;
|
||||
int count=0;
|
||||
while (true) {
|
||||
nextMatch = oldStr.indexOf(searchStr, startIndex);
|
||||
if (nextMatch < 0) {
|
||||
// not enough occurrences found - leave unchanged
|
||||
return oldStr;
|
||||
}
|
||||
count++;
|
||||
if (count == instanceNumber) {
|
||||
StringBuffer sb = new StringBuffer(oldStr.length() + newStr.length());
|
||||
sb.append(oldStr.substring(0, nextMatch));
|
||||
sb.append(newStr);
|
||||
sb.append(oldStr.substring(nextMatch + searchStr.length()));
|
||||
return sb.toString();
|
||||
}
|
||||
startIndex = nextMatch + searchStr.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,29 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Created on May 22, 2005
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
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.BoolEval;
|
||||
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.RefEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.OperandResolver;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
@ -33,75 +31,164 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
*
|
||||
*/
|
||||
public abstract class TextFunction implements Function {
|
||||
|
||||
protected static final String EMPTY_STRING = "";
|
||||
|
||||
protected ValueEval singleOperandEvaluate(Eval eval, int srcRow, short srcCol) {
|
||||
ValueEval retval;
|
||||
if (eval instanceof AreaEval) {
|
||||
AreaEval ae = (AreaEval) eval;
|
||||
if (ae.contains(srcRow, srcCol)) { // circular ref!
|
||||
retval = ErrorEval.CIRCULAR_REF_ERROR;
|
||||
}
|
||||
else if (ae.isRow()) {
|
||||
if (ae.containsColumn(srcCol)) {
|
||||
ValueEval ve = ae.getValueAt(ae.getFirstRow(), srcCol);
|
||||
retval = attemptXlateToText(ve);
|
||||
}
|
||||
else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
}
|
||||
else if (ae.isColumn()) {
|
||||
if (ae.containsRow(srcRow)) {
|
||||
ValueEval ve = ae.getValueAt(srcRow, ae.getFirstColumn());
|
||||
retval = attemptXlateToText(ve);
|
||||
}
|
||||
else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = attemptXlateToText((ValueEval) eval);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* converts from Different ValueEval types to StringEval.
|
||||
* Note: AreaEvals are not handled, if arg is an AreaEval,
|
||||
* the returned value is ErrorEval.VALUE_INVALID
|
||||
* @param ve
|
||||
*/
|
||||
protected ValueEval attemptXlateToText(ValueEval ve) {
|
||||
ValueEval retval;
|
||||
if (ve instanceof StringValueEval) {
|
||||
retval = ve;
|
||||
}
|
||||
else if (ve instanceof RefEval) {
|
||||
RefEval re = (RefEval) ve;
|
||||
ValueEval ive = re.getInnerValueEval();
|
||||
if (ive instanceof StringValueEval) {
|
||||
retval = ive;
|
||||
}
|
||||
else if (ive instanceof BlankEval) {
|
||||
retval = ive;
|
||||
}
|
||||
else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
}
|
||||
else if (ve instanceof BlankEval) {
|
||||
retval = ve;
|
||||
}
|
||||
else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
protected static final String EMPTY_STRING = "";
|
||||
|
||||
protected static final String evaluateStringArg(Eval eval, int srcRow, short srcCol) throws EvaluationException {
|
||||
ValueEval ve = OperandResolver.getSingleValue(eval, srcRow, srcCol);
|
||||
return OperandResolver.coerceValueToString(ve);
|
||||
}
|
||||
protected static final int evaluateIntArg(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
|
||||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
|
||||
return OperandResolver.coerceValueToInt(ve);
|
||||
}
|
||||
|
||||
public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
|
||||
try {
|
||||
return evaluateFunc(args, srcCellRow, srcCellCol);
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract ValueEval evaluateFunc(Eval[] args, int srcCellRow, short srcCellCol) throws EvaluationException;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
private static abstract class SingleArgTextFunc extends TextFunction {
|
||||
|
||||
protected SingleArgTextFunc() {
|
||||
// no fields to initialise
|
||||
}
|
||||
protected ValueEval evaluateFunc(Eval[] args, int srcCellRow, short srcCellCol)
|
||||
throws EvaluationException {
|
||||
if (args.length != 1) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
String arg = evaluateStringArg(args[0], srcCellRow, srcCellCol);
|
||||
return evaluate(arg);
|
||||
}
|
||||
protected abstract ValueEval evaluate(String arg);
|
||||
}
|
||||
|
||||
public static final Function LEN = new SingleArgTextFunc() {
|
||||
protected ValueEval evaluate(String arg) {
|
||||
return new NumberEval(arg.length());
|
||||
}
|
||||
};
|
||||
public static final Function LOWER = new SingleArgTextFunc() {
|
||||
protected ValueEval evaluate(String arg) {
|
||||
return new StringEval(arg.toLowerCase());
|
||||
}
|
||||
};
|
||||
public static final Function UPPER = new SingleArgTextFunc() {
|
||||
protected ValueEval evaluate(String arg) {
|
||||
return new StringEval(arg.toUpperCase());
|
||||
}
|
||||
};
|
||||
/**
|
||||
* An implementation of the TRIM function:
|
||||
* Removes leading and trailing spaces from value if evaluated operand
|
||||
* value is string.
|
||||
* @author Manda Wilson < wilson at c bio dot msk cc dot org >
|
||||
*/
|
||||
public static final Function TRIM = new SingleArgTextFunc() {
|
||||
protected ValueEval evaluate(String arg) {
|
||||
return new StringEval(arg.trim());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An implementation of the MID function<br/>
|
||||
* MID returns a specific number of
|
||||
* characters from a text string, starting at the specified position.<p/>
|
||||
*
|
||||
* <b>Syntax<b>:<br/> <b>MID</b>(<b>text</b>, <b>start_num</b>,
|
||||
* <b>num_chars</b>)<br/>
|
||||
*
|
||||
* @author Manda Wilson < wilson at c bio dot msk cc dot org >
|
||||
*/
|
||||
public static final Function MID = new TextFunction() {
|
||||
|
||||
protected ValueEval evaluateFunc(Eval[] args, int srcCellRow, short srcCellCol)
|
||||
throws EvaluationException {
|
||||
if (args.length != 3) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
String text = evaluateStringArg(args[0], srcCellRow, srcCellCol);
|
||||
int startCharNum = evaluateIntArg(args[1], srcCellRow, srcCellCol);
|
||||
int numChars = evaluateIntArg(args[2], srcCellRow, srcCellCol);
|
||||
int startIx = startCharNum - 1; // convert to zero-based
|
||||
|
||||
// Note - for start_num arg, blank/zero causes error(#VALUE!),
|
||||
// but for num_chars causes empty string to be returned.
|
||||
if (startIx < 0) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
if (numChars < 0) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
int len = text.length();
|
||||
if (numChars < 0 || startIx > len) {
|
||||
return new StringEval("");
|
||||
}
|
||||
int endIx = Math.min(startIx + numChars, len);
|
||||
String result = text.substring(startIx, endIx);
|
||||
return new StringEval(result);
|
||||
}
|
||||
};
|
||||
|
||||
private static final class LeftRight extends TextFunction {
|
||||
|
||||
private final boolean _isLeft;
|
||||
protected LeftRight(boolean isLeft) {
|
||||
_isLeft = isLeft;
|
||||
}
|
||||
protected ValueEval evaluateFunc(Eval[] args, int srcCellRow, short srcCellCol)
|
||||
throws EvaluationException {
|
||||
if (args.length != 2) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
String arg = evaluateStringArg(args[0], srcCellRow, srcCellCol);
|
||||
int index = evaluateIntArg(args[1], srcCellRow, srcCellCol);
|
||||
|
||||
String result;
|
||||
if (_isLeft) {
|
||||
result = arg.substring(0, Math.min(arg.length(), index));
|
||||
} else {
|
||||
result = arg.substring(Math.max(0, arg.length()-index));
|
||||
}
|
||||
return new StringEval(result);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Function LEFT = new LeftRight(true);
|
||||
public static final Function RIGHT = new LeftRight(false);
|
||||
|
||||
public static final Function CONCATENATE = new TextFunction() {
|
||||
|
||||
protected ValueEval evaluateFunc(Eval[] args, int srcCellRow, short srcCellCol)
|
||||
throws EvaluationException {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i=0, iSize=args.length; i<iSize; i++) {
|
||||
sb.append(evaluateStringArg(args[i], srcCellRow, srcCellCol));
|
||||
}
|
||||
return new StringEval(sb.toString());
|
||||
}
|
||||
};
|
||||
|
||||
public static final Function EXACT = new TextFunction() {
|
||||
|
||||
protected ValueEval evaluateFunc(Eval[] args, int srcCellRow, short srcCellCol)
|
||||
throws EvaluationException {
|
||||
if (args.length != 2) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
String s0 = evaluateStringArg(args[0], srcCellRow, srcCellCol);
|
||||
String s1 = evaluateStringArg(args[1], srcCellRow, srcCellCol);
|
||||
return BoolEval.valueOf(s0.equals(s1));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
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.EvaluationException;
|
||||
import org.apache.poi.hssf.record.formula.eval.OperandResolver;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* An implementation of the TRIM function:
|
||||
* Removes leading and trailing spaces from value if evaluated operand
|
||||
* value is string.
|
||||
* @author Manda Wilson < wilson at c bio dot msk cc dot org >
|
||||
*/
|
||||
public final class Trim extends TextFunction {
|
||||
|
||||
public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
|
||||
|
||||
if(args.length != 1) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
ValueEval veval = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
|
||||
|
||||
String str = OperandResolver.coerceValueToString(veval);
|
||||
str = str.trim();
|
||||
if(str.length() < 1) {
|
||||
return StringEval.EMPTY_INSTANCE;
|
||||
}
|
||||
return new StringEval(str);
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Created on May 15, 2005
|
||||
*
|
||||
*/
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
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.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public class Upper extends TextFunction {
|
||||
|
||||
|
||||
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
|
||||
ValueEval retval = null;
|
||||
String s = null;
|
||||
|
||||
switch (operands.length) {
|
||||
default:
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
break;
|
||||
case 1:
|
||||
ValueEval ve = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
|
||||
if (ve instanceof StringValueEval) {
|
||||
StringValueEval sve = (StringValueEval) ve;
|
||||
s = sve.getStringValue();
|
||||
}
|
||||
else if (ve instanceof BlankEval) {}
|
||||
else {
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == null) {
|
||||
s = (s == null) ? EMPTY_STRING : s;
|
||||
retval = new StringEval(s.toUpperCase());
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
Binary file not shown.
@ -35,7 +35,7 @@ public final class TestLen extends TestCase {
|
||||
|
||||
private static Eval invokeLen(Eval text) {
|
||||
Eval[] args = new Eval[] { text, };
|
||||
return new Len().evaluate(args, -1, (short)-1);
|
||||
return TextFunction.LEN.evaluate(args, -1, (short)-1);
|
||||
}
|
||||
|
||||
private void confirmLen(Eval text, int expected) {
|
||||
|
@ -38,7 +38,7 @@ public final class TestMid extends TestCase {
|
||||
|
||||
private static Eval invokeMid(Eval text, Eval startPos, Eval numChars) {
|
||||
Eval[] args = new Eval[] { text, startPos, numChars, };
|
||||
return new Mid().evaluate(args, -1, (short)-1);
|
||||
return TextFunction.MID.evaluate(args, -1, (short)-1);
|
||||
}
|
||||
|
||||
private void confirmMid(Eval text, Eval startPos, Eval numChars, String expected) {
|
||||
|
@ -35,7 +35,7 @@ public final class TestTrim extends TestCase {
|
||||
|
||||
private static Eval invokeTrim(Eval text) {
|
||||
Eval[] args = new Eval[] { text, };
|
||||
return new Trim().evaluate(args, -1, (short)-1);
|
||||
return TextFunction.TRIM.evaluate(args, -1, (short)-1);
|
||||
}
|
||||
|
||||
private void confirmTrim(Eval text, String expected) {
|
||||
|
Loading…
Reference in New Issue
Block a user