Merged revisions 707953,708242,708252,708260,708262,708286 via svnmerge from

https://svn.apache.org/repos/asf/poi/trunk

........
  r707953 | josh | 2008-10-26 01:17:06 -0700 (Sun, 26 Oct 2008) | 1 line
  
  Bugzilla 45966 - added implementation for FIND function (patch from Torstein Tauno Svendsen).
........
  r708242 | nick | 2008-10-27 10:26:52 -0700 (Mon, 27 Oct 2008) | 1 line
  
  Link typo fix
........
  r708252 | nick | 2008-10-27 10:59:39 -0700 (Mon, 27 Oct 2008) | 1 line
  
  Patch from bug #46092 - fix hssf dev utility
........
  r708260 | josh | 2008-10-27 11:12:09 -0700 (Mon, 27 Oct 2008) | 1 line
  
  Removed obsolete class
........
  r708262 | josh | 2008-10-27 11:16:44 -0700 (Mon, 27 Oct 2008) | 1 line
  
  Bugzilla 46065 - added implementation for VALUE function
........
  r708286 | josh | 2008-10-27 12:24:42 -0700 (Mon, 27 Oct 2008) | 1 line
  
  Preparation for fix for bug 46009.  (Bug visible on ooxml branch, but this change will expose the problem)
........


git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@708325 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-10-27 21:30:02 +00:00
parent 6175b9b1fb
commit 8a6625a237
20 changed files with 523 additions and 182 deletions

View File

@ -37,6 +37,8 @@
<!-- Don't forget to update status.xml too! -->
<release version="3.5-beta4" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">46065 - added implementation for VALUE function</action>
<action dev="POI-DEVELOPERS" type="add">45966 - added implementation for FIND function</action>
<action dev="POI-DEVELOPERS" type="fix">45778 - fixed ObjRecord to read ftLbsData properly</action>
<action dev="POI-DEVELOPERS" type="fix">46053 - fixed evaluation cache dependency analysis when changing blank cells</action>
</release>

View File

@ -99,7 +99,7 @@
org.apache.poi.hssf.record.formula.FormulaParser</strong> class. This class implements a hand
written recursive descent parser.
</p>
<p>Check out the <link href="http://poi.apache.org/javadocs/">javadocs </link> for details.
<p>Check out the <link href="http://poi.apache.org/apidocs/">javadocs </link> for details.
</p>
</section>

View File

@ -34,6 +34,8 @@
<!-- Don't forget to update changes.xml too! -->
<changes>
<release version="3.5-beta4" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">46065 - added implementation for VALUE function</action>
<action dev="POI-DEVELOPERS" type="add">45966 - added implementation for FIND function</action>
<action dev="POI-DEVELOPERS" type="fix">45778 - fixed ObjRecord to read ftLbsData properly</action>
<action dev="POI-DEVELOPERS" type="fix">46053 - fixed evaluation cache dependency analysis when changing blank cells</action>
</release>

View File

@ -15,7 +15,6 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.dev;
import java.io.FileInputStream;
@ -30,7 +29,7 @@ import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.util.Region;
@ -222,7 +221,7 @@ public class HSSF
if (args.length < 2)
{
/* try
try
{
HSSF hssf = new HSSF(args[ 0 ]);
@ -231,26 +230,30 @@ public class HSSF
for (int k = 0; k < wb.getNumberOfSheets(); k++)
{
System.out.println("Sheet " + k);
HSSFSheet sheet = wb.getSheetAt(k);
int rows = sheet.getPhysicalNumberOfRows();
System.out.println("Sheet " + k + " \""
+ wb.getSheetName(k) + "\" has "
+ rows + " row(s).");
for (int r = 0; r < rows; r++)
{
HSSFRow row = sheet.getPhysicalRowAt(r);
int cells = row.getPhysicalNumberOfCells();
System.out.println("ROW " + row.getRowNum());
HSSFRow row = sheet.getRow(r);
int cells = (row != null) ? row.getPhysicalNumberOfCells() : 0;
if (row != null) {
System.out.println("\nROW " + row.getRowNum()
+ " has " + cells + " cell(s).");
}
for (int c = 0; c < cells; c++)
{
HSSFCell cell = row.getPhysicalCellAt(c);
HSSFCell cell = row.getCell(c);
String value = null;
switch (cell.getCellType())
{
case HSSFCell.CELL_TYPE_FORMULA :
value = "FORMULA ";
value = "FORMULA value="
+ cell.getCellFormula();
break;
case HSSFCell.CELL_TYPE_NUMERIC :
@ -275,7 +278,7 @@ public class HSSF
catch (Exception e)
{
e.printStackTrace();
}*/
}
}
else if (args.length == 2)
{

View File

@ -68,7 +68,7 @@ import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.PositionTrackingVisitor;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
import org.apache.poi.hssf.record.formula.FormulaShifter;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

View File

@ -51,8 +51,8 @@ public final class CFHeaderRecord extends Record {
{
field_1_numcf = in.readShort();
field_2_need_recalculation = in.readShort();
field_3_enclosing_cell_range = new org.apache.poi.hssf.util.CellRangeAddress(in);
field_4_cell_ranges = new org.apache.poi.hssf.util.CellRangeAddressList(in);
field_3_enclosing_cell_range = new CellRangeAddress(in);
field_4_cell_ranges = new CellRangeAddressList(in);
}
public int getNumberOfConditionalFormats()

View File

@ -50,7 +50,7 @@ public final class MergeCellsRecord extends Record {
int nRegions = in.readUShort();
CellRangeAddress[] cras = new CellRangeAddress[nRegions];
for (int i = 0; i < nRegions; i++) {
cras[i] = new org.apache.poi.hssf.util.CellRangeAddress(in);
cras[i] = new CellRangeAddress(in);
}
_numberOfRegions = nRegions;
_startIndex = 0;

View File

@ -22,8 +22,8 @@ import java.util.List;
import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.MergeCellsRecord;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.CellRangeAddressList;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
/**
*
@ -51,7 +51,8 @@ public final class MergedCellsTable extends RecordAggregate {
MergeCellsRecord mcr = (MergeCellsRecord) rs.getNext();
int nRegions = mcr.getNumAreas();
for (int i = 0; i < nRegions; i++) {
temp.add(mcr.getAreaAt(i));
CellRangeAddress cra = mcr.getAreaAt(i);
temp.add(cra);
}
}
}
@ -102,7 +103,8 @@ public final class MergedCellsTable extends RecordAggregate {
private void addMergeCellsRecord(MergeCellsRecord mcr) {
int nRegions = mcr.getNumAreas();
for (int i = 0; i < nRegions; i++) {
_mergedRegions.add(mcr.getAreaAt(i));
CellRangeAddress cra = mcr.getAreaAt(i);
_mergedRegions.add(cra);
}
}
@ -130,5 +132,4 @@ public final class MergedCellsTable extends RecordAggregate {
public int getNumberOfMergedRegions() {
return _mergedRegions.size();
}
}

View File

@ -1,96 +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 14, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval;
/**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
public abstract class StringOperationEval implements OperationEval {
/**
* Returns an instanceof StringValueEval or ErrorEval or BlankEval
*
* @param eval
* @param srcRow
* @param srcCol
*/
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 = internalResolveEval(eval);
}
else {
retval = ErrorEval.NAME_INVALID;
}
}
else if (ae.isColumn()) {
if (ae.containsRow(srcRow)) {
ValueEval ve = ae.getValueAt(srcRow, ae.getFirstColumn());
retval = internalResolveEval(eval);
}
else {
retval = ErrorEval.NAME_INVALID;
}
}
else {
retval = ErrorEval.NAME_INVALID;
}
}
else {
retval = internalResolveEval(eval);
}
return retval;
}
private ValueEval internalResolveEval(Eval eval) {
ValueEval retval;
if (eval instanceof StringValueEval) {
retval = (StringValueEval) eval;
}
else if (eval instanceof RefEval) {
RefEval re = (RefEval) eval;
ValueEval tve = re.getInnerValueEval();
if (tve instanceof StringValueEval || tve instanceof BlankEval) {
retval = tve;
}
else {
retval = ErrorEval.NAME_INVALID;
}
}
else if (eval instanceof BlankEval) {
retval = (BlankEval) eval;
}
else {
retval = ErrorEval.NAME_INVALID;
}
return retval;
}
}

View File

@ -1,25 +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.
*/
/*
* 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;
public class Find extends NotImplementedFunction {
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
/**
* Implementation of the FIND() function.<p/>
*
* <b>Syntax</b>:<br/>
* <b>FIND</b>(<b>find_text</b>, <b>within_text</b>, start_num)<p/>
*
* FIND returns the character position of the first occurrence of <tt>find_text</tt> inside
* <tt>within_text</tt>. The third parameter, <tt>start_num</tt>, is optional (default=1)
* and specifies where to start searching from. Character positions are 1-based.<p/>
*
* @author Torstein Tauno Svendsen (torstei@officenet.no)
*/
public class Find extends TextFunction {
protected ValueEval evaluateFunc(Eval[] args, int srcCellRow, short srcCellCol)
throws EvaluationException {
int nArgs = args.length;
if (nArgs < 2 || nArgs > 3) {
return ErrorEval.VALUE_INVALID;
}
String needle = evaluateStringArg(args[0], srcCellRow, srcCellCol);
String haystack = evaluateStringArg(args[1], srcCellRow, srcCellCol);
int startpos;
if (nArgs == 3) {
startpos = evaluateIntArg(args[2], srcCellRow, srcCellCol);
if (startpos <= 0) {
return ErrorEval.VALUE_INVALID;
}
startpos--; // convert 1-based to zero based
} else {
startpos = 0;
}
int result = haystack.indexOf(needle, startpos);
if (result == -1) {
return ErrorEval.VALUE_INVALID;
}
return new NumberEval(result + 1);
}
}

View File

@ -1,25 +1,188 @@
/*
* 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;
public class Value 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.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;
/**
* Implementation for Excel VALUE() function.<p/>
*
* <b>Syntax</b>:<br/> <b>VALUE</b>(<b>text</b>)<br/>
*
* Converts the text argument to a number. Leading and/or trailing whitespace is
* ignored. Currency symbols and thousands separators are stripped out.
* Scientific notation is also supported. If the supplied text does not convert
* properly the result is <b>#VALUE!</b> error. Blank string converts to zero.
*
* @author Josh Micich
*/
public final class Value implements Function {
/** "1,0000" is valid, "1,00" is not */
private static final int MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR = 4;
private static final Double ZERO = new Double(0.0);
public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
if (args.length != 1) {
return ErrorEval.VALUE_INVALID;
}
ValueEval veText;
try {
veText = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
} catch (EvaluationException e) {
return e.getErrorEval();
}
String strText = OperandResolver.coerceValueToString(veText);
Double result = convertTextToNumber(strText);
if (result == null) {
return ErrorEval.VALUE_INVALID;
}
return new NumberEval(result.doubleValue());
}
/**
* TODO see if the same functionality is needed in {@link OperandResolver#parseDouble(String)}
*
* @return <code>null</code> if there is any problem converting the text
*/
private static Double convertTextToNumber(String strText) {
boolean foundCurrency = false;
boolean foundUnaryPlus = false;
boolean foundUnaryMinus = false;
int len = strText.length();
int i;
for (i = 0; i < len; i++) {
char ch = strText.charAt(i);
if (Character.isDigit(ch) || ch == '.') {
break;
}
switch (ch) {
case ' ':
// intervening spaces between '$', '-', '+' are OK
continue;
case '$':
if (foundCurrency) {
// only one currency symbols is allowed
return null;
}
foundCurrency = true;
continue;
case '+':
if (foundUnaryMinus || foundUnaryPlus) {
return null;
}
foundUnaryPlus = true;
continue;
case '-':
if (foundUnaryMinus || foundUnaryPlus) {
return null;
}
foundUnaryMinus = true;
continue;
default:
// all other characters are illegal
return null;
}
}
if (i >= len) {
// didn't find digits or '.'
if (foundCurrency || foundUnaryMinus || foundUnaryPlus) {
return null;
}
return ZERO;
}
// remove thousands separators
boolean foundDecimalPoint = false;
int lastThousandsSeparatorIndex = Short.MIN_VALUE;
StringBuffer sb = new StringBuffer(len);
for (; i < len; i++) {
char ch = strText.charAt(i);
if (Character.isDigit(ch)) {
sb.append(ch);
continue;
}
switch (ch) {
case ' ':
String remainingText = strText.substring(i);
if (remainingText.trim().length() > 0) {
// intervening spaces not allowed once the digits start
return null;
}
break;
case '.':
if (foundDecimalPoint) {
return null;
}
if (i - lastThousandsSeparatorIndex < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) {
return null;
}
foundDecimalPoint = true;
sb.append('.');
continue;
case ',':
if (foundDecimalPoint) {
// thousands separators not allowed after '.' or 'E'
return null;
}
int distanceBetweenThousandsSeparators = i - lastThousandsSeparatorIndex;
// as long as there are 3 or more digits between
if (distanceBetweenThousandsSeparators < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) {
return null;
}
lastThousandsSeparatorIndex = i;
// don't append ','
continue;
case 'E':
case 'e':
if (i - lastThousandsSeparatorIndex < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) {
return null;
}
// append rest of strText and skip to end of loop
sb.append(strText.substring(i));
i = len;
break;
default:
// all other characters are illegal
return null;
}
}
if (!foundDecimalPoint) {
if (i - lastThousandsSeparatorIndex < MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR) {
return null;
}
}
double d;
try {
d = Double.parseDouble(sb.toString());
} catch (NumberFormatException e) {
// still a problem parsing the number - probably out of range
return null;
}
return new Double(foundUnaryMinus ? -d : d);
}
}

View File

@ -670,7 +670,7 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet
/**
* @return the merged region at the specified index
*/
public org.apache.poi.hssf.util.CellRangeAddress getMergedRegion(int index) {
public CellRangeAddress getMergedRegion(int index) {
return sheet.getMergedRegionAt(index);
}

View File

@ -18,12 +18,12 @@ package org.apache.poi.hssf.util;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.SelectionRecord;
import org.apache.poi.util.LittleEndian;
/**
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/>
*
* Note - {@link SelectionRecord} uses the BIFF5 version of this structure
* @deprecated use {@link org.apache.poi.ss.util.CellRangeAddress}
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
*/
public class CellRangeAddress extends org.apache.poi.ss.util.CellRangeAddress {

View File

@ -33,6 +33,8 @@ import org.apache.poi.util.LittleEndian;
* range address (called an ADDR structure) contains 4 16-bit-values.
* </p>
*
* @deprecated use {@link org.apache.poi.ss.util.CellRangeAddressList}
*
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
*/
public class CellRangeAddressList extends org.apache.poi.ss.util.CellRangeAddressList {

View File

@ -16,6 +16,7 @@
package org.apache.poi.ss.util;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.SelectionRecord;
import org.apache.poi.util.LittleEndian;
@ -42,6 +43,17 @@ public class CellRangeAddress extends CellRangeAddressBase {
LittleEndian.putUShort(data, offset + 6, getLastColumn());
return ENCODED_SIZE;
}
public CellRangeAddress(RecordInputStream in) {
super(readUShortAndCheck(in), in.readUShort(), in.readUShort(), in.readUShort());
}
private static int readUShortAndCheck(RecordInputStream in) {
if (in.remaining() < ENCODED_SIZE) {
// Ran out of data
throw new RuntimeException("Ran out of data reading CellRangeAddress");
}
return in.readUShort();
}
public CellRangeAddress copy() {
return new CellRangeAddress(getFirstRow(), getLastRow(), getFirstColumn(), getLastColumn());

View File

@ -18,6 +18,8 @@ package org.apache.poi.ss.util;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.util.LittleEndian;
/**
@ -51,7 +53,17 @@ public class CellRangeAddressList {
this();
addCellRangeAddress(firstRow, firstCol, lastRow, lastCol);
}
/**
* @param in the RecordInputstream to read the record from
*/
public CellRangeAddressList(RecordInputStream in) {
this();
int nItems = in.readUShort();
for (int k = 0; k < nItems; k++) {
_list.add(new CellRangeAddress(in));
}
}
/**
* Get the number of following ADDR structures. The number of this
* structures is automatically set when reading an Excel file and/or

View File

@ -17,10 +17,18 @@
package org.apache.poi.hssf.record;
import java.util.ArrayList;
import java.util.List;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.aggregates.MergedCellsTable;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
import org.apache.poi.ss.util.CellRangeAddress;
/**
* Make sure the merge cells record behaves
* @author Danny Mui (dmui at apache dot org)
@ -28,25 +36,45 @@ import org.apache.poi.ss.util.CellRangeAddress;
*/
public final class TestMergeCellsRecord extends TestCase {
/**
* Make sure when a clone is called, we actually clone it.
* @throws Exception
*/
public void testCloneReferences() throws Exception {
CellRangeAddress[] cras = { new CellRangeAddress(0, 1, 0, 2), };
MergeCellsRecord merge = new MergeCellsRecord(cras, 0, cras.length);
MergeCellsRecord clone = (MergeCellsRecord)merge.clone();
/**
* Make sure when a clone is called, we actually clone it.
*/
public void testCloneReferences() {
CellRangeAddress[] cras = { new CellRangeAddress(0, 1, 0, 2), };
MergeCellsRecord merge = new MergeCellsRecord(cras, 0, cras.length);
MergeCellsRecord clone = (MergeCellsRecord)merge.clone();
assertNotSame("Merged and cloned objects are the same", merge, clone);
CellRangeAddress mergeRegion = merge.getAreaAt(0);
CellRangeAddress cloneRegion = clone.getAreaAt(0);
assertNotSame("Should not point to same objects when cloning", mergeRegion, cloneRegion);
assertEquals("New Clone Row From doesnt match", mergeRegion.getFirstRow(), cloneRegion.getFirstRow());
assertEquals("New Clone Row To doesnt match", mergeRegion.getLastRow(), cloneRegion.getLastRow());
assertEquals("New Clone Col From doesnt match", mergeRegion.getFirstColumn(), cloneRegion.getFirstColumn());
assertEquals("New Clone Col To doesnt match", mergeRegion.getLastColumn(), cloneRegion.getLastColumn());
assertNotSame("Merged and cloned objects are the same", merge, clone);
CellRangeAddress mergeRegion = merge.getAreaAt(0);
CellRangeAddress cloneRegion = clone.getAreaAt(0);
assertNotSame("Should not point to same objects when cloning", mergeRegion, cloneRegion);
assertEquals("New Clone Row From doesnt match", mergeRegion.getFirstRow(), cloneRegion.getFirstRow());
assertEquals("New Clone Row To doesnt match", mergeRegion.getLastRow(), cloneRegion.getLastRow());
assertEquals("New Clone Col From doesnt match", mergeRegion.getFirstColumn(), cloneRegion.getFirstColumn());
assertEquals("New Clone Col To doesnt match", mergeRegion.getLastColumn(), cloneRegion.getLastColumn());
assertFalse(merge.getAreaAt(0) == clone.getAreaAt(0));
}
assertFalse(merge.getAreaAt(0) == clone.getAreaAt(0));
}
private static final RecordVisitor dummyRecordVisitor = new RecordVisitor() {
public void visitRecord(Record r) {
// do nothing
}
};
public void testMCTable_bug46009() {
MergedCellsTable mct = new MergedCellsTable();
List recList = new ArrayList();
CellRangeAddress[] cras = new CellRangeAddress[] {
new CellRangeAddress(0, 0, 0, 3),
};
recList.add(new MergeCellsRecord(cras, 0, 1));
RecordStream rs = new RecordStream(recList, 0);
mct.read(rs);
try {
mct.visitContainedRecords(dummyRecordVisitor);
} catch (ArrayStoreException e) {
throw new AssertionFailedError("Identified bug 46009");
}
}
}

View File

@ -32,6 +32,7 @@ public final class AllIndividualFunctionEvaluationTests {
result.addTestSuite(TestAverage.class);
result.addTestSuite(TestCountFuncs.class);
result.addTestSuite(TestDate.class);
result.addTestSuite(TestFind.class);
result.addTestSuite(TestFinanceLib.class);
result.addTestSuite(TestIndex.class);
result.addTestSuite(TestIndexFunctionFromSpreadsheet.class);
@ -49,6 +50,7 @@ public final class AllIndividualFunctionEvaluationTests {
result.addTestSuite(TestStatsLib.class);
result.addTestSuite(TestTFunc.class);
result.addTestSuite(TestTrim.class);
result.addTestSuite(TestValue.class);
result.addTestSuite(TestXYNumericFunction.class);
return result;
}

View File

@ -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.hssf.record.formula.functions;
import junit.framework.TestCase;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellValue;
/**
* Tests for {@link Find}
*
* @author Torstein Svendsen (torstei@officenet.no)
*/
public final class TestFind extends TestCase {
public void testFind() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFCell cell = wb.createSheet().createRow(0).createCell(0);
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
confirmResult(fe, cell, "find(\"h\", \"haystack\")", 1);
confirmResult(fe, cell, "find(\"a\", \"haystack\",2)", 2);
confirmResult(fe, cell, "find(\"a\", \"haystack\",3)", 6);
// number args converted to text
confirmResult(fe, cell, "find(7, 32768)", 3);
confirmResult(fe, cell, "find(\"34\", 1341235233412, 3)", 10);
confirmResult(fe, cell, "find(5, 87654)", 4);
// Errors
confirmError(fe, cell, "find(\"n\", \"haystack\")", HSSFErrorConstants.ERROR_VALUE);
confirmError(fe, cell, "find(\"k\", \"haystack\",9)", HSSFErrorConstants.ERROR_VALUE);
confirmError(fe, cell, "find(\"k\", \"haystack\",#REF!)", HSSFErrorConstants.ERROR_REF);
confirmError(fe, cell, "find(\"k\", \"haystack\",0)", HSSFErrorConstants.ERROR_VALUE);
confirmError(fe, cell, "find(#DIV/0!, #N/A, #REF!)", HSSFErrorConstants.ERROR_DIV_0);
confirmError(fe, cell, "find(2, #N/A, #REF!)", HSSFErrorConstants.ERROR_NA);
}
private static void confirmResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText,
int expectedResult) {
cell.setCellFormula(formulaText);
fe.notifyUpdateCell(cell);
CellValue result = fe.evaluate(cell);
assertEquals(result.getCellType(), HSSFCell.CELL_TYPE_NUMERIC);
assertEquals(expectedResult, result.getNumberValue(), 0.0);
}
private static void confirmError(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText,
int expectedErrorCode) {
cell.setCellFormula(formulaText);
fe.notifyUpdateCell(cell);
CellValue result = fe.evaluate(cell);
assertEquals(result.getCellType(), HSSFCell.CELL_TYPE_ERROR);
assertEquals(expectedErrorCode, result.getErrorValue());
}
}

View File

@ -0,0 +1,94 @@
/* ====================================================================
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 junit.framework.TestCase;
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.StringEval;
/**
* Tests for {@link Value}
*
* @author Josh Micich
*/
public final class TestValue extends TestCase {
private static Eval invokeValue(String strText) {
Eval[] args = new Eval[] { new StringEval(strText), };
return new Value().evaluate(args, -1, (short) -1);
}
private static void confirmValue(String strText, double expected) {
Eval result = invokeValue(strText);
assertEquals(NumberEval.class, result.getClass());
assertEquals(expected, ((NumberEval) result).getNumberValue(), 0.0);
}
private static void confirmValueError(String strText) {
Eval result = invokeValue(strText);
assertEquals(ErrorEval.class, result.getClass());
assertEquals(ErrorEval.VALUE_INVALID, result);
}
public void testBasic() {
confirmValue("100", 100);
confirmValue("-2.3", -2.3);
confirmValue(".5", 0.5);
confirmValue(".5e2", 50);
confirmValue(".5e-2", 0.005);
confirmValue(".5e+2", 50);
confirmValue("+5", 5);
confirmValue("$1,000", 1000);
confirmValue("100.5e1", 1005);
confirmValue("1,0000", 10000);
confirmValue("1,000,0000", 10000000);
confirmValue("1,000,0000,00000", 1000000000000.0);
confirmValue(" 100 ", 100);
confirmValue(" + 100", 100);
confirmValue("10000", 10000);
confirmValue("$-5", -5);
confirmValue("$.5", 0.5);
confirmValue("123e+5", 12300000);
confirmValue("1,000e2", 100000);
confirmValue("$10e2", 1000);
confirmValue("$1,000e2", 100000);
}
public void testErrors() {
confirmValueError("1+1");
confirmValueError("1 1");
confirmValueError("1,00.0");
confirmValueError("1,00");
confirmValueError("$1,00.5e1");
confirmValueError("1,00.5e1");
confirmValueError("1,0,000");
confirmValueError("1,00,000");
confirmValueError("++100");
confirmValueError("$$5");
confirmValueError("-");
confirmValueError("+");
confirmValueError("$");
confirmValueError(",300");
confirmValueError("0.233,4");
confirmValueError("1e2.5");
}
}