1    
2    /* ====================================================================
3     * The Apache Software License, Version 1.1
4     *
5     * Copyright (c) 2002 The Apache Software Foundation.  All rights
6     * reserved.
7     *
8     * Redistribution and use in source and binary forms, with or without
9     * modification, are permitted provided that the following conditions
10    * are met:
11    *
12    * 1. Redistributions of source code must retain the above copyright
13    *    notice, this list of conditions and the following disclaimer.
14    *
15    * 2. Redistributions in binary form must reproduce the above copyright
16    *    notice, this list of conditions and the following disclaimer in
17    *    the documentation and/or other materials provided with the
18    *    distribution.
19    *
20    * 3. The end-user documentation included with the redistribution,
21    *    if any, must include the following acknowledgment:
22    *       "This product includes software developed by the
23    *        Apache Software Foundation (http://www.apache.org/)."
24    *    Alternately, this acknowledgment may appear in the software itself,
25    *    if and wherever such third-party acknowledgments normally appear.
26    *
27    * 4. The names "Apache" and "Apache Software Foundation" and
28    *    "Apache POI" must not be used to endorse or promote products
29    *    derived from this software without prior written permission. For
30    *    written permission, please contact apache@apache.org.
31    *
32    * 5. Products derived from this software may not be called "Apache",
33    *    "Apache POI", nor may "Apache" appear in their name, without
34    *    prior written permission of the Apache Software Foundation.
35    *
36    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47    * SUCH DAMAGE.
48    * ====================================================================
49    *
50    * This software consists of voluntary contributions made by many
51    * individuals on behalf of the Apache Software Foundation.  For more
52    * information on the Apache Software Foundation, please see
53    * <http://www.apache.org/>.
54    */
55   
56   package org.apache.poi.hssf.model;
57   
58   import java.io.*;
59   
60   import java.util.ArrayList;
61   import java.util.List;
62   import java.util.Iterator;
63   
64   import org.apache.poi.hssf.record.*;
65   import org.apache.poi.util.POILogger;
66   import org.apache.poi.util.POILogFactory;
67   
68   /**
69    * Workbook
70    * Low level model implementation of a Workbook.  Provides creational methods
71    * for settings and objects contained in the workbook object.
72    * <P>
73    * This file contains the low level binary records starting at the workbook's BOF and
74    * ending with the workbook's EOF.  Use HSSFWorkbook for a high level representation.
75    * <P>
76    * The structures of the highlevel API use references to this to perform most of their
77    * operations.  Its probably unwise to use these low level structures directly unless you
78    * really know what you're doing.  I recommend you read the Microsoft Excel 97 Developer's
79    * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf
80    * before even attempting to use this.
81    *
82    * @author  Andrew C. Oliver (acoliver at apache dot org)
83    * @author  Glen Stampoultzis (glens at apache.org)
84    * @see org.apache.poi.hssf.usermodel.HSSFWorkbook
85    * @version 1.0-pre
86    */
87   
88   public class Workbook {
89       private static final int   DEBUG       = POILogger.DEBUG;
90       
91       /**
92        * constant used to set the "codepage" wherever "codepage" is set in records
93        * (which is duplciated in more than one record)
94        */
95       
96       private final static short CODEPAGE    = ( short ) 0x4b0;
97       
98       /**
99        * this contains the Worksheet record objects
100       */
101      
102      protected ArrayList        records     = null;
103      
104      /**
105       * this contains a reference to the SSTRecord so that new stings can be added
106       * to it.
107       */
108      
109      protected SSTRecord        sst         = null;
110      
111      /**
112       * Holds the Extern Sheet with referenced to bound sheets
113       */
114      
115      protected ExternSheetRecord externSheet= null;
116      
117      /**
118       * holds the "boundsheet" records (aka bundlesheet) so that they can have their
119       * reference to their "BOF" marker
120       */
121      
122      
123      protected ArrayList        boundsheets = new ArrayList();
124      
125      protected ArrayList        names = new ArrayList();
126      
127      protected int              bspos       =
128      0;   // holds the position of the last bound sheet.
129      protected int              tabpos      =
130      0;   // holds the position of the tabid record
131      protected int              fontpos     =
132      0;   // hold the position of the last font record
133      protected int              numfonts    =
134      0;   // hold the number of font records
135      protected int              xfpos       =
136      0;   // hold the position of the last extended font record
137      protected int              numxfs      =
138      0;   // hold the number of extended format records
139      private int                backuppos   =
140      0;   // holds the position of the backup record.
141      private int                namepos   =
142      0;   // holds the position of last name record
143      private int                supbookpos   =
144      0;   // holds the position of sup book
145      
146      private static POILogger   log         =
147      POILogFactory.getLogger(Workbook.class);
148      
149      /**
150       * Creates new Workbook with no intitialization --useless right now
151       * @see #createWorkbook(List)
152       */
153      
154      public Workbook() {
155      }
156      
157      /**
158       * read support  for low level
159       * API.  Pass in an array of Record objects, A Workbook
160       * object is constructed and passed back with all of its initialization set
161       * to the passed in records and references to those records held. Unlike Sheet
162       * workbook does not use an offset (its assumed to be 0) since its first in a file.
163       * If you need an offset then construct a new array with a 0 offset or write your
164       * own ;-p.
165       *
166       * @param recs an array of Record objects
167       * @return Workbook object
168       */
169      
170      public static Workbook createWorkbook(List recs) {
171          log.log(DEBUG, "Workbook (readfile) created with reclen=",
172          new Integer(recs.size()));
173          Workbook  retval  = new Workbook();
174          ArrayList records = new ArrayList(recs.size() / 3);
175          
176          for (int k = 0; k < recs.size(); k++) {
177              Record rec = ( Record ) recs.get(k);
178              
179              if (rec.getSid() == EOFRecord.sid) {
180                  records.add(rec);
181                  log.log(DEBUG, "found workbook eof record at " + k);
182                  break;
183              }
184              switch (rec.getSid()) {
185                  
186                  case BoundSheetRecord.sid :
187                      log.log(DEBUG, "found boundsheet record at " + k);
188                      retval.boundsheets.add(rec);
189                      retval.bspos = k;
190                      break;
191                      
192                  case SSTRecord.sid :
193                      log.log(DEBUG, "found sst record at " + k);
194                      retval.sst = ( SSTRecord ) rec;
195                      break;
196                      
197                  case FontRecord.sid :
198                      log.log(DEBUG, "found font record at " + k);
199                      retval.fontpos = k;
200                      retval.numfonts++;
201                      break;
202                      
203                  case ExtendedFormatRecord.sid :
204                      log.log(DEBUG, "found XF record at " + k);
205                      retval.xfpos = k;
206                      retval.numxfs++;
207                      break;
208                      
209                  case TabIdRecord.sid :
210                      log.log(DEBUG, "found tabid record at " + k);
211                      retval.tabpos = k;
212                      break;
213                      
214                  case BackupRecord.sid :
215                      log.log(DEBUG, "found backup record at " + k);
216                      retval.backuppos = k;
217                      break;
218                  case ExternSheetRecord.sid :
219                      log.log(DEBUG, "found extern sheet record at " + k);
220                      retval.externSheet = ( ExternSheetRecord ) rec;
221                      break;
222                  case NameRecord.sid :
223                      log.log(DEBUG, "found name record at " + k);
224                      retval.names.add(rec);
225                      retval.namepos = k;
226                      break;
227                  case 0x1AE :
228                      //Havent Implement the sup book , because we dont need extern ranges
229                      //for now
230                      log.log(DEBUG, "found SupBook record at " + k);
231                      retval.supbookpos = k;
232                      break;
233                      
234                  default :
235              }
236              records.add(rec);
237          }
238          //What if we dont have any ranges and supbooks
239          if (retval.supbookpos == 0) {
240              retval.supbookpos = retval.bspos + 1;
241              retval.namepos    = retval.supbookpos + 1;
242          }
243          
244          retval.records = records;
245          log.log(DEBUG, "exit create workbook from existing file function");
246          return retval;
247      }
248      
249      /**
250       * Creates an empty workbook object with three blank sheets and all the empty
251       * fields.  Use this to create a workbook from scratch.
252       */
253      
254      public static Workbook createWorkbook() {
255          log.log(DEBUG, "creating new workbook from scratch");
256          Workbook  retval  = new Workbook();
257          ArrayList records = new ArrayList(30);
258          
259          records.add(retval.createBOF());
260          records.add(retval.createInterfaceHdr());
261          records.add(retval.createMMS());
262          records.add(retval.createInterfaceEnd());
263          records.add(retval.createWriteAccess());
264          records.add(retval.createCodepage());
265          records.add(retval.createDSF());
266          records.add(retval.createTabId());
267          retval.tabpos = records.size() - 1;
268          records.add(retval.createFnGroupCount());
269          records.add(retval.createWindowProtect());
270          records.add(retval.createProtect());
271          records.add(retval.createPassword());
272          records.add(retval.createProtectionRev4());
273          records.add(retval.createPasswordRev4());
274          records.add(retval.createWindowOne());
275          records.add(retval.createBackup());
276          retval.backuppos = records.size() - 1;
277          records.add(retval.createHideObj());
278          records.add(retval.createDateWindow1904());
279          records.add(retval.createPrecision());
280          records.add(retval.createRefreshAll());
281          records.add(retval.createBookBool());
282          records.add(retval.createFont());
283          records.add(retval.createFont());
284          records.add(retval.createFont());
285          records.add(retval.createFont());
286          retval.fontpos  = records.size() - 1;   // last font record postion
287          retval.numfonts = 4;
288          records.add(retval.createFormat(0));
289          records.add(retval.createFormat(1));
290          records.add(retval.createFormat(2));
291          records.add(retval.createFormat(3));
292          records.add(retval.createFormat(4));
293          records.add(retval.createFormat(5));
294          records.add(retval.createFormat(6));
295          records.add(retval.createFormat(7));
296          for (int k = 0; k < 21; k++) {
297              records.add(retval.createExtendedFormat(k));
298              retval.numxfs++;
299          }
300          retval.xfpos = records.size() - 1;
301          for (int k = 0; k < 6; k++) {
302              records.add(retval.createStyle(k));
303          }
304          records.add(retval.createUseSelFS());
305          for (int k = 0; k < 1; k++) {   // now just do 1
306              BoundSheetRecord bsr =
307              ( BoundSheetRecord ) retval.createBoundSheet(k);
308              
309              records.add(bsr);
310              retval.boundsheets.add(bsr);
311              retval.bspos = records.size() - 1;
312          }
313          records.add(retval.createCountry());
314          retval.sst = ( SSTRecord ) retval.createSST();
315          records.add(retval.sst);
316          records.add(retval.createExtendedSST());
317          
318          // TODO
319          records.add(retval.createEOF());
320          retval.records = records;
321          log.log(DEBUG, "exit create new workbook from scratch");
322          return retval;
323      }
324      
325      public int getNumRecords() {
326          return records.size();
327      }
328      
329      /**
330       * gets the font record at the given index in the font table.  Remember
331       * "There is No Four" (someone at M$ must have gone to Rocky Horror one too
332       * many times)
333       *
334       * @param idx the index to look at (0 or greater but NOT 4)
335       * @return FontRecord located at the given index
336       */
337      
338      public FontRecord getFontRecordAt(int idx) {
339          int index = idx;
340          
341          if (index > 4) {
342              index -= 1;   // adjust for "There is no 4"
343          }
344          if (index > (numfonts - 1)) {
345              throw new ArrayIndexOutOfBoundsException(
346              "There are only " + numfonts
347              + " font records, you asked for " + idx);
348          }
349          FontRecord retval =
350          ( FontRecord ) records.get((fontpos - (numfonts - 1)) + index);
351          
352          return retval;
353      }
354      
355      /**
356       * creates a new font record and adds it to the "font table".  This causes the
357       * boundsheets to move down one, extended formats to move down (so this function moves
358       * those pointers as well)
359       *
360       * @return FontRecord that was just created
361       */
362      
363      public FontRecord createNewFont() {
364          FontRecord rec = ( FontRecord ) createFont();
365          
366          ++fontpos;
367          ++bspos;
368          ++xfpos;
369          records.add(fontpos, rec);
370          numfonts++;
371          return rec;
372      }
373      
374      /**
375       * gets the number of font records
376       *
377       * @return   number of font records in the "font table"
378       */
379      
380      public int getNumberOfFontRecords() {
381          return numfonts;
382      }
383      
384      /**
385       * Sets the BOF for a given sheet
386       *
387       * @param sheetnum the number of the sheet to set the positing of the bof for
388       * @param pos the actual bof position
389       */
390      
391      public void setSheetBof(int sheetnum, int pos) {
392          log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetnum),
393          " at pos=", new Integer(pos));
394          checkSheets(sheetnum);
395          (( BoundSheetRecord ) boundsheets.get(sheetnum))
396          .setPositionOfBof(pos);
397      }
398      
399      /**
400       * Returns the position of the backup record.
401       */
402      
403      public BackupRecord getBackupRecord() {
404          return ( BackupRecord ) records.get(backuppos);
405      }
406      
407      /**
408       * sets the name for a given sheet.  If the boundsheet record doesn't exist and
409       * its only one more than we have, go ahead and create it.  If its > 1 more than
410       * we have, except
411       *
412       * @param sheetnum the sheet number (0 based)
413       * @param sheetname the name for the sheet
414       */
415      
416      public void setSheetName(int sheetnum, String sheetname) {
417          checkSheets(sheetnum);
418          (( BoundSheetRecord ) boundsheets.get(sheetnum))
419          .setSheetname(sheetname);
420          (( BoundSheetRecord ) boundsheets.get(sheetnum))
421          .setSheetnameLength(( byte ) sheetname.length());
422      }
423      
424      /**
425       * gets the name for a given sheet.
426       *
427       * @param sheetnum the sheet number (0 based)
428       * @return sheetname the name for the sheet
429       */
430      
431      public String getSheetName(int sheetnum) {
432          return (( BoundSheetRecord ) boundsheets.get(sheetnum))
433          .getSheetname();
434      }
435      
436      /**
437       * get the sheet's index
438       * @param name  sheet name
439       * @return sheet index or -1 if it was not found.
440       */
441      
442      public int getSheetIndex(String name) {
443          int retval = -1;
444          
445          for (int k = 0; k < boundsheets.size(); k++) {
446              String sheet = getSheetName(k);
447              
448              if (sheet.equals(name)) {
449                  retval = k;
450                  break;
451              }
452          }
453          return retval;
454      }
455      
456      /**
457       * if we're trying to address one more sheet than we have, go ahead and add it!  if we're
458       * trying to address >1 more than we have throw an exception!
459       */
460      
461      private void checkSheets(int sheetnum) {
462          if ((boundsheets.size()) <= sheetnum) {   // if we're short one add another..
463              if ((boundsheets.size() + 1) <= sheetnum) {
464                  throw new RuntimeException("Sheet number out of bounds!");
465              }
466              BoundSheetRecord bsr =
467              ( BoundSheetRecord ) createBoundSheet(sheetnum);
468              
469              records.add(++bspos, bsr);
470              boundsheets.add(bsr);
471              fixTabIdRecord();
472          }
473      }
474      
475      public void removeSheet(int sheetnum) {
476          if (boundsheets.size() > sheetnum) {
477              records.remove(bspos - (boundsheets.size() - 1) + sheetnum);
478              bspos--;
479              boundsheets.remove(sheetnum);
480              fixTabIdRecord();
481          }
482      }
483      
484      /**
485       * make the tabid record look like the current situation.
486       *
487       */
488      
489      private void fixTabIdRecord() {
490          TabIdRecord tir = ( TabIdRecord ) records.get(tabpos);
491          short[]     tia = new short[ boundsheets.size() ];
492          
493          for (short k = 0; k < tia.length; k++) {
494              tia[ k ] = k;
495          }
496          tir.setTabIdArray(tia);
497      }
498      
499      /**
500       * returns the number of boundsheet objects contained in this workbook.
501       *
502       * @return number of BoundSheet records
503       */
504      
505      public int getNumSheets() {
506          log.log(DEBUG, "getNumSheets=", new Integer(boundsheets.size()));
507          return boundsheets.size();
508      }
509      
510      /**
511       * get the number of ExtendedFormat records contained in this workbook.
512       *
513       * @return int count of ExtendedFormat records
514       */
515      
516      public int getNumExFormats() {
517          log.log(DEBUG, "getXF=", new Integer(boundsheets.size()));
518          return numxfs;
519      }
520      
521      /**
522       * gets the ExtendedFormatRecord at the given 0-based index
523       *
524       * @param index of the Extended format record (0-based)
525       * @return ExtendedFormatRecord at the given index
526       */
527      
528      public ExtendedFormatRecord getExFormatAt(int index) {
529          int xfptr = xfpos - (numxfs - 1);
530          
531          xfptr += index;
532          ExtendedFormatRecord retval =
533          ( ExtendedFormatRecord ) records.get(xfptr);
534          
535          return retval;
536      }
537      
538      /**
539       * creates a new Cell-type Extneded Format Record and adds it to the end of
540       *  ExtendedFormatRecords collection
541       *
542       * @return ExtendedFormatRecord that was created
543       */
544      
545      public ExtendedFormatRecord createCellXF() {
546          ExtendedFormatRecord xf = createExtendedFormat();
547          
548          ++xfpos;
549          ++bspos;
550          records.add(xfpos, xf);
551          numxfs++;
552          return xf;
553      }
554      
555      /**
556       * Adds a string to the SST table and returns its index (if its a duplicate
557       * just returns its index and update the counts)
558       *
559       * @param string the string to be added to the SSTRecord
560       * @param use16bits whether to use utf 16 or false for compressed unicode
561       * @return index of the string within the SSTRecord
562       */
563      
564      public int addSSTString(String string, boolean use16bits) {
565          log.log(DEBUG, "insert to sst string='", string, "' and use16bits= ",
566          new Boolean(use16bits));
567          if (sst == null) {
568              insertSST();
569          }
570          return sst.addString(string, use16bits);
571      }
572      
573      /**
574       * Adds a string to the SST table and returns its index (if its a duplicate
575       * just returns its index and update the counts) ASSUMES compressed unicode
576       * (meaning 8bit)
577       *
578       * @param string the string to be added to the SSTRecord
579       *
580       * @return index of the string within the SSTRecord
581       */
582      
583      public int addSSTString(String string) {
584          return addSSTString(string, false);
585      }
586      
587      /**
588       * given an index into the SST table, this function returns the corresponding String value
589       * @return String containing the SST String
590       */
591      
592      public String getSSTString(int str) {
593          if (sst == null) {
594              insertSST();
595          }
596          String retval = sst.getString(str);
597          
598          log.log(DEBUG, "Returning SST for index=", new Integer(str),
599          " String= ", retval);
600          return retval;
601      }
602      
603      /**
604       * use this function to add a Shared String Table to an existing sheet (say
605       * generated by a different java api) without an sst....
606       * @see #createSST()
607       * @see org.apache.poi.hssf.record.SSTRecord
608       */
609      
610      public void insertSST() {
611          log.log(DEBUG, "creating new SST via insertSST!");
612          sst = ( SSTRecord ) createSST();
613          records.add(records.size() - 1, createExtendedSST());
614          records.add(records.size() - 2, sst);
615      }
616      
617      /**
618       * Serializes all records int the worksheet section into a big byte array. Use
619       * this to write the Workbook out.
620       *
621       * @return byte array containing the HSSF-only portions of the POIFS file.
622       */
623      
624      public byte [] serialize() {
625          log.log(DEBUG, "Serializing Workbook!");
626          byte[] retval    = null;
627          
628          // ArrayList bytes     = new ArrayList(records.size());
629          int    arraysize = getSize();
630          int    pos       = 0;
631          
632          // for (int k = 0; k < records.size(); k++)
633          // {
634          // bytes.add((( Record ) records.get(k)).serialize());
635          //        }
636          // for (int k = 0; k < bytes.size(); k++)
637          // {
638          // arraysize += (( byte [] ) bytes.get(k)).length;
639          // }
640          retval = new byte[ arraysize ];
641          for (int k = 0; k < records.size(); k++) {
642              
643              // byte[] rec = (( byte [] ) bytes.get(k));
644              // System.arraycopy(rec, 0, retval, pos, rec.length);
645              pos += (( Record ) records.get(k)).serialize(pos,
646              retval);   // rec.length;
647          }
648          log.log(DEBUG, "Exiting serialize workbook");
649          return retval;
650      }
651      
652      /**
653       * Serializes all records int the worksheet section into a big byte array. Use
654       * this to write the Workbook out.
655       * @param offset of the data to be written
656       * @param data array of bytes to write this to
657       */
658      
659      public int serialize(int offset, byte [] data) {
660          log.log(DEBUG, "Serializing Workbook with offsets");
661          
662          // ArrayList bytes     = new ArrayList(records.size());
663          //        int arraysize = getSize();   // 0;
664          int pos       = 0;
665          
666          //        for (int k = 0; k < records.size(); k++)
667          //        {
668          //            bytes.add((( Record ) records.get(k)).serialize());
669          //
670          //        }
671          //        for (int k = 0; k < bytes.size(); k++)
672          //       {
673          //            arraysize += (( byte [] ) bytes.get(k)).length;
674          //        }
675          for (int k = 0; k < records.size(); k++) {
676              
677              // byte[] rec = (( byte [] ) bytes.get(k));
678              // System.arraycopy(rec, 0, data, offset + pos, rec.length);
679              pos += (( Record ) records.get(k)).serialize(pos + offset,
680              data);   // rec.length;
681          }
682          log.log(DEBUG, "Exiting serialize workbook");
683          return pos;
684      }
685      
686      public int getSize() {
687          int retval = 0;
688          
689          for (int k = 0; k < records.size(); k++) {
690              retval += (( Record ) records.get(k)).getRecordSize();
691          }
692          return retval;
693      }
694      
695      /**
696       * creates the BOF record
697       * @see org.apache.poi.hssf.record.BOFRecord
698       * @see org.apache.poi.hssf.record.Record
699       * @return record containing a BOFRecord
700       */
701      
702      protected Record createBOF() {
703          BOFRecord retval = new BOFRecord();
704          
705          retval.setVersion(( short ) 0x600);
706          retval.setType(( short ) 5);
707          retval.setBuild(( short ) 0x10d3);
708          
709          //        retval.setBuild((short)0x0dbb);
710          retval.setBuildYear(( short ) 1996);
711          retval.setHistoryBitMask(0x41);   // was c1 before verify
712          retval.setRequiredVersion(0x6);
713          return retval;
714      }
715      
716      /**
717       * creates the InterfaceHdr record
718       * @see org.apache.poi.hssf.record.InterfaceHdrRecord
719       * @see org.apache.poi.hssf.record.Record
720       * @return record containing a InterfaceHdrRecord
721       */
722      
723      protected Record createInterfaceHdr() {
724          InterfaceHdrRecord retval = new InterfaceHdrRecord();
725          
726          retval.setCodepage(CODEPAGE);
727          return retval;
728      }
729      
730      /**
731       * creates an MMS record
732       * @see org.apache.poi.hssf.record.MMSRecord
733       * @see org.apache.poi.hssf.record.Record
734       * @return record containing a MMSRecord
735       */
736      
737      protected Record createMMS() {
738          MMSRecord retval = new MMSRecord();
739          
740          retval.setAddMenuCount(( byte ) 0);
741          retval.setDelMenuCount(( byte ) 0);
742          return retval;
743      }
744      
745      /**
746       * creates the InterfaceEnd record
747       * @see org.apache.poi.hssf.record.InterfaceEndRecord
748       * @see org.apache.poi.hssf.record.Record
749       * @return record containing a InterfaceEndRecord
750       */
751      
752      protected Record createInterfaceEnd() {
753          return new InterfaceEndRecord();
754      }
755      
756      /**
757       * creates the WriteAccess record containing the logged in user's name
758       * @see org.apache.poi.hssf.record.WriteAccessRecord
759       * @see org.apache.poi.hssf.record.Record
760       * @return record containing a WriteAccessRecord
761       */
762      
763      protected Record createWriteAccess() {
764          WriteAccessRecord retval = new WriteAccessRecord();
765          
766          retval.setUsername(System.getProperty("user.name"));
767          return retval;
768      }
769      
770      /**
771       * creates the Codepage record containing the constant stored in CODEPAGE
772       * @see org.apache.poi.hssf.record.CodepageRecord
773       * @see org.apache.poi.hssf.record.Record
774       * @return record containing a CodepageRecord
775       */
776      
777      protected Record createCodepage() {
778          CodepageRecord retval = new CodepageRecord();
779          
780          retval.setCodepage(CODEPAGE);
781          return retval;
782      }
783      
784      /**
785       * creates the DSF record containing a 0 since HSSF can't even create Dual Stream Files
786       * @see org.apache.poi.hssf.record.DSFRecord
787       * @see org.apache.poi.hssf.record.Record
788       * @return record containing a DSFRecord
789       */
790      
791      protected Record createDSF() {
792          DSFRecord retval = new DSFRecord();
793          
794          retval.setDsf(
795          ( short ) 0);   // we don't even support double stream files
796          return retval;
797      }
798      
799      /**
800       * creates the TabId record containing an array of 0,1,2.  This release of HSSF
801       * always has the default three sheets, no less, no more.
802       * @see org.apache.poi.hssf.record.TabIdRecord
803       * @see org.apache.poi.hssf.record.Record
804       * @return record containing a TabIdRecord
805       */
806      
807      protected Record createTabId() {
808          TabIdRecord retval     = new TabIdRecord();
809          short[]     tabidarray = {
810              0
811          };
812          
813          retval.setTabIdArray(tabidarray);
814          return retval;
815      }
816      
817      /**
818       * creates the FnGroupCount record containing the Magic number constant of 14.
819       * @see org.apache.poi.hssf.record.FnGroupCountRecord
820       * @see org.apache.poi.hssf.record.Record
821       * @return record containing a FnGroupCountRecord
822       */
823      
824      protected Record createFnGroupCount() {
825          FnGroupCountRecord retval = new FnGroupCountRecord();
826          
827          retval.setCount(( short ) 14);
828          return retval;
829      }
830      
831      /**
832       * creates the WindowProtect record with protect set to false.
833       * @see org.apache.poi.hssf.record.WindowProtectRecord
834       * @see org.apache.poi.hssf.record.Record
835       * @return record containing a WindowProtectRecord
836       */
837      
838      protected Record createWindowProtect() {
839          WindowProtectRecord retval = new WindowProtectRecord();
840          
841          retval.setProtect(
842          false);   // by default even when we support it we won't
843          return retval;   // want it to be protected
844      }
845      
846      /**
847       * creates the Protect record with protect set to false.
848       * @see org.apache.poi.hssf.record.ProtectRecord
849       * @see org.apache.poi.hssf.record.Record
850       * @return record containing a ProtectRecord
851       */
852      
853      protected Record createProtect() {
854          ProtectRecord retval = new ProtectRecord();
855          
856          retval.setProtect(
857          false);   // by default even when we support it we won't
858          return retval;   // want it to be protected
859      }
860      
861      /**
862       * creates the Password record with password set to 0.
863       * @see org.apache.poi.hssf.record.PasswordRecord
864       * @see org.apache.poi.hssf.record.Record
865       * @return record containing a PasswordRecord
866       */
867      
868      protected Record createPassword() {
869          PasswordRecord retval = new PasswordRecord();
870          
871          retval.setPassword(( short ) 0);   // no password by default!
872          return retval;
873      }
874      
875      /**
876       * creates the ProtectionRev4 record with protect set to false.
877       * @see org.apache.poi.hssf.record.ProtectionRev4Record
878       * @see org.apache.poi.hssf.record.Record
879       * @return record containing a ProtectionRev4Record
880       */
881      
882      protected Record createProtectionRev4() {
883          ProtectionRev4Record retval = new ProtectionRev4Record();
884          
885          retval.setProtect(false);
886          return retval;
887      }
888      
889      /**
890       * creates the PasswordRev4 record with password set to 0.
891       * @see org.apache.poi.hssf.record.PasswordRev4Record
892       * @see org.apache.poi.hssf.record.Record
893       * @return record containing a PasswordRev4Record
894       */
895      
896      protected Record createPasswordRev4() {
897          PasswordRev4Record retval = new PasswordRev4Record();
898          
899          retval.setPassword(( short ) 0);   // no password by default!
900          return retval;
901      }
902      
903      /**
904       * creates the WindowOne record with the following magic values: <P>
905       * horizontal hold - 0x168 <P>
906       * vertical hold   - 0x10e <P>
907       * width           - 0x3a5c <P>
908       * height          - 0x23be <P>
909       * options         - 0x38 <P>
910       * selected tab    - 0 <P>
911       * displayed tab   - 0 <P>
912       * num selected tab- 0 <P>
913       * tab width ratio - 0x258 <P>
914       * @see org.apache.poi.hssf.record.WindowOneRecord
915       * @see org.apache.poi.hssf.record.Record
916       * @return record containing a WindowOneRecord
917       */
918      
919      protected Record createWindowOne() {
920          WindowOneRecord retval = new WindowOneRecord();
921          
922          retval.setHorizontalHold(( short ) 0x168);
923          retval.setVerticalHold(( short ) 0x10e);
924          retval.setWidth(( short ) 0x3a5c);
925          retval.setHeight(( short ) 0x23be);
926          retval.setOptions(( short ) 0x38);
927          retval.setSelectedTab(( short ) 0x0);
928          retval.setDisplayedTab(( short ) 0x0);
929          retval.setNumSelectedTabs(( short ) 1);
930          retval.setTabWidthRatio(( short ) 0x258);
931          return retval;
932      }
933      
934      /**
935       * creates the Backup record with backup set to 0. (loose the data, who cares)
936       * @see org.apache.poi.hssf.record.BackupRecord
937       * @see org.apache.poi.hssf.record.Record
938       * @return record containing a BackupRecord
939       */
940      
941      protected Record createBackup() {
942          BackupRecord retval = new BackupRecord();
943          
944          retval.setBackup(
945          ( short ) 0);   // by default DONT save backups of files...just loose data
946          return retval;
947      }
948      
949      /**
950       * creates the HideObj record with hide object set to 0. (don't hide)
951       * @see org.apache.poi.hssf.record.HideObjRecord
952       * @see org.apache.poi.hssf.record.Record
953       * @return record containing a HideObjRecord
954       */
955      
956      protected Record createHideObj() {
957          HideObjRecord retval = new HideObjRecord();
958          
959          retval.setHideObj(( short ) 0);   // by default set hide object off
960          return retval;
961      }
962      
963      /**
964       * creates the DateWindow1904 record with windowing set to 0. (don't window)
965       * @see org.apache.poi.hssf.record.DateWindow1904Record
966       * @see org.apache.poi.hssf.record.Record
967       * @return record containing a DateWindow1904Record
968       */
969      
970      protected Record createDateWindow1904() {
971          DateWindow1904Record retval = new DateWindow1904Record();
972          
973          retval.setWindowing(
974          ( short ) 0);   // don't EVER use 1904 date windowing...tick tock..
975          return retval;
976      }
977      
978      /**
979       * creates the Precision record with precision set to true. (full precision)
980       * @see org.apache.poi.hssf.record.PrecisionRecord
981       * @see org.apache.poi.hssf.record.Record
982       * @return record containing a PrecisionRecord
983       */
984      
985      protected Record createPrecision() {
986          PrecisionRecord retval = new PrecisionRecord();
987          
988          retval.setFullPrecision(
989          true);   // always use real numbers in calculations!
990          return retval;
991      }
992      
993      /**
994       * creates the RefreshAll record with refreshAll set to true. (refresh all calcs)
995       * @see org.apache.poi.hssf.record.RefreshAllRecord
996       * @see org.apache.poi.hssf.record.Record
997       * @return record containing a RefreshAllRecord
998       */
999      
1000     protected Record createRefreshAll() {
1001         RefreshAllRecord retval = new RefreshAllRecord();
1002         
1003         retval.setRefreshAll(false);
1004         return retval;
1005     }
1006     
1007     /**
1008      * creates the BookBool record with saveLinkValues set to 0. (don't save link values)
1009      * @see org.apache.poi.hssf.record.BookBoolRecord
1010      * @see org.apache.poi.hssf.record.Record
1011      * @return record containing a BookBoolRecord
1012      */
1013     
1014     protected Record createBookBool() {
1015         BookBoolRecord retval = new BookBoolRecord();
1016         
1017         retval.setSaveLinkValues(( short ) 0);
1018         return retval;
1019     }
1020     
1021     /**
1022      * creates a Font record with the following magic values: <P>
1023      * fontheight           = 0xc8<P>
1024      * attributes           = 0x0<P>
1025      * color palette index  = 0x7fff<P>
1026      * bold weight          = 0x190<P>
1027      * Font Name Length     = 5 <P>
1028      * Font Name            = Arial <P>
1029      *
1030      * @see org.apache.poi.hssf.record.FontRecord
1031      * @see org.apache.poi.hssf.record.Record
1032      * @return record containing a FontRecord
1033      */
1034     
1035     protected Record createFont() {
1036         FontRecord retval = new FontRecord();
1037         
1038         retval.setFontHeight(( short ) 0xc8);
1039         retval.setAttributes(( short ) 0x0);
1040         retval.setColorPaletteIndex(( short ) 0x7fff);
1041         retval.setBoldWeight(( short ) 0x190);
1042         retval.setFontNameLength(( byte ) 5);
1043         retval.setFontName("Arial");
1044         return retval;
1045     }
1046     
1047     /**
1048      * Creates a FormatRecord object
1049      * @param id    the number of the format record to create (meaning its position in
1050      *        a file as M$ Excel would create it.)
1051      * @return record containing a FormatRecord
1052      * @see org.apache.poi.hssf.record.FormatRecord
1053      * @see org.apache.poi.hssf.record.Record
1054      */
1055     
1056     protected Record createFormat(int id) {   // we'll need multiple editions for
1057         FormatRecord retval = new FormatRecord();   // the differnt formats
1058         
1059         switch (id) {
1060             
1061             case 0 :
1062                 retval.setIndexCode(( short ) 5);
1063                 retval.setFormatStringLength(( byte ) 0x17);
1064                 retval.setFormatString("\"$\"#,##0_);\\(\"$\"#,##0\\)");
1065                 break;
1066                 
1067             case 1 :
1068                 retval.setIndexCode(( short ) 6);
1069                 retval.setFormatStringLength(( byte ) 0x1c);
1070                 retval.setFormatString("\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)");
1071                 break;
1072                 
1073             case 2 :
1074                 retval.setIndexCode(( short ) 7);
1075                 retval.setFormatStringLength(( byte ) 0x1d);
1076                 retval.setFormatString("\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)");
1077                 break;
1078                 
1079             case 3 :
1080                 retval.setIndexCode(( short ) 8);
1081                 retval.setFormatStringLength(( byte ) 0x22);
1082                 retval.setFormatString(
1083                 "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)");
1084                 break;
1085                 
1086             case 4 :
1087                 retval.setIndexCode(( short ) 0x2a);
1088                 retval.setFormatStringLength(( byte ) 0x32);
1089                 retval.setFormatString(
1090                 "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)");
1091                 break;
1092                 
1093             case 5 :
1094                 retval.setIndexCode(( short ) 0x29);
1095                 retval.setFormatStringLength(( byte ) 0x29);
1096                 retval.setFormatString(
1097                 "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)");
1098                 break;
1099                 
1100             case 6 :
1101                 retval.setIndexCode(( short ) 0x2c);
1102                 retval.setFormatStringLength(( byte ) 0x3a);
1103                 retval.setFormatString(
1104                 "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)");
1105                 break;
1106                 
1107             case 7 :
1108                 retval.setIndexCode(( short ) 0x2b);
1109                 retval.setFormatStringLength(( byte ) 0x31);
1110                 retval.setFormatString(
1111                 "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)");
1112                 break;
1113         }
1114         return retval;
1115     }
1116     
1117     /**
1118      * Creates an ExtendedFormatRecord object
1119      * @param id    the number of the extended format record to create (meaning its position in
1120      *        a file as MS Excel would create it.)
1121      *
1122      * @return record containing an ExtendedFormatRecord
1123      * @see org.apache.poi.hssf.record.ExtendedFormatRecord
1124      * @see org.apache.poi.hssf.record.Record
1125      */
1126     
1127     protected Record createExtendedFormat(int id) {   // we'll need multiple editions
1128         ExtendedFormatRecord retval = new ExtendedFormatRecord();
1129         
1130         switch (id) {
1131             
1132             case 0 :
1133                 retval.setFontIndex(( short ) 0);
1134                 retval.setFormatIndex(( short ) 0);
1135                 retval.setCellOptions(( short ) 0xfffffff5);
1136                 retval.setAlignmentOptions(( short ) 0x20);
1137                 retval.setIndentionOptions(( short ) 0);
1138                 retval.setBorderOptions(( short ) 0);
1139                 retval.setPaletteOptions(( short ) 0);
1140                 retval.setAdtlPaletteOptions(( short ) 0);
1141                 retval.setFillPaletteOptions(( short ) 0x20c0);
1142                 break;
1143                 
1144             case 1 :
1145                 retval.setFontIndex(( short ) 1);
1146                 retval.setFormatIndex(( short ) 0);
1147                 retval.setCellOptions(( short ) 0xfffffff5);
1148                 retval.setAlignmentOptions(( short ) 0x20);
1149                 retval.setIndentionOptions(( short ) 0xfffff400);
1150                 retval.setBorderOptions(( short ) 0);
1151                 retval.setPaletteOptions(( short ) 0);
1152                 retval.setAdtlPaletteOptions(( short ) 0);
1153                 retval.setFillPaletteOptions(( short ) 0x20c0);
1154                 break;
1155                 
1156             case 2 :
1157                 retval.setFontIndex(( short ) 1);
1158                 retval.setFormatIndex(( short ) 0);
1159                 retval.setCellOptions(( short ) 0xfffffff5);
1160                 retval.setAlignmentOptions(( short ) 0x20);
1161                 retval.setIndentionOptions(( short ) 0xfffff400);
1162                 retval.setBorderOptions(( short ) 0);
1163                 retval.setPaletteOptions(( short ) 0);
1164                 retval.setAdtlPaletteOptions(( short ) 0);
1165                 retval.setFillPaletteOptions(( short ) 0x20c0);
1166                 break;
1167                 
1168             case 3 :
1169                 retval.setFontIndex(( short ) 2);
1170                 retval.setFormatIndex(( short ) 0);
1171                 retval.setCellOptions(( short ) 0xfffffff5);
1172                 retval.setAlignmentOptions(( short ) 0x20);
1173                 retval.setIndentionOptions(( short ) 0xfffff400);
1174                 retval.setBorderOptions(( short ) 0);
1175                 retval.setPaletteOptions(( short ) 0);
1176                 retval.setAdtlPaletteOptions(( short ) 0);
1177                 retval.setFillPaletteOptions(( short ) 0x20c0);
1178                 break;
1179                 
1180             case 4 :
1181                 retval.setFontIndex(( short ) 2);
1182                 retval.setFormatIndex(( short ) 0);
1183                 retval.setCellOptions(( short ) 0xfffffff5);
1184                 retval.setAlignmentOptions(( short ) 0x20);
1185                 retval.setIndentionOptions(( short ) 0xfffff400);
1186                 retval.setBorderOptions(( short ) 0);
1187                 retval.setPaletteOptions(( short ) 0);
1188                 retval.setAdtlPaletteOptions(( short ) 0);
1189                 retval.setFillPaletteOptions(( short ) 0x20c0);
1190                 break;
1191                 
1192             case 5 :
1193                 retval.setFontIndex(( short ) 0);
1194                 retval.setFormatIndex(( short ) 0);
1195                 retval.setCellOptions(( short ) 0xfffffff5);
1196                 retval.setAlignmentOptions(( short ) 0x20);
1197                 retval.setIndentionOptions(( short ) 0xfffff400);
1198                 retval.setBorderOptions(( short ) 0);
1199                 retval.setPaletteOptions(( short ) 0);
1200                 retval.setAdtlPaletteOptions(( short ) 0);
1201                 retval.setFillPaletteOptions(( short ) 0x20c0);
1202                 break;
1203                 
1204             case 6 :
1205                 retval.setFontIndex(( short ) 0);
1206                 retval.setFormatIndex(( short ) 0);
1207                 retval.setCellOptions(( short ) 0xfffffff5);
1208                 retval.setAlignmentOptions(( short ) 0x20);
1209                 retval.setIndentionOptions(( short ) 0xfffff400);
1210                 retval.setBorderOptions(( short ) 0);
1211                 retval.setPaletteOptions(( short ) 0);
1212                 retval.setAdtlPaletteOptions(( short ) 0);
1213                 retval.setFillPaletteOptions(( short ) 0x20c0);
1214                 break;
1215                 
1216             case 7 :
1217                 retval.setFontIndex(( short ) 0);
1218                 retval.setFormatIndex(( short ) 0);
1219                 retval.setCellOptions(( short ) 0xfffffff5);
1220                 retval.setAlignmentOptions(( short ) 0x20);
1221                 retval.setIndentionOptions(( short ) 0xfffff400);
1222                 retval.setBorderOptions(( short ) 0);
1223                 retval.setPaletteOptions(( short ) 0);
1224                 retval.setAdtlPaletteOptions(( short ) 0);
1225                 retval.setFillPaletteOptions(( short ) 0x20c0);
1226                 break;
1227                 
1228             case 8 :
1229                 retval.setFontIndex(( short ) 0);
1230                 retval.setFormatIndex(( short ) 0);
1231                 retval.setCellOptions(( short ) 0xfffffff5);
1232                 retval.setAlignmentOptions(( short ) 0x20);
1233                 retval.setIndentionOptions(( short ) 0xfffff400);
1234                 retval.setBorderOptions(( short ) 0);
1235                 retval.setPaletteOptions(( short ) 0);
1236                 retval.setAdtlPaletteOptions(( short ) 0);
1237                 retval.setFillPaletteOptions(( short ) 0x20c0);
1238                 break;
1239                 
1240             case 9 :
1241                 retval.setFontIndex(( short ) 0);
1242                 retval.setFormatIndex(( short ) 0);
1243                 retval.setCellOptions(( short ) 0xfffffff5);
1244                 retval.setAlignmentOptions(( short ) 0x20);
1245                 retval.setIndentionOptions(( short ) 0xfffff400);
1246                 retval.setBorderOptions(( short ) 0);
1247                 retval.setPaletteOptions(( short ) 0);
1248                 retval.setAdtlPaletteOptions(( short ) 0);
1249                 retval.setFillPaletteOptions(( short ) 0x20c0);
1250                 break;
1251                 
1252             case 10 :
1253                 retval.setFontIndex(( short ) 0);
1254                 retval.setFormatIndex(( short ) 0);
1255                 retval.setCellOptions(( short ) 0xfffffff5);
1256                 retval.setAlignmentOptions(( short ) 0x20);
1257                 retval.setIndentionOptions(( short ) 0xfffff400);
1258                 retval.setBorderOptions(( short ) 0);
1259                 retval.setPaletteOptions(( short ) 0);
1260                 retval.setAdtlPaletteOptions(( short ) 0);
1261                 retval.setFillPaletteOptions(( short ) 0x20c0);
1262                 break;
1263                 
1264             case 11 :
1265                 retval.setFontIndex(( short ) 0);
1266                 retval.setFormatIndex(( short ) 0);
1267                 retval.setCellOptions(( short ) 0xfffffff5);
1268                 retval.setAlignmentOptions(( short ) 0x20);
1269                 retval.setIndentionOptions(( short ) 0xfffff400);
1270                 retval.setBorderOptions(( short ) 0);
1271                 retval.setPaletteOptions(( short ) 0);
1272                 retval.setAdtlPaletteOptions(( short ) 0);
1273                 retval.setFillPaletteOptions(( short ) 0x20c0);
1274                 break;
1275                 
1276             case 12 :
1277                 retval.setFontIndex(( short ) 0);
1278                 retval.setFormatIndex(( short ) 0);
1279                 retval.setCellOptions(( short ) 0xfffffff5);
1280                 retval.setAlignmentOptions(( short ) 0x20);
1281                 retval.setIndentionOptions(( short ) 0xfffff400);
1282                 retval.setBorderOptions(( short ) 0);
1283                 retval.setPaletteOptions(( short ) 0);
1284                 retval.setAdtlPaletteOptions(( short ) 0);
1285                 retval.setFillPaletteOptions(( short ) 0x20c0);
1286                 break;
1287                 
1288             case 13 :
1289                 retval.setFontIndex(( short ) 0);
1290                 retval.setFormatIndex(( short ) 0);
1291                 retval.setCellOptions(( short ) 0xfffffff5);
1292                 retval.setAlignmentOptions(( short ) 0x20);
1293                 retval.setIndentionOptions(( short ) 0xfffff400);
1294                 retval.setBorderOptions(( short ) 0);
1295                 retval.setPaletteOptions(( short ) 0);
1296                 retval.setAdtlPaletteOptions(( short ) 0);
1297                 retval.setFillPaletteOptions(( short ) 0x20c0);
1298                 break;
1299                 
1300             case 14 :
1301                 retval.setFontIndex(( short ) 0);
1302                 retval.setFormatIndex(( short ) 0);
1303                 retval.setCellOptions(( short ) 0xfffffff5);
1304                 retval.setAlignmentOptions(( short ) 0x20);
1305                 retval.setIndentionOptions(( short ) 0xfffff400);
1306                 retval.setBorderOptions(( short ) 0);
1307                 retval.setPaletteOptions(( short ) 0);
1308                 retval.setAdtlPaletteOptions(( short ) 0);
1309                 retval.setFillPaletteOptions(( short ) 0x20c0);
1310                 break;
1311                 
1312                 // cell records
1313             case 15 :
1314                 retval.setFontIndex(( short ) 0);
1315                 retval.setFormatIndex(( short ) 0);
1316                 retval.setCellOptions(( short ) 0x1);
1317                 retval.setAlignmentOptions(( short ) 0x20);
1318                 retval.setIndentionOptions(( short ) 0x0);
1319                 retval.setBorderOptions(( short ) 0);
1320                 retval.setPaletteOptions(( short ) 0);
1321                 retval.setAdtlPaletteOptions(( short ) 0);
1322                 retval.setFillPaletteOptions(( short ) 0x20c0);
1323                 break;
1324                 
1325                 // style
1326             case 16 :
1327                 retval.setFontIndex(( short ) 1);
1328                 retval.setFormatIndex(( short ) 0x2b);
1329                 retval.setCellOptions(( short ) 0xfffffff5);
1330                 retval.setAlignmentOptions(( short ) 0x20);
1331                 retval.setIndentionOptions(( short ) 0xfffff800);
1332                 retval.setBorderOptions(( short ) 0);
1333                 retval.setPaletteOptions(( short ) 0);
1334                 retval.setAdtlPaletteOptions(( short ) 0);
1335                 retval.setFillPaletteOptions(( short ) 0x20c0);
1336                 break;
1337                 
1338             case 17 :
1339                 retval.setFontIndex(( short ) 1);
1340                 retval.setFormatIndex(( short ) 0x29);
1341                 retval.setCellOptions(( short ) 0xfffffff5);
1342                 retval.setAlignmentOptions(( short ) 0x20);
1343                 retval.setIndentionOptions(( short ) 0xfffff800);
1344                 retval.setBorderOptions(( short ) 0);
1345                 retval.setPaletteOptions(( short ) 0);
1346                 retval.setAdtlPaletteOptions(( short ) 0);
1347                 retval.setFillPaletteOptions(( short ) 0x20c0);
1348                 break;
1349                 
1350             case 18 :
1351                 retval.setFontIndex(( short ) 1);
1352                 retval.setFormatIndex(( short ) 0x2c);
1353                 retval.setCellOptions(( short ) 0xfffffff5);
1354                 retval.setAlignmentOptions(( short ) 0x20);
1355                 retval.setIndentionOptions(( short ) 0xfffff800);
1356                 retval.setBorderOptions(( short ) 0);
1357                 retval.setPaletteOptions(( short ) 0);
1358                 retval.setAdtlPaletteOptions(( short ) 0);
1359                 retval.setFillPaletteOptions(( short ) 0x20c0);
1360                 break;
1361                 
1362             case 19 :
1363                 retval.setFontIndex(( short ) 1);
1364                 retval.setFormatIndex(( short ) 0x2a);
1365                 retval.setCellOptions(( short ) 0xfffffff5);
1366                 retval.setAlignmentOptions(( short ) 0x20);
1367                 retval.setIndentionOptions(( short ) 0xfffff800);
1368                 retval.setBorderOptions(( short ) 0);
1369                 retval.setPaletteOptions(( short ) 0);
1370                 retval.setAdtlPaletteOptions(( short ) 0);
1371                 retval.setFillPaletteOptions(( short ) 0x20c0);
1372                 break;
1373                 
1374             case 20 :
1375                 retval.setFontIndex(( short ) 1);
1376                 retval.setFormatIndex(( short ) 0x9);
1377                 retval.setCellOptions(( short ) 0xfffffff5);
1378                 retval.setAlignmentOptions(( short ) 0x20);
1379                 retval.setIndentionOptions(( short ) 0xfffff800);
1380                 retval.setBorderOptions(( short ) 0);
1381                 retval.setPaletteOptions(( short ) 0);
1382                 retval.setAdtlPaletteOptions(( short ) 0);
1383                 retval.setFillPaletteOptions(( short ) 0x20c0);
1384                 break;
1385                 
1386                 // unused from this point down
1387             case 21 :
1388                 retval.setFontIndex(( short ) 5);
1389                 retval.setFormatIndex(( short ) 0x0);
1390                 retval.setCellOptions(( short ) 0x1);
1391                 retval.setAlignmentOptions(( short ) 0x20);
1392                 retval.setIndentionOptions(( short ) 0x800);
1393                 retval.setBorderOptions(( short ) 0);
1394                 retval.setPaletteOptions(( short ) 0);
1395                 retval.setAdtlPaletteOptions(( short ) 0);
1396                 retval.setFillPaletteOptions(( short ) 0x20c0);
1397                 break;
1398                 
1399             case 22 :
1400                 retval.setFontIndex(( short ) 6);
1401                 retval.setFormatIndex(( short ) 0x0);
1402                 retval.setCellOptions(( short ) 0x1);
1403                 retval.setAlignmentOptions(( short ) 0x20);
1404                 retval.setIndentionOptions(( short ) 0x5c00);
1405                 retval.setBorderOptions(( short ) 0);
1406                 retval.setPaletteOptions(( short ) 0);
1407                 retval.setAdtlPaletteOptions(( short ) 0);
1408                 retval.setFillPaletteOptions(( short ) 0x20c0);
1409                 break;
1410                 
1411             case 23 :
1412                 retval.setFontIndex(( short ) 0);
1413                 retval.setFormatIndex(( short ) 0x31);
1414                 retval.setCellOptions(( short ) 0x1);
1415                 retval.setAlignmentOptions(( short ) 0x20);
1416                 retval.setIndentionOptions(( short ) 0x5c00);
1417                 retval.setBorderOptions(( short ) 0);
1418                 retval.setPaletteOptions(( short ) 0);
1419                 retval.setAdtlPaletteOptions(( short ) 0);
1420                 retval.setFillPaletteOptions(( short ) 0x20c0);
1421                 break;
1422                 
1423             case 24 :
1424                 retval.setFontIndex(( short ) 0);
1425                 retval.setFormatIndex(( short ) 0x8);
1426                 retval.setCellOptions(( short ) 0x1);
1427                 retval.setAlignmentOptions(( short ) 0x20);
1428                 retval.setIndentionOptions(( short ) 0x5c00);
1429                 retval.setBorderOptions(( short ) 0);
1430                 retval.setPaletteOptions(( short ) 0);
1431                 retval.setAdtlPaletteOptions(( short ) 0);
1432                 retval.setFillPaletteOptions(( short ) 0x20c0);
1433                 break;
1434                 
1435             case 25 :
1436                 retval.setFontIndex(( short ) 6);
1437                 retval.setFormatIndex(( short ) 0x8);
1438                 retval.setCellOptions(( short ) 0x1);
1439                 retval.setAlignmentOptions(( short ) 0x20);
1440                 retval.setIndentionOptions(( short ) 0x5c00);
1441                 retval.setBorderOptions(( short ) 0);
1442                 retval.setPaletteOptions(( short ) 0);
1443                 retval.setAdtlPaletteOptions(( short ) 0);
1444                 retval.setFillPaletteOptions(( short ) 0x20c0);
1445                 break;
1446         }
1447         return retval;
1448     }
1449     
1450     /**
1451      * creates an default cell type ExtendedFormatRecord object.
1452      * @return ExtendedFormatRecord with intial defaults (cell-type)
1453      */
1454     
1455     protected ExtendedFormatRecord createExtendedFormat() {
1456         ExtendedFormatRecord retval = new ExtendedFormatRecord();
1457         
1458         retval.setFontIndex(( short ) 0);
1459         retval.setFormatIndex(( short ) 0x0);
1460         retval.setCellOptions(( short ) 0x1);
1461         retval.setAlignmentOptions(( short ) 0x20);
1462         retval.setIndentionOptions(( short ) 0);
1463         retval.setBorderOptions(( short ) 0);
1464         retval.setPaletteOptions(( short ) 0);
1465         retval.setAdtlPaletteOptions(( short ) 0);
1466         retval.setFillPaletteOptions(( short ) 0x20c0);
1467         return retval;
1468     }
1469     
1470     /**
1471      * Creates a StyleRecord object
1472      * @param id        the number of the style record to create (meaning its position in
1473      *                  a file as MS Excel would create it.
1474      * @return record containing a StyleRecord
1475      * @see org.apache.poi.hssf.record.StyleRecord
1476      * @see org.apache.poi.hssf.record.Record
1477      */
1478     
1479     protected Record createStyle(int id) {   // we'll need multiple editions
1480         StyleRecord retval = new StyleRecord();
1481         
1482         switch (id) {
1483             
1484             case 0 :
1485                 retval.setIndex(( short ) 0xffff8010);
1486                 retval.setBuiltin(( byte ) 3);
1487                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1488                 break;
1489                 
1490             case 1 :
1491                 retval.setIndex(( short ) 0xffff8011);
1492                 retval.setBuiltin(( byte ) 6);
1493                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1494                 break;
1495                 
1496             case 2 :
1497                 retval.setIndex(( short ) 0xffff8012);
1498                 retval.setBuiltin(( byte ) 4);
1499                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1500                 break;
1501                 
1502             case 3 :
1503                 retval.setIndex(( short ) 0xffff8013);
1504                 retval.setBuiltin(( byte ) 7);
1505                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1506                 break;
1507                 
1508             case 4 :
1509                 retval.setIndex(( short ) 0xffff8000);
1510                 retval.setBuiltin(( byte ) 0);
1511                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1512                 break;
1513                 
1514             case 5 :
1515                 retval.setIndex(( short ) 0xffff8014);
1516                 retval.setBuiltin(( byte ) 5);
1517                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1518                 break;
1519         }
1520         return retval;
1521     }
1522     
1523     /**
1524      * Creates the UseSelFS object with the use natural language flag set to 0 (false)
1525      * @return record containing a UseSelFSRecord
1526      * @see org.apache.poi.hssf.record.UseSelFSRecord
1527      * @see org.apache.poi.hssf.record.Record
1528      */
1529     
1530     protected Record createUseSelFS() {
1531         UseSelFSRecord retval = new UseSelFSRecord();
1532         
1533         retval.setFlag(( short ) 0);
1534         return retval;
1535     }
1536     
1537     /**
1538      * create a "bound sheet" or "bundlesheet" (depending who you ask) record
1539      * Always sets the sheet's bof to 0.  You'll need to set that yourself.
1540      * @param id either sheet 0,1 or 2.
1541      * @return record containing a BoundSheetRecord
1542      * @see org.apache.poi.hssf.record.BoundSheetRecord
1543      * @see org.apache.poi.hssf.record.Record
1544      */
1545     
1546     protected Record createBoundSheet(int id) {   // 1,2,3 sheets
1547         BoundSheetRecord retval = new BoundSheetRecord();
1548         
1549         switch (id) {
1550             
1551             case 0 :
1552                 retval.setPositionOfBof(0x0);   // should be set later
1553                 retval.setOptionFlags(( short ) 0);
1554                 retval.setSheetnameLength(( byte ) 0x6);
1555                 retval.setCompressedUnicodeFlag(( byte ) 0);
1556                 retval.setSheetname("Sheet1");
1557                 break;
1558                 
1559             case 1 :
1560                 retval.setPositionOfBof(0x0);   // should be set later
1561                 retval.setOptionFlags(( short ) 0);
1562                 retval.setSheetnameLength(( byte ) 0x6);
1563                 retval.setCompressedUnicodeFlag(( byte ) 0);
1564                 retval.setSheetname("Sheet2");
1565                 break;
1566                 
1567             case 2 :
1568                 retval.setPositionOfBof(0x0);   // should be set later
1569                 retval.setOptionFlags(( short ) 0);
1570                 retval.setSheetnameLength(( byte ) 0x6);
1571                 retval.setCompressedUnicodeFlag(( byte ) 0);
1572                 retval.setSheetname("Sheet3");
1573                 break;
1574         }
1575         return retval;
1576     }
1577     
1578     /**
1579      * Creates the Country record with the default and current country set to 1
1580      * @return record containing a CountryRecord
1581      * @see org.apache.poi.hssf.record.CountryRecord
1582      * @see org.apache.poi.hssf.record.Record
1583      */
1584     
1585     protected Record createCountry() {   // what a novel idea, create your own!
1586         CountryRecord retval = new CountryRecord();
1587         
1588         retval.setDefaultCountry(( short ) 1);
1589         retval.setCurrentCountry(( short ) 1);
1590         return retval;
1591     }
1592     
1593     /**
1594      * Creates the SST record with no strings and the unique/num string set to 0
1595      * @return record containing a SSTRecord
1596      * @see org.apache.poi.hssf.record.SSTRecord
1597      * @see org.apache.poi.hssf.record.Record
1598      */
1599     
1600     protected Record createSST() {
1601         return new SSTRecord();
1602     }
1603     
1604     /**
1605      * Creates the ExtendedSST record with numstrings per bucket set to 0x8.  HSSF
1606      * doesn't yet know what to do with this thing, but we create it with nothing in
1607      * it hardly just to make Excel happy and our sheets look like Excel's
1608      *
1609      * @return record containing an ExtSSTRecord
1610      * @see org.apache.poi.hssf.record.ExtSSTRecord
1611      * @see org.apache.poi.hssf.record.Record
1612      */
1613     
1614     protected Record createExtendedSST() {
1615         ExtSSTRecord retval = new ExtSSTRecord();
1616         
1617         retval.setNumStringsPerBucket(( short ) 0x8);
1618         return retval;
1619     }
1620     
1621     /**
1622      * creates the EOF record
1623      * @see org.apache.poi.hssf.record.EOFRecord
1624      * @see org.apache.poi.hssf.record.Record
1625      * @return record containing a EOFRecord
1626      */
1627     
1628     protected Record createEOF() {
1629         return new EOFRecord();
1630     }
1631     
1632     /** fins the sheet name by his extern sheet index
1633      * @param num extern sheet index
1634      * @return sheet name
1635      */
1636     public String findSheetNameFromExternSheet(short num){
1637         String result;
1638         
1639         short indexToSheet = externSheet.getREFRecordAt(num).getIndexToFirstSupBook();
1640         result = getSheetName(indexToSheet);
1641         
1642         return result;
1643     }
1644     
1645     /** returns the extern sheet number for specific sheet number ,
1646      *  if this sheet doesn't exist in extern sheet , add it
1647      * @param sheetNumber sheet number
1648      * @return index to extern sheet
1649      */
1650     public short checkExternSheet(int sheetNumber){
1651         
1652         int i = 0;
1653         boolean flag = false;
1654         short result = 0;
1655         
1656         if (externSheet == null) {
1657             externSheet = createExternSheet();
1658         }
1659         
1660         //Trying to find reference to this sheet
1661         while (i < externSheet.getNumOfREFStructures() && !flag){
1662             ExternSheetSubRecord record = externSheet.getREFRecordAt(i);
1663             
1664             if (record.getIndexToFirstSupBook() ==  sheetNumber &&
1665             record.getIndexToLastSupBook() == sheetNumber){
1666                 flag = true;
1667                 result = (short) i;
1668             }
1669             
1670             ++i;
1671         }
1672         
1673         //We Havent found reference to this sheet
1674         if (!flag) {
1675             result = addSheetIndexToExternSheet((short) sheetNumber);
1676         }
1677         
1678         return result;
1679     }
1680     
1681     private short addSheetIndexToExternSheet(short sheetNumber){
1682         short result;
1683         
1684         ExternSheetSubRecord record = new ExternSheetSubRecord();
1685         record.setIndexToFirstSupBook(sheetNumber);
1686         record.setIndexToLastSupBook(sheetNumber);
1687         externSheet.addREFRecord(record);
1688         externSheet.setNumOfREFStructures((short)(externSheet.getNumOfREFStructures() + 1));
1689         result = (short)(externSheet.getNumOfREFStructures() - 1);
1690         
1691         return result;
1692     }
1693     
1694     
1695     
1696     /** gets the total number of names
1697      * @return number of names
1698      */
1699     public int getNumNames(){
1700         int result = names.size();
1701         
1702         return result;
1703     }
1704     
1705     /** gets the name record
1706      * @param index name index
1707      * @return name record
1708      */
1709     public NameRecord getNameRecord(int index){
1710         NameRecord result = (NameRecord) names.get(index);
1711         
1712         return result;
1713         
1714     }
1715     
1716     /** creates new name
1717      * @return new name record
1718      */
1719     public NameRecord createName(){
1720         
1721         NameRecord name = new NameRecord();
1722         
1723         records.add(++namepos, name);
1724         names.add(name);
1725         
1726         return name;
1727     }
1728     
1729     /** removes the name
1730      * @param namenum name index
1731      */
1732     public void removeName(int namenum){
1733         if (names.size() > namenum) {
1734             records.remove(namepos - (names.size() - 1) + namenum);
1735             namepos--;
1736             names.remove(namenum);
1737         }
1738         
1739     }
1740     
1741     /** creates a new extern sheet record
1742      * @return the new extern sheet record
1743      */
1744     protected ExternSheetRecord createExternSheet(){
1745         ExternSheetRecord rec = new ExternSheetRecord();
1746         
1747         records.add(supbookpos + 1 , rec);
1748         
1749         //We also adds the supBook for internal reference
1750         SupBookRecord supbook = new SupBookRecord();
1751         
1752         supbook.setNumberOfSheets((short)getNumSheets());
1753         //supbook.setFlag();
1754         
1755         records.add(supbookpos + 1 , supbook);
1756         
1757         return rec;
1758     }
1759     
1760     
1761     /**
1762      * Returns the first occurance of a record matching a particular sid.
1763      */
1764     
1765     public Record findFirstRecordBySid(short sid) {
1766         for (Iterator iterator = records.iterator(); iterator.hasNext(); ) {
1767             Record record = ( Record ) iterator.next();
1768             
1769             if (record.getSid() == sid) {
1770                 return record;
1771             }
1772         }
1773         return null;
1774     }
1775 
1776     public List getRecords()
1777     {
1778         return records;
1779     }
1780 }
1781