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          // ArrayList bytes     = new ArrayList(records.size());
647  //        int arraysize = getSize();   // 0;
648          int pos       = 0;
649  
650  //        for (int k = 0; k < records.size(); k++)
651  //        {
652  //            bytes.add((( Record ) records.get(k)).serialize());
653  //
654  //        }
655  //        for (int k = 0; k < bytes.size(); k++)
656  //       {
657  //            arraysize += (( byte [] ) bytes.get(k)).length;
658  //        }
659          for (int k = 0; k < records.size(); k++)
660          {
661  
662              // byte[] rec = (( byte [] ) bytes.get(k));
663              // System.arraycopy(rec, 0, data, offset + pos, rec.length);
664              pos += (( Record ) records.get(k)).serialize(pos + offset,
665                      data);   // rec.length;
666          }
667          log.log(DEBUG, "Exiting serialize workbook");
668          return pos;
669      }
670  
671      public int getSize()
672      {
673          int retval = 0;
674  
675          for (int k = 0; k < records.size(); k++)
676          {
677              retval += (( Record ) records.get(k)).getRecordSize();
678          }
679          return retval;
680      }
681  
682      /**
683       * creates the BOF record
684       * @see org.apache.poi.hssf.record.BOFRecord
685       * @see org.apache.poi.hssf.record.Record
686       * @return record containing a BOFRecord
687       */
688  
689      protected Record createBOF()
690      {
691          BOFRecord retval = new BOFRecord();
692  
693          retval.setVersion(( short ) 0x600);
694          retval.setType(( short ) 5);
695          retval.setBuild(( short ) 0x10d3);
696  
697  //        retval.setBuild((short)0x0dbb);        
698          retval.setBuildYear(( short ) 1996);
699          retval.setHistoryBitMask(0x41);   // was c1 before verify
700          retval.setRequiredVersion(0x6);
701          return retval;
702      }
703  
704      /**
705       * creates the InterfaceHdr record
706       * @see org.apache.poi.hssf.record.InterfaceHdrRecord
707       * @see org.apache.poi.hssf.record.Record
708       * @return record containing a InterfaceHdrRecord
709       */
710  
711      protected Record createInterfaceHdr()
712      {
713          InterfaceHdrRecord retval = new InterfaceHdrRecord();
714  
715          retval.setCodepage(CODEPAGE);
716          return retval;
717      }
718  
719      /**
720       * creates an MMS record
721       * @see org.apache.poi.hssf.record.MMSRecord
722       * @see org.apache.poi.hssf.record.Record
723       * @return record containing a MMSRecord
724       */
725  
726      protected Record createMMS()
727      {
728          MMSRecord retval = new MMSRecord();
729  
730          retval.setAddMenuCount(( byte ) 0);
731          retval.setDelMenuCount(( byte ) 0);
732          return retval;
733      }
734  
735      /**
736       * creates the InterfaceEnd record
737       * @see org.apache.poi.hssf.record.InterfaceEndRecord
738       * @see org.apache.poi.hssf.record.Record
739       * @return record containing a InterfaceEndRecord
740       */
741  
742      protected Record createInterfaceEnd()
743      {
744          return new InterfaceEndRecord();
745      }
746  
747      /**
748       * creates the WriteAccess record containing the logged in user's name
749       * @see org.apache.poi.hssf.record.WriteAccessRecord
750       * @see org.apache.poi.hssf.record.Record
751       * @return record containing a WriteAccessRecord
752       */
753  
754      protected Record createWriteAccess()
755      {
756          WriteAccessRecord retval = new WriteAccessRecord();
757  
758          retval.setUsername(System.getProperty("user.name"));
759          return retval;
760      }
761  
762      /**
763       * creates the Codepage record containing the constant stored in CODEPAGE
764       * @see org.apache.poi.hssf.record.CodepageRecord
765       * @see org.apache.poi.hssf.record.Record
766       * @return record containing a CodepageRecord
767       */
768  
769      protected Record createCodepage()
770      {
771          CodepageRecord retval = new CodepageRecord();
772  
773          retval.setCodepage(CODEPAGE);
774          return retval;
775      }
776  
777      /**
778       * creates the DSF record containing a 0 since HSSF can't even create Dual Stream Files
779       * @see org.apache.poi.hssf.record.DSFRecord
780       * @see org.apache.poi.hssf.record.Record
781       * @return record containing a DSFRecord
782       */
783  
784      protected Record createDSF()
785      {
786          DSFRecord retval = new DSFRecord();
787  
788          retval.setDsf(
789              ( short ) 0);   // we don't even support double stream files
790          return retval;
791      }
792  
793      /**
794       * creates the TabId record containing an array of 0,1,2.  This release of HSSF
795       * always has the default three sheets, no less, no more.
796       * @see org.apache.poi.hssf.record.TabIdRecord
797       * @see org.apache.poi.hssf.record.Record
798       * @return record containing a TabIdRecord
799       */
800  
801      protected Record createTabId()
802      {
803          TabIdRecord retval     = new TabIdRecord();
804          short[]     tabidarray =
805          {
806              0
807          };
808  
809          retval.setTabIdArray(tabidarray);
810          return retval;
811      }
812  
813      /**
814       * creates the FnGroupCount record containing the Magic number constant of 14.
815       * @see org.apache.poi.hssf.record.FnGroupCountRecord
816       * @see org.apache.poi.hssf.record.Record
817       * @return record containing a FnGroupCountRecord
818       */
819  
820      protected Record createFnGroupCount()
821      {
822          FnGroupCountRecord retval = new FnGroupCountRecord();
823  
824          retval.setCount(( short ) 14);
825          return retval;
826      }
827  
828      /**
829       * creates the WindowProtect record with protect set to false.
830       * @see org.apache.poi.hssf.record.WindowProtectRecord
831       * @see org.apache.poi.hssf.record.Record
832       * @return record containing a WindowProtectRecord
833       */
834  
835      protected Record createWindowProtect()
836      {
837          WindowProtectRecord retval = new WindowProtectRecord();
838  
839          retval.setProtect(
840              false);   // by default even when we support it we won't
841          return retval;   // want it to be protected
842      }
843  
844      /**
845       * creates the Protect record with protect set to false.
846       * @see org.apache.poi.hssf.record.ProtectRecord
847       * @see org.apache.poi.hssf.record.Record
848       * @return record containing a ProtectRecord
849       */
850  
851      protected Record createProtect()
852      {
853          ProtectRecord retval = new ProtectRecord();
854  
855          retval.setProtect(
856              false);   // by default even when we support it we won't
857          return retval;   // want it to be protected
858      }
859  
860      /**
861       * creates the Password record with password set to 0.
862       * @see org.apache.poi.hssf.record.PasswordRecord
863       * @see org.apache.poi.hssf.record.Record
864       * @return record containing a PasswordRecord
865       */
866  
867      protected Record createPassword()
868      {
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      {
884          ProtectionRev4Record retval = new ProtectionRev4Record();
885  
886          retval.setProtect(false);
887          return retval;
888      }
889  
890      /**
891       * creates the PasswordRev4 record with password set to 0.
892       * @see org.apache.poi.hssf.record.PasswordRev4Record
893       * @see org.apache.poi.hssf.record.Record
894       * @return record containing a PasswordRev4Record
895       */
896  
897      protected Record createPasswordRev4()
898      {
899          PasswordRev4Record retval = new PasswordRev4Record();
900  
901          retval.setPassword(( short ) 0);   // no password by default!
902          return retval;
903      }
904  
905      /**
906       * creates the WindowOne record with the following magic values: <P>
907       * horizontal hold - 0x168 <P>
908       * vertical hold   - 0x10e <P>
909       * width           - 0x3a5c <P>
910       * height          - 0x23be <P>
911       * options         - 0x38 <P>
912       * selected tab    - 0 <P>
913       * displayed tab   - 0 <P>
914       * num selected tab- 0 <P>
915       * tab width ratio - 0x258 <P>
916       * @see org.apache.poi.hssf.record.WindowOneRecord
917       * @see org.apache.poi.hssf.record.Record
918       * @return record containing a WindowOneRecord
919       */
920  
921      protected Record createWindowOne()
922      {
923          WindowOneRecord retval = new WindowOneRecord();
924  
925          retval.setHorizontalHold(( short ) 0x168);
926          retval.setVerticalHold(( short ) 0x10e);
927          retval.setWidth(( short ) 0x3a5c);
928          retval.setHeight(( short ) 0x23be);
929          retval.setOptions(( short ) 0x38);
930          retval.setSelectedTab(( short ) 0x0);
931          retval.setDisplayedTab(( short ) 0x0);
932          retval.setNumSelectedTabs(( short ) 1);
933          retval.setTabWidthRatio(( short ) 0x258);
934          return retval;
935      }
936  
937      /**
938       * creates the Backup record with backup set to 0. (loose the data, who cares)
939       * @see org.apache.poi.hssf.record.BackupRecord
940       * @see org.apache.poi.hssf.record.Record
941       * @return record containing a BackupRecord
942       */
943  
944      protected Record createBackup()
945      {
946          BackupRecord retval = new BackupRecord();
947  
948          retval.setBackup(
949              ( short ) 0);   // by default DONT save backups of files...just loose data
950          return retval;
951      }
952  
953      /**
954       * creates the HideObj record with hide object set to 0. (don't hide)
955       * @see org.apache.poi.hssf.record.HideObjRecord
956       * @see org.apache.poi.hssf.record.Record
957       * @return record containing a HideObjRecord
958       */
959  
960      protected Record createHideObj()
961      {
962          HideObjRecord retval = new HideObjRecord();
963  
964          retval.setHideObj(( short ) 0);   // by default set hide object off
965          return retval;
966      }
967  
968      /**
969       * creates the DateWindow1904 record with windowing set to 0. (don't window)
970       * @see org.apache.poi.hssf.record.DateWindow1904Record
971       * @see org.apache.poi.hssf.record.Record
972       * @return record containing a DateWindow1904Record
973       */
974  
975      protected Record createDateWindow1904()
976      {
977          DateWindow1904Record retval = new DateWindow1904Record();
978  
979          retval.setWindowing(
980              ( short ) 0);   // don't EVER use 1904 date windowing...tick tock..
981          return retval;
982      }
983  
984      /**
985       * creates the Precision record with precision set to true. (full precision)
986       * @see org.apache.poi.hssf.record.PrecisionRecord
987       * @see org.apache.poi.hssf.record.Record
988       * @return record containing a PrecisionRecord
989       */
990  
991      protected Record createPrecision()
992      {
993          PrecisionRecord retval = new PrecisionRecord();
994  
995          retval.setFullPrecision(
996              true);   // always use real numbers in calculations!
997          return retval;
998      }
999  
1000     /**
1001      * creates the RefreshAll record with refreshAll set to true. (refresh all calcs)
1002      * @see org.apache.poi.hssf.record.RefreshAllRecord
1003      * @see org.apache.poi.hssf.record.Record
1004      * @return record containing a RefreshAllRecord
1005      */
1006 
1007     protected Record createRefreshAll()
1008     {
1009         RefreshAllRecord retval = new RefreshAllRecord();
1010 
1011         retval.setRefreshAll(false);
1012         return retval;
1013     }
1014 
1015     /**
1016      * creates the BookBool record with saveLinkValues set to 0. (don't save link values)
1017      * @see org.apache.poi.hssf.record.BookBoolRecord
1018      * @see org.apache.poi.hssf.record.Record
1019      * @return record containing a BookBoolRecord
1020      */
1021 
1022     protected Record createBookBool()
1023     {
1024         BookBoolRecord retval = new BookBoolRecord();
1025 
1026         retval.setSaveLinkValues(( short ) 0);
1027         return retval;
1028     }
1029 
1030     /**
1031      * creates a Font record with the following magic values: <P>
1032      * fontheight           = 0xc8<P>
1033      * attributes           = 0x0<P>
1034      * color palette index  = 0x7fff<P>
1035      * bold weight          = 0x190<P>
1036      * Font Name Length     = 5 <P>
1037      * Font Name            = Arial <P>
1038      *
1039      * @see org.apache.poi.hssf.record.FontRecord
1040      * @see org.apache.poi.hssf.record.Record
1041      * @return record containing a FontRecord
1042      */
1043 
1044     protected Record createFont()
1045     {
1046         FontRecord retval = new FontRecord();
1047 
1048         retval.setFontHeight(( short ) 0xc8);
1049         retval.setAttributes(( short ) 0x0);
1050         retval.setColorPaletteIndex(( short ) 0x7fff);
1051         retval.setBoldWeight(( short ) 0x190);
1052         retval.setFontNameLength(( byte ) 5);
1053         retval.setFontName("Arial");
1054         return retval;
1055     }
1056 
1057     /**
1058      * Creates a FormatRecord object
1059      * @param id    the number of the format record to create (meaning its position in
1060      *        a file as M$ Excel would create it.)
1061      * @return record containing a FormatRecord
1062      * @see org.apache.poi.hssf.record.FormatRecord
1063      * @see org.apache.poi.hssf.record.Record
1064      */
1065 
1066     protected Record createFormat(int id)
1067     {   // we'll need multiple editions for
1068         FormatRecord retval = new FormatRecord();   // the differnt formats
1069 
1070         switch (id)
1071         {
1072 
1073             case 0 :
1074                 retval.setIndexCode(( short ) 5);
1075                 retval.setFormatStringLength(( byte ) 0x17);
1076                 retval.setFormatString("\"$\"#,##0_);\\(\"$\"#,##0\\)");
1077                 break;
1078 
1079             case 1 :
1080                 retval.setIndexCode(( short ) 6);
1081                 retval.setFormatStringLength(( byte ) 0x1c);
1082                 retval.setFormatString("\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)");
1083                 break;
1084 
1085             case 2 :
1086                 retval.setIndexCode(( short ) 7);
1087                 retval.setFormatStringLength(( byte ) 0x1d);
1088                 retval.setFormatString("\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)");
1089                 break;
1090 
1091             case 3 :
1092                 retval.setIndexCode(( short ) 8);
1093                 retval.setFormatStringLength(( byte ) 0x22);
1094                 retval.setFormatString(
1095                     "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)");
1096                 break;
1097 
1098             case 4 :
1099                 retval.setIndexCode(( short ) 0x2a);
1100                 retval.setFormatStringLength(( byte ) 0x32);
1101                 retval.setFormatString(
1102                     "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)");
1103                 break;
1104 
1105             case 5 :
1106                 retval.setIndexCode(( short ) 0x29);
1107                 retval.setFormatStringLength(( byte ) 0x29);
1108                 retval.setFormatString(
1109                     "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)");
1110                 break;
1111 
1112             case 6 :
1113                 retval.setIndexCode(( short ) 0x2c);
1114                 retval.setFormatStringLength(( byte ) 0x3a);
1115                 retval.setFormatString(
1116                     "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)");
1117                 break;
1118 
1119             case 7 :
1120                 retval.setIndexCode(( short ) 0x2b);
1121                 retval.setFormatStringLength(( byte ) 0x31);
1122                 retval.setFormatString(
1123                     "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)");
1124                 break;
1125         }
1126         return retval;
1127     }
1128 
1129     /**
1130      * Creates an ExtendedFormatRecord object
1131      * @param id    the number of the extended format record to create (meaning its position in
1132      *        a file as MS Excel would create it.)
1133      *
1134      * @return record containing an ExtendedFormatRecord
1135      * @see org.apache.poi.hssf.record.ExtendedFormatRecord
1136      * @see org.apache.poi.hssf.record.Record
1137      */
1138 
1139     protected Record createExtendedFormat(int id)
1140     {   // we'll need multiple editions
1141         ExtendedFormatRecord retval = new ExtendedFormatRecord();
1142 
1143         switch (id)
1144         {
1145 
1146             case 0 :
1147                 retval.setFontIndex(( short ) 0);
1148                 retval.setFormatIndex(( short ) 0);
1149                 retval.setCellOptions(( short ) 0xfffffff5);
1150                 retval.setAlignmentOptions(( short ) 0x20);
1151                 retval.setIndentionOptions(( short ) 0);
1152                 retval.setBorderOptions(( short ) 0);
1153                 retval.setPaletteOptions(( short ) 0);
1154                 retval.setAdtlPaletteOptions(( short ) 0);
1155                 retval.setFillPaletteOptions(( short ) 0x20c0);
1156                 break;
1157 
1158             case 1 :
1159                 retval.setFontIndex(( short ) 1);
1160                 retval.setFormatIndex(( short ) 0);
1161                 retval.setCellOptions(( short ) 0xfffffff5);
1162                 retval.setAlignmentOptions(( short ) 0x20);
1163                 retval.setIndentionOptions(( short ) 0xfffff400);
1164                 retval.setBorderOptions(( short ) 0);
1165                 retval.setPaletteOptions(( short ) 0);
1166                 retval.setAdtlPaletteOptions(( short ) 0);
1167                 retval.setFillPaletteOptions(( short ) 0x20c0);
1168                 break;
1169 
1170             case 2 :
1171                 retval.setFontIndex(( short ) 1);
1172                 retval.setFormatIndex(( short ) 0);
1173                 retval.setCellOptions(( short ) 0xfffffff5);
1174                 retval.setAlignmentOptions(( short ) 0x20);
1175                 retval.setIndentionOptions(( short ) 0xfffff400);
1176                 retval.setBorderOptions(( short ) 0);
1177                 retval.setPaletteOptions(( short ) 0);
1178                 retval.setAdtlPaletteOptions(( short ) 0);
1179                 retval.setFillPaletteOptions(( short ) 0x20c0);
1180                 break;
1181 
1182             case 3 :
1183                 retval.setFontIndex(( short ) 2);
1184                 retval.setFormatIndex(( short ) 0);
1185                 retval.setCellOptions(( short ) 0xfffffff5);
1186                 retval.setAlignmentOptions(( short ) 0x20);
1187                 retval.setIndentionOptions(( short ) 0xfffff400);
1188                 retval.setBorderOptions(( short ) 0);
1189                 retval.setPaletteOptions(( short ) 0);
1190                 retval.setAdtlPaletteOptions(( short ) 0);
1191                 retval.setFillPaletteOptions(( short ) 0x20c0);
1192                 break;
1193 
1194             case 4 :
1195                 retval.setFontIndex(( short ) 2);
1196                 retval.setFormatIndex(( short ) 0);
1197                 retval.setCellOptions(( short ) 0xfffffff5);
1198                 retval.setAlignmentOptions(( short ) 0x20);
1199                 retval.setIndentionOptions(( short ) 0xfffff400);
1200                 retval.setBorderOptions(( short ) 0);
1201                 retval.setPaletteOptions(( short ) 0);
1202                 retval.setAdtlPaletteOptions(( short ) 0);
1203                 retval.setFillPaletteOptions(( short ) 0x20c0);
1204                 break;
1205 
1206             case 5 :
1207                 retval.setFontIndex(( short ) 0);
1208                 retval.setFormatIndex(( short ) 0);
1209                 retval.setCellOptions(( short ) 0xfffffff5);
1210                 retval.setAlignmentOptions(( short ) 0x20);
1211                 retval.setIndentionOptions(( short ) 0xfffff400);
1212                 retval.setBorderOptions(( short ) 0);
1213                 retval.setPaletteOptions(( short ) 0);
1214                 retval.setAdtlPaletteOptions(( short ) 0);
1215                 retval.setFillPaletteOptions(( short ) 0x20c0);
1216                 break;
1217 
1218             case 6 :
1219                 retval.setFontIndex(( short ) 0);
1220                 retval.setFormatIndex(( short ) 0);
1221                 retval.setCellOptions(( short ) 0xfffffff5);
1222                 retval.setAlignmentOptions(( short ) 0x20);
1223                 retval.setIndentionOptions(( short ) 0xfffff400);
1224                 retval.setBorderOptions(( short ) 0);
1225                 retval.setPaletteOptions(( short ) 0);
1226                 retval.setAdtlPaletteOptions(( short ) 0);
1227                 retval.setFillPaletteOptions(( short ) 0x20c0);
1228                 break;
1229 
1230             case 7 :
1231                 retval.setFontIndex(( short ) 0);
1232                 retval.setFormatIndex(( short ) 0);
1233                 retval.setCellOptions(( short ) 0xfffffff5);
1234                 retval.setAlignmentOptions(( short ) 0x20);
1235                 retval.setIndentionOptions(( short ) 0xfffff400);
1236                 retval.setBorderOptions(( short ) 0);
1237                 retval.setPaletteOptions(( short ) 0);
1238                 retval.setAdtlPaletteOptions(( short ) 0);
1239                 retval.setFillPaletteOptions(( short ) 0x20c0);
1240                 break;
1241 
1242             case 8 :
1243                 retval.setFontIndex(( short ) 0);
1244                 retval.setFormatIndex(( short ) 0);
1245                 retval.setCellOptions(( short ) 0xfffffff5);
1246                 retval.setAlignmentOptions(( short ) 0x20);
1247                 retval.setIndentionOptions(( short ) 0xfffff400);
1248                 retval.setBorderOptions(( short ) 0);
1249                 retval.setPaletteOptions(( short ) 0);
1250                 retval.setAdtlPaletteOptions(( short ) 0);
1251                 retval.setFillPaletteOptions(( short ) 0x20c0);
1252                 break;
1253 
1254             case 9 :
1255                 retval.setFontIndex(( short ) 0);
1256                 retval.setFormatIndex(( short ) 0);
1257                 retval.setCellOptions(( short ) 0xfffffff5);
1258                 retval.setAlignmentOptions(( short ) 0x20);
1259                 retval.setIndentionOptions(( short ) 0xfffff400);
1260                 retval.setBorderOptions(( short ) 0);
1261                 retval.setPaletteOptions(( short ) 0);
1262                 retval.setAdtlPaletteOptions(( short ) 0);
1263                 retval.setFillPaletteOptions(( short ) 0x20c0);
1264                 break;
1265 
1266             case 10 :
1267                 retval.setFontIndex(( short ) 0);
1268                 retval.setFormatIndex(( short ) 0);
1269                 retval.setCellOptions(( short ) 0xfffffff5);
1270                 retval.setAlignmentOptions(( short ) 0x20);
1271                 retval.setIndentionOptions(( short ) 0xfffff400);
1272                 retval.setBorderOptions(( short ) 0);
1273                 retval.setPaletteOptions(( short ) 0);
1274                 retval.setAdtlPaletteOptions(( short ) 0);
1275                 retval.setFillPaletteOptions(( short ) 0x20c0);
1276                 break;
1277 
1278             case 11 :
1279                 retval.setFontIndex(( short ) 0);
1280                 retval.setFormatIndex(( short ) 0);
1281                 retval.setCellOptions(( short ) 0xfffffff5);
1282                 retval.setAlignmentOptions(( short ) 0x20);
1283                 retval.setIndentionOptions(( short ) 0xfffff400);
1284                 retval.setBorderOptions(( short ) 0);
1285                 retval.setPaletteOptions(( short ) 0);
1286                 retval.setAdtlPaletteOptions(( short ) 0);
1287                 retval.setFillPaletteOptions(( short ) 0x20c0);
1288                 break;
1289 
1290             case 12 :
1291                 retval.setFontIndex(( short ) 0);
1292                 retval.setFormatIndex(( short ) 0);
1293                 retval.setCellOptions(( short ) 0xfffffff5);
1294                 retval.setAlignmentOptions(( short ) 0x20);
1295                 retval.setIndentionOptions(( short ) 0xfffff400);
1296                 retval.setBorderOptions(( short ) 0);
1297                 retval.setPaletteOptions(( short ) 0);
1298                 retval.setAdtlPaletteOptions(( short ) 0);
1299                 retval.setFillPaletteOptions(( short ) 0x20c0);
1300                 break;
1301 
1302             case 13 :
1303                 retval.setFontIndex(( short ) 0);
1304                 retval.setFormatIndex(( short ) 0);
1305                 retval.setCellOptions(( short ) 0xfffffff5);
1306                 retval.setAlignmentOptions(( short ) 0x20);
1307                 retval.setIndentionOptions(( short ) 0xfffff400);
1308                 retval.setBorderOptions(( short ) 0);
1309                 retval.setPaletteOptions(( short ) 0);
1310                 retval.setAdtlPaletteOptions(( short ) 0);
1311                 retval.setFillPaletteOptions(( short ) 0x20c0);
1312                 break;
1313 
1314             case 14 :
1315                 retval.setFontIndex(( short ) 0);
1316                 retval.setFormatIndex(( short ) 0);
1317                 retval.setCellOptions(( short ) 0xfffffff5);
1318                 retval.setAlignmentOptions(( short ) 0x20);
1319                 retval.setIndentionOptions(( short ) 0xfffff400);
1320                 retval.setBorderOptions(( short ) 0);
1321                 retval.setPaletteOptions(( short ) 0);
1322                 retval.setAdtlPaletteOptions(( short ) 0);
1323                 retval.setFillPaletteOptions(( short ) 0x20c0);
1324                 break;
1325 
1326             // cell records
1327             case 15 :
1328                 retval.setFontIndex(( short ) 0);
1329                 retval.setFormatIndex(( short ) 0);
1330                 retval.setCellOptions(( short ) 0x1);
1331                 retval.setAlignmentOptions(( short ) 0x20);
1332                 retval.setIndentionOptions(( short ) 0x0);
1333                 retval.setBorderOptions(( short ) 0);
1334                 retval.setPaletteOptions(( short ) 0);
1335                 retval.setAdtlPaletteOptions(( short ) 0);
1336                 retval.setFillPaletteOptions(( short ) 0x20c0);
1337                 break;
1338 
1339             // style
1340             case 16 :
1341                 retval.setFontIndex(( short ) 1);
1342                 retval.setFormatIndex(( short ) 0x2b);
1343                 retval.setCellOptions(( short ) 0xfffffff5);
1344                 retval.setAlignmentOptions(( short ) 0x20);
1345                 retval.setIndentionOptions(( short ) 0xfffff800);
1346                 retval.setBorderOptions(( short ) 0);
1347                 retval.setPaletteOptions(( short ) 0);
1348                 retval.setAdtlPaletteOptions(( short ) 0);
1349                 retval.setFillPaletteOptions(( short ) 0x20c0);
1350                 break;
1351 
1352             case 17 :
1353                 retval.setFontIndex(( short ) 1);
1354                 retval.setFormatIndex(( short ) 0x29);
1355                 retval.setCellOptions(( short ) 0xfffffff5);
1356                 retval.setAlignmentOptions(( short ) 0x20);
1357                 retval.setIndentionOptions(( short ) 0xfffff800);
1358                 retval.setBorderOptions(( short ) 0);
1359                 retval.setPaletteOptions(( short ) 0);
1360                 retval.setAdtlPaletteOptions(( short ) 0);
1361                 retval.setFillPaletteOptions(( short ) 0x20c0);
1362                 break;
1363 
1364             case 18 :
1365                 retval.setFontIndex(( short ) 1);
1366                 retval.setFormatIndex(( short ) 0x2c);
1367                 retval.setCellOptions(( short ) 0xfffffff5);
1368                 retval.setAlignmentOptions(( short ) 0x20);
1369                 retval.setIndentionOptions(( short ) 0xfffff800);
1370                 retval.setBorderOptions(( short ) 0);
1371                 retval.setPaletteOptions(( short ) 0);
1372                 retval.setAdtlPaletteOptions(( short ) 0);
1373                 retval.setFillPaletteOptions(( short ) 0x20c0);
1374                 break;
1375 
1376             case 19 :
1377                 retval.setFontIndex(( short ) 1);
1378                 retval.setFormatIndex(( short ) 0x2a);
1379                 retval.setCellOptions(( short ) 0xfffffff5);
1380                 retval.setAlignmentOptions(( short ) 0x20);
1381                 retval.setIndentionOptions(( short ) 0xfffff800);
1382                 retval.setBorderOptions(( short ) 0);
1383                 retval.setPaletteOptions(( short ) 0);
1384                 retval.setAdtlPaletteOptions(( short ) 0);
1385                 retval.setFillPaletteOptions(( short ) 0x20c0);
1386                 break;
1387 
1388             case 20 :
1389                 retval.setFontIndex(( short ) 1);
1390                 retval.setFormatIndex(( short ) 0x9);
1391                 retval.setCellOptions(( short ) 0xfffffff5);
1392                 retval.setAlignmentOptions(( short ) 0x20);
1393                 retval.setIndentionOptions(( short ) 0xfffff800);
1394                 retval.setBorderOptions(( short ) 0);
1395                 retval.setPaletteOptions(( short ) 0);
1396                 retval.setAdtlPaletteOptions(( short ) 0);
1397                 retval.setFillPaletteOptions(( short ) 0x20c0);
1398                 break;
1399 
1400             // unused from this point down
1401             case 21 :
1402                 retval.setFontIndex(( short ) 5);
1403                 retval.setFormatIndex(( short ) 0x0);
1404                 retval.setCellOptions(( short ) 0x1);
1405                 retval.setAlignmentOptions(( short ) 0x20);
1406                 retval.setIndentionOptions(( short ) 0x800);
1407                 retval.setBorderOptions(( short ) 0);
1408                 retval.setPaletteOptions(( short ) 0);
1409                 retval.setAdtlPaletteOptions(( short ) 0);
1410                 retval.setFillPaletteOptions(( short ) 0x20c0);
1411                 break;
1412 
1413             case 22 :
1414                 retval.setFontIndex(( short ) 6);
1415                 retval.setFormatIndex(( short ) 0x0);
1416                 retval.setCellOptions(( short ) 0x1);
1417                 retval.setAlignmentOptions(( short ) 0x20);
1418                 retval.setIndentionOptions(( short ) 0x5c00);
1419                 retval.setBorderOptions(( short ) 0);
1420                 retval.setPaletteOptions(( short ) 0);
1421                 retval.setAdtlPaletteOptions(( short ) 0);
1422                 retval.setFillPaletteOptions(( short ) 0x20c0);
1423                 break;
1424 
1425             case 23 :
1426                 retval.setFontIndex(( short ) 0);
1427                 retval.setFormatIndex(( short ) 0x31);
1428                 retval.setCellOptions(( short ) 0x1);
1429                 retval.setAlignmentOptions(( short ) 0x20);
1430                 retval.setIndentionOptions(( short ) 0x5c00);
1431                 retval.setBorderOptions(( short ) 0);
1432                 retval.setPaletteOptions(( short ) 0);
1433                 retval.setAdtlPaletteOptions(( short ) 0);
1434                 retval.setFillPaletteOptions(( short ) 0x20c0);
1435                 break;
1436 
1437             case 24 :
1438                 retval.setFontIndex(( short ) 0);
1439                 retval.setFormatIndex(( short ) 0x8);
1440                 retval.setCellOptions(( short ) 0x1);
1441                 retval.setAlignmentOptions(( short ) 0x20);
1442                 retval.setIndentionOptions(( short ) 0x5c00);
1443                 retval.setBorderOptions(( short ) 0);
1444                 retval.setPaletteOptions(( short ) 0);
1445                 retval.setAdtlPaletteOptions(( short ) 0);
1446                 retval.setFillPaletteOptions(( short ) 0x20c0);
1447                 break;
1448 
1449             case 25 :
1450                 retval.setFontIndex(( short ) 6);
1451                 retval.setFormatIndex(( short ) 0x8);
1452                 retval.setCellOptions(( short ) 0x1);
1453                 retval.setAlignmentOptions(( short ) 0x20);
1454                 retval.setIndentionOptions(( short ) 0x5c00);
1455                 retval.setBorderOptions(( short ) 0);
1456                 retval.setPaletteOptions(( short ) 0);
1457                 retval.setAdtlPaletteOptions(( short ) 0);
1458                 retval.setFillPaletteOptions(( short ) 0x20c0);
1459                 break;
1460         }
1461         return retval;
1462     }
1463 
1464     /**
1465      * creates an default cell type ExtendedFormatRecord object.
1466      * @return ExtendedFormatRecord with intial defaults (cell-type)
1467      */
1468 
1469     protected ExtendedFormatRecord createExtendedFormat()
1470     {
1471         ExtendedFormatRecord retval = new ExtendedFormatRecord();
1472 
1473         retval.setFontIndex(( short ) 0);
1474         retval.setFormatIndex(( short ) 0x0);
1475         retval.setCellOptions(( short ) 0x1);
1476         retval.setAlignmentOptions(( short ) 0x20);
1477         retval.setIndentionOptions(( short ) 0);
1478         retval.setBorderOptions(( short ) 0);
1479         retval.setPaletteOptions(( short ) 0);
1480         retval.setAdtlPaletteOptions(( short ) 0);
1481         retval.setFillPaletteOptions(( short ) 0x20c0);
1482         return retval;
1483     }
1484 
1485     /**
1486      * Creates a StyleRecord object
1487      * @param id        the number of the style record to create (meaning its position in
1488      *                  a file as MS Excel would create it.
1489      * @return record containing a StyleRecord
1490      * @see org.apache.poi.hssf.record.StyleRecord
1491      * @see org.apache.poi.hssf.record.Record
1492      */
1493 
1494     protected Record createStyle(int id)
1495     {   // we'll need multiple editions
1496         StyleRecord retval = new StyleRecord();
1497 
1498         switch (id)
1499         {
1500 
1501             case 0 :
1502                 retval.setIndex(( short ) 0xffff8010);
1503                 retval.setBuiltin(( byte ) 3);
1504                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1505                 break;
1506 
1507             case 1 :
1508                 retval.setIndex(( short ) 0xffff8011);
1509                 retval.setBuiltin(( byte ) 6);
1510                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1511                 break;
1512 
1513             case 2 :
1514                 retval.setIndex(( short ) 0xffff8012);
1515                 retval.setBuiltin(( byte ) 4);
1516                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1517                 break;
1518 
1519             case 3 :
1520                 retval.setIndex(( short ) 0xffff8013);
1521                 retval.setBuiltin(( byte ) 7);
1522                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1523                 break;
1524 
1525             case 4 :
1526                 retval.setIndex(( short ) 0xffff8000);
1527                 retval.setBuiltin(( byte ) 0);
1528                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1529                 break;
1530 
1531             case 5 :
1532                 retval.setIndex(( short ) 0xffff8014);
1533                 retval.setBuiltin(( byte ) 5);
1534                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
1535                 break;
1536         }
1537         return retval;
1538     }
1539 
1540     /**
1541      * Creates the UseSelFS object with the use natural language flag set to 0 (false)
1542      * @return record containing a UseSelFSRecord
1543      * @see org.apache.poi.hssf.record.UseSelFSRecord
1544      * @see org.apache.poi.hssf.record.Record
1545      */
1546 
1547     protected Record createUseSelFS()
1548     {
1549         UseSelFSRecord retval = new UseSelFSRecord();
1550 
1551         retval.setFlag(( short ) 0);
1552         return retval;
1553     }
1554 
1555     /**
1556      * create a "bound sheet" or "bundlesheet" (depending who you ask) record
1557      * Always sets the sheet's bof to 0.  You'll need to set that yourself.
1558      * @param id either sheet 0,1 or 2.
1559      * @return record containing a BoundSheetRecord
1560      * @see org.apache.poi.hssf.record.BoundSheetRecord
1561      * @see org.apache.poi.hssf.record.Record
1562      */
1563 
1564     protected Record createBoundSheet(int id)
1565     {   // 1,2,3 sheets
1566         BoundSheetRecord retval = new BoundSheetRecord();
1567 
1568         switch (id)
1569         {
1570 
1571             case 0 :
1572                 retval.setPositionOfBof(0x0);   // should be set later
1573                 retval.setOptionFlags(( short ) 0);
1574                 retval.setSheetnameLength(( byte ) 0x6);
1575                 retval.setCompressedUnicodeFlag(( byte ) 0);
1576                 retval.setSheetname("Sheet1");
1577                 break;
1578 
1579             case 1 :
1580                 retval.setPositionOfBof(0x0);   // should be set later
1581                 retval.setOptionFlags(( short ) 0);
1582                 retval.setSheetnameLength(( byte ) 0x6);
1583                 retval.setCompressedUnicodeFlag(( byte ) 0);
1584                 retval.setSheetname("Sheet2");
1585                 break;
1586 
1587             case 2 :
1588                 retval.setPositionOfBof(0x0);   // should be set later
1589                 retval.setOptionFlags(( short ) 0);
1590                 retval.setSheetnameLength(( byte ) 0x6);
1591                 retval.setCompressedUnicodeFlag(( byte ) 0);
1592                 retval.setSheetname("Sheet3");
1593                 break;
1594         }
1595         return retval;
1596     }
1597 
1598     /**
1599      * Creates the Country record with the default and current country set to 1
1600      * @return record containing a CountryRecord
1601      * @see org.apache.poi.hssf.record.CountryRecord
1602      * @see org.apache.poi.hssf.record.Record
1603      */
1604 
1605     protected Record createCountry()
1606     {   // what a novel idea, create your own!
1607         CountryRecord retval = new CountryRecord();
1608 
1609         retval.setDefaultCountry(( short ) 1);
1610         retval.setCurrentCountry(( short ) 1);
1611         return retval;
1612     }
1613 
1614     /**
1615      * Creates the SST record with no strings and the unique/num string set to 0
1616      * @return record containing a SSTRecord
1617      * @see org.apache.poi.hssf.record.SSTRecord
1618      * @see org.apache.poi.hssf.record.Record
1619      */
1620 
1621     protected Record createSST()
1622     {
1623         return new SSTRecord();
1624     }
1625 
1626     /**
1627      * Creates the ExtendedSST record with numstrings per bucket set to 0x8.  HSSF
1628      * doesn't yet know what to do with this thing, but we create it with nothing in
1629      * it hardly just to make Excel happy and our sheets look like Excel's
1630      *
1631      * @return record containing an ExtSSTRecord
1632      * @see org.apache.poi.hssf.record.ExtSSTRecord
1633      * @see org.apache.poi.hssf.record.Record
1634      */
1635 
1636     protected Record createExtendedSST()
1637     {
1638         ExtSSTRecord retval = new ExtSSTRecord();
1639 
1640         retval.setNumStringsPerBucket(( short ) 0x8);
1641         return retval;
1642     }
1643 
1644     /**
1645      * creates the EOF record
1646      * @see org.apache.poi.hssf.record.EOFRecord
1647      * @see org.apache.poi.hssf.record.Record
1648      * @return record containing a EOFRecord
1649      */
1650 
1651     protected Record createEOF()
1652     {
1653         return new EOFRecord();
1654     }
1655 
1656     /**
1657      * Returns the first occurance of a record matching a particular sid.
1658      */
1659 
1660     public Record findFirstRecordBySid(short sid)
1661     {
1662         for (Iterator iterator = records.iterator(); iterator.hasNext(); )
1663         {
1664             Record record = ( Record ) iterator.next();
1665 
1666             if (record.getSid() == sid)
1667             {
1668                 return record;
1669             }
1670         }
1671         return null;
1672     }
1673 }
1674