initial work on supporting calls to add-in functions

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@684971 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-08-11 22:55:38 +00:00
parent 3a1f1f4526
commit 647522fef8
17 changed files with 792 additions and 683 deletions

View File

@ -26,6 +26,7 @@ import org.apache.poi.hssf.record.formula.*;
import org.apache.poi.hssf.record.formula.function.FunctionMetadata; import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry; import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFName;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.AreaReference; import org.apache.poi.hssf.util.AreaReference;
import org.apache.poi.hssf.util.CellReference; import org.apache.poi.hssf.util.CellReference;
@ -369,13 +370,31 @@ public final class FormulaParser {
* @param name case preserved function name (as it was entered/appeared in the formula). * @param name case preserved function name (as it was entered/appeared in the formula).
*/ */
private ParseNode function(String name) { private ParseNode function(String name) {
NamePtg nameToken = null; Ptg nameToken = null;
// Note regarding parameter - if(!AbstractFunctionPtg.isBuiltInFunctionName(name)) {
if(!AbstractFunctionPtg.isInternalFunctionName(name)) { // user defined function
// external functions get a Name token which points to a defined name record
nameToken = new NamePtg(name, this.book);
// in the token tree, the name is more or less the first argument // in the token tree, the name is more or less the first argument
int nameIndex = book.getNameIndex(name);
if (nameIndex >= 0) {
HSSFName hName = book.getNameAt(nameIndex);
if (!hName.isFunctionName()) {
throw new FormulaParseException("Attempt to use name '" + name
+ "' as a function, but defined name in workbook does not refer to a function");
}
// calls to user-defined functions within the workbook
// get a Name token which points to a defined name record
nameToken = new NamePtg(name, this.book);
} else {
nameToken = book.getNameXPtg(name);
if (nameToken == null) {
throw new FormulaParseException("Name '" + name
+ "' is completely unknown in the current workbook");
}
}
} }
Match('('); Match('(');
@ -389,11 +408,11 @@ public final class FormulaParser {
* Generates the variable function ptg for the formula. * Generates the variable function ptg for the formula.
* <p> * <p>
* For IF Formulas, additional PTGs are added to the tokens * For IF Formulas, additional PTGs are added to the tokens
* @param name * @param name a {@link NamePtg} or {@link NameXPtg} or <code>null</code>
* @param numArgs * @param numArgs
* @return Ptg a null is returned if we're in an IF formula, it needs extreme manipulation and is handled in this function * @return Ptg a null is returned if we're in an IF formula, it needs extreme manipulation and is handled in this function
*/ */
private ParseNode getFunction(String name, NamePtg namePtg, ParseNode[] args) { private ParseNode getFunction(String name, Ptg namePtg, ParseNode[] args) {
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByName(name.toUpperCase()); FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByName(name.toUpperCase());
int numArgs = args.length; int numArgs = args.length;

View File

@ -25,11 +25,11 @@ import org.apache.poi.hssf.record.CRNCountRecord;
import org.apache.poi.hssf.record.CRNRecord; import org.apache.poi.hssf.record.CRNRecord;
import org.apache.poi.hssf.record.CountryRecord; import org.apache.poi.hssf.record.CountryRecord;
import org.apache.poi.hssf.record.ExternSheetRecord; import org.apache.poi.hssf.record.ExternSheetRecord;
import org.apache.poi.hssf.record.ExternSheetSubRecord;
import org.apache.poi.hssf.record.ExternalNameRecord; import org.apache.poi.hssf.record.ExternalNameRecord;
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;
import org.apache.poi.hssf.record.SupBookRecord; import org.apache.poi.hssf.record.SupBookRecord;
import org.apache.poi.hssf.record.formula.NameXPtg;
/** /**
* Link Table (OOO pdf reference: 4.10.3 ) <p/> * Link Table (OOO pdf reference: 4.10.3 ) <p/>
@ -122,6 +122,19 @@ final class LinkTable {
public String getNameText(int definedNameIndex) { public String getNameText(int definedNameIndex) {
return _externalNameRecords[definedNameIndex].getText(); return _externalNameRecords[definedNameIndex].getText();
} }
/**
* Performs case-insensitive search
* @return -1 if not found
*/
public int getIndexOfName(String name) {
for (int i = 0; i < _externalNameRecords.length; i++) {
if(_externalNameRecords[i].getText().equalsIgnoreCase(name)) {
return i;
}
}
return -1;
}
} }
private final ExternalBookBlock[] _externalBookBlocks; private final ExternalBookBlock[] _externalBookBlocks;
@ -270,42 +283,31 @@ final class LinkTable {
} }
public short getIndexToSheet(short num) { public int getIndexToSheet(int extRefIndex) {
return _externSheetRecord.getREFRecordAt(num).getIndexToFirstSupBook(); return _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex);
} }
public int getSheetIndexFromExternSheetIndex(int externSheetNumber) { public int getSheetIndexFromExternSheetIndex(int extRefIndex) {
if (externSheetNumber >= _externSheetRecord.getNumOfREFStructures()) { if (extRefIndex >= _externSheetRecord.getNumOfRefs()) {
return -1; return -1;
} }
return _externSheetRecord.getREFRecordAt(externSheetNumber).getIndexToFirstSupBook(); return _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex);
} }
public short addSheetIndexToExternSheet(short sheetNumber) { public int addSheetIndexToExternSheet(int sheetNumber) {
// TODO - what about the first parameter (extBookIndex)?
ExternSheetSubRecord record = new ExternSheetSubRecord(); return _externSheetRecord.addRef(0, sheetNumber, sheetNumber);
record.setIndexToFirstSupBook(sheetNumber);
record.setIndexToLastSupBook(sheetNumber);
_externSheetRecord.addREFRecord(record);
_externSheetRecord.setNumOfREFStructures((short)(_externSheetRecord.getNumOfREFStructures() + 1));
return (short)(_externSheetRecord.getNumOfREFStructures() - 1);
} }
public short checkExternSheet(int sheetNumber) { public short checkExternSheet(int sheetIndex) {
//Trying to find reference to this sheet //Trying to find reference to this sheet
int nESRs = _externSheetRecord.getNumOfREFStructures(); int i = _externSheetRecord.getRefIxForSheet(sheetIndex);
for(short i=0; i< nESRs; i++) { if (i>=0) {
ExternSheetSubRecord esr = _externSheetRecord.getREFRecordAt(i); return (short)i;
if (esr.getIndexToFirstSupBook() == sheetNumber
&& esr.getIndexToLastSupBook() == sheetNumber){
return i;
}
} }
//We Haven't found reference to this sheet //We Haven't found reference to this sheet
return addSheetIndexToExternSheet((short) sheetNumber); return (short)addSheetIndexToExternSheet((short) sheetIndex);
} }
@ -326,11 +328,31 @@ final class LinkTable {
} }
public int getNumberOfREFStructures() { public int getNumberOfREFStructures() {
return _externSheetRecord.getNumOfREFStructures(); return _externSheetRecord.getNumOfRefs();
} }
public String resolveNameXText(int refIndex, int definedNameIndex) { public String resolveNameXText(int refIndex, int definedNameIndex) {
short extBookIndex = _externSheetRecord.getREFRecordAt(refIndex).getIndexToSupBook(); int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex);
return _externalBookBlocks[extBookIndex].getNameText(definedNameIndex); return _externalBookBlocks[extBookIndex].getNameText(definedNameIndex);
} }
public NameXPtg getNameXPtg(String name) {
// first find any external book block that contains the name:
for (int i = 0; i < _externalBookBlocks.length; i++) {
int definedNameIndex = _externalBookBlocks[i].getIndexOfName(name);
if (definedNameIndex < 0) {
continue;
}
// found it.
int sheetRefIndex = findRefIndexFromExtBookIndex(i);
if (sheetRefIndex >= 0) {
return new NameXPtg(sheetRefIndex, definedNameIndex);
}
}
return null;
}
private int findRefIndexFromExtBookIndex(int extBookIndex) {
return _externSheetRecord.findRefIndexFromExtBookIndex(extBookIndex);
}
} }

View File

@ -15,21 +15,70 @@
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.model; package org.apache.poi.hssf.model;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.SheetReferences;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherBoolProperty;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherDggRecord;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherRGBProperty;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSplitMenuColorsRecord;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BackupRecord;
import org.apache.poi.hssf.record.BookBoolRecord;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.CodepageRecord;
import org.apache.poi.hssf.record.CountryRecord;
import org.apache.poi.hssf.record.DSFRecord;
import org.apache.poi.hssf.record.DateWindow1904Record;
import org.apache.poi.hssf.record.DrawingGroupRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.ExtSSTRecord;
import org.apache.poi.hssf.record.ExtendedFormatRecord;
import org.apache.poi.hssf.record.ExternSheetRecord;
import org.apache.poi.hssf.record.FileSharingRecord;
import org.apache.poi.hssf.record.FnGroupCountRecord;
import org.apache.poi.hssf.record.FontRecord;
import org.apache.poi.hssf.record.FormatRecord;
import org.apache.poi.hssf.record.HideObjRecord;
import org.apache.poi.hssf.record.HyperlinkRecord;
import org.apache.poi.hssf.record.InterfaceEndRecord;
import org.apache.poi.hssf.record.InterfaceHdrRecord;
import org.apache.poi.hssf.record.MMSRecord;
import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.PaletteRecord;
import org.apache.poi.hssf.record.PasswordRecord;
import org.apache.poi.hssf.record.PasswordRev4Record;
import org.apache.poi.hssf.record.PrecisionRecord;
import org.apache.poi.hssf.record.ProtectRecord;
import org.apache.poi.hssf.record.ProtectionRev4Record;
import org.apache.poi.hssf.record.RecalcIdRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RefreshAllRecord;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.StyleRecord;
import org.apache.poi.hssf.record.SupBookRecord;
import org.apache.poi.hssf.record.TabIdRecord;
import org.apache.poi.hssf.record.UnicodeString;
import org.apache.poi.hssf.record.UseSelFSRecord;
import org.apache.poi.hssf.record.WindowOneRecord;
import org.apache.poi.hssf.record.WindowProtectRecord;
import org.apache.poi.hssf.record.WriteAccessRecord;
import org.apache.poi.hssf.record.WriteProtectRecord;
import org.apache.poi.hssf.record.formula.NameXPtg;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.SheetReferences;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
/** /**
* Low level model implementation of a Workbook. Provides creational methods * Low level model implementation of a Workbook. Provides creational methods
* for settings and objects contained in the workbook object. * for settings and objects contained in the workbook object.
@ -55,7 +104,7 @@ import java.util.Locale;
* @version 1.0-pre * @version 1.0-pre
*/ */
public final class Workbook implements Model { public final class Workbook implements Model {
private static final int DEBUG = POILogger.DEBUG; private static final int DEBUG = POILogger.DEBUG;
/** /**
* constant used to set the "codepage" wherever "codepage" is set in records * constant used to set the "codepage" wherever "codepage" is set in records
@ -461,19 +510,23 @@ public final class Workbook implements Model {
/** /**
* Sets the BOF for a given sheet * Sets the BOF for a given sheet
* *
* @param sheetnum the number of the sheet to set the positing of the bof for * @param sheetIndex the number of the sheet to set the positing of the bof for
* @param pos the actual bof position * @param pos the actual bof position
*/ */
public void setSheetBof(int sheetnum, int pos) { public void setSheetBof(int sheetIndex, int pos) {
if (log.check( POILogger.DEBUG )) if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetnum), log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetIndex),
" at pos=", new Integer(pos)); " at pos=", new Integer(pos));
checkSheets(sheetnum); checkSheets(sheetIndex);
(( BoundSheetRecord ) boundsheets.get(sheetnum)) getBoundSheetRec(sheetIndex)
.setPositionOfBof(pos); .setPositionOfBof(pos);
} }
private BoundSheetRecord getBoundSheetRec(int sheetIndex) {
return ((BoundSheetRecord) boundsheets.get(sheetIndex));
}
/** /**
* Returns the position of the backup record. * Returns the position of the backup record.
*/ */
@ -509,7 +562,7 @@ public final class Workbook implements Model {
{ {
for ( int i = 0; i < boundsheets.size(); i++ ) for ( int i = 0; i < boundsheets.size(); i++ )
{ {
BoundSheetRecord boundSheetRecord = (BoundSheetRecord) boundsheets.get( i ); BoundSheetRecord boundSheetRecord = getBoundSheetRec(i);
if (excludeSheetIdx != i && name.equalsIgnoreCase(boundSheetRecord.getSheetname())) if (excludeSheetIdx != i && name.equalsIgnoreCase(boundSheetRecord.getSheetname()))
return true; return true;
} }
@ -526,7 +579,7 @@ public final class Workbook implements Model {
*/ */
public void setSheetName(int sheetnum, String sheetname, short encoding ) { public void setSheetName(int sheetnum, String sheetname, short encoding ) {
checkSheets(sheetnum); checkSheets(sheetnum);
BoundSheetRecord sheet = (BoundSheetRecord)boundsheets.get( sheetnum ); BoundSheetRecord sheet = getBoundSheetRec(sheetnum);
sheet.setSheetname(sheetname); sheet.setSheetname(sheetname);
sheet.setSheetnameLength( (byte)sheetname.length() ); sheet.setSheetnameLength( (byte)sheetname.length() );
sheet.setCompressedUnicodeFlag( (byte)encoding ); sheet.setCompressedUnicodeFlag( (byte)encoding );
@ -548,13 +601,11 @@ public final class Workbook implements Model {
/** /**
* gets the name for a given sheet. * gets the name for a given sheet.
* *
* @param sheetnum the sheet number (0 based) * @param sheetIndex the sheet number (0 based)
* @return sheetname the name for the sheet * @return sheetname the name for the sheet
*/ */
public String getSheetName(int sheetIndex) {
public String getSheetName(int sheetnum) { return getBoundSheetRec(sheetIndex).getSheetname();
return (( BoundSheetRecord ) boundsheets.get(sheetnum))
.getSheetname();
} }
/** /**
@ -565,8 +616,7 @@ public final class Workbook implements Model {
*/ */
public boolean isSheetHidden(int sheetnum) { public boolean isSheetHidden(int sheetnum) {
BoundSheetRecord bsr = ( BoundSheetRecord ) boundsheets.get(sheetnum); return getBoundSheetRec(sheetnum).isHidden();
return bsr.isHidden();
} }
/** /**
@ -577,8 +627,7 @@ public final class Workbook implements Model {
*/ */
public void setSheetHidden(int sheetnum, boolean hidden) { public void setSheetHidden(int sheetnum, boolean hidden) {
BoundSheetRecord bsr = ( BoundSheetRecord ) boundsheets.get(sheetnum); getBoundSheetRec(sheetnum).setHidden(hidden);
bsr.setHidden(hidden);
} }
/** /**
* get the sheet's index * get the sheet's index
@ -851,7 +900,7 @@ public final class Workbook implements Model {
if (record instanceof BoundSheetRecord) { if (record instanceof BoundSheetRecord) {
if(!wroteBoundSheets) { if(!wroteBoundSheets) {
for (int i = 0; i < boundsheets.size(); i++) { for (int i = 0; i < boundsheets.size(); i++) {
len+= ((BoundSheetRecord)boundsheets.get(i)) len+= getBoundSheetRec(i)
.serialize(pos+offset+len, data); .serialize(pos+offset+len, data);
} }
wroteBoundSheets = true; wroteBoundSheets = true;
@ -1134,8 +1183,8 @@ public final class Workbook implements Model {
retval.setWidth(( short ) 0x3a5c); retval.setWidth(( short ) 0x3a5c);
retval.setHeight(( short ) 0x23be); retval.setHeight(( short ) 0x23be);
retval.setOptions(( short ) 0x38); retval.setOptions(( short ) 0x38);
retval.setSelectedTab(( short ) 0x0); retval.setActiveSheetIndex( 0x0);
retval.setDisplayedTab(( short ) 0x0); retval.setFirstVisibleTab(0x0);
retval.setNumSelectedTabs(( short ) 1); retval.setNumSelectedTabs(( short ) 1);
retval.setTabWidthRatio(( short ) 0x258); retval.setTabWidthRatio(( short ) 0x258);
return retval; return retval;
@ -1882,15 +1931,15 @@ public final class Workbook implements Model {
* @return sheet name * @return sheet name
*/ */
public String findSheetNameFromExternSheet(short num){ public String findSheetNameFromExternSheet(short num){
String result="";
short indexToSheet = linkTable.getIndexToSheet(num); int indexToSheet = linkTable.getIndexToSheet(num);
if (indexToSheet>-1) { //error check, bail out gracefully! if (indexToSheet < 0) {
result = getSheetName(indexToSheet); // TODO - what does '-1' mean here?
//error check, bail out gracefully!
return "";
} }
return getSheetName(indexToSheet);
return result;
} }
/** /**
@ -2402,6 +2451,8 @@ public final class Workbook implements Model {
public String resolveNameXText(int refIndex, int definedNameIndex) { public String resolveNameXText(int refIndex, int definedNameIndex) {
return linkTable.resolveNameXText(refIndex, definedNameIndex); return linkTable.resolveNameXText(refIndex, definedNameIndex);
} }
public NameXPtg getNameXPtg(String name) {
return getOrCreateLinkTable().getNameXPtg(name);
}
} }

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
@ -16,28 +15,84 @@
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import java.util.ArrayList;
/** /**
* Title: Extern Sheet <P> * EXTERNSHEET (0x0017)<br/>
* Description: A List of Inndexes to SupBook <P> * A List of Indexes to EXTERNALBOOK (supplemental book) Records <p/>
* REFERENCE: <P> *
* @author Libin Roman (Vista Portal LDT. Developer) * @author Libin Roman (Vista Portal LDT. Developer)
* @version 1.0-pre
*/ */
public class ExternSheetRecord extends Record { public class ExternSheetRecord extends Record {
public final static short sid = 0x17; public final static short sid = 0x0017;
private short field_1_number_of_REF_sturcutres; private List _list;
private ArrayList field_2_REF_structures;
private final class RefSubRecord {
public static final int ENCODED_SIZE = 6;
/** index to External Book Block (which starts with a EXTERNALBOOK record) */
private int _extBookIndex;
private int _firstSheetIndex; // may be -1 (0xFFFF)
private int _lastSheetIndex; // may be -1 (0xFFFF)
/** a Constructor for making new sub record
*/
public RefSubRecord(int extBookIndex, int firstSheetIndex, int lastSheetIndex) {
_extBookIndex = extBookIndex;
_firstSheetIndex = firstSheetIndex;
_lastSheetIndex = lastSheetIndex;
}
/**
* @param in the RecordInputstream to read the record from
*/
public RefSubRecord(RecordInputStream in) {
this(in.readShort(), in.readShort(), in.readShort());
}
public int getExtBookIndex(){
return _extBookIndex;
}
public int getFirstSheetIndex(){
return _firstSheetIndex;
}
public int getLastSheetIndex(){
return _lastSheetIndex;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("extBook=").append(_extBookIndex);
buffer.append(" firstSheet=").append(_firstSheetIndex);
buffer.append(" lastSheet=").append(_lastSheetIndex);
return buffer.toString();
}
/**
* called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a
* byte array.
*
* @param offset to begin writing at
* @param data byte array containing instance data
* @return number of bytes written
*/
public void serialize(int offset, byte [] data) {
LittleEndian.putUShort(data, 0 + offset, _extBookIndex);
LittleEndian.putUShort(data, 2 + offset, _firstSheetIndex);
LittleEndian.putUShort(data, 4 + offset, _lastSheetIndex);
}
}
public ExternSheetRecord() { public ExternSheetRecord() {
field_2_REF_structures = new ArrayList(); _list = new ArrayList();
} }
/** /**
@ -68,72 +123,60 @@ public class ExternSheetRecord extends Record {
* @param in the RecordInputstream to read the record from * @param in the RecordInputstream to read the record from
*/ */
protected void fillFields(RecordInputStream in) { protected void fillFields(RecordInputStream in) {
field_2_REF_structures = new ArrayList(); _list = new ArrayList();
field_1_number_of_REF_sturcutres = in.readShort(); int nItems = in.readShort();
for (int i = 0 ; i < field_1_number_of_REF_sturcutres ; ++i) { for (int i = 0 ; i < nItems ; ++i) {
ExternSheetSubRecord rec = new ExternSheetSubRecord(in); RefSubRecord rec = new RefSubRecord(in);
field_2_REF_structures.add( rec); _list.add( rec);
} }
} }
/**
* sets the number of the REF structors , that is in Excel file
* @param numStruct number of REF structs
*/
public void setNumOfREFStructures(short numStruct) {
field_1_number_of_REF_sturcutres = numStruct;
}
/** /**
* return the number of the REF structors , that is in Excel file * @return number of REF structures
* @return number of REF structs
*/ */
public short getNumOfREFStructures() { public int getNumOfRefs() {
return field_1_number_of_REF_sturcutres; return _list.size();
} }
/** /**
* adds REF struct (ExternSheetSubRecord) * adds REF struct (ExternSheetSubRecord)
* @param rec REF struct * @param rec REF struct
*/ */
public void addREFRecord(ExternSheetSubRecord rec) { public void addREFRecord(RefSubRecord rec) {
field_2_REF_structures.add(rec); _list.add(rec);
} }
/** returns the number of REF Records, which is in model /** returns the number of REF Records, which is in model
* @return number of REF records * @return number of REF records
*/ */
public int getNumOfREFRecords() { public int getNumOfREFRecords() {
return field_2_REF_structures.size(); return _list.size();
} }
/** returns the REF record (ExternSheetSubRecord)
* @param elem index to place
* @return REF record
*/
public ExternSheetSubRecord getREFRecordAt(int elem) {
ExternSheetSubRecord result = ( ExternSheetSubRecord ) field_2_REF_structures.get(elem);
return result;
}
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer sb = new StringBuffer();
int nItems = _list.size();
buffer.append("[EXTERNSHEET]\n"); sb.append("[EXTERNSHEET]\n");
buffer.append(" numOfRefs = ").append(getNumOfREFStructures()).append("\n"); sb.append(" numOfRefs = ").append(nItems).append("\n");
for (int k=0; k < this.getNumOfREFRecords(); k++) { for (int i=0; i < nItems; i++) {
buffer.append("refrec #").append(k).append('\n'); sb.append("refrec #").append(i).append(": ");
buffer.append(getREFRecordAt(k).toString()); sb.append(getRef(i).toString());
buffer.append("----refrec #").append(k).append('\n'); sb.append('\n');
} }
buffer.append("[/EXTERNSHEET]\n"); sb.append("[/EXTERNSHEET]\n");
return buffer.toString(); return sb.toString();
}
private int getDataSize() {
return 2 + _list.size() * RefSubRecord.ENCODED_SIZE;
} }
/** /**
@ -146,24 +189,29 @@ public class ExternSheetRecord extends Record {
* @return number of bytes written * @return number of bytes written
*/ */
public int serialize(int offset, byte [] data) { public int serialize(int offset, byte [] data) {
LittleEndian.putShort(data, 0 + offset, sid); int dataSize = getDataSize();
LittleEndian.putShort(data, 2 + offset,(short)(2 + (getNumOfREFRecords() *6)));
LittleEndian.putShort(data, 4 + offset, getNumOfREFStructures()); int nItems = _list.size();
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, dataSize);
LittleEndian.putUShort(data, 4 + offset, nItems);
int pos = 6 ; int pos = 6 ;
for (int k = 0; k < getNumOfREFRecords(); k++) { for (int i = 0; i < nItems; i++) {
ExternSheetSubRecord record = getREFRecordAt(k); getRef(i).serialize(offset + pos, data);
System.arraycopy(record.serialize(), 0, data, pos + offset, 6);
pos +=6; pos +=6;
} }
return getRecordSize(); return dataSize + 4;
} }
private RefSubRecord getRef(int i) {
return (RefSubRecord) _list.get(i);
}
public int getRecordSize() { public int getRecordSize() {
return 4 + 2 + getNumOfREFRecords() * 6; return 4 + getDataSize();
} }
/** /**
@ -172,4 +220,44 @@ public class ExternSheetRecord extends Record {
public short getSid() { public short getSid() {
return sid; return sid;
} }
public int getExtbookIndexFromRefIndex(int refIndex) {
return getRef(refIndex).getExtBookIndex();
}
/**
* @return -1 if not found
*/
public int findRefIndexFromExtBookIndex(int extBookIndex) {
int nItems = _list.size();
for (int i = 0; i < nItems; i++) {
if (getRef(i).getExtBookIndex() == extBookIndex) {
return i;
}
}
return -1;
}
public int getFirstSheetIndexFromRefIndex(int extRefIndex) {
return getRef(extRefIndex).getFirstSheetIndex();
}
/**
* @return index of newly added ref
*/
public int addRef(int extBookIndex, int firstSheetIndex, int lastSheetIndex) {
_list.add(new RefSubRecord(extBookIndex, firstSheetIndex, lastSheetIndex));
return _list.size() - 1;
}
public int getRefIxForSheet(int sheetIndex) {
int nItems = _list.size();
for (int i = 0; i < nItems; i++) {
RefSubRecord ref = getRef(i);
if (ref.getFirstSheetIndex() == sheetIndex && ref.getLastSheetIndex() == sheetIndex) {
return i;
}
}
return -1;
}
} }

View File

@ -1,154 +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;
import org.apache.poi.util.LittleEndian;
/**
* Title: A sub Record for Extern Sheet <P>
* Description: Defines a named range within a workbook. <P>
* REFERENCE: <P>
* @author Libin Roman (Vista Portal LDT. Developer)
* @version 1.0-pre
*/
public class ExternSheetSubRecord extends Record {
public final static short sid = 0xFFF; // only here for conformance, doesn't really have an sid
private short field_1_index_to_supbook;
private short field_2_index_to_first_supbook_sheet;
private short field_3_index_to_last_supbook_sheet;
/** a Constractor for making new sub record
*/
public ExternSheetSubRecord() {
}
/**
* Constructs a Extern Sheet Sub Record record and sets its fields appropriately.
*
* @param in the RecordInputstream to read the record from
*/
public ExternSheetSubRecord(RecordInputStream in) {
super(in);
}
/** Sets the Index to the sup book
* @param index sup book index
*/
public void setIndexToSupBook(short index){
field_1_index_to_supbook = index;
}
/** gets the index to sup book
* @return sup book index
*/
public short getIndexToSupBook(){
return field_1_index_to_supbook;
}
/** sets the index to first sheet in supbook
* @param index index to first sheet
*/
public void setIndexToFirstSupBook(short index){
field_2_index_to_first_supbook_sheet = index;
}
/** gets the index to first sheet from supbook
* @return index to first supbook
*/
public short getIndexToFirstSupBook(){
return field_2_index_to_first_supbook_sheet;
}
/** sets the index to last sheet in supbook
* @param index index to last sheet
*/
public void setIndexToLastSupBook(short index){
field_3_index_to_last_supbook_sheet = index;
}
/** gets the index to last sheet in supbook
* @return index to last supbook
*/
public short getIndexToLastSupBook(){
return field_3_index_to_last_supbook_sheet;
}
/**
* called by constructor, should throw runtime exception in the event of a
* record passed with a differing ID.
*
* @param id alleged id for this record
*/
protected void validateSid(short id) {
// do nothing
}
/**
* @param in the RecordInputstream to read the record from
*/
protected void fillFields(RecordInputStream in) {
field_1_index_to_supbook = in.readShort();
field_2_index_to_first_supbook_sheet = in.readShort();
field_3_index_to_last_supbook_sheet = in.readShort();
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(" supbookindex =").append(getIndexToSupBook()).append('\n');
buffer.append(" 1stsbindex =").append(getIndexToFirstSupBook()).append('\n');
buffer.append(" lastsbindex =").append(getIndexToLastSupBook()).append('\n');
return buffer.toString();
}
/**
* called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a
* byte array.
*
* @param offset to begin writing at
* @param data byte array containing instance data
* @return number of bytes written
*/
public int serialize(int offset, byte [] data) {
LittleEndian.putShort(data, 0 + offset, getIndexToSupBook());
LittleEndian.putShort(data, 2 + offset, getIndexToFirstSupBook());
LittleEndian.putShort(data, 4 + offset, getIndexToLastSupBook());
return getRecordSize();
}
/** returns the record size
*/
public int getRecordSize() {
return 6;
}
/**
* return the non static version of the id for this record.
*/
public short getSid() {
return sid;
}
}

View File

@ -34,7 +34,7 @@ import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /**
* Title: Name Record (aka Named Range) <P> * Title: DEFINEDNAME Record (0x0018) <p/>
* Description: Defines a named range within a workbook. <P> * Description: Defines a named range within a workbook. <P>
* REFERENCE: <P> * REFERENCE: <P>
* @author Libin Roman (Vista Portal LDT. Developer) * @author Libin Roman (Vista Portal LDT. Developer)
@ -43,10 +43,7 @@ import org.apache.poi.util.StringUtil;
* @version 1.0-pre * @version 1.0-pre
*/ */
public final class NameRecord extends Record { public final class NameRecord extends Record {
/** public final static short sid = 0x0018;
*/
public final static short sid = 0x18; //Docs says that it is 0x218
/**Included for completeness sake, not implemented /**Included for completeness sake, not implemented
*/ */
public final static byte BUILTIN_CONSOLIDATE_AREA = (byte)1; public final static byte BUILTIN_CONSOLIDATE_AREA = (byte)1;
@ -92,14 +89,15 @@ public final class NameRecord extends Record {
*/ */
public final static byte BUILTIN_SHEET_TITLE = (byte)12; public final static byte BUILTIN_SHEET_TITLE = (byte)12;
public static final short OPT_HIDDEN_NAME = (short) 0x0001; private static final class Option {
public static final short OPT_FUNCTION_NAME = (short) 0x0002; public static final int OPT_HIDDEN_NAME = 0x0001;
public static final short OPT_COMMAND_NAME = (short) 0x0004; public static final int OPT_FUNCTION_NAME = 0x0002;
public static final short OPT_MACRO = (short) 0x0008; public static final int OPT_COMMAND_NAME = 0x0004;
public static final short OPT_COMPLEX = (short) 0x0010; public static final int OPT_MACRO = 0x0008;
public static final short OPT_BUILTIN = (short) 0x0020; public static final int OPT_COMPLEX = 0x0010;
public static final short OPT_BINDATA = (short) 0x1000; public static final int OPT_BUILTIN = 0x0020;
public static final int OPT_BINDATA = 0x1000;
}
private short field_1_option_flag; private short field_1_option_flag;
private byte field_2_keyboard_shortcut; private byte field_2_keyboard_shortcut;
@ -124,13 +122,13 @@ public final class NameRecord extends Record {
/** Creates new NameRecord */ /** Creates new NameRecord */
public NameRecord() { public NameRecord() {
field_13_name_definition = new Stack(); field_13_name_definition = new Stack();
field_12_name_text = new String(); field_12_name_text = new String();
field_14_custom_menu_text = new String(); field_14_custom_menu_text = new String();
field_15_description_text = new String(); field_15_description_text = new String();
field_16_help_topic_text = new String(); field_16_help_topic_text = new String();
field_17_status_bar_text = new String(); field_17_status_bar_text = new String();
} }
/** /**
@ -139,7 +137,7 @@ public final class NameRecord extends Record {
* @param in the RecordInputstream to read the record from * @param in the RecordInputstream to read the record from
*/ */
public NameRecord(RecordInputStream in) { public NameRecord(RecordInputStream in) {
super(in); super(in);
} }
/** /**
@ -148,13 +146,13 @@ public final class NameRecord extends Record {
*/ */
public NameRecord(byte builtin, int sheetNumber) public NameRecord(byte builtin, int sheetNumber)
{ {
this(); this();
this.field_12_builtIn_name = builtin; this.field_12_builtIn_name = builtin;
this.setOptionFlag((short)(this.getOptionFlag() | OPT_BUILTIN)); this.setOptionFlag((short)(this.field_1_option_flag | Option.OPT_BUILTIN));
this.setNameTextLength((byte)1); this.setNameTextLength((byte)1);
field_6_sheetNumber = sheetNumber; //the extern sheets are set through references field_6_sheetNumber = sheetNumber; //the extern sheets are set through references
//clearing these because they are not used with builtin records //clearing these because they are not used with builtin records
this.setCustomMenuLength((byte)0); this.setCustomMenuLength((byte)0);
this.setDescriptionTextLength((byte)0); this.setDescriptionTextLength((byte)0);
this.setHelpTopicLength((byte)0); this.setHelpTopicLength((byte)0);
@ -167,7 +165,7 @@ public final class NameRecord extends Record {
* @param flag option flag * @param flag option flag
*/ */
public void setOptionFlag(short flag){ public void setOptionFlag(short flag){
field_1_option_flag = flag; field_1_option_flag = flag;
} }
@ -175,21 +173,21 @@ public final class NameRecord extends Record {
* @param shortcut keyboard shortcut * @param shortcut keyboard shortcut
*/ */
public void setKeyboardShortcut(byte shortcut){ public void setKeyboardShortcut(byte shortcut){
field_2_keyboard_shortcut = shortcut; field_2_keyboard_shortcut = shortcut;
} }
/** sets the name of the named range length /** sets the name of the named range length
* @param length name length * @param length name length
*/ */
public void setNameTextLength(byte length){ public void setNameTextLength(byte length){
field_3_length_name_text = length; field_3_length_name_text = length;
} }
/** sets the definition (reference - formula) length /** sets the definition (reference - formula) length
* @param length defenition length * @param length defenition length
*/ */
public void setDefinitionTextLength(short length){ public void setDefinitionTextLength(short length){
field_4_length_name_definition = length; field_4_length_name_definition = length;
} }
/** sets the index number to the extern sheet (thats is what writen in documentation /** sets the index number to the extern sheet (thats is what writen in documentation
@ -197,9 +195,9 @@ public final class NameRecord extends Record {
* @param index extern sheet index * @param index extern sheet index
*/ */
public void setUnused(short index){ public void setUnused(short index){
field_5_index_to_sheet = index; field_5_index_to_sheet = index;
// field_6_equals_to_index_to_sheet is equal to field_5_index_to_sheet // field_6_equals_to_index_to_sheet is equal to field_5_index_to_sheet
// field_6_equals_to_index_to_sheet = index; // field_6_equals_to_index_to_sheet = index;
} }
@ -209,7 +207,7 @@ public final class NameRecord extends Record {
*/ */
public int getSheetNumber() public int getSheetNumber()
{ {
return field_6_sheetNumber; return field_6_sheetNumber;
} }
/** /**
@ -217,14 +215,14 @@ public final class NameRecord extends Record {
* @see FnGroupCountRecord * @see FnGroupCountRecord
*/ */
public byte getFnGroup() { public byte getFnGroup() {
int masked = field_1_option_flag & 0x0fc0; int masked = field_1_option_flag & 0x0fc0;
return (byte) (masked >> 4); return (byte) (masked >> 4);
} }
public void setSheetNumber(int value) public void setSheetNumber(int value)
{ {
field_6_sheetNumber = value; field_6_sheetNumber = value;
} }
@ -232,87 +230,87 @@ public final class NameRecord extends Record {
* @param length custom menu length * @param length custom menu length
*/ */
public void setCustomMenuLength(byte length){ public void setCustomMenuLength(byte length){
field_7_length_custom_menu = length; field_7_length_custom_menu = length;
} }
/** sets the length of named range description /** sets the length of named range description
* @param length description length * @param length description length
*/ */
public void setDescriptionTextLength(byte length){ public void setDescriptionTextLength(byte length){
field_8_length_description_text = length; field_8_length_description_text = length;
} }
/** sets the help topic length /** sets the help topic length
* @param length help topic length * @param length help topic length
*/ */
public void setHelpTopicLength(byte length){ public void setHelpTopicLength(byte length){
field_9_length_help_topic_text = length; field_9_length_help_topic_text = length;
} }
/** sets the length of the status bar text /** sets the length of the status bar text
* @param length status bar text length * @param length status bar text length
*/ */
public void setStatusBarLength(byte length){ public void setStatusBarLength(byte length){
field_10_length_status_bar_text = length; field_10_length_status_bar_text = length;
} }
/** sets the compressed unicode flag /** sets the compressed unicode flag
* @param flag unicode flag * @param flag unicode flag
*/ */
public void setCompressedUnicodeFlag(byte flag) { public void setCompressedUnicodeFlag(byte flag) {
field_11_compressed_unicode_flag = flag; field_11_compressed_unicode_flag = flag;
} }
/** sets the name of the named range /** sets the name of the named range
* @param name named range name * @param name named range name
*/ */
public void setNameText(String name){ public void setNameText(String name){
field_12_name_text = name; field_12_name_text = name;
setCompressedUnicodeFlag( setCompressedUnicodeFlag(
StringUtil.hasMultibyte(name) ? (byte)1 : (byte)0 StringUtil.hasMultibyte(name) ? (byte)1 : (byte)0
); );
} }
/** sets the custom menu text /** sets the custom menu text
* @param text custom menu text * @param text custom menu text
*/ */
public void setCustomMenuText(String text){ public void setCustomMenuText(String text){
field_14_custom_menu_text = text; field_14_custom_menu_text = text;
} }
/** sets the description text /** sets the description text
* @param text the description text * @param text the description text
*/ */
public void setDescriptionText(String text){ public void setDescriptionText(String text){
field_15_description_text = text; field_15_description_text = text;
} }
/** sets the help topic text /** sets the help topic text
* @param text help topix text * @param text help topix text
*/ */
public void setHelpTopicText(String text){ public void setHelpTopicText(String text){
field_16_help_topic_text = text; field_16_help_topic_text = text;
} }
/** sets the status bar text /** sets the status bar text
* @param text status bar text * @param text status bar text
*/ */
public void setStatusBarText(String text){ public void setStatusBarText(String text){
field_17_status_bar_text = text; field_17_status_bar_text = text;
} }
/** gets the option flag /** gets the option flag
* @return option flag * @return option flag
*/ */
public short getOptionFlag(){ public short getOptionFlag(){
return field_1_option_flag; return field_1_option_flag;
} }
/** returns the keyboard shortcut /** returns the keyboard shortcut
* @return keyboard shortcut * @return keyboard shortcut
*/ */
public byte getKeyboardShortcut(){ public byte getKeyboardShortcut(){
return field_2_keyboard_shortcut ; return field_2_keyboard_shortcut ;
} }
/** /**
@ -320,7 +318,7 @@ public final class NameRecord extends Record {
* @return name length * @return name length
*/ */
public byte getNameTextLength(){ public byte getNameTextLength(){
return field_3_length_name_text; return field_3_length_name_text;
} }
/** /**
@ -338,92 +336,90 @@ public final class NameRecord extends Record {
* @return definition length * @return definition length
*/ */
public short getDefinitionLength(){ public short getDefinitionLength(){
return field_4_length_name_definition; return field_4_length_name_definition;
} }
/** gets the index to extern sheet /** gets the index to extern sheet
* @return index to extern sheet * @return index to extern sheet
*/ */
public short getUnused(){ public short getUnused(){
return field_5_index_to_sheet; return field_5_index_to_sheet;
} }
/** gets the custom menu length /** gets the custom menu length
* @return custom menu length * @return custom menu length
*/ */
public byte getCustomMenuLength(){ public byte getCustomMenuLength(){
return field_7_length_custom_menu; return field_7_length_custom_menu;
} }
/** gets the description text length /** gets the description text length
* @return description text length * @return description text length
*/ */
public byte getDescriptionTextLength(){ public byte getDescriptionTextLength(){
return field_8_length_description_text; return field_8_length_description_text;
} }
/** gets the help topic length /** gets the help topic length
* @return help topic length * @return help topic length
*/ */
public byte getHelpTopicLength(){ public byte getHelpTopicLength(){
return field_9_length_help_topic_text; return field_9_length_help_topic_text;
} }
/** get the status bar text length /** get the status bar text length
* @return satus bar length * @return satus bar length
*/ */
public byte getStatusBarLength(){ public byte getStatusBarLength(){
return field_10_length_status_bar_text; return field_10_length_status_bar_text;
} }
/** gets the name compressed Unicode flag /** gets the name compressed Unicode flag
* @return compressed unicode flag * @return compressed unicode flag
*/ */
public byte getCompressedUnicodeFlag() { public byte getCompressedUnicodeFlag() {
return field_11_compressed_unicode_flag; return field_11_compressed_unicode_flag;
} }
/** /**
* @return true if name is hidden * @return true if name is hidden
*/ */
public boolean isHiddenName() { public boolean isHiddenName() {
return (field_1_option_flag & OPT_HIDDEN_NAME) != 0; return (field_1_option_flag & Option.OPT_HIDDEN_NAME) != 0;
} }
/** /**
* @return true if name is a function * @return true if name is a function
*/ */
public boolean isFunctionName() { public boolean isFunctionName() {
return (field_1_option_flag & OPT_FUNCTION_NAME) != 0; return (field_1_option_flag & Option.OPT_FUNCTION_NAME) != 0;
} }
/** /**
* @return true if name is a command * @return true if name is a command
*/ */
public boolean isCommandName() { public boolean isCommandName() {
return (field_1_option_flag & OPT_COMMAND_NAME) != 0; return (field_1_option_flag & Option.OPT_COMMAND_NAME) != 0;
} }
/** /**
* @return true if function macro or command macro * @return true if function macro or command macro
*/ */
public boolean isMacro() { public boolean isMacro() {
return (field_1_option_flag & OPT_MACRO) != 0; return (field_1_option_flag & Option.OPT_MACRO) != 0;
} }
/** /**
* @return true if array formula or user defined * @return true if array formula or user defined
*/ */
public boolean isComplexFunction() { public boolean isComplexFunction() {
return (field_1_option_flag & OPT_COMPLEX) != 0; return (field_1_option_flag & Option.OPT_COMPLEX) != 0;
} }
/**Convenience Function to determine if the name is a built-in name /**Convenience Function to determine if the name is a built-in name
*/ */
public boolean isBuiltInName() public boolean isBuiltInName()
{ {
return ((this.getOptionFlag() & OPT_BUILTIN) != 0); return ((this.field_1_option_flag & Option.OPT_BUILTIN) != 0);
} }
@ -440,7 +436,7 @@ public final class NameRecord extends Record {
*/ */
public byte getBuiltInName() public byte getBuiltInName()
{ {
return this.field_12_builtIn_name; return this.field_12_builtIn_name;
} }
@ -448,39 +444,39 @@ public final class NameRecord extends Record {
* @return definition -- can be null if we cant parse ptgs * @return definition -- can be null if we cant parse ptgs
*/ */
public List getNameDefinition() { public List getNameDefinition() {
return field_13_name_definition; return field_13_name_definition;
} }
public void setNameDefinition(Stack nameDefinition) { public void setNameDefinition(Stack nameDefinition) {
field_13_name_definition = nameDefinition; field_13_name_definition = nameDefinition;
} }
/** get the custom menu text /** get the custom menu text
* @return custom menu text * @return custom menu text
*/ */
public String getCustomMenuText(){ public String getCustomMenuText(){
return field_14_custom_menu_text; return field_14_custom_menu_text;
} }
/** gets the description text /** gets the description text
* @return description text * @return description text
*/ */
public String getDescriptionText(){ public String getDescriptionText(){
return field_15_description_text; return field_15_description_text;
} }
/** get the help topic text /** get the help topic text
* @return gelp topic text * @return gelp topic text
*/ */
public String getHelpTopicText(){ public String getHelpTopicText(){
return field_16_help_topic_text; return field_16_help_topic_text;
} }
/** gets the status bar text /** gets the status bar text
* @return status bar text * @return status bar text
*/ */
public String getStatusBarText(){ public String getStatusBarText(){
return field_17_status_bar_text; return field_17_status_bar_text;
} }
/** /**
@ -490,9 +486,9 @@ public final class NameRecord extends Record {
* @param id alleged id for this record * @param id alleged id for this record
*/ */
protected void validateSid(short id) { protected void validateSid(short id) {
if (id != sid) { if (id != sid) {
throw new RecordFormatException("NOT A valid Name RECORD"); throw new RecordFormatException("NOT A valid Name RECORD");
} }
} }
/** /**
@ -504,21 +500,21 @@ public final class NameRecord extends Record {
*/ */
public int serialize( int offset, byte[] data ) public int serialize( int offset, byte[] data )
{ {
LittleEndian.putShort( data, 0 + offset, sid ); LittleEndian.putShort( data, 0 + offset, sid );
short size = (short)( 15 + getTextsLength() + getNameDefinitionSize()); short size = (short)( 15 + getTextsLength() + getNameDefinitionSize());
LittleEndian.putShort( data, 2 + offset, size ); LittleEndian.putShort( data, 2 + offset, size );
// size defined below // size defined below
LittleEndian.putShort( data, 4 + offset, getOptionFlag() ); LittleEndian.putShort( data, 4 + offset, getOptionFlag() );
data[6 + offset] = getKeyboardShortcut(); data[6 + offset] = getKeyboardShortcut();
data[7 + offset] = getNameTextLength(); data[7 + offset] = getNameTextLength();
LittleEndian.putShort( data, 8 + offset, getDefinitionLength() ); LittleEndian.putShort( data, 8 + offset, getDefinitionLength() );
LittleEndian.putShort( data, 10 + offset, getUnused() ); LittleEndian.putShort( data, 10 + offset, getUnused() );
LittleEndian.putUShort( data, 12 + offset, field_6_sheetNumber); LittleEndian.putUShort( data, 12 + offset, field_6_sheetNumber);
data[14 + offset] = getCustomMenuLength(); data[14 + offset] = getCustomMenuLength();
data[15 + offset] = getDescriptionTextLength(); data[15 + offset] = getDescriptionTextLength();
data[16 + offset] = getHelpTopicLength(); data[16 + offset] = getHelpTopicLength();
data[17 + offset] = getStatusBarLength(); data[17 + offset] = getStatusBarLength();
data[18 + offset] = getCompressedUnicodeFlag(); data[18 + offset] = getCompressedUnicodeFlag();
int start_of_name_definition = 19 + field_3_length_name_text; int start_of_name_definition = 19 + field_3_length_name_text;
@ -536,20 +532,20 @@ public final class NameRecord extends Record {
Ptg.serializePtgStack(field_13_name_definition, data, start_of_name_definition + offset ); Ptg.serializePtgStack(field_13_name_definition, data, start_of_name_definition + offset );
int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition; int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition;
StringUtil.putCompressedUnicode( getCustomMenuText(), data, start_of_custom_menu_text + offset ); StringUtil.putCompressedUnicode( getCustomMenuText(), data, start_of_custom_menu_text + offset );
int start_of_description_text = start_of_custom_menu_text + field_7_length_custom_menu; int start_of_description_text = start_of_custom_menu_text + field_7_length_custom_menu;
StringUtil.putCompressedUnicode( getDescriptionText(), data, start_of_description_text + offset ); StringUtil.putCompressedUnicode( getDescriptionText(), data, start_of_description_text + offset );
int start_of_help_topic_text = start_of_description_text + field_8_length_description_text; int start_of_help_topic_text = start_of_description_text + field_8_length_description_text;
StringUtil.putCompressedUnicode( getHelpTopicText(), data, start_of_help_topic_text + offset ); StringUtil.putCompressedUnicode( getHelpTopicText(), data, start_of_help_topic_text + offset );
int start_of_status_bar_text = start_of_help_topic_text + field_9_length_help_topic_text; int start_of_status_bar_text = start_of_help_topic_text + field_9_length_help_topic_text;
StringUtil.putCompressedUnicode( getStatusBarText(), data, start_of_status_bar_text + offset ); StringUtil.putCompressedUnicode( getStatusBarText(), data, start_of_status_bar_text + offset );
return getRecordSize(); return getRecordSize();
/* } */ /* } */
} }
/** /**
@ -557,83 +553,83 @@ public final class NameRecord extends Record {
* @return total length * @return total length
*/ */
public int getTextsLength(){ public int getTextsLength(){
int result; int result;
result = getRawNameTextLength() + getDescriptionTextLength() + result = getRawNameTextLength() + getDescriptionTextLength() +
getHelpTopicLength() + getStatusBarLength(); getHelpTopicLength() + getStatusBarLength();
return result; return result;
} }
private int getNameDefinitionSize() { private int getNameDefinitionSize() {
int result = 0; int result = 0;
List list = field_13_name_definition; List list = field_13_name_definition;
for (int k = 0; k < list.size(); k++) for (int k = 0; k < list.size(); k++)
{ {
Ptg ptg = ( Ptg ) list.get(k); Ptg ptg = ( Ptg ) list.get(k);
result += ptg.getSize(); result += ptg.getSize();
} }
return result; return result;
} }
/** returns the record size /** returns the record size
*/ */
public int getRecordSize(){ public int getRecordSize(){
int result; int result;
result = 19 + getTextsLength() + getNameDefinitionSize(); result = 19 + getTextsLength() + getNameDefinitionSize();
return result; return result;
} }
/** gets the extern sheet number /** gets the extern sheet number
* @return extern sheet index * @return extern sheet index
*/ */
public short getExternSheetNumber(){ public short getExternSheetNumber(){
if (field_13_name_definition == null || field_13_name_definition.isEmpty()) return 0; if (field_13_name_definition == null || field_13_name_definition.isEmpty()) return 0;
Ptg ptg = (Ptg) field_13_name_definition.peek(); Ptg ptg = (Ptg) field_13_name_definition.peek();
short result = 0; short result = 0;
if (ptg.getClass() == Area3DPtg.class){ if (ptg.getClass() == Area3DPtg.class){
result = ((Area3DPtg) ptg).getExternSheetIndex(); result = ((Area3DPtg) ptg).getExternSheetIndex();
} else if (ptg.getClass() == Ref3DPtg.class){ } else if (ptg.getClass() == Ref3DPtg.class){
result = ((Ref3DPtg) ptg).getExternSheetIndex(); result = ((Ref3DPtg) ptg).getExternSheetIndex();
} }
return result; return result;
} }
/** sets the extern sheet number /** sets the extern sheet number
* @param externSheetNumber extern sheet number * @param externSheetNumber extern sheet number
*/ */
public void setExternSheetNumber(short externSheetNumber){ public void setExternSheetNumber(short externSheetNumber){
Ptg ptg; Ptg ptg;
if (field_13_name_definition == null || field_13_name_definition.isEmpty()){ if (field_13_name_definition == null || field_13_name_definition.isEmpty()){
field_13_name_definition = new Stack(); field_13_name_definition = new Stack();
ptg = createNewPtg(); ptg = createNewPtg();
} else { } else {
ptg = (Ptg) field_13_name_definition.peek(); ptg = (Ptg) field_13_name_definition.peek();
} }
if (ptg.getClass() == Area3DPtg.class){ if (ptg.getClass() == Area3DPtg.class){
((Area3DPtg) ptg).setExternSheetIndex(externSheetNumber); ((Area3DPtg) ptg).setExternSheetIndex(externSheetNumber);
} else if (ptg.getClass() == Ref3DPtg.class){ } else if (ptg.getClass() == Ref3DPtg.class){
((Ref3DPtg) ptg).setExternSheetIndex(externSheetNumber); ((Ref3DPtg) ptg).setExternSheetIndex(externSheetNumber);
} }
} }
private Ptg createNewPtg(){ private Ptg createNewPtg(){
Ptg ptg = new Area3DPtg(); Ptg ptg = new Area3DPtg();
field_13_name_definition.push(ptg); field_13_name_definition.push(ptg);
return ptg; return ptg;
} }
/** gets the reference , the area only (range) /** gets the reference , the area only (range)
@ -647,55 +643,55 @@ public final class NameRecord extends Record {
* @param ref area reference * @param ref area reference
*/ */
public void setAreaReference(String ref){ public void setAreaReference(String ref){
//Trying to find if what ptg do we need //Trying to find if what ptg do we need
RangeAddress ra = new RangeAddress(ref); RangeAddress ra = new RangeAddress(ref);
Ptg oldPtg; Ptg oldPtg;
Ptg ptg; Ptg ptg;
if (field_13_name_definition==null ||field_13_name_definition.isEmpty()){ if (field_13_name_definition==null ||field_13_name_definition.isEmpty()){
field_13_name_definition = new Stack(); field_13_name_definition = new Stack();
oldPtg = createNewPtg(); oldPtg = createNewPtg();
} else { } else {
//Trying to find extern sheet index //Trying to find extern sheet index
oldPtg = (Ptg) field_13_name_definition.pop(); oldPtg = (Ptg) field_13_name_definition.pop();
} }
short externSheetIndex = 0; short externSheetIndex = 0;
if (oldPtg.getClass() == Area3DPtg.class){ if (oldPtg.getClass() == Area3DPtg.class){
externSheetIndex = ((Area3DPtg) oldPtg).getExternSheetIndex(); externSheetIndex = ((Area3DPtg) oldPtg).getExternSheetIndex();
} else if (oldPtg.getClass() == Ref3DPtg.class){ } else if (oldPtg.getClass() == Ref3DPtg.class){
externSheetIndex = ((Ref3DPtg) oldPtg).getExternSheetIndex(); externSheetIndex = ((Ref3DPtg) oldPtg).getExternSheetIndex();
} }
if (ra.hasRange()) { if (ra.hasRange()) {
// Is it contiguous or not? // Is it contiguous or not?
AreaReference[] refs = AreaReference[] refs =
AreaReference.generateContiguous(ref); AreaReference.generateContiguous(ref);
this.setDefinitionTextLength((short)0); this.setDefinitionTextLength((short)0);
// Add the area reference(s) // Add the area reference(s)
for(int i=0; i<refs.length; i++) { for(int i=0; i<refs.length; i++) {
ptg = new Area3DPtg(); ptg = new Area3DPtg();
((Area3DPtg) ptg).setExternSheetIndex(externSheetIndex); ((Area3DPtg) ptg).setExternSheetIndex(externSheetIndex);
((Area3DPtg) ptg).setArea(refs[i].formatAsString()); ((Area3DPtg) ptg).setArea(refs[i].formatAsString());
field_13_name_definition.push(ptg); field_13_name_definition.push(ptg);
this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) ); this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) );
} }
// And then a union if we had more than one area // And then a union if we had more than one area
if(refs.length > 1) { if(refs.length > 1) {
ptg = UnionPtg.instance; ptg = UnionPtg.instance;
field_13_name_definition.push(ptg); field_13_name_definition.push(ptg);
this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) ); this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) );
} }
} else { } else {
ptg = new Ref3DPtg(); ptg = new Ref3DPtg();
((Ref3DPtg) ptg).setExternSheetIndex(externSheetIndex); ((Ref3DPtg) ptg).setExternSheetIndex(externSheetIndex);
((Ref3DPtg) ptg).setArea(ref); ((Ref3DPtg) ptg).setArea(ref);
field_13_name_definition.push(ptg); field_13_name_definition.push(ptg);
this.setDefinitionTextLength((short)ptg.getSize()); this.setDefinitionTextLength((short)ptg.getSize());
} }
} }
/** /**
@ -705,47 +701,47 @@ public final class NameRecord extends Record {
* @param in the RecordInputstream to read the record from * @param in the RecordInputstream to read the record from
*/ */
protected void fillFields(RecordInputStream in) { protected void fillFields(RecordInputStream in) {
field_1_option_flag = in.readShort(); field_1_option_flag = in.readShort();
field_2_keyboard_shortcut = in.readByte(); field_2_keyboard_shortcut = in.readByte();
field_3_length_name_text = in.readByte(); field_3_length_name_text = in.readByte();
field_4_length_name_definition = in.readShort(); field_4_length_name_definition = in.readShort();
field_5_index_to_sheet = in.readShort(); field_5_index_to_sheet = in.readShort();
field_6_sheetNumber = in.readUShort(); field_6_sheetNumber = in.readUShort();
field_7_length_custom_menu = in.readByte(); field_7_length_custom_menu = in.readByte();
field_8_length_description_text = in.readByte(); field_8_length_description_text = in.readByte();
field_9_length_help_topic_text = in.readByte(); field_9_length_help_topic_text = in.readByte();
field_10_length_status_bar_text = in.readByte(); field_10_length_status_bar_text = in.readByte();
//store the name in byte form if it's a builtin name //store the name in byte form if it's a builtin name
field_11_compressed_unicode_flag= in.readByte(); field_11_compressed_unicode_flag= in.readByte();
if (this.isBuiltInName()) { if (this.isBuiltInName()) {
field_12_builtIn_name = in.readByte(); field_12_builtIn_name = in.readByte();
} else { } else {
if (field_11_compressed_unicode_flag == 1) { if (field_11_compressed_unicode_flag == 1) {
field_12_name_text = in.readUnicodeLEString(field_3_length_name_text); field_12_name_text = in.readUnicodeLEString(field_3_length_name_text);
} else { } else {
field_12_name_text = in.readCompressedUnicode(field_3_length_name_text); field_12_name_text = in.readCompressedUnicode(field_3_length_name_text);
} }
} }
field_13_name_definition = Ptg.createParsedExpressionTokens(field_4_length_name_definition, in); field_13_name_definition = Ptg.createParsedExpressionTokens(field_4_length_name_definition, in);
//Who says that this can only ever be compressed unicode??? //Who says that this can only ever be compressed unicode???
field_14_custom_menu_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_7_length_custom_menu)); field_14_custom_menu_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_7_length_custom_menu));
field_15_description_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_8_length_description_text)); field_15_description_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_8_length_description_text));
field_16_help_topic_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_9_length_help_topic_text)); field_16_help_topic_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_9_length_help_topic_text));
field_17_status_bar_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_10_length_status_bar_text)); field_17_status_bar_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_10_length_status_bar_text));
/*} */ /*} */
} }
/** /**
* return the non static version of the id for this record. * return the non static version of the id for this record.
*/ */
public short getSid() { public short getSid() {
return sid; return sid;
} }
/* /*
20 00 20 00
@ -802,53 +798,53 @@ public final class NameRecord extends Record {
* @see Object#toString() * @see Object#toString()
*/ */
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("[NAME]\n"); buffer.append("[NAME]\n");
buffer.append(" .option flags = ").append( HexDump.toHex( field_1_option_flag ) ) buffer.append(" .option flags = ").append( HexDump.toHex( field_1_option_flag ) )
.append("\n"); .append("\n");
buffer.append(" .keyboard shortcut = ").append( HexDump.toHex( field_2_keyboard_shortcut ) ) buffer.append(" .keyboard shortcut = ").append( HexDump.toHex( field_2_keyboard_shortcut ) )
.append("\n"); .append("\n");
buffer.append(" .length of the name = ").append( field_3_length_name_text ) buffer.append(" .length of the name = ").append( field_3_length_name_text )
.append("\n"); .append("\n");
buffer.append(" .size of the formula data = ").append( field_4_length_name_definition ) buffer.append(" .size of the formula data = ").append( field_4_length_name_definition )
.append("\n"); .append("\n");
buffer.append(" .unused = ").append( field_5_index_to_sheet ) buffer.append(" .unused = ").append( field_5_index_to_sheet )
.append("\n"); .append("\n");
buffer.append(" .index to sheet (1-based, 0=Global) = ").append( field_6_sheetNumber ) buffer.append(" .index to sheet (1-based, 0=Global) = ").append( field_6_sheetNumber )
.append("\n"); .append("\n");
buffer.append(" .Length of menu text (character count) = ").append( field_7_length_custom_menu ) buffer.append(" .Length of menu text (character count) = ").append( field_7_length_custom_menu )
.append("\n"); .append("\n");
buffer.append(" .Length of description text (character count) = ").append( field_8_length_description_text ) buffer.append(" .Length of description text (character count) = ").append( field_8_length_description_text )
.append("\n"); .append("\n");
buffer.append(" .Length of help topic text (character count) = ").append( field_9_length_help_topic_text ) buffer.append(" .Length of help topic text (character count) = ").append( field_9_length_help_topic_text )
.append("\n"); .append("\n");
buffer.append(" .Length of status bar text (character count) = ").append( field_10_length_status_bar_text ) buffer.append(" .Length of status bar text (character count) = ").append( field_10_length_status_bar_text )
.append("\n"); .append("\n");
buffer.append(" .Name (Unicode flag) = ").append( field_11_compressed_unicode_flag ) buffer.append(" .Name (Unicode flag) = ").append( field_11_compressed_unicode_flag )
.append("\n"); .append("\n");
buffer.append(" .Name (Unicode text) = ").append( getNameText() ) buffer.append(" .Name (Unicode text) = ").append( getNameText() )
.append("\n"); .append("\n");
buffer.append(" .Parts (" + field_13_name_definition.size() +"):") buffer.append(" .Parts (" + field_13_name_definition.size() +"):")
.append("\n"); .append("\n");
Iterator it = field_13_name_definition.iterator(); Iterator it = field_13_name_definition.iterator();
while(it.hasNext()) { while(it.hasNext()) {
Ptg ptg = (Ptg)it.next(); Ptg ptg = (Ptg)it.next();
buffer.append(" " + ptg.toString()).append("\n"); buffer.append(" " + ptg.toString()).append("\n");
} }
buffer.append(" .Menu text (Unicode string without length field) = ").append( field_14_custom_menu_text ) buffer.append(" .Menu text (Unicode string without length field) = ").append( field_14_custom_menu_text )
.append("\n"); .append("\n");
buffer.append(" .Description text (Unicode string without length field) = ").append( field_15_description_text ) buffer.append(" .Description text (Unicode string without length field) = ").append( field_15_description_text )
.append("\n"); .append("\n");
buffer.append(" .Help topic text (Unicode string without length field) = ").append( field_16_help_topic_text ) buffer.append(" .Help topic text (Unicode string without length field) = ").append( field_16_help_topic_text )
.append("\n"); .append("\n");
buffer.append(" .Status bar text (Unicode string without length field) = ").append( field_17_status_bar_text ) buffer.append(" .Status bar text (Unicode string without length field) = ").append( field_17_status_bar_text )
.append("\n"); .append("\n");
buffer.append("[/NAME]\n"); buffer.append("[/NAME]\n");
return buffer.toString(); return buffer.toString();
} }
/**Creates a human readable name for built in types /**Creates a human readable name for built in types
@ -856,23 +852,23 @@ public final class NameRecord extends Record {
*/ */
protected String translateBuiltInName(byte name) protected String translateBuiltInName(byte name)
{ {
switch (name) switch (name)
{ {
case NameRecord.BUILTIN_AUTO_ACTIVATE : return "Auto_Activate"; case NameRecord.BUILTIN_AUTO_ACTIVATE : return "Auto_Activate";
case NameRecord.BUILTIN_AUTO_CLOSE : return "Auto_Close"; case NameRecord.BUILTIN_AUTO_CLOSE : return "Auto_Close";
case NameRecord.BUILTIN_AUTO_DEACTIVATE : return "Auto_Deactivate"; case NameRecord.BUILTIN_AUTO_DEACTIVATE : return "Auto_Deactivate";
case NameRecord.BUILTIN_AUTO_OPEN : return "Auto_Open"; case NameRecord.BUILTIN_AUTO_OPEN : return "Auto_Open";
case NameRecord.BUILTIN_CONSOLIDATE_AREA : return "Consolidate_Area"; case NameRecord.BUILTIN_CONSOLIDATE_AREA : return "Consolidate_Area";
case NameRecord.BUILTIN_CRITERIA : return "Criteria"; case NameRecord.BUILTIN_CRITERIA : return "Criteria";
case NameRecord.BUILTIN_DATABASE : return "Database"; case NameRecord.BUILTIN_DATABASE : return "Database";
case NameRecord.BUILTIN_DATA_FORM : return "Data_Form"; case NameRecord.BUILTIN_DATA_FORM : return "Data_Form";
case NameRecord.BUILTIN_PRINT_AREA : return "Print_Area"; case NameRecord.BUILTIN_PRINT_AREA : return "Print_Area";
case NameRecord.BUILTIN_PRINT_TITLE : return "Print_Titles"; case NameRecord.BUILTIN_PRINT_TITLE : return "Print_Titles";
case NameRecord.BUILTIN_RECORDER : return "Recorder"; case NameRecord.BUILTIN_RECORDER : return "Recorder";
case NameRecord.BUILTIN_SHEET_TITLE : return "Sheet_Title"; case NameRecord.BUILTIN_SHEET_TITLE : return "Sheet_Title";
} }
return "Unknown"; return "Unknown";
} }
} }

View File

@ -22,7 +22,7 @@ import org.apache.poi.util.LittleEndian;
/** /**
* Title: Sup Book (EXTERNALBOOK) <P> * Title: Sup Book (EXTERNALBOOK) <P>
* Description: A External Workbook Description (Suplemental Book) * Description: A External Workbook Description (Supplemental Book)
* Its only a dummy record for making new ExternSheet Record <P> * Its only a dummy record for making new ExternSheet Record <P>
* REFERENCE: 5.38<P> * REFERENCE: 5.38<P>
* @author Libin Roman (Vista Portal LDT. Developer) * @author Libin Roman (Vista Portal LDT. Developer)

View File

@ -110,7 +110,7 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
* @return <code>true</code> if the name specifies a standard worksheet function, * @return <code>true</code> if the name specifies a standard worksheet function,
* <code>false</code> if the name should be assumed to be an external function. * <code>false</code> if the name should be assumed to be an external function.
*/ */
public static final boolean isInternalFunctionName(String name) { public static final boolean isBuiltInFunctionName(String name) {
short ix = FunctionMetadataRegistry.lookupIndexByName(name.toUpperCase()); short ix = FunctionMetadataRegistry.lookupIndexByName(name.toUpperCase());
return ix >= 0; return ix >= 0;
} }

View File

@ -23,40 +23,54 @@ import org.apache.poi.hssf.record.RecordInputStream;
/** /**
* *
* @author aviks * @author aviks
*/ */
public final class NameXPtg extends OperandPtg { public final class NameXPtg extends OperandPtg {
public final static short sid = 0x39; public final static short sid = 0x39;
private final static int SIZE = 7; private final static int SIZE = 7;
private short field_1_ixals; // index to REF entry in externsheet record
private short field_2_ilbl; //index to defined name or externname table(1 based)
private short field_3_reserved; // reserved must be 0
/** index to REF entry in externsheet record */
private int _sheetRefIndex;
/** index to defined name or externname table(1 based) */
private int _nameNumber;
/** reserved must be 0 */
private int _reserved;
public NameXPtg(RecordInputStream in) { private NameXPtg(int sheetRefIndex, int nameNumber, int reserved) {
field_1_ixals = in.readShort(); _sheetRefIndex = sheetRefIndex;
field_2_ilbl = in.readShort(); _nameNumber = nameNumber;
field_3_reserved = in.readShort(); _reserved = reserved;
} }
public void writeBytes(byte [] array, int offset) { /**
array[ offset + 0 ] = (byte)(sid + getPtgClass()); * @param sheetRefIndex index to REF entry in externsheet record
LittleEndian.putShort(array, offset + 1, field_1_ixals); * @param nameIndex index to defined name or externname table
LittleEndian.putShort(array,offset+3, field_2_ilbl); */
LittleEndian.putShort(array, offset + 5, field_3_reserved); public NameXPtg(int sheetRefIndex, int nameIndex) {
} this(sheetRefIndex, nameIndex + 1, 0);
}
public int getSize() { public NameXPtg(RecordInputStream in) {
return SIZE; this(in.readUShort(), in.readUShort(), in.readUShort());
} }
public String toFormulaString(HSSFWorkbook book) public void writeBytes(byte[] array, int offset) {
{ LittleEndian.putByte(array, offset + 0, sid + getPtgClass());
// -1 to convert definedNameIndex from 1-based to zero-based LittleEndian.putUShort(array, offset + 1, _sheetRefIndex);
return book.resolveNameXText(field_1_ixals, field_2_ilbl-1); LittleEndian.putUShort(array, offset + 3, _nameNumber);
} LittleEndian.putUShort(array, offset + 5, _reserved);
}
public byte getDefaultOperandClass() { public int getSize() {
return SIZE;
}
public String toFormulaString(HSSFWorkbook book) {
// -1 to convert definedNameIndex from 1-based to zero-based
return book.resolveNameXText(_sheetRefIndex, _nameNumber - 1);
}
public byte getDefaultOperandClass() {
return Ptg.CLASS_VALUE; return Ptg.CLASS_VALUE;
} }
} }

View File

@ -22,67 +22,57 @@ import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.util.RangeAddress; import org.apache.poi.hssf.util.RangeAddress;
/** /**
* Title: High Level Represantion of Named Range <P> * High Level Representation of a 'defined name' which could be a 'built-in' name,
* REFERENCE: <P> * 'named range' or name of a user defined function.
*
* @author Libin Roman (Vista Portal LDT. Developer) * @author Libin Roman (Vista Portal LDT. Developer)
*/ */
public final class HSSFName {
public class HSSFName { private HSSFWorkbook _book;
private HSSFWorkbook book; private NameRecord _definedNameRec;
private NameRecord name;
/** Creates new HSSFName - called by HSSFWorkbook to create a sheet from /** Creates new HSSFName - called by HSSFWorkbook to create a sheet from
* scratch. * scratch.
* *
* @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createName() * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createName()
* @param name the Name Record * @param name the Name Record
* @param book lowlevel Workbook object associated with the sheet. * @param book workbook object associated with the sheet.
*/ */
/* package */ HSSFName(HSSFWorkbook book, NameRecord name) {
protected HSSFName(HSSFWorkbook book, NameRecord name) { _book = book;
this.book = book; _definedNameRec = name;
this.name = name;
} }
/** Get the sheets name which this named range is referenced to /** Get the sheets name which this named range is referenced to
* @return sheet name, which this named range refered to * @return sheet name, which this named range referred to
*/ */
public String getSheetName() { public String getSheetName() {
String result ; short indexToExternSheet = _definedNameRec.getExternSheetNumber();
short indexToExternSheet = name.getExternSheetNumber();
result = book.getWorkbook().findSheetNameFromExternSheet(indexToExternSheet); return _book.getWorkbook().findSheetNameFromExternSheet(indexToExternSheet);
return result;
} }
/** /**
* gets the name of the named range * @return text name of this defined name
* @return named range name
*/ */
public String getNameName(){ public String getNameName(){
String result = name.getNameText(); return _definedNameRec.getNameText();
return result;
} }
/** /**
* sets the name of the named range * sets the name of the named range
* @param nameName named range name to set * @param nameName named range name to set
*/ */
public void setNameName(String nameName){ public void setNameName(String nameName){
name.setNameText(nameName); _definedNameRec.setNameText(nameName);
name.setNameTextLength((byte)nameName.length()); _definedNameRec.setNameTextLength((byte)nameName.length());
Workbook wb = book.getWorkbook(); Workbook wb = _book.getWorkbook();
//Check to ensure no other names have the same case-insensitive name //Check to ensure no other names have the same case-insensitive name
for ( int i = wb.getNumNames()-1; i >=0; i-- ) for ( int i = wb.getNumNames()-1; i >=0; i-- )
{ {
NameRecord rec = wb.getNameRecord(i); NameRecord rec = wb.getNameRecord(i);
if (rec != name) { if (rec != _definedNameRec) {
if (rec.getNameText().equalsIgnoreCase(getNameName())) if (rec.getNameText().equalsIgnoreCase(getNameName()))
throw new IllegalArgumentException("The workbook already contains this name (case-insensitive)"); throw new IllegalArgumentException("The workbook already contains this name (case-insensitive)");
} }
@ -90,31 +80,24 @@ public class HSSFName {
} }
/** /**
* gets the reference of the named range * Note - this method only applies to named ranges
* @return reference of the named range * @return the formula text defining the named range
*/ */
public String getReference() { public String getReference() {
String result; if (_definedNameRec.isFunctionName()) {
result = name.getAreaReference(book); throw new IllegalStateException("Only applicable to named ranges");
}
return result; return _definedNameRec.getAreaReference(_book);
} }
/** /**
* sets the sheet name which this named range referenced to * sets the sheet name which this named range referenced to
* @param sheetName the sheet name of the reference * @param sheetName the sheet name of the reference
*/ */
private void setSheetName(String sheetName){ private void setSheetName(String sheetName){
int sheetNumber = book.getSheetIndex(sheetName); int sheetNumber = _book.getSheetIndex(sheetName);
short externSheetNumber = _book.getExternalSheetIndex(sheetNumber);
short externSheetNumber = book.getExternalSheetIndex(sheetNumber); _definedNameRec.setExternSheetNumber(externSheetNumber);
name.setExternSheetNumber(externSheetNumber);
// name.setIndexToSheet(externSheetNumber);
} }
@ -122,7 +105,6 @@ public class HSSFName {
* sets the reference of this named range * sets the reference of this named range
* @param ref the reference to set * @param ref the reference to set
*/ */
public void setReference(String ref){ public void setReference(String ref){
RangeAddress ra = new RangeAddress(ref); RangeAddress ra = new RangeAddress(ref);
@ -134,8 +116,7 @@ public class HSSFName {
} }
//allow the poi utilities to parse it out //allow the poi utilities to parse it out
name.setAreaReference(ref); _definedNameRec.setAreaReference(ref);
} }
/** /**
@ -147,4 +128,14 @@ public class HSSFName {
String ref = getReference(); String ref = getReference();
return "#REF!".endsWith(ref); return "#REF!".endsWith(ref);
} }
public boolean isFunctionName() {
return _definedNameRec.isFunctionName();
}
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append(_definedNameRec.getNameText());
sb.append("]");
return sb.toString();
}
} }

View File

@ -17,24 +17,6 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.POIDocument;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherBitmapBlip;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherBlipRecord;
import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.formula.Area3DPtg;
import org.apache.poi.hssf.record.formula.MemFuncPtg;
import org.apache.poi.hssf.record.formula.UnionPtg;
import org.apache.poi.hssf.usermodel.HSSFRow.MissingCellPolicy;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.hssf.util.SheetReferences;
import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
@ -47,6 +29,40 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Stack; import java.util.Stack;
import org.apache.poi.POIDocument;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherBitmapBlip;
import org.apache.poi.ddf.EscherBlipRecord;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.AbstractEscherHolderRecord;
import org.apache.poi.hssf.record.BackupRecord;
import org.apache.poi.hssf.record.DrawingGroupRecord;
import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
import org.apache.poi.hssf.record.ExtendedFormatRecord;
import org.apache.poi.hssf.record.FontRecord;
import org.apache.poi.hssf.record.LabelRecord;
import org.apache.poi.hssf.record.LabelSSTRecord;
import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.UnicodeString;
import org.apache.poi.hssf.record.UnknownRecord;
import org.apache.poi.hssf.record.formula.Area3DPtg;
import org.apache.poi.hssf.record.formula.MemFuncPtg;
import org.apache.poi.hssf.record.formula.NameXPtg;
import org.apache.poi.hssf.record.formula.UnionPtg;
import org.apache.poi.hssf.usermodel.HSSFRow.MissingCellPolicy;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.hssf.util.SheetReferences;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
/** /**
* High level representation of a workbook. This is the first object most users * High level representation of a workbook. This is the first object most users
* will construct whether they are reading or writing a workbook. It is also the * will construct whether they are reading or writing a workbook. It is also the
@ -1640,9 +1656,16 @@ public class HSSFWorkbook extends POIDocument
} }
} }
private byte[] newUID() private static byte[] newUID() {
{ return new byte[16];
byte[] bytes = new byte[16];
return bytes;
} }
/**
* Note - This method should only used by POI internally.
* It may get deleted or change definition in future POI versions
*/
public NameXPtg getNameXPtg(String name) {
return workbook.getNameXPtg(name);
}
} }

Binary file not shown.

View File

@ -20,6 +20,7 @@ package org.apache.poi.hssf.model;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.FormulaParser.FormulaParseException; import org.apache.poi.hssf.model.FormulaParser.FormulaParseException;
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg; import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
import org.apache.poi.hssf.record.formula.AddPtg; import org.apache.poi.hssf.record.formula.AddPtg;
@ -123,12 +124,15 @@ public final class TestFormulaParser extends TestCase {
} }
public void testMacroFunction() { public void testMacroFunction() {
HSSFWorkbook w = new HSSFWorkbook(); // testNames.xls contains a VB function called 'myFunc'
Ptg[] ptg = FormulaParser.parse("FOO()", w); HSSFWorkbook w = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
Ptg[] ptg = FormulaParser.parse("myFunc()", w);
// myFunc() actually takes 1 parameter. Don't know if POI will ever be able to detect this problem
// the name gets encoded as the first arg // the name gets encoded as the first arg
NamePtg tname = (NamePtg) ptg[0]; NamePtg tname = (NamePtg) ptg[0];
assertEquals("FOO", tname.toFormulaString(w)); assertEquals("myFunc", tname.toFormulaString(w));
AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1]; AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1];
assertTrue(tfunc.isExternalFunction()); assertTrue(tfunc.isExternalFunction());

View File

@ -17,11 +17,19 @@
package org.apache.poi.hssf.record.formula; package org.apache.poi.hssf.record.formula;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
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.FormulaParser;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.CellValue;
/** /**
* Tests for functions from external workbooks (e.g. YEARFRAC). * Tests for functions from external workbooks (e.g. YEARFRAC).
* *
@ -30,17 +38,45 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
*/ */
public final class TestExternalFunctionFormulas extends TestCase { public final class TestExternalFunctionFormulas extends TestCase {
/**
* tests <tt>NameXPtg.toFormulaString(Workbook)</tt> and logic in Workbook below that
*/
public void testReadFormulaContainingExternalFunction() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("externalFunctionExample.xls");
/** String expectedFormula = "YEARFRAC(B1,C1)";
* tests <tt>NameXPtg.toFormulaString(Workbook)</tt> and logic in Workbook below that HSSFSheet sht = wb.getSheetAt(0);
*/ String cellFormula = sht.getRow(0).getCell(0).getCellFormula();
public void testReadFormulaContainingExternalFunction() { assertEquals(expectedFormula, cellFormula);
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("externalFunctionExample.xls"); }
String expectedFormula = "YEARFRAC(B1,C1)"; public void testParse() {
HSSFSheet sht = wb.getSheetAt(0); HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("externalFunctionExample.xls");
String cellFormula = sht.getRow(0).getCell((short)0).getCellFormula(); Ptg[] ptgs = FormulaParser.parse("YEARFRAC(B1,C1)", wb);
assertEquals(expectedFormula, cellFormula); assertEquals(4, ptgs.length);
} assertEquals(NameXPtg.class, ptgs[0].getClass());
wb.getSheetAt(0).getRow(0).createCell(6).setCellFormula("YEARFRAC(C1,B1)");
if (false) {
// In case you fancy checking in excel
try {
File tempFile = File.createTempFile("testExtFunc", ".xls");
FileOutputStream fout = new FileOutputStream(tempFile);
wb.write(fout);
fout.close();
System.out.println("check out " + tempFile.getAbsolutePath());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public void DISABLEDtestEvaluate() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("externalFunctionExample.xls");
HSSFSheet sheet = wb.getSheetAt(0);
HSSFCell cell = sheet.getRow(0).getCell(0);
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
CellValue evalResult = fe.evaluate(cell);
evalResult.toString();
}
} }

View File

@ -17,8 +17,11 @@
package org.apache.poi.hssf.record.formula.eval; package org.apache.poi.hssf.record.formula.eval;
import java.io.IOException;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFName; import org.apache.poi.hssf.usermodel.HSSFName;
@ -34,20 +37,33 @@ public final class TestExternalFunction extends TestCase {
/** /**
* Checks that an external function can get invoked from the formula evaluator. * Checks that an external function can get invoked from the formula evaluator.
* @throws IOException
*/ */
public void testInvoke() { public void testInvoke() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
wb.setSheetName(0, "Sheet1");
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell(0);
HSSFName hssfName = wb.createName(); HSSFWorkbook wb;
hssfName.setNameName("myFunc"); HSSFSheet sheet;
HSSFCell cell;
if (false) {
// TODO - this code won't work until we can create user-defined functions directly with POI
wb = new HSSFWorkbook();
sheet = wb.createSheet();
wb.setSheetName(0, "Sheet1");
HSSFName hssfName = wb.createName();
hssfName.setNameName("myFunc");
cell.setCellFormula("myFunc()"); } else {
String actualFormula=cell.getCellFormula(); // This sample spreadsheet already has a VB function called 'myFunc'
assertEquals("myFunc()", actualFormula); wb = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
sheet = wb.getSheetAt(0);
HSSFRow row = sheet.createRow(0);
cell = row.createCell(1);
}
cell.setCellFormula("myFunc()");
String actualFormula=cell.getCellFormula();
assertEquals("myFunc()", actualFormula);
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb); HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
CellValue evalResult = fe.evaluate(cell); CellValue evalResult = fe.evaluate(cell);

View File

@ -415,6 +415,9 @@ public final class TestBugs extends TestCase {
for(int i = 0 ; i < wb.getNumberOfNames(); i++){ for(int i = 0 ; i < wb.getNumberOfNames(); i++){
HSSFName name = wb.getNameAt(i); HSSFName name = wb.getNameAt(i);
name.getNameName(); name.getNameName();
if (name.isFunctionName()) {
continue;
}
name.getReference(); name.getReference();
} }
} }