diff --git a/src/java/org/apache/poi/hssf/model/Workbook.java b/src/java/org/apache/poi/hssf/model/Workbook.java index d45153f9c9..a6ab7af382 100644 --- a/src/java/org/apache/poi/hssf/model/Workbook.java +++ b/src/java/org/apache/poi/hssf/model/Workbook.java @@ -85,62 +85,75 @@ import org.apache.poi.util.POILogFactory; * @version 1.0-pre */ -public class Workbook -{ +public class Workbook { private static final int DEBUG = POILogger.DEBUG; - + /** * constant used to set the "codepage" wherever "codepage" is set in records * (which is duplciated in more than one record) */ - + private final static short CODEPAGE = ( short ) 0x4b0; - + /** * this contains the Worksheet record objects */ - + protected ArrayList records = null; - + /** * this contains a reference to the SSTRecord so that new stings can be added * to it. */ - + protected SSTRecord sst = null; - + + /** + * Holds the Extern Sheet with referenced to bound sheets + */ + + protected ExternSheetRecord externSheet= null; + /** * holds the "boundsheet" records (aka bundlesheet) so that they can have their * reference to their "BOF" marker */ - + + protected ArrayList boundsheets = new ArrayList(); + + protected ArrayList names = new ArrayList(); + protected int bspos = - 0; // holds the position of the last bound sheet. + 0; // holds the position of the last bound sheet. protected int tabpos = - 0; // holds the position of the tabid record + 0; // holds the position of the tabid record protected int fontpos = - 0; // hold the position of the last font record + 0; // hold the position of the last font record protected int numfonts = - 0; // hold the number of font records + 0; // hold the number of font records protected int xfpos = - 0; // hold the position of the last extended font record + 0; // hold the position of the last extended font record protected int numxfs = - 0; // hold the number of extended format records + 0; // hold the number of extended format records private int backuppos = - 0; // holds the position of the backup record. + 0; // holds the position of the backup record. + private int namepos = + 0; // holds the position of last name record + private int supbookpos = + 0; // holds the position of sup book + private static POILogger log = - POILogFactory.getLogger(Workbook.class); - + POILogFactory.getLogger(Workbook.class); + /** * Creates new Workbook with no intitialization --useless right now * @see #createWorkbook(List) */ - - public Workbook() - { + + public Workbook() { } - + /** * read support for low level * API. Pass in an array of Record objects, A Workbook @@ -153,80 +166,96 @@ public class Workbook * @param recs an array of Record objects * @return Workbook object */ - - public static Workbook createWorkbook(List recs) - { + + public static Workbook createWorkbook(List recs) { log.log(DEBUG, "Workbook (readfile) created with reclen=", - new Integer(recs.size())); + new Integer(recs.size())); Workbook retval = new Workbook(); ArrayList records = new ArrayList(recs.size() / 3); - - for (int k = 0; k < recs.size(); k++) - { + + for (int k = 0; k < recs.size(); k++) { Record rec = ( Record ) recs.get(k); - - if (rec.getSid() == EOFRecord.sid) - { + + if (rec.getSid() == EOFRecord.sid) { records.add(rec); log.log(DEBUG, "found workbook eof record at " + k); break; } - switch (rec.getSid()) - { - + switch (rec.getSid()) { + case BoundSheetRecord.sid : log.log(DEBUG, "found boundsheet record at " + k); retval.boundsheets.add(rec); retval.bspos = k; break; - + case SSTRecord.sid : log.log(DEBUG, "found sst record at " + k); retval.sst = ( SSTRecord ) rec; break; - + case FontRecord.sid : log.log(DEBUG, "found font record at " + k); retval.fontpos = k; retval.numfonts++; break; - + case ExtendedFormatRecord.sid : log.log(DEBUG, "found XF record at " + k); retval.xfpos = k; retval.numxfs++; break; - + case TabIdRecord.sid : log.log(DEBUG, "found tabid record at " + k); retval.tabpos = k; break; - + case BackupRecord.sid : log.log(DEBUG, "found backup record at " + k); retval.backuppos = k; break; - + case ExternSheetRecord.sid : + log.log(DEBUG, "found extern sheet record at " + k); + retval.externSheet = ( ExternSheetRecord ) rec; + break; + case NameRecord.sid : + log.log(DEBUG, "found name record at " + k); + retval.names.add(rec); + retval.namepos = k; + break; + case 0x1AE : + //Havent Implement the sup book , because we dont need extern ranges + //for now + log.log(DEBUG, "found SupBook record at " + k); + retval.supbookpos = k; + break; + default : } records.add(rec); } + //What if we dont have any ranges and supbooks + if (retval.supbookpos == 0) { + retval.supbookpos = retval.bspos + 1; + retval.namepos = retval.supbookpos + 1; + } + retval.records = records; log.log(DEBUG, "exit create workbook from existing file function"); return retval; } - + /** * Creates an empty workbook object with three blank sheets and all the empty * fields. Use this to create a workbook from scratch. */ - - public static Workbook createWorkbook() - { + + public static Workbook createWorkbook() { log.log(DEBUG, "creating new workbook from scratch"); Workbook retval = new Workbook(); ArrayList records = new ArrayList(30); - + records.add(retval.createBOF()); records.add(retval.createInterfaceHdr()); records.add(retval.createMMS()); @@ -264,22 +293,19 @@ public class Workbook records.add(retval.createFormat(5)); records.add(retval.createFormat(6)); records.add(retval.createFormat(7)); - for (int k = 0; k < 21; k++) - { + for (int k = 0; k < 21; k++) { records.add(retval.createExtendedFormat(k)); retval.numxfs++; } retval.xfpos = records.size() - 1; - for (int k = 0; k < 6; k++) - { + for (int k = 0; k < 6; k++) { records.add(retval.createStyle(k)); } records.add(retval.createUseSelFS()); - for (int k = 0; k < 1; k++) - { // now just do 1 + for (int k = 0; k < 1; k++) { // now just do 1 BoundSheetRecord bsr = - ( BoundSheetRecord ) retval.createBoundSheet(k); - + ( BoundSheetRecord ) retval.createBoundSheet(k); + records.add(bsr); retval.boundsheets.add(bsr); retval.bspos = records.size() - 1; @@ -288,19 +314,18 @@ public class Workbook retval.sst = ( SSTRecord ) retval.createSST(); records.add(retval.sst); records.add(retval.createExtendedSST()); - + // TODO records.add(retval.createEOF()); retval.records = records; log.log(DEBUG, "exit create new workbook from scratch"); return retval; } - - public int getNumRecords() - { + + public int getNumRecords() { return records.size(); } - + /** * gets the font record at the given index in the font table. Remember * "There is No Four" (someone at M$ must have gone to Rocky Horror one too @@ -309,27 +334,24 @@ public class Workbook * @param idx the index to look at (0 or greater but NOT 4) * @return FontRecord located at the given index */ - - public FontRecord getFontRecordAt(int idx) - { + + public FontRecord getFontRecordAt(int idx) { int index = idx; - - if (index > 4) - { + + if (index > 4) { index -= 1; // adjust for "There is no 4" } - if (index > (numfonts - 1)) - { + if (index > (numfonts - 1)) { throw new ArrayIndexOutOfBoundsException( - "There are only " + numfonts - + " font records, you asked for " + idx); + "There are only " + numfonts + + " font records, you asked for " + idx); } FontRecord retval = - ( FontRecord ) records.get((fontpos - (numfonts - 1)) + index); - + ( FontRecord ) records.get((fontpos - (numfonts - 1)) + index); + return retval; } - + /** * creates a new font record and adds it to the "font table". This causes the * boundsheets to move down one, extended formats to move down (so this function moves @@ -337,11 +359,10 @@ public class Workbook * * @return FontRecord that was just created */ - - public FontRecord createNewFont() - { + + public FontRecord createNewFont() { FontRecord rec = ( FontRecord ) createFont(); - + ++fontpos; ++bspos; ++xfpos; @@ -349,43 +370,40 @@ public class Workbook numfonts++; return rec; } - + /** * gets the number of font records * * @return number of font records in the "font table" */ - - public int getNumberOfFontRecords() - { + + public int getNumberOfFontRecords() { return numfonts; } - + /** * Sets the BOF for a given sheet * * @param sheetnum the number of the sheet to set the positing of the bof for * @param pos the actual bof position */ - - public void setSheetBof(int sheetnum, int pos) - { + + public void setSheetBof(int sheetnum, int pos) { log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetnum), - " at pos=", new Integer(pos)); + " at pos=", new Integer(pos)); checkSheets(sheetnum); (( BoundSheetRecord ) boundsheets.get(sheetnum)) - .setPositionOfBof(pos); + .setPositionOfBof(pos); } - + /** * Returns the position of the backup record. */ - - public BackupRecord getBackupRecord() - { + + public BackupRecord getBackupRecord() { return ( BackupRecord ) records.get(backuppos); } - + /** * sets the name for a given sheet. If the boundsheet record doesn't exist and * its only one more than we have, go ahead and create it. If its > 1 more than @@ -394,139 +412,146 @@ public class Workbook * @param sheetnum the sheet number (0 based) * @param sheetname the name for the sheet */ - - public void setSheetName(int sheetnum, String sheetname) - { + + public void setSheetName(int sheetnum, String sheetname) { checkSheets(sheetnum); (( BoundSheetRecord ) boundsheets.get(sheetnum)) - .setSheetname(sheetname); + .setSheetname(sheetname); (( BoundSheetRecord ) boundsheets.get(sheetnum)) - .setSheetnameLength(( byte ) sheetname.length()); + .setSheetnameLength(( byte ) sheetname.length()); } - + /** * gets the name for a given sheet. * * @param sheetnum the sheet number (0 based) * @return sheetname the name for the sheet */ - - public String getSheetName(int sheetnum) - { + + public String getSheetName(int sheetnum) { return (( BoundSheetRecord ) boundsheets.get(sheetnum)) - .getSheetname(); + .getSheetname(); } - + + /** + * get the sheet's index + * @param name sheet name + * @return sheet index or -1 if it was not found. + */ + + public int getSheetIndex(String name) { + int retval = -1; + + for (int k = 0; k < boundsheets.size(); k++) { + String sheet = getSheetName(k); + + if (sheet.equals(name)) { + retval = k; + break; + } + } + return retval; + } + /** * if we're trying to address one more sheet than we have, go ahead and add it! if we're * trying to address >1 more than we have throw an exception! */ - - private void checkSheets(int sheetnum) - { - if ((boundsheets.size()) <= sheetnum) - { // if we're short one add another.. - if ((boundsheets.size() + 1) <= sheetnum) - { + + private void checkSheets(int sheetnum) { + if ((boundsheets.size()) <= sheetnum) { // if we're short one add another.. + if ((boundsheets.size() + 1) <= sheetnum) { throw new RuntimeException("Sheet number out of bounds!"); } BoundSheetRecord bsr = - ( BoundSheetRecord ) createBoundSheet(sheetnum); - + ( BoundSheetRecord ) createBoundSheet(sheetnum); + records.add(++bspos, bsr); boundsheets.add(bsr); fixTabIdRecord(); } } - - public void removeSheet(int sheetnum) - { - if (boundsheets.size() > sheetnum) - { + + public void removeSheet(int sheetnum) { + if (boundsheets.size() > sheetnum) { records.remove(bspos - (boundsheets.size() - 1) + sheetnum); bspos--; boundsheets.remove(sheetnum); fixTabIdRecord(); } } - + /** * make the tabid record look like the current situation. * */ - - private void fixTabIdRecord() - { + + private void fixTabIdRecord() { TabIdRecord tir = ( TabIdRecord ) records.get(tabpos); short[] tia = new short[ boundsheets.size() ]; - - for (short k = 0; k < tia.length; k++) - { + + for (short k = 0; k < tia.length; k++) { tia[ k ] = k; } tir.setTabIdArray(tia); } - + /** * returns the number of boundsheet objects contained in this workbook. * * @return number of BoundSheet records */ - - public int getNumSheets() - { + + public int getNumSheets() { log.log(DEBUG, "getNumSheets=", new Integer(boundsheets.size())); return boundsheets.size(); } - + /** * get the number of ExtendedFormat records contained in this workbook. * * @return int count of ExtendedFormat records */ - - public int getNumExFormats() - { + + public int getNumExFormats() { log.log(DEBUG, "getXF=", new Integer(boundsheets.size())); return numxfs; } - + /** * gets the ExtendedFormatRecord at the given 0-based index * * @param index of the Extended format record (0-based) * @return ExtendedFormatRecord at the given index */ - - public ExtendedFormatRecord getExFormatAt(int index) - { + + public ExtendedFormatRecord getExFormatAt(int index) { int xfptr = xfpos - (numxfs - 1); - + xfptr += index; ExtendedFormatRecord retval = - ( ExtendedFormatRecord ) records.get(xfptr); - + ( ExtendedFormatRecord ) records.get(xfptr); + return retval; } - + /** * creates a new Cell-type Extneded Format Record and adds it to the end of * ExtendedFormatRecords collection * * @return ExtendedFormatRecord that was created */ - - public ExtendedFormatRecord createCellXF() - { + + public ExtendedFormatRecord createCellXF() { ExtendedFormatRecord xf = createExtendedFormat(); - + ++xfpos; ++bspos; records.add(xfpos, xf); numxfs++; return xf; } - + /** * Adds a string to the SST table and returns its index (if its a duplicate * just returns its index and update the counts) @@ -535,18 +560,16 @@ public class Workbook * @param use16bits whether to use utf 16 or false for compressed unicode * @return index of the string within the SSTRecord */ - - public int addSSTString(String string, boolean use16bits) - { + + public int addSSTString(String string, boolean use16bits) { log.log(DEBUG, "insert to sst string='", string, "' and use16bits= ", - new Boolean(use16bits)); - if (sst == null) - { + new Boolean(use16bits)); + if (sst == null) { insertSST(); } return sst.addString(string, use16bits); } - + /** * Adds a string to the SST table and returns its index (if its a duplicate * just returns its index and update the counts) ASSUMES compressed unicode @@ -556,240 +579,223 @@ public class Workbook * * @return index of the string within the SSTRecord */ - - public int addSSTString(String string) - { + + public int addSSTString(String string) { return addSSTString(string, false); } - + /** * given an index into the SST table, this function returns the corresponding String value * @return String containing the SST String */ - - public String getSSTString(int str) - { - if (sst == null) - { + + public String getSSTString(int str) { + if (sst == null) { insertSST(); } String retval = sst.getString(str); - + log.log(DEBUG, "Returning SST for index=", new Integer(str), - " String= ", retval); + " String= ", retval); return retval; } - + /** * use this function to add a Shared String Table to an existing sheet (say * generated by a different java api) without an sst.... * @see #createSST() * @see org.apache.poi.hssf.record.SSTRecord */ - - public void insertSST() - { + + public void insertSST() { log.log(DEBUG, "creating new SST via insertSST!"); sst = ( SSTRecord ) createSST(); records.add(records.size() - 1, createExtendedSST()); records.add(records.size() - 2, sst); } - + /** * Serializes all records int the worksheet section into a big byte array. Use * this to write the Workbook out. * * @return byte array containing the HSSF-only portions of the POIFS file. */ - - public byte [] serialize() - { + + public byte [] serialize() { log.log(DEBUG, "Serializing Workbook!"); byte[] retval = null; - + // ArrayList bytes = new ArrayList(records.size()); int arraysize = getSize(); int pos = 0; - + // for (int k = 0; k < records.size(); k++) // { // bytes.add((( Record ) records.get(k)).serialize()); -// } + // } // for (int k = 0; k < bytes.size(); k++) // { // arraysize += (( byte [] ) bytes.get(k)).length; // } retval = new byte[ arraysize ]; - for (int k = 0; k < records.size(); k++) - { - + for (int k = 0; k < records.size(); k++) { + // byte[] rec = (( byte [] ) bytes.get(k)); // System.arraycopy(rec, 0, retval, pos, rec.length); pos += (( Record ) records.get(k)).serialize(pos, - retval); // rec.length; + retval); // rec.length; } log.log(DEBUG, "Exiting serialize workbook"); return retval; } - + /** * Serializes all records int the worksheet section into a big byte array. Use * this to write the Workbook out. * @param offset of the data to be written * @param data array of bytes to write this to */ - - public int serialize(int offset, byte [] data) - { + + public int serialize(int offset, byte [] data) { log.log(DEBUG, "Serializing Workbook with offsets"); - + // ArrayList bytes = new ArrayList(records.size()); -// int arraysize = getSize(); // 0; + // int arraysize = getSize(); // 0; int pos = 0; - -// for (int k = 0; k < records.size(); k++) -// { -// bytes.add((( Record ) records.get(k)).serialize()); -// -// } -// for (int k = 0; k < bytes.size(); k++) -// { -// arraysize += (( byte [] ) bytes.get(k)).length; -// } - for (int k = 0; k < records.size(); k++) - { - + + // for (int k = 0; k < records.size(); k++) + // { + // bytes.add((( Record ) records.get(k)).serialize()); + // + // } + // for (int k = 0; k < bytes.size(); k++) + // { + // arraysize += (( byte [] ) bytes.get(k)).length; + // } + for (int k = 0; k < records.size(); k++) { + // byte[] rec = (( byte [] ) bytes.get(k)); // System.arraycopy(rec, 0, data, offset + pos, rec.length); pos += (( Record ) records.get(k)).serialize(pos + offset, - data); // rec.length; + data); // rec.length; } log.log(DEBUG, "Exiting serialize workbook"); return pos; } - - public int getSize() - { + + public int getSize() { int retval = 0; - - for (int k = 0; k < records.size(); k++) - { + + for (int k = 0; k < records.size(); k++) { retval += (( Record ) records.get(k)).getRecordSize(); } return retval; } - + /** * creates the BOF record * @see org.apache.poi.hssf.record.BOFRecord * @see org.apache.poi.hssf.record.Record * @return record containing a BOFRecord */ - - protected Record createBOF() - { + + protected Record createBOF() { BOFRecord retval = new BOFRecord(); - + retval.setVersion(( short ) 0x600); retval.setType(( short ) 5); retval.setBuild(( short ) 0x10d3); - -// retval.setBuild((short)0x0dbb); + + // retval.setBuild((short)0x0dbb); retval.setBuildYear(( short ) 1996); retval.setHistoryBitMask(0x41); // was c1 before verify retval.setRequiredVersion(0x6); return retval; } - + /** * creates the InterfaceHdr record * @see org.apache.poi.hssf.record.InterfaceHdrRecord * @see org.apache.poi.hssf.record.Record * @return record containing a InterfaceHdrRecord */ - - protected Record createInterfaceHdr() - { + + protected Record createInterfaceHdr() { InterfaceHdrRecord retval = new InterfaceHdrRecord(); - + retval.setCodepage(CODEPAGE); return retval; } - + /** * creates an MMS record * @see org.apache.poi.hssf.record.MMSRecord * @see org.apache.poi.hssf.record.Record * @return record containing a MMSRecord */ - - protected Record createMMS() - { + + protected Record createMMS() { MMSRecord retval = new MMSRecord(); - + retval.setAddMenuCount(( byte ) 0); retval.setDelMenuCount(( byte ) 0); return retval; } - + /** * creates the InterfaceEnd record * @see org.apache.poi.hssf.record.InterfaceEndRecord * @see org.apache.poi.hssf.record.Record * @return record containing a InterfaceEndRecord */ - - protected Record createInterfaceEnd() - { + + protected Record createInterfaceEnd() { return new InterfaceEndRecord(); } - + /** * creates the WriteAccess record containing the logged in user's name * @see org.apache.poi.hssf.record.WriteAccessRecord * @see org.apache.poi.hssf.record.Record * @return record containing a WriteAccessRecord */ - - protected Record createWriteAccess() - { + + protected Record createWriteAccess() { WriteAccessRecord retval = new WriteAccessRecord(); - + retval.setUsername(System.getProperty("user.name")); return retval; } - + /** * creates the Codepage record containing the constant stored in CODEPAGE * @see org.apache.poi.hssf.record.CodepageRecord * @see org.apache.poi.hssf.record.Record * @return record containing a CodepageRecord */ - - protected Record createCodepage() - { + + protected Record createCodepage() { CodepageRecord retval = new CodepageRecord(); - + retval.setCodepage(CODEPAGE); return retval; } - + /** * creates the DSF record containing a 0 since HSSF can't even create Dual Stream Files * @see org.apache.poi.hssf.record.DSFRecord * @see org.apache.poi.hssf.record.Record * @return record containing a DSFRecord */ - - protected Record createDSF() - { + + protected Record createDSF() { DSFRecord retval = new DSFRecord(); - + retval.setDsf( - ( short ) 0); // we don't even support double stream files + ( short ) 0); // we don't even support double stream files return retval; } - + /** * creates the TabId record containing an array of 0,1,2. This release of HSSF * always has the default three sheets, no less, no more. @@ -797,111 +803,103 @@ public class Workbook * @see org.apache.poi.hssf.record.Record * @return record containing a TabIdRecord */ - - protected Record createTabId() - { + + protected Record createTabId() { TabIdRecord retval = new TabIdRecord(); - short[] tabidarray = - { + short[] tabidarray = { 0 }; - + retval.setTabIdArray(tabidarray); return retval; } - + /** * creates the FnGroupCount record containing the Magic number constant of 14. * @see org.apache.poi.hssf.record.FnGroupCountRecord * @see org.apache.poi.hssf.record.Record * @return record containing a FnGroupCountRecord */ - - protected Record createFnGroupCount() - { + + protected Record createFnGroupCount() { FnGroupCountRecord retval = new FnGroupCountRecord(); - + retval.setCount(( short ) 14); return retval; } - + /** * creates the WindowProtect record with protect set to false. * @see org.apache.poi.hssf.record.WindowProtectRecord * @see org.apache.poi.hssf.record.Record * @return record containing a WindowProtectRecord */ - - protected Record createWindowProtect() - { + + protected Record createWindowProtect() { WindowProtectRecord retval = new WindowProtectRecord(); - + retval.setProtect( - false); // by default even when we support it we won't + false); // by default even when we support it we won't return retval; // want it to be protected } - + /** * creates the Protect record with protect set to false. * @see org.apache.poi.hssf.record.ProtectRecord * @see org.apache.poi.hssf.record.Record * @return record containing a ProtectRecord */ - - protected Record createProtect() - { + + protected Record createProtect() { ProtectRecord retval = new ProtectRecord(); - + retval.setProtect( - false); // by default even when we support it we won't + false); // by default even when we support it we won't return retval; // want it to be protected } - + /** * creates the Password record with password set to 0. * @see org.apache.poi.hssf.record.PasswordRecord * @see org.apache.poi.hssf.record.Record * @return record containing a PasswordRecord */ - - protected Record createPassword() - { + + protected Record createPassword() { PasswordRecord retval = new PasswordRecord(); - + retval.setPassword(( short ) 0); // no password by default! return retval; } - + /** * creates the ProtectionRev4 record with protect set to false. * @see org.apache.poi.hssf.record.ProtectionRev4Record * @see org.apache.poi.hssf.record.Record * @return record containing a ProtectionRev4Record */ - - protected Record createProtectionRev4() - { + + protected Record createProtectionRev4() { ProtectionRev4Record retval = new ProtectionRev4Record(); - + retval.setProtect(false); return retval; } - + /** * creates the PasswordRev4 record with password set to 0. * @see org.apache.poi.hssf.record.PasswordRev4Record * @see org.apache.poi.hssf.record.Record * @return record containing a PasswordRev4Record */ - - protected Record createPasswordRev4() - { + + protected Record createPasswordRev4() { PasswordRev4Record retval = new PasswordRev4Record(); - + retval.setPassword(( short ) 0); // no password by default! return retval; } - + /** * creates the WindowOne record with the following magic values:

* horizontal hold - 0x168

@@ -917,11 +915,10 @@ public class Workbook * @see org.apache.poi.hssf.record.Record * @return record containing a WindowOneRecord */ - - protected Record createWindowOne() - { + + protected Record createWindowOne() { WindowOneRecord retval = new WindowOneRecord(); - + retval.setHorizontalHold(( short ) 0x168); retval.setVerticalHold(( short ) 0x10e); retval.setWidth(( short ) 0x3a5c); @@ -933,100 +930,94 @@ public class Workbook retval.setTabWidthRatio(( short ) 0x258); return retval; } - + /** * creates the Backup record with backup set to 0. (loose the data, who cares) * @see org.apache.poi.hssf.record.BackupRecord * @see org.apache.poi.hssf.record.Record * @return record containing a BackupRecord */ - - protected Record createBackup() - { + + protected Record createBackup() { BackupRecord retval = new BackupRecord(); - + retval.setBackup( - ( short ) 0); // by default DONT save backups of files...just loose data + ( short ) 0); // by default DONT save backups of files...just loose data return retval; } - + /** * creates the HideObj record with hide object set to 0. (don't hide) * @see org.apache.poi.hssf.record.HideObjRecord * @see org.apache.poi.hssf.record.Record * @return record containing a HideObjRecord */ - - protected Record createHideObj() - { + + protected Record createHideObj() { HideObjRecord retval = new HideObjRecord(); - + retval.setHideObj(( short ) 0); // by default set hide object off return retval; } - + /** * creates the DateWindow1904 record with windowing set to 0. (don't window) * @see org.apache.poi.hssf.record.DateWindow1904Record * @see org.apache.poi.hssf.record.Record * @return record containing a DateWindow1904Record */ - - protected Record createDateWindow1904() - { + + protected Record createDateWindow1904() { DateWindow1904Record retval = new DateWindow1904Record(); - + retval.setWindowing( - ( short ) 0); // don't EVER use 1904 date windowing...tick tock.. + ( short ) 0); // don't EVER use 1904 date windowing...tick tock.. return retval; } - + /** * creates the Precision record with precision set to true. (full precision) * @see org.apache.poi.hssf.record.PrecisionRecord * @see org.apache.poi.hssf.record.Record * @return record containing a PrecisionRecord */ - - protected Record createPrecision() - { + + protected Record createPrecision() { PrecisionRecord retval = new PrecisionRecord(); - + retval.setFullPrecision( - true); // always use real numbers in calculations! + true); // always use real numbers in calculations! return retval; } - + /** * creates the RefreshAll record with refreshAll set to true. (refresh all calcs) * @see org.apache.poi.hssf.record.RefreshAllRecord * @see org.apache.poi.hssf.record.Record * @return record containing a RefreshAllRecord */ - - protected Record createRefreshAll() - { + + protected Record createRefreshAll() { RefreshAllRecord retval = new RefreshAllRecord(); - + retval.setRefreshAll(false); return retval; } - + /** * creates the BookBool record with saveLinkValues set to 0. (don't save link values) * @see org.apache.poi.hssf.record.BookBoolRecord * @see org.apache.poi.hssf.record.Record * @return record containing a BookBoolRecord */ - - protected Record createBookBool() - { + + protected Record createBookBool() { BookBoolRecord retval = new BookBoolRecord(); - + retval.setSaveLinkValues(( short ) 0); return retval; } - + /** * creates a Font record with the following magic values:

* fontheight = 0xc8

@@ -1040,11 +1031,10 @@ public class Workbook * @see org.apache.poi.hssf.record.Record * @return record containing a FontRecord */ - - protected Record createFont() - { + + protected Record createFont() { FontRecord retval = new FontRecord(); - + retval.setFontHeight(( short ) 0xc8); retval.setAttributes(( short ) 0x0); retval.setColorPaletteIndex(( short ) 0x7fff); @@ -1053,7 +1043,7 @@ public class Workbook retval.setFontName("Arial"); return retval; } - + /** * Creates a FormatRecord object * @param id the number of the format record to create (meaning its position in @@ -1062,70 +1052,68 @@ public class Workbook * @see org.apache.poi.hssf.record.FormatRecord * @see org.apache.poi.hssf.record.Record */ - - protected Record createFormat(int id) - { // we'll need multiple editions for + + protected Record createFormat(int id) { // we'll need multiple editions for FormatRecord retval = new FormatRecord(); // the differnt formats - - switch (id) - { - + + switch (id) { + case 0 : retval.setIndexCode(( short ) 5); retval.setFormatStringLength(( byte ) 0x17); retval.setFormatString("\"$\"#,##0_);\\(\"$\"#,##0\\)"); break; - + case 1 : retval.setIndexCode(( short ) 6); retval.setFormatStringLength(( byte ) 0x1c); retval.setFormatString("\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)"); break; - + case 2 : retval.setIndexCode(( short ) 7); retval.setFormatStringLength(( byte ) 0x1d); retval.setFormatString("\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)"); break; - + case 3 : retval.setIndexCode(( short ) 8); retval.setFormatStringLength(( byte ) 0x22); retval.setFormatString( - "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)"); + "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)"); break; - + case 4 : retval.setIndexCode(( short ) 0x2a); retval.setFormatStringLength(( byte ) 0x32); retval.setFormatString( - "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)"); + "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)"); break; - + case 5 : retval.setIndexCode(( short ) 0x29); retval.setFormatStringLength(( byte ) 0x29); retval.setFormatString( - "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)"); + "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)"); break; - + case 6 : retval.setIndexCode(( short ) 0x2c); retval.setFormatStringLength(( byte ) 0x3a); retval.setFormatString( - "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)"); + "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)"); break; - + case 7 : retval.setIndexCode(( short ) 0x2b); retval.setFormatStringLength(( byte ) 0x31); retval.setFormatString( - "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)"); + "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)"); break; } return retval; } - + /** * Creates an ExtendedFormatRecord object * @param id the number of the extended format record to create (meaning its position in @@ -1135,14 +1123,12 @@ public class Workbook * @see org.apache.poi.hssf.record.ExtendedFormatRecord * @see org.apache.poi.hssf.record.Record */ - - protected Record createExtendedFormat(int id) - { // we'll need multiple editions + + protected Record createExtendedFormat(int id) { // we'll need multiple editions ExtendedFormatRecord retval = new ExtendedFormatRecord(); - - switch (id) - { - + + switch (id) { + case 0 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1154,7 +1140,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 1 : retval.setFontIndex(( short ) 1); retval.setFormatIndex(( short ) 0); @@ -1166,7 +1152,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 2 : retval.setFontIndex(( short ) 1); retval.setFormatIndex(( short ) 0); @@ -1178,7 +1164,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 3 : retval.setFontIndex(( short ) 2); retval.setFormatIndex(( short ) 0); @@ -1190,7 +1176,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 4 : retval.setFontIndex(( short ) 2); retval.setFormatIndex(( short ) 0); @@ -1202,7 +1188,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 5 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1214,7 +1200,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 6 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1226,7 +1212,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 7 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1238,7 +1224,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 8 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1250,7 +1236,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 9 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1262,7 +1248,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 10 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1274,7 +1260,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 11 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1286,7 +1272,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 12 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1298,7 +1284,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 13 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1310,7 +1296,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 14 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1322,8 +1308,8 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - - // cell records + + // cell records case 15 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0); @@ -1335,8 +1321,8 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - - // style + + // style case 16 : retval.setFontIndex(( short ) 1); retval.setFormatIndex(( short ) 0x2b); @@ -1348,7 +1334,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 17 : retval.setFontIndex(( short ) 1); retval.setFormatIndex(( short ) 0x29); @@ -1360,7 +1346,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 18 : retval.setFontIndex(( short ) 1); retval.setFormatIndex(( short ) 0x2c); @@ -1372,7 +1358,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 19 : retval.setFontIndex(( short ) 1); retval.setFormatIndex(( short ) 0x2a); @@ -1384,7 +1370,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 20 : retval.setFontIndex(( short ) 1); retval.setFormatIndex(( short ) 0x9); @@ -1396,8 +1382,8 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - - // unused from this point down + + // unused from this point down case 21 : retval.setFontIndex(( short ) 5); retval.setFormatIndex(( short ) 0x0); @@ -1409,7 +1395,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 22 : retval.setFontIndex(( short ) 6); retval.setFormatIndex(( short ) 0x0); @@ -1421,7 +1407,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 23 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0x31); @@ -1433,7 +1419,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 24 : retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0x8); @@ -1445,7 +1431,7 @@ public class Workbook retval.setAdtlPaletteOptions(( short ) 0); retval.setFillPaletteOptions(( short ) 0x20c0); break; - + case 25 : retval.setFontIndex(( short ) 6); retval.setFormatIndex(( short ) 0x8); @@ -1460,16 +1446,15 @@ public class Workbook } return retval; } - + /** * creates an default cell type ExtendedFormatRecord object. * @return ExtendedFormatRecord with intial defaults (cell-type) */ - - protected ExtendedFormatRecord createExtendedFormat() - { + + protected ExtendedFormatRecord createExtendedFormat() { ExtendedFormatRecord retval = new ExtendedFormatRecord(); - + retval.setFontIndex(( short ) 0); retval.setFormatIndex(( short ) 0x0); retval.setCellOptions(( short ) 0x1); @@ -1481,7 +1466,7 @@ public class Workbook retval.setFillPaletteOptions(( short ) 0x20c0); return retval; } - + /** * Creates a StyleRecord object * @param id the number of the style record to create (meaning its position in @@ -1490,44 +1475,42 @@ public class Workbook * @see org.apache.poi.hssf.record.StyleRecord * @see org.apache.poi.hssf.record.Record */ - - protected Record createStyle(int id) - { // we'll need multiple editions + + protected Record createStyle(int id) { // we'll need multiple editions StyleRecord retval = new StyleRecord(); - - switch (id) - { - + + switch (id) { + case 0 : retval.setIndex(( short ) 0xffff8010); retval.setBuiltin(( byte ) 3); retval.setOutlineStyleLevel(( byte ) 0xffffffff); break; - + case 1 : retval.setIndex(( short ) 0xffff8011); retval.setBuiltin(( byte ) 6); retval.setOutlineStyleLevel(( byte ) 0xffffffff); break; - + case 2 : retval.setIndex(( short ) 0xffff8012); retval.setBuiltin(( byte ) 4); retval.setOutlineStyleLevel(( byte ) 0xffffffff); break; - + case 3 : retval.setIndex(( short ) 0xffff8013); retval.setBuiltin(( byte ) 7); retval.setOutlineStyleLevel(( byte ) 0xffffffff); break; - + case 4 : retval.setIndex(( short ) 0xffff8000); retval.setBuiltin(( byte ) 0); retval.setOutlineStyleLevel(( byte ) 0xffffffff); break; - + case 5 : retval.setIndex(( short ) 0xffff8014); retval.setBuiltin(( byte ) 5); @@ -1536,22 +1519,21 @@ public class Workbook } return retval; } - + /** * Creates the UseSelFS object with the use natural language flag set to 0 (false) * @return record containing a UseSelFSRecord * @see org.apache.poi.hssf.record.UseSelFSRecord * @see org.apache.poi.hssf.record.Record */ - - protected Record createUseSelFS() - { + + protected Record createUseSelFS() { UseSelFSRecord retval = new UseSelFSRecord(); - + retval.setFlag(( short ) 0); return retval; } - + /** * create a "bound sheet" or "bundlesheet" (depending who you ask) record * Always sets the sheet's bof to 0. You'll need to set that yourself. @@ -1560,14 +1542,12 @@ public class Workbook * @see org.apache.poi.hssf.record.BoundSheetRecord * @see org.apache.poi.hssf.record.Record */ - - protected Record createBoundSheet(int id) - { // 1,2,3 sheets + + protected Record createBoundSheet(int id) { // 1,2,3 sheets BoundSheetRecord retval = new BoundSheetRecord(); - - switch (id) - { - + + switch (id) { + case 0 : retval.setPositionOfBof(0x0); // should be set later retval.setOptionFlags(( short ) 0); @@ -1575,7 +1555,7 @@ public class Workbook retval.setCompressedUnicodeFlag(( byte ) 0); retval.setSheetname("Sheet1"); break; - + case 1 : retval.setPositionOfBof(0x0); // should be set later retval.setOptionFlags(( short ) 0); @@ -1583,7 +1563,7 @@ public class Workbook retval.setCompressedUnicodeFlag(( byte ) 0); retval.setSheetname("Sheet2"); break; - + case 2 : retval.setPositionOfBof(0x0); // should be set later retval.setOptionFlags(( short ) 0); @@ -1594,35 +1574,33 @@ public class Workbook } return retval; } - + /** * Creates the Country record with the default and current country set to 1 * @return record containing a CountryRecord * @see org.apache.poi.hssf.record.CountryRecord * @see org.apache.poi.hssf.record.Record */ - - protected Record createCountry() - { // what a novel idea, create your own! + + protected Record createCountry() { // what a novel idea, create your own! CountryRecord retval = new CountryRecord(); - + retval.setDefaultCountry(( short ) 1); retval.setCurrentCountry(( short ) 1); return retval; } - + /** * Creates the SST record with no strings and the unique/num string set to 0 * @return record containing a SSTRecord * @see org.apache.poi.hssf.record.SSTRecord * @see org.apache.poi.hssf.record.Record */ - - protected Record createSST() - { + + protected Record createSST() { return new SSTRecord(); } - + /** * Creates the ExtendedSST record with numstrings per bucket set to 0x8. HSSF * doesn't yet know what to do with this thing, but we create it with nothing in @@ -1632,39 +1610,163 @@ public class Workbook * @see org.apache.poi.hssf.record.ExtSSTRecord * @see org.apache.poi.hssf.record.Record */ - - protected Record createExtendedSST() - { + + protected Record createExtendedSST() { ExtSSTRecord retval = new ExtSSTRecord(); - + retval.setNumStringsPerBucket(( short ) 0x8); return retval; } - + /** * creates the EOF record * @see org.apache.poi.hssf.record.EOFRecord * @see org.apache.poi.hssf.record.Record * @return record containing a EOFRecord */ - - protected Record createEOF() - { + + protected Record createEOF() { return new EOFRecord(); } - + + /** fins the sheet name by his extern sheet index + * @param num extern sheet index + * @return sheet name + */ + public String findSheetNameFromExternSheet(short num){ + String result; + + short indexToSheet = externSheet.getREFRecordAt(num).getIndexToFirstSupBook(); + result = getSheetName(indexToSheet); + + return result; + } + + /** returns the extern sheet number for specific sheet number , + * if this sheet doesn't exist in extern sheet , add it + * @param sheetNumber sheet number + * @return index to extern sheet + */ + public short checkExternSheet(int sheetNumber){ + + int i = 0; + boolean flag = false; + short result = 0; + + if (externSheet == null) { + externSheet = createExternSheet(); + } + + //Trying to find reference to this sheet + while (i < externSheet.getNumOfREFStructures() && !flag){ + ExternSheetSubRecord record = externSheet.getREFRecordAt(i); + + if (record.getIndexToFirstSupBook() == sheetNumber && + record.getIndexToLastSupBook() == sheetNumber){ + flag = true; + result = (short) i; + } + + ++i; + } + + //We Havent found reference to this sheet + if (!flag) { + result = addSheetIndexToExternSheet((short) sheetNumber); + } + + return result; + } + + private short addSheetIndexToExternSheet(short sheetNumber){ + short result; + + ExternSheetSubRecord record = new ExternSheetSubRecord(); + record.setIndexToFirstSupBook(sheetNumber); + record.setIndexToLastSupBook(sheetNumber); + externSheet.addREFRecord(record); + externSheet.setNumOfREFStructures((short)(externSheet.getNumOfREFStructures() + 1)); + result = (short)(externSheet.getNumOfREFStructures() - 1); + + return result; + } + + + + /** gets the total number of names + * @return number of names + */ + public int getNumNames(){ + int result = names.size(); + + return result; + } + + /** gets the name record + * @param index name index + * @return name record + */ + public NameRecord getNameRecord(int index){ + NameRecord result = (NameRecord) names.get(index); + + return result; + + } + + /** creates new name + * @return new name record + */ + public NameRecord createName(){ + + NameRecord name = new NameRecord(); + + records.add(++namepos, name); + names.add(name); + + return name; + } + + /** removes the name + * @param namenum name index + */ + public void removeName(int namenum){ + if (names.size() > namenum) { + records.remove(namepos - (names.size() - 1) + namenum); + namepos--; + names.remove(namenum); + } + + } + + /** creates a new extern sheet record + * @return the new extern sheet record + */ + protected ExternSheetRecord createExternSheet(){ + ExternSheetRecord rec = new ExternSheetRecord(); + + records.add(supbookpos + 1 , rec); + + //We also adds the supBook for internal reference + SupBookRecord supbook = new SupBookRecord(); + + supbook.setNumberOfSheets((short)getNumSheets()); + supbook.setFlag(); + + records.add(supbookpos + 1 , supbook); + + return rec; + } + + /** * Returns the first occurance of a record matching a particular sid. */ - - public Record findFirstRecordBySid(short sid) - { - for (Iterator iterator = records.iterator(); iterator.hasNext(); ) - { + + public Record findFirstRecordBySid(short sid) { + for (Iterator iterator = records.iterator(); iterator.hasNext(); ) { Record record = ( Record ) iterator.next(); - - if (record.getSid() == sid) - { + + if (record.getSid() == sid) { return record; } } diff --git a/src/java/org/apache/poi/hssf/record/SupBookRecord.java b/src/java/org/apache/poi/hssf/record/SupBookRecord.java new file mode 100644 index 0000000000..e0e34d533e --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/SupBookRecord.java @@ -0,0 +1,176 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.util.LittleEndian; + +import java.util.ArrayList; + +/** + * Title: Sup Book

+ * Description: A Extrenal Workbook Deciption (Sup Book) + * Its only a dummy record for making new ExternSheet Record

+ * REFERENCE:

+ * @author Libin Roman (Vista Portal LDT. Developer) + * @version 1.0-pre + */ + +public class SupBookRecord extends Record +{ + public final static short sid = 0x1AE; + private short field_1_number_of_sheets; + private short field_2_flag; + + + public SupBookRecord() + { + } + + /** + * Constructs a Extern Sheet record and sets its fields appropriately. + * + * @param id id must be 0x16 or an exception will be throw upon validation + * @param size the size of the data area of the record + * @param data data of the record (should not contain sid/len) + */ + + public SupBookRecord(short id, short size, byte[] data) + { + super(id, size, data); + } + + /** + * Constructs a Extern Sheet record and sets its fields appropriately. + * + * @param id id must be 0x16 or an exception will be throw upon validation + * @param size the size of the data area of the record + * @param data data of the record (should not contain sid/len) + * @param offset of the record's data + */ + + public SupBookRecord(short id, short size, byte[] data, int offset) + { + super(id, size, data, offset); + } + + protected void validateSid(short id) + { + if (id != sid) + { + throw new RecordFormatException("NOT An ExternSheet RECORD"); + } + } + + /** + * called by the constructor, should set class level fields. Should throw + * runtime exception for bad/icomplete data. + * + * @param data raw data + * @param size size of data + * @param offset of the record's data (provided a big array of the file) + */ + protected void fillFields(byte [] data, short size, int offset) + { + //For now We use it only for one case + //When we need to add an named range when no named ranges was + //before it + + } + + + public String toString() + { + return ""; + } + + /** + * 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, sid); + LittleEndian.putShort(data, 2 + offset, (short) 4); + LittleEndian.putShort(data, 4 + offset, field_1_number_of_sheets); + LittleEndian.putShort(data, 6 + offset, field_2_flag); + + + return getRecordSize(); + } + + public void setNumberOfSheets(short number){ + field_1_number_of_sheets = number; + } + + public void setFlag(){ + field_2_flag = 0x0401; + } + + public int getRecordSize() + { + return 4 + 4; + } + + public short getSid() + { + return this.sid; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java b/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java new file mode 100644 index 0000000000..a52fcd58a9 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java @@ -0,0 +1,247 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record.formula; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.hssf.util.RangeAddress; + +/** + * Title: Area 3D Ptg

+ * Description: Defined a area in Extern Sheet.

+ * REFERENCE:

+ * @author Libin Roman (Vista Portal LDT. Developer) + * @version 1.0-pre + */ + +public class Area3DPtg extends Ptg +{ + public final static short sid = 0x3b; + private final static int SIZE = 11; // 10 + 1 for Ptg + private short field_1_index_extern_sheet; + private short field_2_first_row; + private short field_3_last_row; + private short field_4_first_column; + private short field_5_last_column; + + /** Creates new AreaPtg */ + + public Area3DPtg() + { + } + + public Area3DPtg(byte[] data, int offset) + { + offset++; + field_1_index_extern_sheet = LittleEndian.getShort(data, 0 + offset); + field_2_first_row = LittleEndian.getShort(data, 2 + offset); + field_3_last_row = LittleEndian.getShort(data, 4 + offset); + field_4_first_column = LittleEndian.getShort(data, 6 + offset); + field_5_last_column = LittleEndian.getShort(data, 8 + offset); + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append("AreaPtg\n"); + buffer.append("Index to Extern Sheet = " + getExternSheetIndex()).append("\n"); + buffer.append("firstRow = " + getFirstRow()).append("\n"); + buffer.append("lastRow = " + getLastRow()).append("\n"); + buffer.append("firstCol = " + getFirstColumn()).append("\n"); + buffer.append("lastCol = " + getLastColumn()).append("\n"); + buffer.append("firstColRowRel= " + + isFirstColRowRelative()).append("\n"); + buffer.append("lastColRowRel = " + + isLastColRowRelative()).append("\n"); + buffer.append("firstColRel = " + isFirstColRelative()).append("\n"); + buffer.append("lastColRel = " + isLastColRelative()).append("\n"); + return buffer.toString(); + } + + public void writeBytes(byte [] array, int offset) + { + array[ 0 + offset ] = sid; + LittleEndian.putShort(array, 1 + offset , getExternSheetIndex()); + LittleEndian.putShort(array, 3 + offset , getFirstRow()); + LittleEndian.putShort(array, 5 + offset , getLastRow()); + LittleEndian.putShort(array, 7 + offset , getFirstColumnRaw()); + LittleEndian.putShort(array, 9 + offset , getLastColumnRaw()); + } + + public int getSize() + { + return SIZE; + } + + public short getExternSheetIndex(){ + return field_1_index_extern_sheet; + } + + public void setExternSheetIndex(short index){ + field_1_index_extern_sheet = index; + } + + public short getFirstRow() + { + return field_2_first_row; + } + + public void setFirstRow(short row) + { + field_2_first_row = row; + } + + public short getLastRow() + { + return field_3_last_row; + } + + public void setLastRow(short row) + { + field_3_last_row = row; + } + + public short getFirstColumn() + { + return ( short ) (field_4_first_column & 0xFF); + } + + public short getFirstColumnRaw() + { + return field_4_first_column; + } + + public boolean isFirstColRowRelative() + { + return (((getFirstColumnRaw()) & 0x8000) == 0x8000); + } + + public boolean isFirstColRelative() + { + return (((getFirstColumnRaw()) & 0x4000) == 0x4000); + } + + public void setFirstColumn(short column) + { + field_4_first_column &= 0xFF00; + field_4_first_column |= column & 0xFF; + } + + public void setFirstColumnRaw(short column) + { + field_4_first_column = column; + } + + public short getLastColumn() + { + return ( short ) (field_5_last_column & 0xFF); + } + + public short getLastColumnRaw() + { + return field_5_last_column; + } + + public boolean isLastColRowRelative() + { + return (((getLastColumnRaw()) & 0x8000) == 1); + } + + public boolean isLastColRelative() + { + return (((getFirstColumnRaw()) & 0x4000) == 1); + } + + public void setLastColumn(short column) + { + field_5_last_column &= 0xFF00; + field_5_last_column |= column & 0xFF; + } + + public void setLastColumnRaw(short column) + { + field_5_last_column = column; + } + + public String getArea(){ + RangeAddress ra = new RangeAddress( getFirstColumn(),getFirstRow() + 1, getLastColumn(), getLastRow() + 1); + String result = ra.getAddress(); + + return result; + } + + public void setArea(String ref){ + RangeAddress ra = new RangeAddress(ref); + + String from = ra.getFromCell(); + String to = ra.getToCell(); + + setFirstColumn((short) (ra.getXPosition(from) -1)); + setFirstRow((short) (ra.getYPosition(from) -1)); + setLastColumn((short) (ra.getXPosition(to) -1)); + setLastRow((short) (ra.getYPosition(to) -1)); + + } + + public String toFormulaString() + { + String result = getArea(); + + return result; + } + + +} diff --git a/src/java/org/apache/poi/hssf/record/formula/Ptg.java b/src/java/org/apache/poi/hssf/record/formula/Ptg.java index 5db1dbfe97..44eef7ce13 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Ptg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Ptg.java @@ -113,9 +113,7 @@ public abstract class Ptg { byte id = data[ offset + 0 ]; Ptg retval = null; - - System.out.println("PTG = " + Integer.toHexString(id) + " (" + id - + ")"); + switch (id) { @@ -175,6 +173,14 @@ public abstract class Ptg retval = new ExpPtg(data, offset); break; + case Area3DPtg.sid : + retval = new Area3DPtg(data, offset); + break; + + case Ref3DPtg.sid: + retval = new Ref3DPtg(data, offset); + break; + default : // retval = new UnknownPtg(); diff --git a/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java b/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java new file mode 100644 index 0000000000..885a8bac1c --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java @@ -0,0 +1,177 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.record.formula; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.hssf.util.RangeAddress; + +/** + * Title: Reference 3D Ptg

+ * Description: Defined a cell in extern sheet.

+ * REFERENCE:

+ * @author Libin Roman (Vista Portal LDT. Developer) + * @version 1.0-pre + */ + +public class Ref3DPtg extends Ptg { + public final static short sid = 0x3a; + private final static int SIZE = 7; // 6 + 1 for Ptg + private short field_1_index_extern_sheet; + private short field_2_row; + private short field_3_column; + + /** Creates new AreaPtg */ + + public Ref3DPtg() { + } + + public Ref3DPtg(byte[] data, int offset) { + offset++; + field_1_index_extern_sheet = LittleEndian.getShort(data, 0 + offset); + field_2_row = LittleEndian.getShort(data, 2 + offset); + field_3_column = LittleEndian.getShort(data, 4 + offset); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + + buffer.append("Ref3dPrg\n"); + buffer.append("Index to Extern Sheet = " + getExternSheetIndex()).append("\n"); + buffer.append("Row = " + getRow()).append("\n"); + buffer.append("Col = " + getColumn()).append("\n"); + buffer.append("ColRowRel= " + + isColRowRelative()).append("\n"); + buffer.append("ColRel = " + isColRelative()).append("\n"); + return buffer.toString(); + } + + public void writeBytes(byte [] array, int offset) { + array[ 0 + offset ] = sid; + LittleEndian.putShort(array, 1 + offset , getExternSheetIndex()); + LittleEndian.putShort(array, 3 + offset , getRow()); + LittleEndian.putShort(array, 5 + offset , getColumnRaw()); + } + + public int getSize() { + return SIZE; + } + + public short getExternSheetIndex(){ + return field_1_index_extern_sheet; + } + + public void setExternSheetIndex(short index){ + field_1_index_extern_sheet = index; + } + + public short getRow() { + return field_2_row; + } + + public void setRow(short row) { + field_2_row = row; + } + + public short getColumn() { + return ( short ) (field_3_column & 0xFF); + } + + public short getColumnRaw() { + return field_3_column; + } + + public boolean isColRowRelative() { + return (((getColumnRaw()) & 0x8000) == 0x8000); + } + + public boolean isColRelative() { + return (((getColumnRaw()) & 0x4000) == 0x4000); + } + + public void setColumn(short column) { + field_3_column &= 0xFF00; + field_3_column |= column & 0xFF; + } + + public void setColumnRaw(short column) { + field_3_column = column; + } + + public String getArea(){ + RangeAddress ra = new RangeAddress(""); + + String result = (ra.numTo26Sys(getColumn()) + (getRow() + 1)); + + return result; + } + + public void setArea(String ref){ + RangeAddress ra = new RangeAddress(ref); + + String from = ra.getFromCell(); + + setColumn((short) (ra.getXPosition(from) -1)); + setRow((short) (ra.getYPosition(from) -1)); + + } + + public String toFormulaString() { + String result = getArea(); + + return result; + } + +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFName.java b/src/java/org/apache/poi/hssf/usermodel/HSSFName.java new file mode 100644 index 0000000000..c4d3fb2583 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFName.java @@ -0,0 +1,170 @@ + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.util.POILogFactory; +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.util.Region; +import org.apache.poi.util.POILogger; + +import java.util.Iterator; +import java.util.TreeMap; +import org.apache.poi.hssf.util.RangeAddress; + +/** + * Title: High Level Represantion of Named Range

+ * REFERENCE:

+ * @author Libin Roman (Vista Portal LDT. Developer) + * @version 1.0-pre + */ + +public class HSSFName { + private Workbook book; + private NameRecord name; + + /** Creates new HSSFName - called by HSSFWorkbook to create a sheet from + * scratch. + * + * @see #org.apache.poi.hssf.usermodel.HSSFWorkbook.createName() + * @param name the Name Record + * @param book - lowlevel Workbook object associated with the sheet. + * @param book the Workbook */ + + protected HSSFName(Workbook book, NameRecord name) { + this.book = book; + this.name = name; + } + + /** private default constructor prevents bogus initializationless construction */ + + private HSSFName() { + } + + /** Get the sheets name which this named range is referenced to + * @return sheet name, which this named range refered to + */ + public String getSheetName() { + String result ; + short indexToExternSheet = name.getExternSheetNumber(); + + result = book.findSheetNameFromExternSheet(indexToExternSheet); + + return result; + } + + /** gets the name of the named range + * @return named range name + */ + public String getNameName(){ + String result = name.getNameText(); + + return result; + } + + /** sets the name of the named range + * @param nameName named range name to set + */ + public void setNameName(String nameName){ + name.setNameText(nameName); + name.setNameTextLength((byte)nameName.length()); + } + + /** gets the reference of the named range + * @return reference of the named range + */ + public String getReference() { + String result; + + result = getSheetName() + "." + name.getAreaReference(); + + return result; + } + + /** sets the sheet name which this named range referenced to + * @param sheetName the sheet name of the reference + */ + public void setSheetName(String sheetName){ + int sheetNumber = book.getSheetIndex(sheetName); + + short externSheetNumber = book.checkExternSheet(sheetNumber); + name.setExternSheetNumber(externSheetNumber); +// name.setIndexToSheet(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); + } + + if (ra.getFromCell().equals(ra.getToCell()) == false) { + name.setAreaReference(ra.getFromCell() + ":" + ra.getToCell()); + } else { + name.setAreaReference(ra.getFromCell()); + } + + } + + +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index e2daea9eb8..46fad9ae1d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -110,6 +110,13 @@ public class HSSFWorkbook */ private ArrayList sheets; + + /** + * this holds the HSSFName objects attached to this workbook + */ + + private ArrayList names; + private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class); /** @@ -121,6 +128,7 @@ public class HSSFWorkbook { workbook = Workbook.createWorkbook(); sheets = new ArrayList(INITIAL_CAPACITY); + names = new ArrayList(INITIAL_CAPACITY); } /** @@ -136,6 +144,8 @@ public class HSSFWorkbook throws IOException { sheets = new ArrayList(INITIAL_CAPACITY); + names = new ArrayList(INITIAL_CAPACITY); + InputStream stream = fs.createDocumentInputStream("Workbook"); List records = RecordFactory.createRecords(stream); @@ -157,6 +167,11 @@ public class HSSFWorkbook // workbook.setSheetName(sheets.size() -1, "Sheet"+sheets.size()); } + + for (int i = 0 ; i < workbook.getNumNames() ; ++i){ + HSSFName name = new HSSFName(workbook, workbook.getNameRecord(i)); + names.add(name); + } } /** @@ -216,29 +231,23 @@ public class HSSFWorkbook return workbook.getSheetName(sheet); } - /** + /* * get the sheet's index * @param name sheet name * @return sheet index or -1 if it was not found. */ + /** Returns the index of the sheet by his name + * @param name the sheet name + * @return index of the sheet (0 based) + */ public int getSheetIndex(String name) { - int retval = -1; - - for (int k = 0; k < sheets.size(); k++) - { - String sheet = workbook.getSheetName(k); - - if (sheet.equals(name)) - { - retval = k; - break; - } - } + int retval = workbook.getSheetIndex(name); + return retval; } - + /** * create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and returns * the high level representation. Use this to create new sheets. @@ -534,4 +543,87 @@ public class HSSFWorkbook { return workbook; } + + /** gets the total number of named ranges in the workboko + * @return number of named ranges + */ + public int getNumberOfNames(){ + int result = names.size(); + return result; + } + + /** gets the Named range + * @param index position of the named range + * @return named range high level + */ + public HSSFName getNameAt(int index){ + HSSFName result = (HSSFName) names.get(index); + + return result; + } + + /** gets the named range name + * @param index the named range index (0 based) + * @return named range name + */ + public String getNameName(int index){ + String result = getNameAt(index).getNameName(); + + return result; + } + + + /** creates a new named range and add it to the model + * @return named range high level + */ + public HSSFName createName(){ + NameRecord nameRecord = workbook.createName(); + + HSSFName newName = new HSSFName(workbook, nameRecord); + + names.add(newName); + + return newName; + } + + /** gets the named range index by his name + * @param name named range name + * @return named range index + */ + public int getNameIndex(String name) + { + int retval = -1; + + for (int k = 0; k < names.size(); k++) + { + String nameName = getNameName(k); + + if (nameName.equals(name)) + { + retval = k; + break; + } + } + return retval; + } + + + /** remove the named range by his index + * @param index named range index (0 based) + */ + public void removeName(int index){ + names.remove(index); + workbook.removeName(index); + } + + /** remove the named range by his name + * @param name named range name + */ + public void removeName(String name){ + int index = getNameIndex(name); + + removeName(index); + + } + } diff --git a/src/java/org/apache/poi/hssf/util/RangeAddress.java b/src/java/org/apache/poi/hssf/util/RangeAddress.java new file mode 100644 index 0000000000..3e9289e95c --- /dev/null +++ b/src/java/org/apache/poi/hssf/util/RangeAddress.java @@ -0,0 +1,392 @@ +package org.apache.poi.hssf.util; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache POI" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache POI", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + + +/** + * Title: Range Address

+ * Description: provides connectivity utilities for ranges

+ * REFERENCE:

+ * @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; + + public RangeAddress (String _url) { + init (_url); + } + + public RangeAddress (int _startCol, int _startRow, int _endCol, int _endRow) { + init (numTo26Sys (_startCol) + _startRow + ":" + + numTo26Sys (_endCol) + _endRow); + } + + 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 (){ + if(m_cellFrom == null || m_cellTo == null) + return false; + return true; + } + + 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, ""); + } + +}