added implementations for CLEAN(), CHAR() and ADDRESS(), see Bugzilla 50607
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1060788 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
db25367237
commit
48544b470b
@ -34,6 +34,7 @@
|
||||
|
||||
<changes>
|
||||
<release version="3.8-beta1" date="2010-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="add">50607 - Added implementation for CLEAN(), CHAR() and ADDRESS()</action>
|
||||
<action dev="poi-developers" type="add">50587 - Improved documentation on user-defined functions</action>
|
||||
<action dev="poi-developers" type="add">Inside ExtractorFactory, support finding embedded OOXML documents and providing extractors for them</action>
|
||||
<action dev="poi-developers" type="add">Partial HDGF LZW compression support</action>
|
||||
|
@ -130,6 +130,7 @@ public final class FunctionEval {
|
||||
|
||||
retval[109] = NumericFunction.LOG;
|
||||
|
||||
retval[111] = TextFunction.CHAR;
|
||||
retval[112] = TextFunction.LOWER;
|
||||
retval[113] = TextFunction.UPPER;
|
||||
|
||||
@ -148,7 +149,7 @@ public final class FunctionEval {
|
||||
retval[130] = new T();
|
||||
|
||||
retval[ID.INDIRECT] = null; // Indirect.evaluate has different signature
|
||||
|
||||
retval[162] = TextFunction.CLEAN; //Aniket Banerjee
|
||||
retval[169] = new Counta();
|
||||
|
||||
retval[183] = AggregateFunction.PRODUCT;
|
||||
@ -161,7 +162,7 @@ public final class FunctionEval {
|
||||
|
||||
retval[212] = NumericFunction.ROUNDUP;
|
||||
retval[213] = NumericFunction.ROUNDDOWN;
|
||||
|
||||
retval[219] = new Address(); //Aniket Banerjee
|
||||
retval[220] = new Days360();
|
||||
retval[221] = new Today();
|
||||
|
||||
|
103
src/java/org/apache/poi/ss/formula/functions/Address.java
Normal file
103
src/java/org/apache/poi/ss/formula/functions/Address.java
Normal file
@ -0,0 +1,103 @@
|
||||
/* ====================================================================
|
||||
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.ss.formula.functions;
|
||||
|
||||
import org.apache.poi.ss.formula.SheetNameFormatter;
|
||||
import org.apache.poi.ss.formula.eval.*;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
|
||||
/**
|
||||
* Creates a text reference as text, given specified row and column numbers.
|
||||
*
|
||||
* @author Aniket Banerjee (banerjee@google.com)
|
||||
*/
|
||||
public class Address implements Function {
|
||||
public static final int REF_ABSOLUTE = 1;
|
||||
public static final int REF_ROW_ABSOLUTE_COLUMN_RELATIVE = 2;
|
||||
public static final int REF_ROW_RELATIVE_RELATIVE_ABSOLUTE = 3;
|
||||
public static final int REF_RELATIVE = 4;
|
||||
|
||||
public ValueEval evaluate(ValueEval[] args, int srcRowIndex,
|
||||
int srcColumnIndex) {
|
||||
if(args.length < 2 || args.length > 5) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
try {
|
||||
boolean pAbsRow, pAbsCol;
|
||||
|
||||
int row = (int)NumericFunction.singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex);
|
||||
int col = (int)NumericFunction.singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex);
|
||||
|
||||
int refType;
|
||||
if(args.length > 2){
|
||||
refType = (int)NumericFunction.singleOperandEvaluate(args[2], srcRowIndex, srcColumnIndex);
|
||||
} else {
|
||||
refType = REF_ABSOLUTE;
|
||||
}
|
||||
switch (refType){
|
||||
case REF_ABSOLUTE:
|
||||
pAbsRow = true;
|
||||
pAbsCol = true;
|
||||
break;
|
||||
case REF_ROW_ABSOLUTE_COLUMN_RELATIVE:
|
||||
pAbsRow = true;
|
||||
pAbsCol = false;
|
||||
break;
|
||||
case REF_ROW_RELATIVE_RELATIVE_ABSOLUTE:
|
||||
pAbsRow = false;
|
||||
pAbsCol = true;
|
||||
break;
|
||||
case REF_RELATIVE:
|
||||
pAbsRow = false;
|
||||
pAbsCol = false;
|
||||
break;
|
||||
default:
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
|
||||
boolean a1;
|
||||
if(args.length > 3){
|
||||
ValueEval ve = OperandResolver.getSingleValue(args[3], srcRowIndex, srcColumnIndex);
|
||||
// TODO R1C1 style is not yet supported
|
||||
a1 = ve == MissingArgEval.instance ? true : OperandResolver.coerceValueToBoolean(ve, false);
|
||||
} else {
|
||||
a1 = true;
|
||||
}
|
||||
|
||||
String sheetName;
|
||||
if(args.length == 5){
|
||||
ValueEval ve = OperandResolver.getSingleValue(args[4], srcRowIndex, srcColumnIndex);
|
||||
sheetName = ve == MissingArgEval.instance ? null : OperandResolver.coerceValueToString(ve);
|
||||
} else {
|
||||
sheetName = null;
|
||||
}
|
||||
|
||||
CellReference ref = new CellReference(row - 1, col - 1, pAbsRow, pAbsCol);
|
||||
StringBuffer sb = new StringBuffer(32);
|
||||
if(sheetName != null) {
|
||||
SheetNameFormatter.appendFormat(sb, sheetName);
|
||||
sb.append('!');
|
||||
}
|
||||
sb.append(ref.formatAsString());
|
||||
|
||||
return new StringEval(sb.toString());
|
||||
|
||||
} catch (EvaluationException e){
|
||||
return e.getErrorEval();
|
||||
}
|
||||
}
|
||||
}
|
@ -83,6 +83,25 @@ public abstract class TextFunction implements Function {
|
||||
protected abstract ValueEval evaluate(String arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the character specified by a number.
|
||||
*/
|
||||
public static final Function CHAR = new Fixed1ArgFunction() {
|
||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
|
||||
int arg;
|
||||
try {
|
||||
arg = evaluateIntArg(arg0, srcRowIndex, srcColumnIndex);
|
||||
if (arg < 0 || arg >= 256) {
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
return new StringEval(String.valueOf((char)arg));
|
||||
}
|
||||
};
|
||||
|
||||
public static final Function LEN = new SingleArgTextFunc() {
|
||||
protected ValueEval evaluate(String arg) {
|
||||
return new NumberEval(arg.length());
|
||||
@ -110,6 +129,41 @@ public abstract class TextFunction implements Function {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An implementation of the CLEAN function:
|
||||
* In Excel, the Clean function removes all non-printable characters from a string.
|
||||
*
|
||||
* Author: Aniket Banerjee(banerjee@google.com)
|
||||
*/
|
||||
public static final Function CLEAN = new SingleArgTextFunc() {
|
||||
protected ValueEval evaluate(String arg) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < arg.length(); i++) {
|
||||
char c = arg.charAt(i);
|
||||
if (isPrintable(c)) {
|
||||
result.append(c);
|
||||
}
|
||||
}
|
||||
return new StringEval(result.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* From Excel docs: The CLEAN function was designed to remove the first 32 nonprinting characters
|
||||
* in the 7-bit ASCII code (values 0 through 31) from text. In the Unicode character set,
|
||||
* there are additional nonprinting characters (values 127, 129, 141, 143, 144, and 157). By itself,
|
||||
* the CLEAN function does not remove these additional nonprinting characters. To do this task,
|
||||
* use the SUBSTITUTE function to replace the higher value Unicode characters with the 7-bit ASCII
|
||||
* characters for which the TRIM and CLEAN functions were designed.
|
||||
*
|
||||
* @param c the character to test
|
||||
* @return whether the character is printable
|
||||
*/
|
||||
private boolean isPrintable(char c){
|
||||
int charCode = (int)c ;
|
||||
return charCode >= 32;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An implementation of the MID function<br/>
|
||||
* MID returns a specific number of
|
||||
|
@ -60,6 +60,8 @@ public final class AllIndividualFunctionEvaluationTests {
|
||||
result.addTestSuite(TestTrunc.class);
|
||||
result.addTestSuite(TestValue.class);
|
||||
result.addTestSuite(TestXYNumericFunction.class);
|
||||
result.addTestSuite(TestAddress.class);
|
||||
result.addTestSuite(TestClean.class);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,76 @@
|
||||
/* ====================================================================
|
||||
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.ss.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.CellValue;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
|
||||
public final class TestAddress extends TestCase {
|
||||
|
||||
public void testAddress() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFCell cell = wb.createSheet().createRow(0).createCell(0);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
|
||||
String formulaText = "ADDRESS(1,2)";
|
||||
confirmResult(fe, cell, formulaText, "$B$1");
|
||||
|
||||
formulaText = "ADDRESS(22,44)";
|
||||
confirmResult(fe, cell, formulaText, "$AR$22");
|
||||
|
||||
formulaText = "ADDRESS(1,1)";
|
||||
confirmResult(fe, cell, formulaText, "$A$1");
|
||||
|
||||
formulaText = "ADDRESS(1,128)";
|
||||
confirmResult(fe, cell, formulaText, "$DX$1");
|
||||
|
||||
formulaText = "ADDRESS(1,512)";
|
||||
confirmResult(fe, cell, formulaText, "$SR$1");
|
||||
|
||||
formulaText = "ADDRESS(1,1000)";
|
||||
confirmResult(fe, cell, formulaText, "$ALL$1");
|
||||
|
||||
formulaText = "ADDRESS(1,10000)";
|
||||
confirmResult(fe, cell, formulaText, "$NTP$1");
|
||||
|
||||
formulaText = "ADDRESS(2,3)";
|
||||
confirmResult(fe, cell, formulaText, "$C$2");
|
||||
|
||||
formulaText = "ADDRESS(2,3,2)";
|
||||
confirmResult(fe, cell, formulaText, "C$2");
|
||||
|
||||
formulaText = "ADDRESS(2,3,2,,\"EXCEL SHEET\")";
|
||||
confirmResult(fe, cell, formulaText, "'EXCEL SHEET'!C$2");
|
||||
|
||||
formulaText = "ADDRESS(2,3,3,TRUE,\"[Book1]Sheet1\")";
|
||||
confirmResult(fe, cell, formulaText, "'[Book1]Sheet1'!$C2");
|
||||
}
|
||||
|
||||
private static void confirmResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText,
|
||||
String expectedResult) {
|
||||
cell.setCellFormula(formulaText);
|
||||
fe.notifyUpdateCell(cell);
|
||||
CellValue result = fe.evaluate(cell);
|
||||
assertEquals(result.getCellType(), HSSFCell.CELL_TYPE_STRING);
|
||||
assertEquals(expectedResult, result.getStringValue());
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/* ====================================================================
|
||||
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.ss.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.CellValue;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public final class TestClean extends TestCase {
|
||||
|
||||
public void testClean() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFCell cell = wb.createSheet().createRow(0).createCell(0);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
|
||||
String[] asserts = {
|
||||
"aniket\u0007\u0017\u0019", "aniket",
|
||||
"\u0011aniket\u0007\u0017\u0010", "aniket",
|
||||
"\u0011aniket\u0007\u0017\u007F", "aniket\u007F",
|
||||
"\u2116aniket\u2211\uFB5E\u2039", "\u2116aniket\u2211\uFB5E\u2039",
|
||||
};
|
||||
|
||||
for(int i = 0; i < asserts.length; i+= 2){
|
||||
String formulaText = "CLEAN(\"" + asserts[i] + "\")";
|
||||
confirmResult(fe, cell, formulaText, asserts[i + 1]);
|
||||
}
|
||||
|
||||
asserts = new String[] {
|
||||
"CHAR(7)&\"text\"&CHAR(7)", "text",
|
||||
"CHAR(7)&\"text\"&CHAR(17)", "text",
|
||||
"CHAR(181)&\"text\"&CHAR(190)", "\u00B5text\u00BE",
|
||||
"\"text\"&CHAR(160)&\"'\"", "text\u00A0'",
|
||||
};
|
||||
for(int i = 0; i < asserts.length; i+= 2){
|
||||
String formulaText = "CLEAN(" + asserts[i] + ")";
|
||||
confirmResult(fe, cell, formulaText, asserts[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void confirmResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText,
|
||||
String expectedResult) {
|
||||
cell.setCellFormula(formulaText);
|
||||
fe.notifyUpdateCell(cell);
|
||||
CellValue result = fe.evaluate(cell);
|
||||
assertEquals(result.getCellType(), HSSFCell.CELL_TYPE_STRING);
|
||||
assertEquals(expectedResult, result.getStringValue());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user