KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > poi > hssf > model > Workbook


1 /* ====================================================================
2    Copyright 2002-2004 Apache Software Foundation
3
4    Licensed under the Apache License, Version 2.0 (the "License");
5    you may not use this file except in compliance with the License.
6    You may obtain a copy of the License at
7
8        http://www.apache.org/licenses/LICENSE-2.0
9
10    Unless required by applicable law or agreed to in writing, software
11    distributed under the License is distributed on an "AS IS" BASIS,
12    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    See the License for the specific language governing permissions and
14    limitations under the License.
15 ==================================================================== */

16
17
18 package org.apache.poi.hssf.model;
19
20 import org.apache.poi.ddf.*;
21 import org.apache.poi.hssf.record.*;
22 import org.apache.poi.hssf.util.HSSFColor;
23 import org.apache.poi.hssf.util.SheetReferences;
24 import org.apache.poi.util.POILogFactory;
25 import org.apache.poi.util.POILogger;
26
27 import java.util.ArrayList JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Locale JavaDoc;
31
32 /**
33  * Low level model implementation of a Workbook. Provides creational methods
34  * for settings and objects contained in the workbook object.
35  * <P>
36  * This file contains the low level binary records starting at the workbook's BOF and
37  * ending with the workbook's EOF. Use HSSFWorkbook for a high level representation.
38  * <P>
39  * The structures of the highlevel API use references to this to perform most of their
40  * operations. Its probably unwise to use these low level structures directly unless you
41  * really know what you're doing. I recommend you read the Microsoft Excel 97 Developer's
42  * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf
43  * before even attempting to use this.
44  *
45  *
46  * @author Shawn Laubach (slaubach at apache dot org) (Data Formats)
47  * @author Andrew C. Oliver (acoliver at apache dot org)
48  * @author Glen Stampoultzis (glens at apache.org)
49  * @author Sergei Kozello (sergeikozello at mail.ru)
50  * @author Luc Girardin (luc dot girardin at macrofocus dot com)
51  * @author Dan Sherman (dsherman at isisph.com)
52  * @author Brian Sanders (bsanders at risklabs dot com) - custom palette
53  * @see org.apache.poi.hssf.usermodel.HSSFWorkbook
54  * @version 1.0-pre
55  */

56
57 public class Workbook implements Model
58 {
59     private static final int DEBUG = POILogger.DEBUG;
60
61 // public static Workbook currentBook = null;
62

63     /**
64      * constant used to set the "codepage" wherever "codepage" is set in records
65      * (which is duplciated in more than one record)
66      */

67
68     private final static short CODEPAGE = ( short ) 0x4b0;
69
70     /**
71      * this contains the Worksheet record objects
72      */

73     protected WorkbookRecordList records = new WorkbookRecordList();
74
75     /**
76      * this contains a reference to the SSTRecord so that new stings can be added
77      * to it.
78      */

79     protected SSTRecord sst = null;
80
81     /**
82      * Holds the Extern Sheet with references to bound sheets
83      */

84     protected ExternSheetRecord externSheet= null;
85
86     /**
87      * holds the "boundsheet" records (aka bundlesheet) so that they can have their
88      * reference to their "BOF" marker
89      */

90     protected ArrayList JavaDoc boundsheets = new ArrayList JavaDoc();
91
92     protected ArrayList JavaDoc formats = new ArrayList JavaDoc();
93
94     protected ArrayList JavaDoc names = new ArrayList JavaDoc();
95
96     protected int numxfs = 0; // hold the number of extended format records
97
protected int numfonts = 0; // hold the number of font records
98
private short maxformatid = -1; // holds the max format id
99
private boolean uses1904datewindowing = false; // whether 1904 date windowing is being used
100
private DrawingManager drawingManager;
101
102     private static POILogger log = POILogFactory.getLogger(Workbook.class);
103
104     /**
105      * Creates new Workbook with no intitialization --useless right now
106      * @see #createWorkbook(List)
107      */

108     public Workbook() {
109     }
110
111     /**
112      * read support for low level
113      * API. Pass in an array of Record objects, A Workbook
114      * object is constructed and passed back with all of its initialization set
115      * to the passed in records and references to those records held. Unlike Sheet
116      * workbook does not use an offset (its assumed to be 0) since its first in a file.
117      * If you need an offset then construct a new array with a 0 offset or write your
118      * own ;-p.
119      *
120      * @param recs an array of Record objects
121      * @return Workbook object
122      */

123     public static Workbook createWorkbook(List JavaDoc recs) {
124         if (log.check( POILogger.DEBUG ))
125             log.log(DEBUG, "Workbook (readfile) created with reclen=",
126                     new Integer JavaDoc(recs.size()));
127         Workbook retval = new Workbook();
128         ArrayList JavaDoc records = new ArrayList JavaDoc(recs.size() / 3);
129
130         for (int k = 0; k < recs.size(); k++) {
131             Record rec = ( Record ) recs.get(k);
132
133             if (rec.getSid() == EOFRecord.sid) {
134                 records.add(rec);
135                 if (log.check( POILogger.DEBUG ))
136                     log.log(DEBUG, "found workbook eof record at " + k);
137                 break;
138             }
139             switch (rec.getSid()) {
140
141                 case BoundSheetRecord.sid :
142                     if (log.check( POILogger.DEBUG ))
143                         log.log(DEBUG, "found boundsheet record at " + k);
144                     retval.boundsheets.add(rec);
145                     retval.records.setBspos( k );
146                     break;
147
148                 case SSTRecord.sid :
149                     if (log.check( POILogger.DEBUG ))
150                         log.log(DEBUG, "found sst record at " + k);
151                     retval.sst = ( SSTRecord ) rec;
152                     break;
153
154                 case FontRecord.sid :
155                     if (log.check( POILogger.DEBUG ))
156                         log.log(DEBUG, "found font record at " + k);
157                     retval.records.setFontpos( k );
158                     retval.numfonts++;
159                     break;
160
161                 case ExtendedFormatRecord.sid :
162                     if (log.check( POILogger.DEBUG ))
163                         log.log(DEBUG, "found XF record at " + k);
164                     retval.records.setXfpos( k );
165                     retval.numxfs++;
166                     break;
167
168                 case TabIdRecord.sid :
169                     if (log.check( POILogger.DEBUG ))
170                         log.log(DEBUG, "found tabid record at " + k);
171                     retval.records.setTabpos( k );
172                     break;
173
174                 case ProtectRecord.sid :
175                     if (log.check( POILogger.DEBUG ))
176                         log.log(DEBUG, "found protect record at " + k);
177                     retval.records.setProtpos( k );
178                     break;
179
180                 case BackupRecord.sid :
181                     if (log.check( POILogger.DEBUG ))
182                         log.log(DEBUG, "found backup record at " + k);
183                     retval.records.setBackuppos( k );
184                     break;
185                 case ExternSheetRecord.sid :
186                     if (log.check( POILogger.DEBUG ))
187                         log.log(DEBUG, "found extern sheet record at " + k);
188                     retval.externSheet = ( ExternSheetRecord ) rec;
189                     break;
190                 case NameRecord.sid :
191                     if (log.check( POILogger.DEBUG ))
192                         log.log(DEBUG, "found name record at " + k);
193                     retval.names.add(rec);
194                     // retval.records.namepos = k;
195
break;
196                 case SupBookRecord.sid :
197                     if (log.check( POILogger.DEBUG ))
198                         log.log(DEBUG, "found SupBook record at " + k);
199                     // retval.records.supbookpos = k;
200
break;
201                 case FormatRecord.sid :
202                     if (log.check( POILogger.DEBUG ))
203                         log.log(DEBUG, "found format record at " + k);
204                     retval.formats.add(rec);
205                     retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode();
206                     break;
207                 case DateWindow1904Record.sid :
208                     if (log.check( POILogger.DEBUG ))
209                         log.log(DEBUG, "found datewindow1904 record at " + k);
210                     retval.uses1904datewindowing = ((DateWindow1904Record)rec).getWindowing() == 1;
211                     break;
212                 case PaletteRecord.sid:
213                     if (log.check( POILogger.DEBUG ))
214                         log.log(DEBUG, "found palette record at " + k);
215                     retval.records.setPalettepos( k );
216                 default :
217             }
218             records.add(rec);
219         }
220         //What if we dont have any ranges and supbooks
221
// if (retval.records.supbookpos == 0) {
222
// retval.records.supbookpos = retval.records.bspos + 1;
223
// retval.records.namepos = retval.records.supbookpos + 1;
224
// }
225

226         retval.records.setRecords(records);
227         if (log.check( POILogger.DEBUG ))
228             log.log(DEBUG, "exit create workbook from existing file function");
229         return retval;
230     }
231
232     /**
233      * Creates an empty workbook object with three blank sheets and all the empty
234      * fields. Use this to create a workbook from scratch.
235      */

236     public static Workbook createWorkbook()
237     {
238         if (log.check( POILogger.DEBUG ))
239             log.log( DEBUG, "creating new workbook from scratch" );
240         Workbook retval = new Workbook();
241         ArrayList JavaDoc records = new ArrayList JavaDoc( 30 );
242         ArrayList JavaDoc formats = new ArrayList JavaDoc( 8 );
243
244         records.add( retval.createBOF() );
245         records.add( retval.createInterfaceHdr() );
246         records.add( retval.createMMS() );
247         records.add( retval.createInterfaceEnd() );
248         records.add( retval.createWriteAccess() );
249         records.add( retval.createCodepage() );
250         records.add( retval.createDSF() );
251         records.add( retval.createTabId() );
252         retval.records.setTabpos( records.size() - 1 );
253         records.add( retval.createFnGroupCount() );
254         records.add( retval.createWindowProtect() );
255         records.add( retval.createProtect() );
256         retval.records.setProtpos( records.size() - 1 );
257         records.add( retval.createPassword() );
258         records.add( retval.createProtectionRev4() );
259         records.add( retval.createPasswordRev4() );
260         records.add( retval.createWindowOne() );
261         records.add( retval.createBackup() );
262         retval.records.setBackuppos( records.size() - 1 );
263         records.add( retval.createHideObj() );
264         records.add( retval.createDateWindow1904() );
265         records.add( retval.createPrecision() );
266         records.add( retval.createRefreshAll() );
267         records.add( retval.createBookBool() );
268         records.add( retval.createFont() );
269         records.add( retval.createFont() );
270         records.add( retval.createFont() );
271         records.add( retval.createFont() );
272         retval.records.setFontpos( records.size() - 1 ); // last font record postion
273
retval.numfonts = 4;
274
275         // set up format records
276
for ( int i = 0; i <= 7; i++ )
277         {
278             Record rec;
279             rec = retval.createFormat( i );
280             retval.maxformatid = retval.maxformatid >= ( (FormatRecord) rec ).getIndexCode() ? retval.maxformatid : ( (FormatRecord) rec ).getIndexCode();
281             formats.add( rec );
282             records.add( rec );
283         }
284         retval.formats = formats;
285
286         for ( int k = 0; k < 21; k++ )
287         {
288             records.add( retval.createExtendedFormat( k ) );
289             retval.numxfs++;
290         }
291         retval.records.setXfpos( records.size() - 1 );
292         for ( int k = 0; k < 6; k++ )
293         {
294             records.add( retval.createStyle( k ) );
295         }
296         records.add( retval.createUseSelFS() );
297         for ( int k = 0; k < 1; k++ )
298         { // now just do 1
299
BoundSheetRecord bsr =
300                     (BoundSheetRecord) retval.createBoundSheet( k );
301
302             records.add( bsr );
303             retval.boundsheets.add( bsr );
304             retval.records.setBspos( records.size() - 1 );
305         }
306 // retval.records.supbookpos = retval.records.bspos + 1;
307
// retval.records.namepos = retval.records.supbookpos + 2;
308
records.add( retval.createCountry() );
309         retval.sst = (SSTRecord) retval.createSST();
310         records.add( retval.sst );
311         records.add( retval.createExtendedSST() );
312
313         records.add( retval.createEOF() );
314         retval.records.setRecords(records);
315         if (log.check( POILogger.DEBUG ))
316             log.log( DEBUG, "exit create new workbook from scratch" );
317         return retval;
318     }
319
320
321     /**Retrieves the Builtin NameRecord that matches the name and index
322      * There shouldn't be too many names to make the sequential search too slow
323      * @param name byte representation of the builtin name to match
324      * @param sheetIndex Index to match
325      * @return null if no builtin NameRecord matches
326      */

327     public NameRecord getSpecificBuiltinRecord(byte name, int sheetIndex)
328     {
329         Iterator JavaDoc iterator = names.iterator();
330         while (iterator.hasNext()) {
331             NameRecord record = ( NameRecord ) iterator.next();
332     
333             //print areas are one based
334
if (record.getBuiltInName() == name && record.getIndexToSheet() == sheetIndex) {
335                 return record;
336             }
337         }
338         
339         return null;
340         
341     }
342
343     /**
344      * Removes the specified Builtin NameRecord that matches the name and index
345      * @param name byte representation of the builtin to match
346      * @param sheetIndex zero-based sheet reference
347      */

348     public void removeBuiltinRecord(byte name, int sheetIndex) {
349         //the name array is smaller so searching through it should be faster than
350
//using the findFirstXXXX methods
351
NameRecord record = getSpecificBuiltinRecord(name, sheetIndex);
352         if (record != null) {
353             names.remove(record);
354         }
355         
356     }
357
358     public int getNumRecords() {
359         return records.size();
360     }
361
362     /**
363      * gets the font record at the given index in the font table. Remember
364      * "There is No Four" (someone at M$ must have gone to Rocky Horror one too
365      * many times)
366      *
367      * @param idx the index to look at (0 or greater but NOT 4)
368      * @return FontRecord located at the given index
369      */

370
371     public FontRecord getFontRecordAt(int idx) {
372         int index = idx;
373
374         if (index > 4) {
375             index -= 1; // adjust for "There is no 4"
376
}
377         if (index > (numfonts - 1)) {
378             throw new ArrayIndexOutOfBoundsException JavaDoc(
379             "There are only " + numfonts
380             + " font records, you asked for " + idx);
381         }
382         FontRecord retval =
383         ( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + index);
384
385         return retval;
386     }
387
388     /**
389      * creates a new font record and adds it to the "font table". This causes the
390      * boundsheets to move down one, extended formats to move down (so this function moves
391      * those pointers as well)
392      *
393      * @return FontRecord that was just created
394      */

395
396     public FontRecord createNewFont() {
397         FontRecord rec = ( FontRecord ) createFont();
398
399         records.add(records.getFontpos()+1, rec);
400         records.setFontpos( records.getFontpos() + 1 );
401         numfonts++;
402         return rec;
403     }
404
405     /**
406      * gets the number of font records
407      *
408      * @return number of font records in the "font table"
409      */

410
411     public int getNumberOfFontRecords() {
412         return numfonts;
413     }
414
415     /**
416      * Sets the BOF for a given sheet
417      *
418      * @param sheetnum the number of the sheet to set the positing of the bof for
419      * @param pos the actual bof position
420      */

421
422     public void setSheetBof(int sheetnum, int pos) {
423         if (log.check( POILogger.DEBUG ))
424             log.log(DEBUG, "setting bof for sheetnum =", new Integer JavaDoc(sheetnum),
425                 " at pos=", new Integer JavaDoc(pos));
426         checkSheets(sheetnum);
427         (( BoundSheetRecord ) boundsheets.get(sheetnum))
428         .setPositionOfBof(pos);
429     }
430
431     /**
432      * Returns the position of the backup record.
433      */

434
435     public BackupRecord getBackupRecord() {
436         return ( BackupRecord ) records.get(records.getBackuppos());
437     }
438
439
440     /**
441      * sets the name for a given sheet. If the boundsheet record doesn't exist and
442      * its only one more than we have, go ahead and create it. If its > 1 more than
443      * we have, except
444      *
445      * @param sheetnum the sheet number (0 based)
446      * @param sheetname the name for the sheet
447      */

448
449     // for compatibility
450
public void setSheetName(int sheetnum, String JavaDoc sheetname ) {
451         setSheetName( sheetnum, sheetname, (byte)0 );
452     }
453
454     /**
455      * Determines whether a workbook contains the privided sheet name.
456      *
457      * @param name the name to test
458      * @param excludeSheetIdx the sheet to exclude from the check or -1 to include all sheets in the check.
459      * @return true if the sheet contains the name, false otherwise.
460      */

461     public boolean doesContainsSheetName( String JavaDoc name, int excludeSheetIdx )
462     {
463         for ( int i = 0; i < boundsheets.size(); i++ )
464         {
465             BoundSheetRecord boundSheetRecord = (BoundSheetRecord) boundsheets.get( i );
466             if (excludeSheetIdx != i && name.equals(boundSheetRecord.getSheetname()))
467                 return true;
468         }
469         return false;
470     }
471
472     public void setSheetName(int sheetnum, String JavaDoc sheetname, short encoding ) {
473         checkSheets(sheetnum);
474         BoundSheetRecord sheet = (BoundSheetRecord)boundsheets.get( sheetnum );
475         sheet.setSheetname(sheetname);
476         sheet.setSheetnameLength( (byte)sheetname.length() );
477         sheet.setCompressedUnicodeFlag( (byte)encoding );
478     }
479     
480     /**
481      * sets the order of appearance for a given sheet.
482      *
483      * @param sheetname the name of the sheet to reorder
484      * @param pos the position that we want to insert the sheet into (0 based)
485      */

486     
487     public void setSheetOrder(String JavaDoc sheetname, int pos ) {
488     int sheetNumber = getSheetIndex(sheetname);
489     //remove the sheet that needs to be reordered and place it in the spot we want
490
boundsheets.add(pos, boundsheets.remove(sheetNumber));
491     }
492
493     /**
494      * gets the name for a given sheet.
495      *
496      * @param sheetnum the sheet number (0 based)
497      * @return sheetname the name for the sheet
498      */

499
500     public String JavaDoc getSheetName(int sheetnum) {
501         return (( BoundSheetRecord ) boundsheets.get(sheetnum))
502         .getSheetname();
503     }
504
505     /**
506      * get the sheet's index
507      * @param name sheet name
508      * @return sheet index or -1 if it was not found.
509      */

510
511     public int getSheetIndex(String JavaDoc name) {
512         int retval = -1;
513
514         for (int k = 0; k < boundsheets.size(); k++) {
515             String JavaDoc sheet = getSheetName(k);
516
517             if (sheet.equalsIgnoreCase(name)) {
518                 retval = k;
519                 break;
520             }
521         }
522         return retval;
523     }
524
525     /**
526      * if we're trying to address one more sheet than we have, go ahead and add it! if we're
527      * trying to address >1 more than we have throw an exception!
528      */

529
530     private void checkSheets(int sheetnum) {
531         if ((boundsheets.size()) <= sheetnum) { // if we're short one add another..
532
if ((boundsheets.size() + 1) <= sheetnum) {
533                 throw new RuntimeException JavaDoc("Sheet number out of bounds!");
534             }
535             BoundSheetRecord bsr = (BoundSheetRecord ) createBoundSheet(sheetnum);
536
537             records.add(records.getBspos()+1, bsr);
538             records.setBspos( records.getBspos() + 1 );
539             boundsheets.add(bsr);
540             fixTabIdRecord();
541         }
542     }
543
544     public void removeSheet(int sheetnum) {
545         if (boundsheets.size() > sheetnum) {
546             records.remove(records.getBspos() - (boundsheets.size() - 1) + sheetnum);
547 // records.bspos--;
548
boundsheets.remove(sheetnum);
549             fixTabIdRecord();
550         }
551     }
552
553     /**
554      * make the tabid record look like the current situation.
555      *
556      */

557     private void fixTabIdRecord() {
558         TabIdRecord tir = ( TabIdRecord ) records.get(records.getTabpos());
559         short[] tia = new short[ boundsheets.size() ];
560
561         for (short k = 0; k < tia.length; k++) {
562             tia[ k ] = k;
563         }
564         tir.setTabIdArray(tia);
565     }
566
567     /**
568      * returns the number of boundsheet objects contained in this workbook.
569      *
570      * @return number of BoundSheet records
571      */

572
573     public int getNumSheets() {
574         if (log.check( POILogger.DEBUG ))
575             log.log(DEBUG, "getNumSheets=", new Integer JavaDoc(boundsheets.size()));
576         return boundsheets.size();
577     }
578
579     /**
580      * get the number of ExtendedFormat records contained in this workbook.
581      *
582      * @return int count of ExtendedFormat records
583      */

584
585     public int getNumExFormats() {
586         if (log.check( POILogger.DEBUG ))
587             log.log(DEBUG, "getXF=", new Integer JavaDoc(numxfs));
588         return numxfs;
589     }
590
591     /**
592      * gets the ExtendedFormatRecord at the given 0-based index
593      *
594      * @param index of the Extended format record (0-based)
595      * @return ExtendedFormatRecord at the given index
596      */

597
598     public ExtendedFormatRecord getExFormatAt(int index) {
599         int xfptr = records.getXfpos() - (numxfs - 1);
600
601         xfptr += index;
602         ExtendedFormatRecord retval =
603         ( ExtendedFormatRecord ) records.get(xfptr);
604
605         return retval;
606     }
607
608     /**
609      * creates a new Cell-type Extneded Format Record and adds it to the end of
610      * ExtendedFormatRecords collection
611      *
612      * @return ExtendedFormatRecord that was created
613      */

614
615     public ExtendedFormatRecord createCellXF() {
616         ExtendedFormatRecord xf = createExtendedFormat();
617
618         records.add(records.getXfpos()+1, xf);
619         records.setXfpos( records.getXfpos() + 1 );
620         numxfs++;
621         return xf;
622     }
623
624     /**
625      * Adds a string to the SST table and returns its index (if its a duplicate
626      * just returns its index and update the counts)
627      *
628      * @param string the string to be added to the SSTRecord
629      * @param use16bits whether to use utf 16 or false for compressed unicode
630      * @return index of the string within the SSTRecord
631      */

632
633     public int addSSTString(String JavaDoc string, boolean use16bits) {
634         if (log.check( POILogger.DEBUG ))
635             log.log(DEBUG, "insert to sst string='", string, "' and use16bits= ",
636         new Boolean JavaDoc(use16bits));
637         if (sst == null) {
638             insertSST();
639         }
640         return sst.addString(string, use16bits);
641     }
642
643     /**
644      * Adds a string to the SST table and returns its index (if its a duplicate
645      * just returns its index and update the counts) ASSUMES compressed unicode
646      * (meaning 8bit)
647      *
648      * @param string the string to be added to the SSTRecord
649      *
650      * @return index of the string within the SSTRecord
651      */

652
653     public int addSSTString(String JavaDoc string) {
654         return addSSTString(string, false);
655     }
656
657     /**
658      * given an index into the SST table, this function returns the corresponding String value
659      * @return String containing the SST String
660      */

661
662     public String JavaDoc getSSTString(int str) {
663         if (sst == null) {
664             insertSST();
665         }
666         String JavaDoc retval = sst.getString(str);
667
668         if (log.check( POILogger.DEBUG ))
669             log.log(DEBUG, "Returning SST for index=", new Integer JavaDoc(str),
670                 " String= ", retval);
671         return retval;
672     }
673
674     /**
675      * use this function to add a Shared String Table to an existing sheet (say
676      * generated by a different java api) without an sst....
677      * @see #createSST()
678      * @see org.apache.poi.hssf.record.SSTRecord
679      */

680
681     public void insertSST() {
682         if (log.check( POILogger.DEBUG ))
683             log.log(DEBUG, "creating new SST via insertSST!");
684         sst = ( SSTRecord ) createSST();
685         records.add(records.size() - 1, createExtendedSST());
686         records.add(records.size() - 2, sst);
687     }
688
689     /**
690      * Serializes all records int the worksheet section into a big byte array. Use
691      * this to write the Workbook out.
692      *
693      * @return byte array containing the HSSF-only portions of the POIFS file.
694      */

695      // GJS: Not used so why keep it.
696
// public byte [] serialize() {
697
// log.log(DEBUG, "Serializing Workbook!");
698
// byte[] retval = null;
699
//
700
//// ArrayList bytes = new ArrayList(records.size());
701
// int arraysize = getSize();
702
// int pos = 0;
703
//
704
// retval = new byte[ arraysize ];
705
// for (int k = 0; k < records.size(); k++) {
706
//
707
// Record record = records.get(k);
708
//// Let's skip RECALCID records, as they are only use for optimization
709
// if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) {
710
// pos += record.serialize(pos, retval); // rec.length;
711
// }
712
// }
713
// log.log(DEBUG, "Exiting serialize workbook");
714
// return retval;
715
// }
716

717     /**
718      * Serializes all records int the worksheet section into a big byte array. Use
719      * this to write the Workbook out.
720      * @param offset of the data to be written
721      * @param data array of bytes to write this to
722      */

723
724     public int serialize( int offset, byte[] data )
725     {
726         if (log.check( POILogger.DEBUG ))
727             log.log( DEBUG, "Serializing Workbook with offsets" );
728
729         int pos = 0;
730
731         SSTRecord sst = null;
732         int sstPos = 0;
733         for ( int k = 0; k < records.size(); k++ )
734         {
735
736             Record record = records.get( k );
737             // Let's skip RECALCID records, as they are only use for optimization
738
if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
739             {
740                 if (record instanceof SSTRecord)
741                 {
742                     sst = (SSTRecord)record;
743                     sstPos = pos;
744                 }
745                 if (record.getSid() == ExtSSTRecord.sid && sst != null)
746                 {
747                     record = sst.createExtSSTRecord(sstPos + offset);
748                 }
749                 pos += record.serialize( pos + offset, data ); // rec.length;
750
}
751         }
752         if (log.check( POILogger.DEBUG ))
753             log.log( DEBUG, "Exiting serialize workbook" );
754         return pos;
755     }
756
757     public int getSize()
758     {
759         int retval = 0;
760
761         SSTRecord sst = null;
762         for ( int k = 0; k < records.size(); k++ )
763         {
764             Record record = records.get( k );
765             // Let's skip RECALCID records, as they are only use for optimization
766
if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
767             {
768                 if (record instanceof SSTRecord)
769                     sst = (SSTRecord)record;
770                 if (record.getSid() == ExtSSTRecord.sid && sst != null)
771                     retval += sst.calcExtSSTRecordSize();
772                 else
773                     retval += record.getRecordSize();
774             }
775         }
776         return retval;
777     }
778
779     /**
780      * creates the BOF record
781      * @see org.apache.poi.hssf.record.BOFRecord
782      * @see org.apache.poi.hssf.record.Record
783      * @return record containing a BOFRecord
784      */

785
786     protected Record createBOF() {
787         BOFRecord retval = new BOFRecord();
788
789         retval.setVersion(( short ) 0x600);
790         retval.setType(( short ) 5);
791         retval.setBuild(( short ) 0x10d3);
792
793         // retval.setBuild((short)0x0dbb);
794
retval.setBuildYear(( short ) 1996);
795         retval.setHistoryBitMask(0x41); // was c1 before verify
796
retval.setRequiredVersion(0x6);
797         return retval;
798     }
799
800     /**
801      * creates the InterfaceHdr record
802      * @see org.apache.poi.hssf.record.InterfaceHdrRecord
803      * @see org.apache.poi.hssf.record.Record
804      * @return record containing a InterfaceHdrRecord
805      */

806
807     protected Record createInterfaceHdr() {
808         InterfaceHdrRecord retval = new InterfaceHdrRecord();
809
810         retval.setCodepage(CODEPAGE);
811         return retval;
812     }
813
814     /**
815      * creates an MMS record
816      * @see org.apache.poi.hssf.record.MMSRecord
817      * @see org.apache.poi.hssf.record.Record
818      * @return record containing a MMSRecord
819      */

820
821     protected Record createMMS() {
822         MMSRecord retval = new MMSRecord();
823
824         retval.setAddMenuCount(( byte ) 0);
825         retval.setDelMenuCount(( byte ) 0);
826         return retval;
827     }
828
829     /**
830      * creates the InterfaceEnd record
831      * @see org.apache.poi.hssf.record.InterfaceEndRecord
832      * @see org.apache.poi.hssf.record.Record
833      * @return record containing a InterfaceEndRecord
834      */

835
836     protected Record createInterfaceEnd() {
837         return new InterfaceEndRecord();
838     }
839
840     /**
841      * creates the WriteAccess record containing the logged in user's name
842      * @see org.apache.poi.hssf.record.WriteAccessRecord
843      * @see org.apache.poi.hssf.record.Record
844      * @return record containing a WriteAccessRecord
845      */

846
847     protected Record createWriteAccess() {
848         WriteAccessRecord retval = new WriteAccessRecord();
849
850         try
851         {
852             retval.setUsername(System.getProperty("user.name"));
853         }
854         catch (java.security.AccessControlException JavaDoc e)
855         {
856                 // AccessControlException can occur in a restricted context
857
// (client applet/jws application or restricted security server)
858
retval.setUsername("POI");
859         }
860         return retval;
861     }
862
863     /**
864      * creates the Codepage record containing the constant stored in CODEPAGE
865      * @see org.apache.poi.hssf.record.CodepageRecord
866      * @see org.apache.poi.hssf.record.Record
867      * @return record containing a CodepageRecord
868      */

869
870     protected Record createCodepage() {
871         CodepageRecord retval = new CodepageRecord();
872
873         retval.setCodepage(CODEPAGE);
874         return retval;
875     }
876
877     /**
878      * creates the DSF record containing a 0 since HSSF can't even create Dual Stream Files
879      * @see org.apache.poi.hssf.record.DSFRecord
880      * @see org.apache.poi.hssf.record.Record
881      * @return record containing a DSFRecord
882      */

883
884     protected Record createDSF() {
885         DSFRecord retval = new DSFRecord();
886
887         retval.setDsf(
888         ( short ) 0); // we don't even support double stream files
889
return retval;
890     }
891
892     /**
893      * creates the TabId record containing an array of 0,1,2. This release of HSSF
894      * always has the default three sheets, no less, no more.
895      * @see org.apache.poi.hssf.record.TabIdRecord
896      * @see org.apache.poi.hssf.record.Record
897      * @return record containing a TabIdRecord
898      */

899
900     protected Record createTabId() {
901         TabIdRecord retval = new TabIdRecord();
902         short[] tabidarray = {
903             0
904         };
905
906         retval.setTabIdArray(tabidarray);
907         return retval;
908     }
909
910     /**
911      * creates the FnGroupCount record containing the Magic number constant of 14.
912      * @see org.apache.poi.hssf.record.FnGroupCountRecord
913      * @see org.apache.poi.hssf.record.Record
914      * @return record containing a FnGroupCountRecord
915      */

916
917     protected Record createFnGroupCount() {
918         FnGroupCountRecord retval = new FnGroupCountRecord();
919
920         retval.setCount(( short ) 14);
921         return retval;
922     }
923
924     /**
925      * creates the WindowProtect record with protect set to false.
926      * @see org.apache.poi.hssf.record.WindowProtectRecord
927      * @see org.apache.poi.hssf.record.Record
928      * @return record containing a WindowProtectRecord
929      */

930
931     protected Record createWindowProtect() {
932         WindowProtectRecord retval = new WindowProtectRecord();
933
934         retval.setProtect(
935         false); // by default even when we support it we won't
936
return retval; // want it to be protected
937
}
938
939     /**
940      * creates the Protect record with protect set to false.
941      * @see org.apache.poi.hssf.record.ProtectRecord
942      * @see org.apache.poi.hssf.record.Record
943      * @return record containing a ProtectRecord
944      */

945
946     protected Record createProtect() {
947         ProtectRecord retval = new ProtectRecord();
948
949         retval.setProtect(
950         false); // by default even when we support it we won't
951
return retval; // want it to be protected
952
}
953
954     /**
955      * creates the Password record with password set to 0.
956      * @see org.apache.poi.hssf.record.PasswordRecord
957      * @see org.apache.poi.hssf.record.Record
958      * @return record containing a PasswordRecord
959      */

960
961     protected Record createPassword() {
962         PasswordRecord retval = new PasswordRecord();
963
964         retval.setPassword(( short ) 0); // no password by default!
965
return retval;
966     }
967
968     /**
969      * creates the ProtectionRev4 record with protect set to false.
970      * @see org.apache.poi.hssf.record.ProtectionRev4Record
971      * @see org.apache.poi.hssf.record.Record
972      * @return record containing a ProtectionRev4Record
973      */

974
975     protected Record createProtectionRev4() {
976         ProtectionRev4Record retval = new ProtectionRev4Record();
977
978         retval.setProtect(false);
979         return retval;
980     }
981
982     /**
983      * creates the PasswordRev4 record with password set to 0.
984      * @see org.apache.poi.hssf.record.PasswordRev4Record
985      * @see org.apache.poi.hssf.record.Record
986      * @return record containing a PasswordRev4Record
987      */

988
989     protected Record createPasswordRev4() {
990         PasswordRev4Record retval = new PasswordRev4Record();
991
992         retval.setPassword(( short ) 0); // no password by default!
993
return retval;
994     }
995
996     /**
997      * creates the WindowOne record with the following magic values: <P>
998      * horizontal hold - 0x168 <P>
999      * vertical hold - 0x10e <P>
1000     * width - 0x3a5c <P>
1001     * height - 0x23be <P>
1002     * options - 0x38 <P>
1003     * selected tab - 0 <P>
1004     * displayed tab - 0 <P>
1005     * num selected tab- 0 <P>
1006     * tab width ratio - 0x258 <P>
1007     * @see org.apache.poi.hssf.record.WindowOneRecord
1008     * @see org.apache.poi.hssf.record.Record
1009     * @return record containing a WindowOneRecord
1010     */

1011
1012    protected Record createWindowOne() {
1013        WindowOneRecord retval = new WindowOneRecord();
1014
1015        retval.setHorizontalHold(( short ) 0x168);
1016        retval.setVerticalHold(( short ) 0x10e);
1017        retval.setWidth(( short ) 0x3a5c);
1018        retval.setHeight(( short ) 0x23be);
1019        retval.setOptions(( short ) 0x38);
1020        retval.setSelectedTab(( short ) 0x0);
1021        retval.setDisplayedTab(( short ) 0x0);
1022        retval.setNumSelectedTabs(( short ) 1);
1023        retval.setTabWidthRatio(( short ) 0x258);
1024        return retval;
1025    }
1026
1027    /**
1028     * creates the Backup record with backup set to 0. (loose the data, who cares)
1029     * @see org.apache.poi.hssf.record.BackupRecord
1030     * @see org.apache.poi.hssf.record.Record
1031     * @return record containing a BackupRecord
1032     */

1033
1034    protected Record createBackup() {
1035        BackupRecord retval = new BackupRecord();
1036
1037        retval.setBackup(
1038        ( short ) 0); // by default DONT save backups of files...just loose data
1039
return retval;
1040    }
1041
1042    /**
1043     * creates the HideObj record with hide object set to 0. (don't hide)
1044     * @see org.apache.poi.hssf.record.HideObjRecord
1045     * @see org.apache.poi.hssf.record.Record
1046     * @return record containing a HideObjRecord
1047     */

1048
1049    protected Record createHideObj() {
1050        HideObjRecord retval = new HideObjRecord();
1051
1052        retval.setHideObj(( short ) 0); // by default set hide object off
1053
return retval;
1054    }
1055
1056    /**
1057     * creates the DateWindow1904 record with windowing set to 0. (don't window)
1058     * @see org.apache.poi.hssf.record.DateWindow1904Record
1059     * @see org.apache.poi.hssf.record.Record
1060     * @return record containing a DateWindow1904Record
1061     */

1062
1063    protected Record createDateWindow1904() {
1064        DateWindow1904Record retval = new DateWindow1904Record();
1065
1066        retval.setWindowing(
1067        ( short ) 0); // don't EVER use 1904 date windowing...tick tock..
1068
return retval;
1069    }
1070
1071    /**
1072     * creates the Precision record with precision set to true. (full precision)
1073     * @see org.apache.poi.hssf.record.PrecisionRecord
1074     * @see org.apache.poi.hssf.record.Record
1075     * @return record containing a PrecisionRecord
1076     */

1077
1078    protected Record createPrecision() {
1079        PrecisionRecord retval = new PrecisionRecord();
1080
1081        retval.setFullPrecision(
1082        true); // always use real numbers in calculations!
1083
return retval;
1084    }
1085
1086    /**
1087     * creates the RefreshAll record with refreshAll set to true. (refresh all calcs)
1088     * @see org.apache.poi.hssf.record.RefreshAllRecord
1089     * @see org.apache.poi.hssf.record.Record
1090     * @return record containing a RefreshAllRecord
1091     */

1092
1093    protected Record createRefreshAll() {
1094        RefreshAllRecord retval = new RefreshAllRecord();
1095
1096        retval.setRefreshAll(false);
1097        return retval;
1098    }
1099
1100    /**
1101     * creates the BookBool record with saveLinkValues set to 0. (don't save link values)
1102     * @see org.apache.poi.hssf.record.BookBoolRecord
1103     * @see org.apache.poi.hssf.record.Record
1104     * @return record containing a BookBoolRecord
1105     */

1106
1107    protected Record createBookBool() {
1108        BookBoolRecord retval = new BookBoolRecord();
1109
1110        retval.setSaveLinkValues(( short ) 0);
1111        return retval;
1112    }
1113
1114    /**
1115     * creates a Font record with the following magic values: <P>
1116     * fontheight = 0xc8<P>
1117     * attributes = 0x0<P>
1118     * color palette index = 0x7fff<P>
1119     * bold weight = 0x190<P>
1120     * Font Name Length = 5 <P>
1121     * Font Name = Arial <P>
1122     *
1123     * @see org.apache.poi.hssf.record.FontRecord
1124     * @see org.apache.poi.hssf.record.Record
1125     * @return record containing a FontRecord
1126     */

1127
1128    protected Record createFont() {
1129        FontRecord retval = new FontRecord();
1130
1131        retval.setFontHeight(( short ) 0xc8);
1132        retval.setAttributes(( short ) 0x0);
1133        retval.setColorPaletteIndex(( short ) 0x7fff);
1134        retval.setBoldWeight(( short ) 0x190);
1135        retval.setFontNameLength(( byte ) 5);
1136        retval.setFontName("Arial");
1137        return retval;
1138    }
1139
1140    /**
1141     * Creates a FormatRecord object
1142     * @param id the number of the format record to create (meaning its position in
1143     * a file as M$ Excel would create it.)
1144     * @return record containing a FormatRecord
1145     * @see org.apache.poi.hssf.record.FormatRecord
1146     * @see org.apache.poi.hssf.record.Record
1147     */

1148
1149    protected Record createFormat(int id) { // we'll need multiple editions for
1150
FormatRecord retval = new FormatRecord(); // the differnt formats
1151

1152        switch (id) {
1153
1154            case 0 :
1155                retval.setIndexCode(( short ) 5);
1156                retval.setFormatStringLength(( byte ) 0x17);
1157                retval.setFormatString("\"$\"#,##0_);\\(\"$\"#,##0\\)");
1158                break;
1159
1160            case 1 :
1161                retval.setIndexCode(( short ) 6);
1162                retval.setFormatStringLength(( byte ) 0x1c);
1163                retval.setFormatString("\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)");
1164                break;
1165
1166            case 2 :
1167                retval.setIndexCode(( short ) 7);
1168                retval.setFormatStringLength(( byte ) 0x1d);
1169                retval.setFormatString("\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)");
1170                break;
1171
1172            case 3 :
1173                retval.setIndexCode(( short ) 8);
1174                retval.setFormatStringLength(( byte ) 0x22);
1175                retval.setFormatString(
1176                "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)");
1177                break;
1178
1179            case 4 :
1180                retval.setIndexCode(( short ) 0x2a);
1181                retval.setFormatStringLength(( byte ) 0x32);
1182                retval.setFormatString(
1183                "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)");
1184                break;
1185
1186            case 5 :
1187                retval.setIndexCode(( short ) 0x29);
1188                retval.setFormatStringLength(( byte ) 0x29);
1189                retval.setFormatString(
1190                "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)");
1191                break;
1192
1193            case 6 :
1194                retval.setIndexCode(( short ) 0x2c);
1195                retval.setFormatStringLength(( byte ) 0x3a);
1196                retval.setFormatString(
1197                "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)");
1198                break;
1199
1200            case 7 :
1201                retval.setIndexCode(( short ) 0x2b);
1202                retval.setFormatStringLength(( byte ) 0x31);
1203                retval.setFormatString(
1204                "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)");
1205                break;
1206        }
1207        return retval;
1208    }
1209
1210    /**
1211     * Creates an ExtendedFormatRecord object
1212     * @param id the number of the extended format record to create (meaning its position in
1213     * a file as MS Excel would create it.)
1214     *
1215     * @return record containing an ExtendedFormatRecord
1216     * @see org.apache.poi.hssf.record.ExtendedFormatRecord
1217     * @see org.apache.poi.hssf.record.Record
1218     */

1219
1220    protected Record createExtendedFormat(int id) { // we'll need multiple editions
1221
ExtendedFormatRecord retval = new ExtendedFormatRecord();
1222
1223        switch (id) {
1224
1225            case 0 :
1226                retval.setFontIndex(( short ) 0);
1227                retval.setFormatIndex(( short ) 0);
1228                retval.setCellOptions(( short ) 0xfffffff5);
1229                retval.setAlignmentOptions(( short ) 0x20);
1230                retval.setIndentionOptions(( short ) 0);
1231                retval.setBorderOptions(( short ) 0);
1232                retval.setPaletteOptions(( short ) 0);
1233                retval.setAdtlPaletteOptions(( short ) 0);
1234                retval.setFillPaletteOptions(( short ) 0x20c0);
1235                break;
1236
1237            case 1 :
1238                retval.setFontIndex(( short ) 1);
1239                retval.setFormatIndex(( short ) 0);
1240                retval.setCellOptions(( short ) 0xfffffff5);
1241                retval.setAlignmentOptions(( short ) 0x20);
1242                retval.setIndentionOptions(( short ) 0xfffff400);
1243                retval.setBorderOptions(( short ) 0);
1244                retval.setPaletteOptions(( short ) 0);
1245                retval.setAdtlPaletteOptions(( short ) 0);
1246                retval.setFillPaletteOptions(( short ) 0x20c0);
1247                break;
1248
1249            case 2 :
1250                retval.setFontIndex(( short ) 1);
1251                retval.setFormatIndex(( short ) 0);
1252                retval.setCellOptions(( short ) 0xfffffff5);
1253                retval.setAlignmentOptions(( short ) 0x20);
1254                retval.setIndentionOptions(( short ) 0xfffff400);
1255                retval.setBorderOptions(( short ) 0);
1256                retval.setPaletteOptions(( short ) 0);
1257                retval.setAdtlPaletteOptions(( short ) 0);
1258                retval.setFillPaletteOptions(( short ) 0x20c0);
1259                break;
1260
1261            case 3 :
1262                retval.setFontIndex(( short ) 2);
1263                retval.setFormatIndex(( short ) 0);
1264                retval.setCellOptions(( short ) 0xfffffff5);
1265                retval.setAlignmentOptions(( short ) 0x20);
1266                retval.setIndentionOptions(( short ) 0xfffff400);
1267                retval.setBorderOptions(( short ) 0);
1268                retval.setPaletteOptions(( short ) 0);
1269                retval.setAdtlPaletteOptions(( short ) 0);
1270                retval.setFillPaletteOptions(( short ) 0x20c0);
1271                break;
1272
1273            case 4 :
1274                retval.setFontIndex(( short ) 2);
1275                retval.setFormatIndex(( short ) 0);
1276                retval.setCellOptions(( short ) 0xfffffff5);
1277                retval.setAlignmentOptions(( short ) 0x20);
1278                retval.setIndentionOptions(( short ) 0xfffff400);
1279                retval.setBorderOptions(( short ) 0);
1280                retval.setPaletteOptions(( short ) 0);
1281                retval.setAdtlPaletteOptions(( short ) 0);
1282                retval.setFillPaletteOptions(( short ) 0x20c0);
1283                break;
1284
1285            case 5 :
1286                retval.setFontIndex(( short ) 0);
1287                retval.setFormatIndex(( short ) 0);
1288                retval.setCellOptions(( short ) 0xfffffff5);
1289                retval.setAlignmentOptions(( short ) 0x20);
1290                retval.setIndentionOptions(( short ) 0xfffff400);
1291                retval.setBorderOptions(( short ) 0);
1292                retval.setPaletteOptions(( short ) 0);
1293                retval.setAdtlPaletteOptions(( short ) 0);
1294                retval.setFillPaletteOptions(( short ) 0x20c0);
1295                break;
1296
1297            case 6 :
1298                retval.setFontIndex(( short ) 0);
1299                retval.setFormatIndex(( short ) 0);
1300                retval.setCellOptions(( short ) 0xfffffff5);
1301                retval.setAlignmentOptions(( short ) 0x20);
1302                retval.setIndentionOptions(( short ) 0xfffff400);
1303                retval.setBorderOptions(( short ) 0);
1304                retval.setPaletteOptions(( short ) 0);
1305                retval.setAdtlPaletteOptions(( short ) 0);
1306                retval.setFillPaletteOptions(( short ) 0x20c0);
1307                break;
1308
1309            case 7 :
1310                retval.setFontIndex(( short ) 0);
1311                retval.setFormatIndex(( short ) 0);
1312                retval.setCellOptions(( short ) 0xfffffff5);
1313                retval.setAlignmentOptions(( short ) 0x20);
1314                retval.setIndentionOptions(( short ) 0xfffff400);
1315                retval.setBorderOptions(( short ) 0);
1316                retval.setPaletteOptions(( short ) 0);
1317                retval.setAdtlPaletteOptions(( short ) 0);
1318                retval.setFillPaletteOptions(( short ) 0x20c0);
1319                break;
1320
1321            case 8 :
1322                retval.setFontIndex(( short ) 0);
1323                retval.setFormatIndex(( short ) 0);
1324                retval.setCellOptions(( short ) 0xfffffff5);
1325                retval.setAlignmentOptions(( short ) 0x20);
1326                retval.setIndentionOptions(( short ) 0xfffff400);
1327                retval.setBorderOptions(( short ) 0);
1328                retval.setPaletteOptions(( short ) 0);
1329                retval.setAdtlPaletteOptions(( short ) 0);
1330                retval.setFillPaletteOptions(( short ) 0x20c0);
1331                break;
1332
1333            case 9 :
1334                retval.setFontIndex(( short ) 0);
1335                retval.setFormatIndex(( short ) 0);
1336                retval.setCellOptions(( short ) 0xfffffff5);
1337                retval.setAlignmentOptions(( short ) 0x20);
1338                retval.setIndentionOptions(( short ) 0xfffff400);
1339                retval.setBorderOptions(( short ) 0);
1340                retval.setPaletteOptions(( short ) 0);
1341                retval.setAdtlPaletteOptions(( short ) 0);
1342                retval.setFillPaletteOptions(( short ) 0x20c0);
1343                break;
1344
1345            case 10 :
1346                retval.setFontIndex(( short ) 0);
1347                retval.setFormatIndex(( short ) 0);
1348                retval.setCellOptions(( short ) 0xfffffff5);
1349                retval.setAlignmentOptions(( short ) 0x20);
1350                retval.setIndentionOptions(( short ) 0xfffff400);
1351                retval.setBorderOptions(( short ) 0);
1352                retval.setPaletteOptions(( short ) 0);
1353                retval.setAdtlPaletteOptions(( short ) 0);
1354                retval.setFillPaletteOptions(( short ) 0x20c0);
1355                break;
1356
1357            case 11 :
1358                retval.setFontIndex(( short ) 0);
1359                retval.setFormatIndex(( short ) 0);
1360                retval.setCellOptions(( short ) 0xfffffff5);
1361                retval.setAlignmentOptions(( short ) 0x20);
1362                retval.setIndentionOptions(( short ) 0xfffff400);
1363                retval.setBorderOptions(( short ) 0);
1364                retval.setPaletteOptions(( short ) 0);
1365                retval.setAdtlPaletteOptions(( short ) 0);
1366                retval.setFillPaletteOptions(( short ) 0x20c0);
1367                break;
1368
1369            case 12 :
1370                retval.setFontIndex(( short ) 0);
1371                retval.setFormatIndex(( short ) 0);
1372                retval.setCellOptions(( short ) 0xfffffff5);
1373                retval.setAlignmentOptions(( short ) 0x20);
1374                retval.setIndentionOptions(( short ) 0xfffff400);
1375                retval.setBorderOptions(( short ) 0);
1376                retval.setPaletteOptions(( short ) 0);
1377                retval.setAdtlPaletteOptions(( short ) 0);
1378                retval.setFillPaletteOptions(( short ) 0x20c0);
1379                break;
1380
1381            case 13 :
1382                retval.setFontIndex(( short ) 0);
1383                retval.setFormatIndex(( short ) 0);
1384                retval.setCellOptions(( short ) 0xfffffff5);
1385                retval.setAlignmentOptions(( short ) 0x20);
1386                retval.setIndentionOptions(( short ) 0xfffff400);
1387                retval.setBorderOptions(( short ) 0);
1388                retval.setPaletteOptions(( short ) 0);
1389                retval.setAdtlPaletteOptions(( short ) 0);
1390                retval.setFillPaletteOptions(( short ) 0x20c0);
1391                break;
1392
1393            case 14 :
1394                retval.setFontIndex(( short ) 0);
1395                retval.setFormatIndex(( short ) 0);
1396                retval.setCellOptions(( short ) 0xfffffff5);
1397                retval.setAlignmentOptions(( short ) 0x20);
1398                retval.setIndentionOptions(( short ) 0xfffff400);
1399                retval.setBorderOptions(( short ) 0);
1400                retval.setPaletteOptions(( short ) 0);
1401                retval.setAdtlPaletteOptions(( short ) 0);
1402                retval.setFillPaletteOptions(( short ) 0x20c0);
1403                break;
1404
1405                // cell records
1406
case 15 :
1407                retval.setFontIndex(( short ) 0);
1408                retval.setFormatIndex(( short ) 0);
1409                retval.setCellOptions(( short ) 0x1);
1410                retval.setAlignmentOptions(( short ) 0x20);
1411                retval.setIndentionOptions(( short ) 0x0);
1412                retval.setBorderOptions(( short ) 0);
1413                retval.setPaletteOptions(( short ) 0);
1414                retval.setAdtlPaletteOptions(( short ) 0);
1415                retval.setFillPaletteOptions(( short ) 0x20c0);
1416                break;
1417
1418                // style
1419
case 16 :
1420                retval.setFontIndex(( short ) 1);
1421                retval.setFormatIndex(( short ) 0x2b);
1422                retval.setCellOptions(( short ) 0xfffffff5);
1423                retval.setAlignmentOptions(( short ) 0x20);
1424                retval.setIndentionOptions(( short ) 0xfffff800);
1425                retval.setBorderOptions(( short ) 0);
1426                retval.setPaletteOptions(( short ) 0);
1427                retval.setAdtlPaletteOptions(( short ) 0);
1428                retval.setFillPaletteOptions(( short ) 0x20c0);
1429                break;
1430
1431            case 17 :
1432                retval.setFontIndex(( short ) 1);
1433                retval.setFormatIndex(( short ) 0x29);
1434                retval.setCellOptions(( short ) 0xfffffff5);
1435                retval.setAlignmentOptions(( short ) 0x20);
1436                retval.setIndentionOptions(( short ) 0xfffff800);
1437                retval.setBorderOptions(( short ) 0);
1438                retval.setPaletteOptions(( short ) 0);
1439                retval.setAdtlPaletteOptions(( short ) 0);
1440                retval.setFillPaletteOptions(( short ) 0x20c0);
1441                break;
1442
1443            case 18 :
1444                retval.setFontIndex(( short ) 1);
1445                retval.setFormatIndex(( short ) 0x2c);
1446                retval.setCellOptions(( short ) 0xfffffff5);
1447                retval.setAlignmentOptions(( short ) 0x20);
1448                retval.setIndentionOptions(( short ) 0xfffff800);
1449                retval.setBorderOptions(( short ) 0);
1450                retval.setPaletteOptions(( short ) 0);
1451                retval.setAdtlPaletteOptions(( short ) 0);
1452                retval.setFillPaletteOptions(( short ) 0x20c0);
1453                break;
1454
1455            case 19 :
1456                retval.setFontIndex(( short ) 1);
1457                retval.setFormatIndex(( short ) 0x2a);
1458                retval.setCellOptions(( short ) 0xfffffff5);
1459                retval.setAlignmentOptions(( short ) 0x20);
1460                retval.setIndentionOptions(( short ) 0xfffff800);
1461                retval.setBorderOptions(( short ) 0);
1462                retval.setPaletteOptions(( short ) 0);
1463                retval.setAdtlPaletteOptions(( short ) 0);
1464                retval.setFillPaletteOptions(( short ) 0x20c0);
1465                break;
1466
1467            case 20 :
1468                retval.setFontIndex(( short ) 1);
1469                retval.setFormatIndex(( short ) 0x9);
1470                retval.setCellOptions(( short ) 0xfffffff5);
1471                retval.setAlignmentOptions(( short ) 0x20);
1472                retval.setIndentionOptions(( short ) 0xfffff800);
1473                retval.setBorderOptions(( short ) 0);
1474                retval.setPaletteOptions(( short ) 0);
1475                retval.setAdtlPaletteOptions(( short ) 0);
1476                retval.setFillPaletteOptions(( short ) 0x20c0);
1477                break;
1478
1479                // unused from this point down
1480
case 21 :
1481                retval.setFontIndex(( short ) 5);
1482                retval.setFormatIndex(( short ) 0x0);
1483                retval.setCellOptions(( short ) 0x1);
1484                retval.setAlignmentOptions(( short ) 0x20);
1485                retval.setIndentionOptions(( short ) 0x800);
1486                retval.setBorderOptions(( short ) 0);
1487                retval.setPaletteOptions(( short ) 0);
1488                retval.setAdtlPaletteOptions(( short ) 0);
1489                retval.setFillPaletteOptions(( short ) 0x20c0);
1490                break;
1491
1492            case 22 :
1493                retval.setFontIndex(( short ) 6);
1494                retval.setFormatIndex(( short ) 0x0);
1495                retval.setCellOptions(( short ) 0x1);
1496                retval.setAlignmentOptions(( short ) 0x20);
1497                retval.setIndentionOptions(( short ) 0x5c00);
1498                retval.setBorderOptions(( short ) 0);
1499                retval.setPaletteOptions(( short ) 0);
1500                retval.setAdtlPaletteOptions(( short ) 0);
1501                retval.setFillPaletteOptions(( short ) 0x20c0);
1502                break;
1503
1504            case 23 :
1505                retval.setFontIndex(( short ) 0);
1506                retval.setFormatIndex(( short ) 0x31);
1507                retval.setCellOptions(( short ) 0x1);
1508                retval.setAlignmentOptions(( short ) 0x20);
1509                retval.setIndentionOptions(( short ) 0x5c00);
1510                retval.setBorderOptions(( short ) 0);
1511                retval.setPaletteOptions(( short ) 0);
1512                retval.setAdtlPaletteOptions(( short ) 0);
1513                retval.setFillPaletteOptions(( short ) 0x20c0);
1514                break;
1515
1516            case 24 :
1517                retval.setFontIndex(( short ) 0);
1518                retval.setFormatIndex(( short ) 0x8);
1519                retval.setCellOptions(( short ) 0x1);
1520                retval.setAlignmentOptions(( short ) 0x20);
1521                retval.setIndentionOptions(( short ) 0x5c00);
1522                retval.setBorderOptions(( short ) 0);
1523                retval.setPaletteOptions(( short ) 0);
1524                retval.setAdtlPaletteOptions(( short ) 0);
1525                retval.setFillPaletteOptions(( short ) 0x20c0);
1526                break;
1527
1528            case 25 :
1529                retval.setFontIndex(( short ) 6);
1530                retval.setFormatIndex(( short ) 0x8);
1531                retval.setCellOptions(( short ) 0x1);
1532                retval.setAlignmentOptions(( short ) 0x20);
1533                retval.setIndentionOptions(( short ) 0x5c00);
1534                retval.setBorderOptions(( short ) 0);
1535                retval.setPaletteOptions(( short ) 0);
1536                retval.setAdtlPaletteOptions(( short ) 0);
1537                retval.setFillPaletteOptions(( short ) 0x20c0);
1538                break;
1539        }
1540        return retval;
1541    }
1542
1543    /**
1544     * creates an default cell type ExtendedFormatRecord object.
1545     * @return ExtendedFormatRecord with intial defaults (cell-type)
1546     */

1547
1548    protected ExtendedFormatRecord createExtendedFormat() {
1549        ExtendedFormatRecord retval = new ExtendedFormatRecord();
1550
1551        retval.setFontIndex(( short ) 0);
1552        retval.setFormatIndex(( short ) 0x0);
1553        retval.setCellOptions(( short ) 0x1);
1554        retval.setAlignmentOptions(( short ) 0x20);
1555        retval.setIndentionOptions(( short ) 0);
1556        retval.setBorderOptions(( short ) 0);
1557        retval.setPaletteOptions(( short ) 0);
1558        retval.setAdtlPaletteOptions(( short ) 0);
1559        retval.setFillPaletteOptions(( short ) 0x20c0);
1560        retval.setTopBorderPaletteIdx(HSSFColor.BLACK.index);
1561        retval.setBottomBorderPaletteIdx(HSSFColor.BLACK.index);
1562        retval.setLeftBorderPaletteIdx(HSSFColor.BLACK.index);
1563        retval.setRightBorderPaletteIdx(HSSFColor.BLACK.index);
1564        return retval;
1565    }
1566
1567    /**
1568     * Creates a StyleRecord object
1569     * @param id the number of the style record to create (meaning its position in
1570     * a file as MS Excel would create it.
1571     * @return record containing a StyleRecord
1572     * @see org.apache.poi.hssf.record.StyleRecord
1573     * @see org.apache.poi.hssf.record.Record
1574     */

1575
1576    protected Record createStyle(int id) { // we'll need multiple editions
1577
StyleRecord retval = new StyleRecord();
1578
1579        switch (id) {
1580
1581            case 0 :
1582                retval.setIndex(( short ) 0xffff8010);
1583                retval.setBuiltin(( byte ) 3);
1584                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1585                break;
1586
1587            case 1 :
1588                retval.setIndex(( short ) 0xffff8011);
1589                retval.setBuiltin(( byte ) 6);
1590                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1591                break;
1592
1593            case 2 :
1594                retval.setIndex(( short ) 0xffff8012);
1595                retval.setBuiltin(( byte ) 4);
1596                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1597                break;
1598
1599            case 3 :
1600                retval.setIndex(( short ) 0xffff8013);
1601                retval.setBuiltin(( byte ) 7);
1602                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1603                break;
1604
1605            case 4 :
1606                retval.setIndex(( short ) 0xffff8000);
1607                retval.setBuiltin(( byte ) 0);
1608                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1609                break;
1610
1611            case 5 :
1612                retval.setIndex(( short ) 0xffff8014);
1613                retval.setBuiltin(( byte ) 5);
1614                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1615                break;
1616        }
1617        return retval;
1618    }
1619
1620    /**
1621     * Creates a palette record initialized to the default palette
1622     * @return a PaletteRecord instance populated with the default colors
1623     * @see org.apache.poi.hssf.record.PaletteRecord
1624     */

1625    protected PaletteRecord createPalette()
1626    {
1627        return new PaletteRecord(PaletteRecord.sid);
1628    }
1629    
1630    /**
1631     * Creates the UseSelFS object with the use natural language flag set to 0 (false)
1632     * @return record containing a UseSelFSRecord
1633     * @see org.apache.poi.hssf.record.UseSelFSRecord
1634     * @see org.apache.poi.hssf.record.Record
1635     */

1636
1637    protected Record createUseSelFS() {
1638        UseSelFSRecord retval = new UseSelFSRecord();
1639
1640        retval.setFlag(( short ) 0);
1641        return retval;
1642    }
1643
1644    /**
1645     * create a "bound sheet" or "bundlesheet" (depending who you ask) record
1646     * Always sets the sheet's bof to 0. You'll need to set that yourself.
1647     * @param id either sheet 0,1 or 2.
1648     * @return record containing a BoundSheetRecord
1649     * @see org.apache.poi.hssf.record.BoundSheetRecord
1650     * @see org.apache.poi.hssf.record.Record
1651     */

1652
1653    protected Record createBoundSheet(int id) { // 1,2,3 sheets
1654
BoundSheetRecord retval = new BoundSheetRecord();
1655
1656        switch (id) {
1657
1658            case 0 :
1659                retval.setPositionOfBof(0x0); // should be set later
1660
retval.setOptionFlags(( short ) 0);
1661                retval.setSheetnameLength(( byte ) 0x6);
1662                retval.setCompressedUnicodeFlag(( byte ) 0);
1663                retval.setSheetname("Sheet1");
1664                break;
1665
1666            case 1 :
1667                retval.setPositionOfBof(0x0); // should be set later
1668
retval.setOptionFlags(( short ) 0);
1669                retval.setSheetnameLength(( byte ) 0x6);
1670                retval.setCompressedUnicodeFlag(( byte ) 0);
1671                retval.setSheetname("Sheet2");
1672                break;
1673
1674            case 2 :
1675                retval.setPositionOfBof(0x0); // should be set later
1676
retval.setOptionFlags(( short ) 0);
1677                retval.setSheetnameLength(( byte ) 0x6);
1678                retval.setCompressedUnicodeFlag(( byte ) 0);
1679                retval.setSheetname("Sheet3");
1680                break;
1681        }
1682        return retval;
1683    }
1684
1685    /**
1686     * Creates the Country record with the default country set to 1
1687     * and current country set to 7 in case of russian locale ("ru_RU") and 1 otherwise
1688     * @return record containing a CountryRecord
1689     * @see org.apache.poi.hssf.record.CountryRecord
1690     * @see org.apache.poi.hssf.record.Record
1691     */

1692
1693    protected Record createCountry() { // what a novel idea, create your own!
1694
CountryRecord retval = new CountryRecord();
1695
1696        retval.setDefaultCountry(( short ) 1);
1697
1698        // from Russia with love ;)
1699
if ( Locale.getDefault().toString().equals( "ru_RU" ) ) {
1700            retval.setCurrentCountry(( short ) 7);
1701        }
1702        else {
1703            retval.setCurrentCountry(( short ) 1);
1704        }
1705
1706        return retval;
1707    }
1708
1709    /**
1710     * Creates the SST record with no strings and the unique/num string set to 0
1711     * @return record containing a SSTRecord
1712     * @see org.apache.poi.hssf.record.SSTRecord
1713     * @see org.apache.poi.hssf.record.Record
1714     */

1715
1716    protected Record createSST() {
1717        return new SSTRecord();
1718    }
1719
1720    /**
1721     * Creates the ExtendedSST record with numstrings per bucket set to 0x8. HSSF
1722     * doesn't yet know what to do with this thing, but we create it with nothing in
1723     * it hardly just to make Excel happy and our sheets look like Excel's
1724     *
1725     * @return record containing an ExtSSTRecord
1726     * @see org.apache.poi.hssf.record.ExtSSTRecord
1727     * @see org.apache.poi.hssf.record.Record
1728     */

1729
1730    protected Record createExtendedSST() {
1731        ExtSSTRecord retval = new ExtSSTRecord();
1732
1733        retval.setNumStringsPerBucket(( short ) 0x8);
1734        return retval;
1735    }
1736
1737    /**
1738     * creates the EOF record
1739     * @see org.apache.poi.hssf.record.EOFRecord
1740     * @see org.apache.poi.hssf.record.Record
1741     * @return record containing a EOFRecord
1742     */

1743
1744    protected Record createEOF() {
1745        return new EOFRecord();
1746    }
1747
1748    public SheetReferences getSheetReferences() {
1749        SheetReferences refs = new SheetReferences();
1750        
1751        if (externSheet != null) {
1752            for (int k = 0; k < externSheet.getNumOfREFStructures(); k++) {
1753                
1754                String JavaDoc sheetName = findSheetNameFromExternSheet((short)k);
1755                refs.addSheetReference(sheetName, k);
1756                
1757            }
1758        }
1759        return refs;
1760    }
1761
1762    /** finds the sheet name by his extern sheet index
1763     * @param num extern sheet index
1764     * @return sheet name
1765     */

1766    public String JavaDoc findSheetNameFromExternSheet(short num){
1767        String JavaDoc result="";
1768
1769        short indexToSheet = externSheet.getREFRecordAt(num).getIndexToFirstSupBook();
1770        if (indexToSheet>-1) { //error check, bail out gracefully!
1771
result = getSheetName(indexToSheet);
1772        }
1773
1774        return result;
1775    }
1776
1777    /**
1778     * Finds the sheet index for a particular external sheet number.
1779     * @param externSheetNumber The external sheet number to convert
1780     * @return The index to the sheet found.
1781     */

1782    public int getSheetIndexFromExternSheetIndex(int externSheetNumber)
1783    {
1784        if (externSheetNumber >= externSheet.getNumOfREFStructures())
1785            return -1;
1786        else
1787            return externSheet.getREFRecordAt(externSheetNumber).getIndexToFirstSupBook();
1788    }
1789
1790    /** returns the extern sheet number for specific sheet number ,
1791     * if this sheet doesn't exist in extern sheet , add it
1792     * @param sheetNumber sheet number
1793     * @return index to extern sheet
1794     */

1795    public short checkExternSheet(int sheetNumber){
1796
1797        int i = 0;
1798        boolean flag = false;
1799        short result = 0;
1800
1801        if (externSheet == null) {
1802            externSheet = createExternSheet();
1803        }
1804
1805        //Trying to find reference to this sheet
1806
while (i < externSheet.getNumOfREFStructures() && !flag){
1807            ExternSheetSubRecord record = externSheet.getREFRecordAt(i);
1808
1809            if (record.getIndexToFirstSupBook() == sheetNumber &&
1810            record.getIndexToLastSupBook() == sheetNumber){
1811                flag = true;
1812                result = (short) i;
1813            }
1814
1815            ++i;
1816        }
1817
1818        //We Havent found reference to this sheet
1819
if (!flag) {
1820            result = addSheetIndexToExternSheet((short) sheetNumber);
1821        }
1822
1823        return result;
1824    }
1825
1826    private short addSheetIndexToExternSheet(short sheetNumber){
1827        short result;
1828
1829        ExternSheetSubRecord record = new ExternSheetSubRecord();
1830        record.setIndexToFirstSupBook(sheetNumber);
1831        record.setIndexToLastSupBook(sheetNumber);
1832        externSheet.addREFRecord(record);
1833        externSheet.setNumOfREFStructures((short)(externSheet.getNumOfREFStructures() + 1));
1834        result = (short)(externSheet.getNumOfREFStructures() - 1);
1835
1836        return result;
1837    }
1838
1839
1840
1841    /** gets the total number of names
1842     * @return number of names
1843     */

1844    public int getNumNames(){
1845        int result = names.size();
1846
1847        return result;
1848    }
1849
1850    /** gets the name record
1851     * @param index name index
1852     * @return name record
1853     */

1854    public NameRecord getNameRecord(int index){
1855        NameRecord result = (NameRecord) names.get(index);
1856
1857        return result;
1858
1859    }
1860
1861    /** creates new name
1862     * @return new name record
1863     */

1864    public NameRecord createName(){
1865
1866        NameRecord name = new NameRecord();
1867
1868        // Not the most efficient way but the other way was causing too many bugs
1869
int idx = findFirstRecordLocBySid(ExternSheetRecord.sid);
1870        if (idx == -1) idx = findFirstRecordLocBySid(SupBookRecord.sid);
1871        if (idx == -1) idx = findFirstRecordLocBySid(CountryRecord.sid);
1872
1873        records.add(idx+names.size()+1, name);
1874        names.add(name);
1875
1876        return name;
1877    }
1878
1879
1880    /** creates new name
1881     * @return new name record
1882     */

1883    public NameRecord addName(NameRecord name)
1884    {
1885        // Not the most efficient way but the other way was causing too many bugs
1886
int idx = findFirstRecordLocBySid(ExternSheetRecord.sid);
1887        if (idx == -1) idx = findFirstRecordLocBySid(SupBookRecord.sid);
1888        if (idx == -1) idx = findFirstRecordLocBySid(CountryRecord.sid);
1889        records.add(idx+names.size()+1, name);
1890        names.add(name);
1891
1892        return name;
1893    }
1894
1895    /**Generates a NameRecord to represent a built-in region
1896     * @return a new NameRecord unless the index is invalid
1897     */

1898    public NameRecord createBuiltInName(byte builtInName, int index)
1899    {
1900        if (index == -1 || index+1 > (int)Short.MAX_VALUE)
1901            throw new IllegalArgumentException JavaDoc("Index is not valid ["+index+"]");
1902        
1903        NameRecord name = new NameRecord(builtInName, (short)(index));
1904                
1905        addName(name);
1906        
1907        return name;
1908    }
1909
1910
1911    /** removes the name
1912     * @param namenum name index
1913     */

1914    public void removeName(int namenum){
1915        if (names.size() > namenum) {
1916            int idx = findFirstRecordLocBySid(NameRecord.sid);
1917            records.remove(idx + namenum);
1918            names.remove(namenum);
1919        }
1920
1921    }
1922
1923    /** creates a new extern sheet record
1924     * @return the new extern sheet record
1925     */

1926    protected ExternSheetRecord createExternSheet(){
1927        ExternSheetRecord externSheet = new ExternSheetRecord();
1928
1929        int idx = findFirstRecordLocBySid(CountryRecord.sid);
1930
1931        records.add(idx+1, externSheet);
1932// records.add(records.supbookpos + 1 , rec);
1933

1934        //We also adds the supBook for internal reference
1935
SupBookRecord supbook = new SupBookRecord();
1936
1937        supbook.setNumberOfSheets((short)getNumSheets());
1938        //supbook.setFlag();
1939

1940        records.add(idx+1, supbook);
1941// records.add(records.supbookpos + 1 , supbook);
1942

1943        return externSheet;
1944    }
1945
1946    /**
1947     * Returns a format index that matches the passed in format. It does not tie into HSSFDataFormat.
1948     * @param format the format string
1949     * @param createIfNotFound creates a new format if format not found
1950     * @return the format id of a format that matches or -1 if none found and createIfNotFound
1951     */

1952    public short getFormat(String JavaDoc format, boolean createIfNotFound) {
1953    Iterator JavaDoc iterator;
1954    for (iterator = formats.iterator(); iterator.hasNext();) {
1955        FormatRecord r = (FormatRecord)iterator.next();
1956        if (r.getFormatString().equals(format)) {
1957        return r.getIndexCode();
1958        }
1959    }
1960
1961    if (createIfNotFound) {
1962        return createFormat(format);
1963    }
1964
1965    return -1;
1966    }
1967
1968    /**
1969     * Returns the list of FormatRecords in the workbook.
1970     * @return ArrayList of FormatRecords in the notebook
1971     */

1972    public ArrayList JavaDoc getFormats() {
1973    return formats;
1974    }
1975
1976    /**
1977     * Creates a FormatRecord, inserts it, and returns the index code.
1978     * @param format the format string
1979     * @return the index code of the format record.
1980     * @see org.apache.poi.hssf.record.FormatRecord
1981     * @see org.apache.poi.hssf.record.Record
1982     */

1983    public short createFormat( String JavaDoc format )
1984    {
1985// ++xfpos; //These are to ensure that positions are updated properly
1986
// ++palettepos;
1987
// ++bspos;
1988
FormatRecord rec = new FormatRecord();
1989        maxformatid = maxformatid >= (short) 0xa4 ? (short) ( maxformatid + 1 ) : (short) 0xa4; //Starting value from M$ empiracle study.
1990
rec.setIndexCode( maxformatid );
1991        rec.setFormatStringLength( (byte) format.length() );
1992        rec.setFormatString( format );
1993
1994        int pos = 0;
1995        while ( pos < records.size() && records.get( pos ).getSid() != FormatRecord.sid )
1996            pos++;
1997        pos += formats.size();
1998        formats.add( rec );
1999        records.add( pos, rec );
2000        return maxformatid;
2001    }
2002
2003
2004    /**
2005     * Returns the first occurance of a record matching a particular sid.
2006     */

2007    public Record findFirstRecordBySid(short sid) {
2008        for (Iterator JavaDoc iterator = records.iterator(); iterator.hasNext(); ) {
2009            Record record = ( Record ) iterator.next();
2010            
2011            if (record.getSid() == sid) {
2012                return record;
2013            }
2014        }
2015        return null;
2016    }
2017
2018    /**
2019     * Returns the index of a record matching a particular sid.
2020     * @param sid The sid of the record to match
2021     * @return The index of -1 if no match made.
2022     */

2023    public int findFirstRecordLocBySid(short sid) {
2024        int index = 0;
2025        for (Iterator JavaDoc iterator = records.iterator(); iterator.hasNext(); ) {
2026            Record record = ( Record ) iterator.next();
2027
2028            if (record.getSid() == sid) {
2029                return index;
2030            }
2031            index ++;
2032        }
2033        return -1;
2034    }
2035
2036    /**
2037     * Returns the next occurance of a record matching a particular sid.
2038     */

2039    public Record findNextRecordBySid(short sid, int pos) {
2040        int matches = 0;
2041        for (Iterator JavaDoc iterator = records.iterator(); iterator.hasNext(); ) {
2042            Record record = ( Record ) iterator.next();
2043
2044            if (record.getSid() == sid) {
2045                if (matches++ == pos)
2046                    return record;
2047            }
2048        }
2049        return null;
2050    }
2051
2052    public List JavaDoc getRecords()
2053    {
2054        return records.getRecords();
2055    }
2056
2057// public void insertChartRecords( List chartRecords )
2058
// {
2059
// backuppos += chartRecords.size();
2060
// fontpos += chartRecords.size();
2061
// palettepos += chartRecords.size();
2062
// bspos += chartRecords.size();
2063
// xfpos += chartRecords.size();
2064
//
2065
// records.addAll(protpos, chartRecords);
2066
// }
2067

2068    /**
2069    * Whether date windowing is based on 1/2/1904 or 1/1/1900.
2070    * Some versions of Excel (Mac) can save workbooks using 1904 date windowing.
2071    *
2072    * @return true if using 1904 date windowing
2073    */

2074    public boolean isUsing1904DateWindowing() {
2075        return uses1904datewindowing;
2076    }
2077    
2078    /**
2079     * Returns the custom palette in use for this workbook; if a custom palette record
2080     * does not exist, then it is created.
2081     */

2082    public PaletteRecord getCustomPalette()
2083    {
2084      PaletteRecord palette;
2085      int palettePos = records.getPalettepos();
2086      if (palettePos != -1) {
2087        Record rec = records.get(palettePos);
2088        if (rec instanceof PaletteRecord) {
2089          palette = (PaletteRecord) rec;
2090        } else throw new RuntimeException JavaDoc("InternalError: Expected PaletteRecord but got a '"+rec+"'");
2091      }
2092      else
2093      {
2094          palette = createPalette();
2095          //Add the palette record after the bof which is always the first record
2096
records.add(1, palette);
2097          records.setPalettepos(1);
2098      }
2099      return palette;
2100    }
2101
2102    /**
2103     * Creates a drawing group record. If it already exists then it's left
2104     * alone.
2105     */

2106    public void createDrawingGroup()
2107    {
2108        int dggLoc = findFirstRecordLocBySid(EscherContainerRecord.DGG_CONTAINER);
2109        if (dggLoc == -1)
2110        {
2111            EscherContainerRecord dggContainer = new EscherContainerRecord();
2112            EscherDggRecord dgg = new EscherDggRecord();
2113            EscherOptRecord opt = new EscherOptRecord();
2114            EscherSplitMenuColorsRecord splitMenuColors = new EscherSplitMenuColorsRecord();
2115
2116            dggContainer.setRecordId((short) 0xF000);
2117            dggContainer.setOptions((short) 0x000F);
2118            dgg.setRecordId(EscherDggRecord.RECORD_ID);
2119            dgg.setOptions((short)0x0000);
2120            dgg.setShapeIdMax(1024);
2121            dgg.setNumShapesSaved(0);
2122            dgg.setDrawingsSaved(0);
2123            dgg.setFileIdClusters(new EscherDggRecord.FileIdCluster[] {} );
2124            drawingManager = new DrawingManager(dgg);
2125            opt.setRecordId((short) 0xF00B);
2126            opt.setOptions((short) 0x0033);
2127            opt.addEscherProperty( new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 524296) );
2128            opt.addEscherProperty( new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 134217737) );
2129            opt.addEscherProperty( new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, 134217792) );
2130            splitMenuColors.setRecordId((short) 0xF11E);
2131            splitMenuColors.setOptions((short) 0x0040);
2132            splitMenuColors.setColor1(0x0800000D);
2133            splitMenuColors.setColor2(0x0800000C);
2134            splitMenuColors.setColor3(0x08000017);
2135            splitMenuColors.setColor4(0x100000F7);
2136
2137            dggContainer.addChildRecord(dgg);
2138            dggContainer.addChildRecord(opt);
2139            dggContainer.addChildRecord(splitMenuColors);
2140
2141            DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
2142            drawingGroup.addEscherRecord(dggContainer);
2143            int loc = findFirstRecordLocBySid(CountryRecord.sid);
2144            getRecords().add(loc+1, drawingGroup);
2145        }
2146    }
2147
2148    public DrawingManager getDrawingManager()
2149    {
2150        return drawingManager;
2151    }
2152
2153}
2154
2155
Popular Tags