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