Fix for bug 46174 - HSSFName now handles general formulas (not just area references)

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@713909 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-11-14 02:20:22 +00:00
parent ed5c2dac01
commit e703a254ed
13 changed files with 162 additions and 645 deletions

View File

@ -37,6 +37,7 @@
<!-- Don't forget to update status.xml too! --> <!-- Don't forget to update status.xml too! -->
<release version="3.5-beta4" date="2008-??-??"> <release version="3.5-beta4" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="fix">46174 - Fixed HSSFName to handle general formulas (not just area references)</header>
<action dev="POI-DEVELOPERS" type="add">46189 - added chart records: CHARTFRTINFO, STARTBLOCK, ENDBLOCK, STARTOBJECT, ENDOBJECT, and CATLAB</action> <action dev="POI-DEVELOPERS" type="add">46189 - added chart records: CHARTFRTINFO, STARTBLOCK, ENDBLOCK, STARTOBJECT, ENDOBJECT, and CATLAB</action>
<action dev="POI-DEVELOPERS" type="fix">46199 - More tweaks to EmbeddedObjectRefSubRecord</header> <action dev="POI-DEVELOPERS" type="fix">46199 - More tweaks to EmbeddedObjectRefSubRecord</header>
<action dev="POI-DEVELOPERS" type="add">Changes to formula evaluation allowing for reduced memory usage</action> <action dev="POI-DEVELOPERS" type="add">Changes to formula evaluation allowing for reduced memory usage</action>

View File

@ -34,6 +34,7 @@
<!-- Don't forget to update changes.xml too! --> <!-- Don't forget to update changes.xml too! -->
<changes> <changes>
<release version="3.5-beta4" date="2008-??-??"> <release version="3.5-beta4" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="fix">46174 - Fixed HSSFName to handle general formulas (not just area references)</header>
<action dev="POI-DEVELOPERS" type="add">46189 - added chart records: CHARTFRTINFO, STARTBLOCK, ENDBLOCK, STARTOBJECT, ENDOBJECT, and CATLAB</action> <action dev="POI-DEVELOPERS" type="add">46189 - added chart records: CHARTFRTINFO, STARTBLOCK, ENDBLOCK, STARTOBJECT, ENDOBJECT, and CATLAB</action>
<action dev="POI-DEVELOPERS" type="fix">46199 - More tweaks to EmbeddedObjectRefSubRecord</header> <action dev="POI-DEVELOPERS" type="fix">46199 - More tweaks to EmbeddedObjectRefSubRecord</header>
<action dev="POI-DEVELOPERS" type="add">Changes to formula evaluation allowing for reduced memory usage</action> <action dev="POI-DEVELOPERS" type="add">Changes to formula evaluation allowing for reduced memory usage</action>

View File

@ -17,18 +17,10 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.formula.Area3DPtg; import org.apache.poi.hssf.record.formula.Area3DPtg;
import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.Ref3DPtg; import org.apache.poi.hssf.record.formula.Ref3DPtg;
import org.apache.poi.hssf.record.formula.UnionPtg;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.RangeAddress;
import org.apache.poi.ss.formula.Formula; import org.apache.poi.ss.formula.Formula;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
@ -414,87 +406,6 @@ public final class NameRecord extends StandardRecord {
return 0; return 0;
} }
/** sets the extern sheet number
* @param externSheetNumber extern sheet number
*/
public void setExternSheetNumber(short externSheetNumber){
Ptg[] ptgs = field_13_name_definition.getTokens();
Ptg ptg;
if (ptgs.length < 1){
ptg = createNewPtg();
ptgs = new Ptg[] { ptg, };
} else {
ptg = ptgs[0];
}
if (ptg.getClass() == Area3DPtg.class){
((Area3DPtg) ptg).setExternSheetIndex(externSheetNumber);
} else if (ptg.getClass() == Ref3DPtg.class){
((Ref3DPtg) ptg).setExternSheetIndex(externSheetNumber);
}
field_13_name_definition = Formula.create(ptgs);
}
private static Ptg createNewPtg(){
return new Area3DPtg("A1:A1", 0); // TODO - change to not be partially initialised
}
/** gets the reference , the area only (range)
* @return area reference
*/
public String getAreaReference(HSSFWorkbook book){
return HSSFFormulaParser.toFormulaString(book, field_13_name_definition.getTokens());
}
/** sets the reference , the area only (range)
* @param ref area reference
*/
public void setAreaReference(String ref){
//Trying to find if what ptg do we need
RangeAddress ra = new RangeAddress(ref);
Ptg oldPtg;
if (field_13_name_definition.getEncodedTokenSize() < 1){
oldPtg = createNewPtg();
} else {
//Trying to find extern sheet index
oldPtg = field_13_name_definition.getTokens()[0];
}
List temp = new ArrayList();
int externSheetIndex = 0;
if (oldPtg.getClass() == Area3DPtg.class){
externSheetIndex = ((Area3DPtg) oldPtg).getExternSheetIndex();
} else if (oldPtg.getClass() == Ref3DPtg.class){
externSheetIndex = ((Ref3DPtg) oldPtg).getExternSheetIndex();
}
if (ra.hasRange()) {
// Is it contiguous or not?
AreaReference[] refs = AreaReference.generateContiguous(ref);
// Add the area reference(s)
for(int i=0; i<refs.length; i++) {
Ptg ptg = new Area3DPtg(refs[i].formatAsString(), externSheetIndex);
temp.add(ptg);
}
// And then a union if we had more than one area
if(refs.length > 1) {
Ptg ptg = UnionPtg.instance;
temp.add(ptg);
}
} else {
Ref3DPtg ptg = new Ref3DPtg(ra.getFromCell(), externSheetIndex);
temp.add(ptg);
}
Ptg[] ptgs = new Ptg[temp.size()];
temp.toArray(ptgs);
field_13_name_definition = Formula.create(ptgs);
}
/** /**
* called by the constructor, should set class level fields. Should throw * called by the constructor, should set class level fields. Should throw
* runtime exception for bad/icomplete data. * runtime exception for bad/icomplete data.

View File

@ -17,9 +17,10 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.NameRecord; import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.util.RangeAddress; import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.usermodel.Name;
/** /**
@ -80,43 +81,33 @@ public final class HSSFName implements Name {
} }
/** /**
* Note - this method only applies to named ranges * @deprecated (Nov 2008) Misleading name. Use {@link #getFormula()} instead.
* @return the formula text defining the named range
*/ */
public String getReference() { public String getReference() {
return getFormula();
}
/**
* @deprecated (Nov 2008) Misleading name. Use {@link #setFormula(String)} instead.
*/
public void setReference(String ref){
setFormula(ref);
}
public void setFormula(String formulaText) {
Ptg[] ptgs = HSSFFormulaParser.parse(formulaText, _book);
_definedNameRec.setNameDefinition(ptgs);
}
/**
* Note - this method only applies to named ranges
* @return the formula text defining this name
*/
public String getFormula() {
if (_definedNameRec.isFunctionName()) { if (_definedNameRec.isFunctionName()) {
throw new IllegalStateException("Only applicable to named ranges"); throw new IllegalStateException("Only applicable to named ranges");
} }
return _definedNameRec.getAreaReference(_book); return HSSFFormulaParser.toFormulaString(_book, _definedNameRec.getNameDefinition());
}
/**
* sets the sheet name which this named range referenced to
* @param sheetName the sheet name of the reference
*/
private void setSheetName(String sheetName){
int sheetNumber = _book.getSheetIndex(sheetName);
short externSheetNumber = _book.getWorkbook().checkExternSheet(sheetNumber);
_definedNameRec.setExternSheetNumber(externSheetNumber);
}
/**
* sets the reference of this named range
* @param ref the reference to set
*/
public void setReference(String ref){
RangeAddress ra = new RangeAddress(ref);
String sheetName = ra.getSheetName();
if (ra.hasSheetName()) {
setSheetName(sheetName);
}
//allow the poi utilities to parse it out
_definedNameRec.setAreaReference(ref);
} }
/** /**

View File

@ -33,6 +33,7 @@ import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherBitmapBlip; import org.apache.poi.ddf.EscherBitmapBlip;
import org.apache.poi.ddf.EscherBlipRecord; import org.apache.poi.ddf.EscherBlipRecord;
import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.model.RecordStream; import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.model.Workbook;
@ -57,6 +58,7 @@ import org.apache.poi.hssf.record.formula.MemFuncPtg;
import org.apache.poi.hssf.record.formula.NameXPtg; import org.apache.poi.hssf.record.formula.NameXPtg;
import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.Ref3DPtg; import org.apache.poi.hssf.record.formula.Ref3DPtg;
import org.apache.poi.hssf.record.formula.SheetNameFormatter;
import org.apache.poi.hssf.record.formula.UnionPtg; import org.apache.poi.hssf.record.formula.UnionPtg;
import org.apache.poi.hssf.util.CellReference; import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
@ -1364,15 +1366,15 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
NameRecord name = workbook.getSpecificBuiltinRecord(NameRecord.BUILTIN_PRINT_AREA, sheetIndex+1); NameRecord name = workbook.getSpecificBuiltinRecord(NameRecord.BUILTIN_PRINT_AREA, sheetIndex+1);
if (name == null) if (name == null) {
name = workbook.createBuiltInName(NameRecord.BUILTIN_PRINT_AREA, sheetIndex+1); name = workbook.createBuiltInName(NameRecord.BUILTIN_PRINT_AREA, sheetIndex+1);
//adding one here because 0 indicates a global named region; doesnt make sense for print areas // adding one here because 0 indicates a global named region; doesn't make sense for print areas
}
short externSheetIndex = getWorkbook().checkExternSheet(sheetIndex); StringBuffer sb = new StringBuffer(32);
name.setExternSheetNumber(externSheetIndex); SheetNameFormatter.appendFormat(sb, getSheetName(sheetIndex));
name.setAreaReference(reference); sb.append("!");
sb.append(reference);
name.setNameDefinition(HSSFFormulaParser.parse(sb.toString(), this));
} }
/** /**
@ -1403,13 +1405,14 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
* @param sheetIndex Zero-based sheet index (0 Represents the first sheet to keep consistent with java) * @param sheetIndex Zero-based sheet index (0 Represents the first sheet to keep consistent with java)
* @return String Null if no print area has been defined * @return String Null if no print area has been defined
*/ */
public String getPrintArea(int sheetIndex) public String getPrintArea(int sheetIndex) {
{
NameRecord name = workbook.getSpecificBuiltinRecord(NameRecord.BUILTIN_PRINT_AREA, sheetIndex+1); NameRecord name = workbook.getSpecificBuiltinRecord(NameRecord.BUILTIN_PRINT_AREA, sheetIndex+1);
if (name == null) return null; //adding one here because 0 indicates a global named region; doesn't make sense for print areas
//adding one here because 0 indicates a global named region; doesnt make sense for print areas if (name == null) {
return null;
}
return name.getAreaReference(this); return HSSFFormulaParser.toFormulaString(this, name.getNameDefinition());
} }
/** /**

View File

@ -1,367 +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.util;
/**
* Title: Range Address <P>
* Description: provides connectivity utilities for ranges<P>
*
*
* REFERENCE: <P>
* @author IgOr KaTz && EuGeNe BuMaGiN (Tal Moshaiov) (VistaPortal LDT.)
@version 1.0
*/
public class RangeAddress {
final static int WRONG_POS = -1;
final static int MAX_HEIGHT = 66666;
final static char SO_FORMNAME_ENCLOSURE = '\'';
String m_sheetName;
String m_cellFrom;
String m_cellTo;
/**
* Accepts an external reference from excel.
* <p>
* i.e. Sheet1!$A$4:$B$9
* @param _url
*/
public RangeAddress (String _url) {
init (_url);
}
public RangeAddress (int _startCol, int _startRow, int _endCol, int _endRow) {
init (numTo26Sys (_startCol) + _startRow + ":"
+ numTo26Sys (_endCol) + _endRow);
}
/**
*
* @return String <b>note: </b> All absolute references are removed
*/
public String getAddress (){
String result = "";
if(m_sheetName != null)
result += m_sheetName+"!";
if(m_cellFrom != null){
result += m_cellFrom;
if(m_cellTo != null)
result += ":" + m_cellTo;
}
return result;
}
public String getSheetName (){
return m_sheetName;
}
public String getRange (){
String result = "";
if(m_cellFrom != null){
result += m_cellFrom;
if(m_cellTo != null)
result += ":" + m_cellTo;
}
return result;
}
public boolean isCellOk (String _cell){
if (_cell != null){
if ( (getYPosition (_cell) != WRONG_POS) &&
(getXPosition (_cell) != WRONG_POS) )
return true;
else
return false;
} else
return false;
}
public boolean isSheetNameOk (){
return isSheetNameOk (m_sheetName);
}
private static boolean intern_isSheetNameOk (String _sheetName, boolean _canBeWaitSpace){
for (int i = 0 ; i < _sheetName.length (); i++){
char ch = _sheetName.charAt (i);
if (! (Character.isLetterOrDigit (ch) || (ch == '_')||
_canBeWaitSpace&&(ch == ' '))){
return false;
}
}
return true;
}
public static boolean isSheetNameOk (String _sheetName){
boolean res = false;
if ( ( _sheetName != null) && !_sheetName.equals ("")){
res = intern_isSheetNameOk (_sheetName,true);
}else
res = true;
return res;
}
public String getFromCell (){
return m_cellFrom;
}
public String getToCell (){
return m_cellTo;
}
public int getWidth (){
if(m_cellFrom != null && m_cellTo != null){
int toX = getXPosition (m_cellTo);
int fromX = getXPosition (m_cellFrom);
if ((toX == WRONG_POS) || (fromX == WRONG_POS)){
return 0;
}else
return toX - fromX + 1;
}
return 0;
}
public int getHeight (){
if(m_cellFrom != null && m_cellTo != null){
int toY = getYPosition (m_cellTo);
int fromY = getYPosition (m_cellFrom);
if ((toY == WRONG_POS) || (fromY == WRONG_POS)){
return 0;
}else
return toY - fromY + 1;
}
return 0;
}
public void setSize (int _width, int _height){
if(m_cellFrom == null)
m_cellFrom = "a1";
int tlX, tlY, rbX, rbY;
tlX = getXPosition (m_cellFrom);
tlY = getYPosition (m_cellFrom);
m_cellTo = numTo26Sys (tlX + _width - 1);
m_cellTo += String.valueOf (tlY + _height - 1);
}
public boolean hasSheetName (){
if(m_sheetName == null)
return false;
return true;
}
public boolean hasRange (){
return (m_cellFrom != null && m_cellTo != null && !m_cellFrom.equals(m_cellTo));
}
public boolean hasCell (){
if(m_cellFrom == null)
return false;
return true;
}
private void init (String _url){
_url = removeString(_url, "$");
_url = removeString(_url, "'");
String[] urls = parseURL (_url);
m_sheetName = urls[0];
m_cellFrom = urls[1];
m_cellTo = urls[2];
//What if range is one celled ?
if (m_cellTo == null){
m_cellTo = m_cellFrom;
}
//Removing noneeds characters
m_cellTo = removeString(m_cellTo,".");
}
private String[] parseURL (String _url){
String[] result = new String[3];
int index = _url.indexOf(':');
if (index >= 0) {
String fromStr = _url.substring(0, index);
String toStr = _url.substring(index+1);
index = fromStr.indexOf('!');
if (index >= 0) {
result[0] = fromStr.substring(0, index);
result[1] = fromStr.substring(index+1);
} else {
result[1] = fromStr;
}
index = toStr.indexOf('!');
if (index >= 0) {
result[2] = toStr.substring(index+1);
} else {
result[2] = toStr;
}
} else {
index = _url.indexOf('!');
if (index >= 0) {
result[0] = _url.substring(0, index);
result[1] = _url.substring(index+1);
} else {
result[1] = _url;
}
}
return result;
}
public int getYPosition (String _subrange){
int result = WRONG_POS;
_subrange = _subrange.trim ();
if (_subrange.length () != 0){
String digitstr = getDigitPart (_subrange);
try {
result = Integer.parseInt (digitstr);
if (result > MAX_HEIGHT){
result = WRONG_POS;
}
}
catch (Exception ex) {
result = WRONG_POS;
}
}
return result;
}
private static boolean isLetter (String _str){
boolean res = true;
if ( !_str.equals ("") ){
for (int i = 0 ; i < _str.length (); i++){
char ch = _str.charAt (i);
if (! Character.isLetter (ch)){
res = false;
break;
}
}
}else
res = false;
return res;
}
public int getXPosition (String _subrange){
int result = WRONG_POS;
String tmp = filter$ (_subrange);
tmp = this.getCharPart (_subrange);
// we will process only 2 letters ranges
if (isLetter (tmp) && ((tmp.length () == 2)|| (tmp.length () == 1) )){
result = get26Sys (tmp);
}
return result;
}
public String getDigitPart (String _value){
String result = "";
int digitpos = getFirstDigitPosition (_value);
if(digitpos >= 0){
result = _value.substring (digitpos);
}
return result;
}
public String getCharPart (String _value){
String result = "";
int digitpos = getFirstDigitPosition (_value);
if(digitpos >= 0){
result = _value.substring (0, digitpos);
}
return result;
}
private String filter$ (String _range){
String res = "";
for (int i = 0 ; i < _range.length () ; i++){
char ch = _range.charAt (i);
if ( ch != '$' ){
res = res + ch;
}
}
return res;
}
private int getFirstDigitPosition (String _value){
int result = WRONG_POS;
if(_value != null && _value.trim ().length () == 0){
return result;
}
_value = _value.trim ();
int length = _value.length ();
for(int i = 0; i < length; i++){
if(Character.isDigit (_value.charAt (i))){
result = i;
break;
}
}
return result;
}
public int get26Sys (String _s){
int sum = 0;
int multiplier = 1;
if (_s != "") {
for (int i = _s.length ()-1 ; i >= 0 ; i--){
char ch = _s.charAt (i);
int val = Character.getNumericValue (ch) - Character.getNumericValue ('A')+1;
sum = sum + val * multiplier;
multiplier = multiplier * 26;
}
return sum;
}
return WRONG_POS;
}
public String numTo26Sys (int _num){
int sum = 0;
int reminder;
String s ="";
do{
_num --;
reminder = _num % 26;
int val = 65 + reminder;
_num = _num / 26;
s = (char)val + s; // reverce
}while(_num > 0);
return s;
}
public String replaceString(String _source , String _oldPattern,
String _newPattern){
StringBuffer res = new StringBuffer(_source);
int pos = -1;
while ((pos = res.toString().indexOf(_oldPattern, pos)) > -1){
res.replace(pos, pos + _oldPattern.length(), _newPattern);
}
return res.toString();
}
public String removeString(String _source, String _match){
return replaceString(_source, _match, "");
}
}

View File

@ -41,7 +41,6 @@ public final class TestFormulaParserEval extends TestCase {
public void testWithNamedRange() { public void testWithNamedRange() {
HSSFWorkbook workbook = new HSSFWorkbook(); HSSFWorkbook workbook = new HSSFWorkbook();
Ptg[] ptgs;
HSSFSheet s = workbook.createSheet("Foo"); HSSFSheet s = workbook.createSheet("Foo");
s.createRow(0).createCell(0).setCellValue(1.1); s.createRow(0).createCell(0).setCellValue(1.1);
@ -52,21 +51,25 @@ public final class TestFormulaParserEval extends TestCase {
name.setNameName("testName"); name.setNameName("testName");
name.setReference("A1:A2"); name.setReference("A1:A2");
ptgs = HSSFFormulaParser.parse("SUM(testName)", workbook); confirmParseFormula(workbook);
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
assertEquals(NamePtg.class, ptgs[0].getClass());
assertEquals(FuncVarPtg.class, ptgs[1].getClass());
// Now make it a single cell // Now make it a single cell
name.setReference("C3"); name.setReference("C3");
ptgs = HSSFFormulaParser.parse("SUM(testName)", workbook); confirmParseFormula(workbook);
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
assertEquals(NamePtg.class, ptgs[0].getClass());
assertEquals(FuncVarPtg.class, ptgs[1].getClass());
// And make it non-contiguous // And make it non-contiguous
if (false) { // TODO (Nov 2008) - make the formula parser support area unions
name.setReference("A1:A2,C3"); name.setReference("A1:A2,C3");
ptgs = HSSFFormulaParser.parse("SUM(testName)", workbook); }
confirmParseFormula(workbook);
}
/**
* Makes sure that a formula referring to the named range parses properly
*/
private static void confirmParseFormula(HSSFWorkbook workbook) {
Ptg[] ptgs = HSSFFormulaParser.parse("SUM(testName)", workbook);
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2); assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
assertEquals(NamePtg.class, ptgs[0].getClass()); assertEquals(NamePtg.class, ptgs[0].getClass());
assertEquals(FuncVarPtg.class, ptgs[1].getClass()); assertEquals(FuncVarPtg.class, ptgs[1].getClass());

View File

@ -17,8 +17,11 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.hssf.usermodel.HSSFName;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.HexRead; import org.apache.poi.util.HexRead;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
/** /**
@ -55,4 +58,27 @@ public final class TestNameRecord extends TestCase {
byte[] data2 = nr.serialize(); byte[] data2 = nr.serialize();
TestcaseRecordInputStream.confirmRecordEncoding(NameRecord.sid, data, data2); TestcaseRecordInputStream.confirmRecordEncoding(NameRecord.sid, data, data2);
} }
public void testFormulaRelAbs_bug46174() {
// perhaps this testcase belongs on TestHSSFName
HSSFWorkbook wb = new HSSFWorkbook();
HSSFName name = wb.createName();
wb.createSheet("Sheet1");
name.setNameName("test");
name.setReference("Sheet1!$B$3");
if (name.getReference().equals("Sheet1!B3")) {
throw new AssertionFailedError("Identified bug 46174");
}
assertEquals("Sheet1!$B$3", name.getReference());
}
public void testFormulaGeneral() {
// perhaps this testcase belongs on TestHSSFName
HSSFWorkbook wb = new HSSFWorkbook();
HSSFName name = wb.createName();
wb.createSheet("Sheet1");
name.setNameName("test");
name.setFormula("Sheet1!A1+Sheet1!A2");
assertEquals("Sheet1!A1+Sheet1!A2", name.getFormula());
name.setFormula("5*6");
assertEquals("5*6", name.getFormula());
}
} }

View File

@ -26,6 +26,7 @@ import junit.framework.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.record.NameRecord; import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.Record;
@ -533,7 +534,7 @@ public final class TestHSSFWorkbook extends TestCase {
assertEquals(3, wb.getWorkbook().getNumNames()); assertEquals(3, wb.getWorkbook().getNumNames());
nr = wb.getWorkbook().getNameRecord(2); nr = wb.getWorkbook().getNameRecord(2);
// TODO - render full row and full column refs properly // TODO - render full row and full column refs properly
assertEquals("Sheet2!$A$1:$IV$1", nr.getAreaReference(wb)); // 1:1 assertEquals("Sheet2!$A$1:$IV$1", HSSFFormulaParser.toFormulaString(wb, nr.getNameDefinition())); // 1:1
try { try {
wb.setRepeatingRowsAndColumns(3, 4, 5, 8, 11); wb.setRepeatingRowsAndColumns(3, 4, 5, 8, 11);
@ -547,6 +548,6 @@ public final class TestHSSFWorkbook extends TestCase {
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
assertEquals(3, wb.getWorkbook().getNumNames()); assertEquals(3, wb.getWorkbook().getNumNames());
nr = wb.getWorkbook().getNameRecord(2); nr = wb.getWorkbook().getNameRecord(2);
assertEquals("Sheet2!E:F,Sheet2!$A$9:$IV$12", nr.getAreaReference(wb)); // E:F,9:12 assertEquals("Sheet2!E:F,Sheet2!$A$9:$IV$12", HSSFFormulaParser.toFormulaString(wb, nr.getNameDefinition())); // E:F,9:12
} }
} }

View File

@ -59,8 +59,6 @@ public final class TestNamedRange extends TestCase {
HSSFName namedRange1 = wb.getNameAt(0); HSSFName namedRange1 = wb.getNameAt(0);
//Getting it sheet name //Getting it sheet name
sheetName = namedRange1.getSheetName(); sheetName = namedRange1.getSheetName();
//Getting its reference
String referece = namedRange1.getReference();
// sanity check // sanity check
SanityChecker c = new SanityChecker(); SanityChecker c = new SanityChecker();
@ -142,9 +140,7 @@ public final class TestNamedRange extends TestCase {
newNamedRange2.setNameName("AnotherTest"); newNamedRange2.setNameName("AnotherTest");
newNamedRange2.setReference(sheetName + "!$F$1:$G$6"); newNamedRange2.setReference(sheetName + "!$F$1:$G$6");
wb.getNameAt(0);
HSSFName namedRange1 = wb.getNameAt(0);
String referece = namedRange1.getReference();
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
HSSFName nm =wb.getNameAt(wb.getNameIndex("RangeTest")); HSSFName nm =wb.getNameAt(wb.getNameIndex("RangeTest"));
@ -223,13 +219,12 @@ public final class TestNamedRange extends TestCase {
/** /**
* Test to see if the print areas can be retrieved/created in memory * Test to see if the print areas can be retrieved/created in memory
*/ */
public void testSinglePrintArea() public void testSinglePrintArea() {
{
HSSFWorkbook workbook = new HSSFWorkbook(); HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Test Print Area"); workbook.createSheet("Test Print Area");
String sheetName = workbook.getSheetName(0); String sheetName = workbook.getSheetName(0);
String reference = sheetName+"!$A$1:$B$1"; String reference = "$A$1:$B$1";
workbook.setPrintArea(0, reference); workbook.setPrintArea(0, reference);
String retrievedPrintArea = workbook.getPrintArea(0); String retrievedPrintArea = workbook.getPrintArea(0);
@ -239,12 +234,12 @@ public final class TestNamedRange extends TestCase {
} }
/** /**
* For Convenience, dont force sheet names to be used * For Convenience, don't force sheet names to be used
*/ */
public void testSinglePrintAreaWOSheet() public void testSinglePrintAreaWOSheet()
{ {
HSSFWorkbook workbook = new HSSFWorkbook(); HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Test Print Area"); workbook.createSheet("Test Print Area");
String sheetName = workbook.getSheetName(0); String sheetName = workbook.getSheetName(0);
String reference = "$A$1:$B$1"; String reference = "$A$1:$B$1";
@ -277,7 +272,7 @@ public final class TestNamedRange extends TestCase {
String sheetName = workbook.getSheetName(0); String sheetName = workbook.getSheetName(0);
String reference = sheetName+"!$A$1:$B$1"; String reference = "$A$1:$B$1";
workbook.setPrintArea(0, reference); workbook.setPrintArea(0, reference);
workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook); workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
@ -296,9 +291,9 @@ public final class TestNamedRange extends TestCase {
workbook.createSheet("Sheet1"); workbook.createSheet("Sheet1");
workbook.createSheet("Sheet2"); workbook.createSheet("Sheet2");
workbook.createSheet("Sheet3"); workbook.createSheet("Sheet3");
String reference1 = "Sheet1!$A$1:$B$1"; String reference1 = "$A$1:$B$1";
String reference2 = "Sheet2!$B$2:$D$5"; String reference2 = "$B$2:$D$5";
String reference3 = "Sheet3!$D$2:$F$5"; String reference3 = "$D$2:$F$5";
workbook.setPrintArea(0, reference1); workbook.setPrintArea(0, reference1);
workbook.setPrintArea(1, reference2); workbook.setPrintArea(1, reference2);
@ -309,30 +304,30 @@ public final class TestNamedRange extends TestCase {
retrievedPrintArea = workbook.getPrintArea(0); retrievedPrintArea = workbook.getPrintArea(0);
assertNotNull("Print Area Not Found (Sheet 1)", retrievedPrintArea); assertNotNull("Print Area Not Found (Sheet 1)", retrievedPrintArea);
assertEquals(reference1, retrievedPrintArea); assertEquals("Sheet1!" + reference1, retrievedPrintArea);
retrievedPrintArea = workbook.getPrintArea(1); retrievedPrintArea = workbook.getPrintArea(1);
assertNotNull("Print Area Not Found (Sheet 2)", retrievedPrintArea); assertNotNull("Print Area Not Found (Sheet 2)", retrievedPrintArea);
assertEquals(reference2, retrievedPrintArea); assertEquals("Sheet2!" + reference2, retrievedPrintArea);
retrievedPrintArea = workbook.getPrintArea(2); retrievedPrintArea = workbook.getPrintArea(2);
assertNotNull("Print Area Not Found (Sheet 3)", retrievedPrintArea); assertNotNull("Print Area Not Found (Sheet 3)", retrievedPrintArea);
assertEquals(reference3, retrievedPrintArea); assertEquals("Sheet3!" + reference3, retrievedPrintArea);
// Check print areas after re-reading workbook // Check print areas after re-reading workbook
workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook); workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
retrievedPrintArea = workbook.getPrintArea(0); retrievedPrintArea = workbook.getPrintArea(0);
assertNotNull("Print Area Not Found (Sheet 1)", retrievedPrintArea); assertNotNull("Print Area Not Found (Sheet 1)", retrievedPrintArea);
assertEquals(reference1, retrievedPrintArea); assertEquals("Sheet1!" + reference1, retrievedPrintArea);
retrievedPrintArea = workbook.getPrintArea(1); retrievedPrintArea = workbook.getPrintArea(1);
assertNotNull("Print Area Not Found (Sheet 2)", retrievedPrintArea); assertNotNull("Print Area Not Found (Sheet 2)", retrievedPrintArea);
assertEquals(reference2, retrievedPrintArea); assertEquals("Sheet2!" + reference2, retrievedPrintArea);
retrievedPrintArea = workbook.getPrintArea(2); retrievedPrintArea = workbook.getPrintArea(2);
assertNotNull("Print Area Not Found (Sheet 3)", retrievedPrintArea); assertNotNull("Print Area Not Found (Sheet 3)", retrievedPrintArea);
assertEquals(reference3, retrievedPrintArea); assertEquals("Sheet3!" + reference3, retrievedPrintArea);
} }
/** /**
@ -341,10 +336,9 @@ public final class TestNamedRange extends TestCase {
*/ */
public void testPrintAreaCoords(){ public void testPrintAreaCoords(){
HSSFWorkbook workbook = new HSSFWorkbook(); HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Test Print Area"); workbook.createSheet("Test Print Area");
String sheetName = workbook.getSheetName(0); String sheetName = workbook.getSheetName(0);
String reference = sheetName+"!$A$1:$B$1";
workbook.setPrintArea(0, 0, 1, 0, 0); workbook.setPrintArea(0, 0, 1, 0, 0);
String retrievedPrintArea = workbook.getPrintArea(0); String retrievedPrintArea = workbook.getPrintArea(0);
@ -360,18 +354,17 @@ public final class TestNamedRange extends TestCase {
*/ */
public void testPrintAreaUnion(){ public void testPrintAreaUnion(){
HSSFWorkbook workbook = new HSSFWorkbook(); HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Test Print Area"); workbook.createSheet("Test Print Area");
String sheetName = workbook.getSheetName(0); String sheetName = workbook.getSheetName(0);
String reference = sheetName + "!$A$1:$B$1, " + sheetName + "!$D$1:$F$2"; if (false) { // TODO - fix formula parser to support unions
String expResult = "'" + sheetName + "'!$A$1:$B$1,'" + sheetName + "'!$D$1:$F$2"; String reference = "'" + sheetName + "'!$A$1:$B$1,'" + sheetName + "'!$D$1:$F$2";
workbook.setPrintArea(0, reference); workbook.setPrintArea(0, reference);
String retrievedPrintArea = workbook.getPrintArea(0); String retrievedPrintArea = workbook.getPrintArea(0);
assertNotNull("Print Area not defined for first sheet", retrievedPrintArea); assertNotNull("Print Area not defined for first sheet", retrievedPrintArea);
assertEquals(expResult, retrievedPrintArea); assertEquals(reference, retrievedPrintArea);
}
} }
/** /**
@ -380,10 +373,9 @@ public final class TestNamedRange extends TestCase {
*/ */
public void testPrintAreaRemove() { public void testPrintAreaRemove() {
HSSFWorkbook workbook = new HSSFWorkbook(); HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Test Print Area"); workbook.createSheet("Test Print Area");
String sheetName = workbook.getSheetName(0); workbook.getSheetName(0);
String reference = sheetName+"!$A$1:$B$1";
workbook.setPrintArea(0, 0, 1, 0, 0); workbook.setPrintArea(0, 0, 1, 0, 0);
String retrievedPrintArea = workbook.getPrintArea(0); String retrievedPrintArea = workbook.getPrintArea(0);
@ -410,7 +402,7 @@ public final class TestNamedRange extends TestCase {
// create named range for a single cell using areareference // create named range for a single cell using areareference
HSSFName namedCell = wb.createName(); HSSFName namedCell = wb.createName();
namedCell.setNameName(cellName); namedCell.setNameName(cellName);
String reference = sheetName+"!A1:A1"; String reference = "'" + sheetName + "'" + "!A1:A1";
namedCell.setReference(reference); namedCell.setReference(reference);
// retrieve the newly created named range // retrieve the newly created named range
@ -471,7 +463,7 @@ public final class TestNamedRange extends TestCase {
HSSFName name1 = wb.getNameAt(0); HSSFName name1 = wb.getNameAt(0);
assertEquals("a", name1.getNameName()); assertEquals("a", name1.getNameName());
assertEquals("Sheet1!$A$1", name1.getReference()); assertEquals("Sheet1!$A$1", name1.getReference());
AreaReference ref1 = new AreaReference(name1.getReference()); new AreaReference(name1.getReference());
assertTrue("Successfully constructed first reference", true); assertTrue("Successfully constructed first reference", true);
HSSFName name2 = wb.getNameAt(1); HSSFName name2 = wb.getNameAt(1);
@ -479,7 +471,7 @@ public final class TestNamedRange extends TestCase {
assertEquals("Sheet1!#REF!", name2.getReference()); assertEquals("Sheet1!#REF!", name2.getReference());
assertTrue(name2.isDeleted()); assertTrue(name2.isDeleted());
try { try {
AreaReference ref2 = new AreaReference(name2.getReference()); new AreaReference(name2.getReference());
fail("attempt to supply an invalid reference to AreaReference constructor results in exception"); fail("attempt to supply an invalid reference to AreaReference constructor results in exception");
} catch (StringIndexOutOfBoundsException e) { // TODO - use a different exception for this condition } catch (StringIndexOutOfBoundsException e) { // TODO - use a different exception for this condition
// expected during successful test // expected during successful test

View File

@ -32,7 +32,6 @@ public class AllHSSFUtilTests {
result.addTestSuite(TestAreaReference.class); result.addTestSuite(TestAreaReference.class);
result.addTestSuite(TestCellReference.class); result.addTestSuite(TestCellReference.class);
result.addTestSuite(TestHSSFColor.class); result.addTestSuite(TestHSSFColor.class);
result.addTestSuite(TestRangeAddress.class);
result.addTestSuite(TestRKUtil.class); result.addTestSuite(TestRKUtil.class);
return result; return result;
} }

View File

@ -23,6 +23,7 @@ import java.io.InputStream;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.NameRecord; import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.formula.Area3DPtg; import org.apache.poi.hssf.record.formula.Area3DPtg;
@ -107,6 +108,7 @@ public final class TestAreaReference extends TestCase {
TestCellReference.confirmCell(allCells[2], "Tabelle1", 6, 1, true, true, "Tabelle1!$B$7"); TestCellReference.confirmCell(allCells[2], "Tabelle1", 6, 1, true, true, "Tabelle1!$B$7");
} }
// TODO - remove this sub-class
private static final class HSSFWB extends HSSFWorkbook { private static final class HSSFWB extends HSSFWorkbook {
public HSSFWB(InputStream in) throws IOException { public HSSFWB(InputStream in) throws IOException {
super(in); super(in);
@ -220,7 +222,7 @@ public final class TestAreaReference extends TestCase {
assertEquals(refB, ptgC.toFormulaString(eb)); assertEquals(refB, ptgC.toFormulaString(eb));
assertEquals(",", ptgD.toFormulaString()); assertEquals(",", ptgD.toFormulaString());
assertEquals(ref, nr.getAreaReference(wb)); assertEquals(ref, HSSFFormulaParser.toFormulaString(wb, nr.getNameDefinition()));
// Check the high level definition // Check the high level definition
int idx = wb.getNameIndex("test"); int idx = wb.getNameIndex("test");

View File

@ -1,46 +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.util;
import junit.framework.TestCase;
/**
* Tests the Range Address Utility Functionality
* @author Danny Mui (danny at muibros.com)
*/
public class TestRangeAddress extends TestCase {
public TestRangeAddress(String s) {
super(s);
}
public static void main(java.lang.String[] args) {
junit.textui.TestRunner.run(TestRangeAddress.class);
}
public void testReferenceParse() {
String reference = "Sheet2!$A$1:$C$3";
RangeAddress ra = new RangeAddress(reference);
assertEquals("Sheet2!A1:C3", ra.getAddress());
}
}