]> source.dussan.org Git - poi.git/commitdiff
Renamed model.Workbook to InternalWorkbook to alleviate name clash.
authorJosh Micich <josh@apache.org>
Tue, 22 Dec 2009 00:51:29 +0000 (00:51 +0000)
committerJosh Micich <josh@apache.org>
Tue, 22 Dec 2009 00:51:29 +0000 (00:51 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@893050 13f79535-47bb-0310-9956-ffa450edef68

23 files changed:
src/java/org/apache/poi/hssf/eventusermodel/EventWorkbookBuilder.java
src/java/org/apache/poi/hssf/model/InternalWorkbook.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/model/Sheet.java
src/java/org/apache/poi/hssf/model/Workbook.java [deleted file]
src/java/org/apache/poi/hssf/record/FormatRecord.java
src/java/org/apache/poi/hssf/record/PaletteRecord.java
src/java/org/apache/poi/hssf/record/RecalcIdRecord.java
src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
src/java/org/apache/poi/hssf/usermodel/HSSFDataFormat.java
src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
src/java/org/apache/poi/hssf/usermodel/HSSFName.java
src/java/org/apache/poi/hssf/usermodel/HSSFRichTextString.java
src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
src/testcases/org/apache/poi/hssf/eventusermodel/TestEventWorkbookBuilder.java
src/testcases/org/apache/poi/hssf/model/TestWorkbook.java
src/testcases/org/apache/poi/hssf/usermodel/SanityChecker.java
src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java
src/testcases/org/apache/poi/hssf/usermodel/TestWorkbook.java
src/testcases/org/apache/poi/hssf/util/TestAreaReference.java

index c7a1471a7d958acf38a16ce3930355691b7ecd70..c8c2491f3c23e2317f4f05fe7ec6fdfafaaae505 100644 (file)
@@ -20,7 +20,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.BoundSheetRecord;
 import org.apache.poi.hssf.record.EOFRecord;
 import org.apache.poi.hssf.record.ExternSheetRecord;
@@ -30,39 +30,31 @@ import org.apache.poi.hssf.record.SupBookRecord;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 
 /**
- * When working with the EventUserModel, if you want to 
+ * When working with the EventUserModel, if you want to
  *  process formulas, you need an instance of
- *  {@link Workbook} to pass to a {@link HSSFWorkbook},
- *  to finally give to {@link HSSFFormulaParser}, 
+ *  {@link InternalWorkbook} to pass to a {@link HSSFWorkbook},
+ *  to finally give to {@link HSSFFormulaParser},
  *  and this will build you stub ones.
  * Since you're working with the EventUserModel, you
- *  wouldn't want to get a full {@link Workbook} and
+ *  wouldn't want to get a full {@link InternalWorkbook} and
  *  {@link HSSFWorkbook}, as they would eat too much memory.
  *  Instead, you should collect a few key records as they
  *  go past, then call this once you have them to build a
- *  stub {@link Workbook}, and from that a stub
+ *  stub {@link InternalWorkbook}, and from that a stub
  *  {@link HSSFWorkbook}, to use with the {@link HSSFFormulaParser}.
- * 
+ *
  * The records you should collect are:
  *  * {@link ExternSheetRecord}
  *  * {@link BoundSheetRecord}
- * You should probably also collect {@link SSTRecord}, 
+ * You should probably also collect {@link SSTRecord},
  *  but it's not required to pass this in.
- *  
+ *
  * To help, this class includes a HSSFListener wrapper
  *  that will do the collecting for you.
  */
 public class EventWorkbookBuilder {
-       /**
-        * Wraps up your stub {@link Workbook} as a stub
-        *  {@link HSSFWorkbook}, ready for passing to
-        *  {@link HSSFFormulaParser}
-        * @param workbook A stub {@link Workbook}
-        */
-       public static HSSFWorkbook createStubHSSFWorkbook(Workbook workbook) {
-               return new StubHSSFWorkbook(workbook);
-       }
-       
+
+
        /**
         * Creates a stub Workbook from the supplied records,
         *  suitable for use with the {@link HSSFFormulaParser}
@@ -71,10 +63,10 @@ public class EventWorkbookBuilder {
         * @param sst The SSTRecord in your file.
         * @return A stub Workbook suitable for use with {@link HSSFFormulaParser}
         */
-       public static Workbook createStubWorkbook(ExternSheetRecord[] externs,
+       public static InternalWorkbook createStubWorkbook(ExternSheetRecord[] externs,
                        BoundSheetRecord[] bounds, SSTRecord sst) {
                List wbRecords = new ArrayList();
-               
+
                // Core Workbook records go first
                if(bounds != null) {
                        for(int i=0; i<bounds.length; i++) {
@@ -84,7 +76,7 @@ public class EventWorkbookBuilder {
                if(sst != null) {
                        wbRecords.add(sst);
                }
-               
+
                // Now we can have the ExternSheetRecords,
                //  preceded by a SupBookRecord
                if(externs != null) {
@@ -94,13 +86,13 @@ public class EventWorkbookBuilder {
                                wbRecords.add(externs[i]);
                        }
                }
-               
+
                // Finally we need an EoF record
                wbRecords.add(EOFRecord.instance);
-               
-               return Workbook.createWorkbook(wbRecords);
+
+               return InternalWorkbook.createWorkbook(wbRecords);
        }
-       
+
        /**
         * Creates a stub workbook from the supplied records,
         *  suitable for use with the {@link HSSFFormulaParser}
@@ -108,16 +100,16 @@ public class EventWorkbookBuilder {
         * @param bounds The BoundSheetRecords in your file
         * @return A stub Workbook suitable for use with {@link HSSFFormulaParser}
         */
-       public static Workbook createStubWorkbook(ExternSheetRecord[] externs,
+       public static InternalWorkbook createStubWorkbook(ExternSheetRecord[] externs,
                        BoundSheetRecord[] bounds) {
                return createStubWorkbook(externs, bounds, null);
        }
-       
-       
+
+
        /**
-        * A wrapping HSSFListener which will collect 
+        * A wrapping HSSFListener which will collect
         *  {@link BoundSheetRecord}s and {@link ExternSheetRecord}s as
-        *  they go past, so you can create a Stub {@link Workbook} from
+        *  they go past, so you can create a Stub {@link InternalWorkbook} from
         *  them once required.
         */
        public static class SheetRecordCollectingListener implements HSSFListener {
@@ -125,12 +117,12 @@ public class EventWorkbookBuilder {
                private List boundSheetRecords = new ArrayList();
                private List externSheetRecords = new ArrayList();
                private SSTRecord sstRecord = null;
-               
+
                public SheetRecordCollectingListener(HSSFListener childListener) {
                        this.childListener = childListener;
                }
-               
-               
+
+
                public BoundSheetRecord[] getBoundSheetRecords() {
                        return (BoundSheetRecord[])boundSheetRecords.toArray(
                                        new BoundSheetRecord[boundSheetRecords.size()]
@@ -144,20 +136,18 @@ public class EventWorkbookBuilder {
                public SSTRecord getSSTRecord() {
                        return sstRecord;
                }
-               
+
                public HSSFWorkbook getStubHSSFWorkbook() {
-                       return createStubHSSFWorkbook(
-                                       getStubWorkbook()
-                       );
+                       return HSSFWorkbook.create(getStubWorkbook());
                }
-               public Workbook getStubWorkbook() {
+               public InternalWorkbook getStubWorkbook() {
                        return createStubWorkbook(
-                                       getExternSheetRecords(), getBoundSheetRecords(), 
+                                       getExternSheetRecords(), getBoundSheetRecords(),
                                        getSSTRecord()
                        );
                }
-               
-               
+
+
                /**
                 * Process this record ourselves, and then
                 *  pass it on to our child listener
@@ -165,11 +155,11 @@ public class EventWorkbookBuilder {
                public void processRecord(Record record) {
                        // Handle it ourselves
                        processRecordInternally(record);
-                       
+
                        // Now pass on to our child
                        childListener.processRecord(record);
                }
-               
+
                /**
                 * Process the record ourselves, but do not
                 *  pass it on to the child Listener.
@@ -186,14 +176,4 @@ public class EventWorkbookBuilder {
                        }
                }
        }
-       
-       /**
-        * Let us at the {@link Workbook} constructor on
-        *  {@link HSSFWorkbook}
-        */
-       private static class StubHSSFWorkbook extends HSSFWorkbook {
-               private StubHSSFWorkbook(Workbook wb) {
-                       super(wb);
-               }
-       }
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java
new file mode 100644 (file)
index 0000000..4102d81
--- /dev/null
@@ -0,0 +1,2340 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.model;
+
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.poi.ddf.EscherBSERecord;
+import org.apache.poi.ddf.EscherBoolProperty;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherDgRecord;
+import org.apache.poi.ddf.EscherDggRecord;
+import org.apache.poi.ddf.EscherOptRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.ddf.EscherRGBProperty;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.ddf.EscherSplitMenuColorsRecord;
+import org.apache.poi.hssf.record.BOFRecord;
+import org.apache.poi.hssf.record.BackupRecord;
+import org.apache.poi.hssf.record.BookBoolRecord;
+import org.apache.poi.hssf.record.BoundSheetRecord;
+import org.apache.poi.hssf.record.CodepageRecord;
+import org.apache.poi.hssf.record.CountryRecord;
+import org.apache.poi.hssf.record.DSFRecord;
+import org.apache.poi.hssf.record.DateWindow1904Record;
+import org.apache.poi.hssf.record.DrawingGroupRecord;
+import org.apache.poi.hssf.record.EOFRecord;
+import org.apache.poi.hssf.record.EscherAggregate;
+import org.apache.poi.hssf.record.ExtSSTRecord;
+import org.apache.poi.hssf.record.ExtendedFormatRecord;
+import org.apache.poi.hssf.record.ExternSheetRecord;
+import org.apache.poi.hssf.record.FileSharingRecord;
+import org.apache.poi.hssf.record.FnGroupCountRecord;
+import org.apache.poi.hssf.record.FontRecord;
+import org.apache.poi.hssf.record.FormatRecord;
+import org.apache.poi.hssf.record.HideObjRecord;
+import org.apache.poi.hssf.record.HyperlinkRecord;
+import org.apache.poi.hssf.record.InterfaceEndRecord;
+import org.apache.poi.hssf.record.InterfaceHdrRecord;
+import org.apache.poi.hssf.record.MMSRecord;
+import org.apache.poi.hssf.record.NameRecord;
+import org.apache.poi.hssf.record.PaletteRecord;
+import org.apache.poi.hssf.record.PasswordRecord;
+import org.apache.poi.hssf.record.PasswordRev4Record;
+import org.apache.poi.hssf.record.PrecisionRecord;
+import org.apache.poi.hssf.record.ProtectRecord;
+import org.apache.poi.hssf.record.ProtectionRev4Record;
+import org.apache.poi.hssf.record.RecalcIdRecord;
+import org.apache.poi.hssf.record.Record;
+import org.apache.poi.hssf.record.RefreshAllRecord;
+import org.apache.poi.hssf.record.SSTRecord;
+import org.apache.poi.hssf.record.StyleRecord;
+import org.apache.poi.hssf.record.SupBookRecord;
+import org.apache.poi.hssf.record.TabIdRecord;
+import org.apache.poi.hssf.record.UnicodeString;
+import org.apache.poi.hssf.record.UseSelFSRecord;
+import org.apache.poi.hssf.record.WindowOneRecord;
+import org.apache.poi.hssf.record.WindowProtectRecord;
+import org.apache.poi.hssf.record.WriteAccessRecord;
+import org.apache.poi.hssf.record.WriteProtectRecord;
+import org.apache.poi.hssf.record.formula.NameXPtg;
+import org.apache.poi.hssf.record.formula.FormulaShifter;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.util.HSSFColor;
+import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+/**
+ * Low level model implementation of a Workbook.  Provides creational methods
+ * for settings and objects contained in the workbook object.
+ * <P>
+ * This file contains the low level binary records starting at the workbook's BOF and
+ * ending with the workbook's EOF.  Use HSSFWorkbook for a high level representation.
+ * <P>
+ * The structures of the highlevel API use references to this to perform most of their
+ * operations.  Its probably unwise to use these low level structures directly unless you
+ * really know what you're doing.  I recommend you read the Microsoft Excel 97 Developer's
+ * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf
+ * before even attempting to use this.
+ *
+ *
+ * @author  Luc Girardin (luc dot girardin at macrofocus dot com)
+ * @author  Sergei Kozello (sergeikozello at mail.ru)
+ * @author  Shawn Laubach (slaubach at apache dot org) (Data Formats)
+ * @author  Andrew C. Oliver (acoliver at apache dot org)
+ * @author  Brian Sanders (bsanders at risklabs dot com) - custom palette
+ * @author  Dan Sherman (dsherman at isisph.com)
+ * @author  Glen Stampoultzis (glens at apache.org)
+ * @see org.apache.poi.hssf.usermodel.HSSFWorkbook
+ */
+@Internal
+public final class InternalWorkbook {
+    /**
+     * Excel silently truncates long sheet names to 31 chars.
+     * This constant is used to ensure uniqueness in the first 31 chars
+     */
+    private static final int MAX_SENSITIVE_SHEET_NAME_LEN = 31;
+
+
+    private static final POILogger log = POILogFactory.getLogger(InternalWorkbook.class);
+    private static final int DEBUG = POILogger.DEBUG;
+
+    /**
+     * constant used to set the "codepage" wherever "codepage" is set in records
+     * (which is duplicated in more than one record)
+     */
+    private final static short CODEPAGE = 0x04B0;
+
+    /**
+     * this contains the Worksheet record objects
+     */
+    private final WorkbookRecordList records;
+
+    /**
+     * this contains a reference to the SSTRecord so that new stings can be added
+     * to it.
+     */
+    protected SSTRecord sst;
+
+
+    private LinkTable linkTable; // optionally occurs if there are  references in the document. (4.10.3)
+
+    /**
+     * holds the "boundsheet" records (aka bundlesheet) so that they can have their
+     * reference to their "BOF" marker
+     */
+    private final List<BoundSheetRecord> boundsheets;
+    private final List<FormatRecord> formats;
+    private final List<HyperlinkRecord> hyperlinks;
+
+    /** the number of extended format records */
+       private int numxfs;
+    /** the number of font records */
+       private int numfonts;
+    /** holds the max format id */
+       private int maxformatid;
+    /** whether 1904 date windowing is being used */
+    private boolean uses1904datewindowing;
+    private DrawingManager2 drawingManager;
+    private List<EscherBSERecord> escherBSERecords;
+    private WindowOneRecord windowOne;
+    private FileSharingRecord fileShare;
+    private WriteAccessRecord writeAccess;
+    private WriteProtectRecord writeProtect;
+
+    private InternalWorkbook() {
+       records     = new WorkbookRecordList();
+
+               boundsheets = new ArrayList<BoundSheetRecord>();
+               formats = new ArrayList<FormatRecord>();
+               hyperlinks = new ArrayList<HyperlinkRecord>();
+               numxfs = 0;
+               numfonts = 0;
+               maxformatid = -1;
+               uses1904datewindowing = false;
+               escherBSERecords = new ArrayList<EscherBSERecord>();
+    }
+
+    /**
+     * read support  for low level
+     * API.  Pass in an array of Record objects, A Workbook
+     * object is constructed and passed back with all of its initialization set
+     * to the passed in records and references to those records held. Unlike Sheet
+     * workbook does not use an offset (its assumed to be 0) since its first in a file.
+     * If you need an offset then construct a new array with a 0 offset or write your
+     * own ;-p.
+     *
+     * @param recs an array of Record objects
+     * @return Workbook object
+     */
+    public static InternalWorkbook createWorkbook(List<Record> recs) {
+        if (log.check( POILogger.DEBUG ))
+            log.log(DEBUG, "Workbook (readfile) created with reclen=",
+                    Integer.valueOf(recs.size()));
+        InternalWorkbook retval = new InternalWorkbook();
+        List<Record> records = new ArrayList<Record>(recs.size() / 3);
+        retval.records.setRecords(records);
+
+        int k;
+        for (k = 0; k < recs.size(); k++) {
+            Record rec = recs.get(k);
+
+            if (rec.getSid() == EOFRecord.sid) {
+                records.add(rec);
+                if (log.check( POILogger.DEBUG ))
+                    log.log(DEBUG, "found workbook eof record at " + k);
+                break;
+            }
+            switch (rec.getSid()) {
+
+                case BoundSheetRecord.sid :
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found boundsheet record at " + k);
+                    retval.boundsheets.add((BoundSheetRecord) rec);
+                    retval.records.setBspos( k );
+                    break;
+
+                case SSTRecord.sid :
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found sst record at " + k);
+                    retval.sst = ( SSTRecord ) rec;
+                    break;
+
+                case FontRecord.sid :
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found font record at " + k);
+                    retval.records.setFontpos( k );
+                    retval.numfonts++;
+                    break;
+
+                case ExtendedFormatRecord.sid :
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found XF record at " + k);
+                    retval.records.setXfpos( k );
+                    retval.numxfs++;
+                    break;
+
+                case TabIdRecord.sid :
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found tabid record at " + k);
+                    retval.records.setTabpos( k );
+                    break;
+
+                case ProtectRecord.sid :
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found protect record at " + k);
+                    retval.records.setProtpos( k );
+                    break;
+
+                case BackupRecord.sid :
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found backup record at " + k);
+                    retval.records.setBackuppos( k );
+                    break;
+                case ExternSheetRecord.sid :
+                    throw new RuntimeException("Extern sheet is part of LinkTable");
+                case NameRecord.sid :
+                case SupBookRecord.sid :
+                    // LinkTable can start with either of these
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found SupBook record at " + k);
+                    retval.linkTable = new LinkTable(recs, k, retval.records);
+                    k+=retval.linkTable.getRecordCount() - 1;
+                    continue;
+                case FormatRecord.sid :
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found format record at " + k);
+                    retval.formats.add((FormatRecord) rec);
+                    retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode();
+                    break;
+                case DateWindow1904Record.sid :
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found datewindow1904 record at " + k);
+                    retval.uses1904datewindowing = ((DateWindow1904Record)rec).getWindowing() == 1;
+                    break;
+                case PaletteRecord.sid:
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found palette record at " + k);
+                    retval.records.setPalettepos( k );
+                    break;
+                case WindowOneRecord.sid:
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found WindowOneRecord at " + k);
+                    retval.windowOne = (WindowOneRecord) rec;
+                    break;
+                case WriteAccessRecord.sid:
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found WriteAccess at " + k);
+                    retval.writeAccess = (WriteAccessRecord) rec;
+                    break;
+                case WriteProtectRecord.sid:
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found WriteProtect at " + k);
+                    retval.writeProtect = (WriteProtectRecord) rec;
+                    break;
+                case FileSharingRecord.sid:
+                    if (log.check( POILogger.DEBUG ))
+                        log.log(DEBUG, "found FileSharing at " + k);
+                    retval.fileShare = (FileSharingRecord) rec;
+                default :
+            }
+            records.add(rec);
+        }
+        //What if we dont have any ranges and supbooks
+        //        if (retval.records.supbookpos == 0) {
+        //            retval.records.supbookpos = retval.records.bspos + 1;
+        //            retval.records.namepos    = retval.records.supbookpos + 1;
+        //        }
+
+        // Look for other interesting values that
+        //  follow the EOFRecord
+        for ( ; k < recs.size(); k++) {
+            Record rec = recs.get(k);
+            switch (rec.getSid()) {
+                case HyperlinkRecord.sid:
+                    retval.hyperlinks.add((HyperlinkRecord)rec);
+                    break;
+            }
+        }
+
+        if (retval.windowOne == null) {
+            retval.windowOne = createWindowOne();
+        }
+        if (log.check( POILogger.DEBUG ))
+            log.log(DEBUG, "exit create workbook from existing file function");
+        return retval;
+    }
+
+    /**
+     * Creates an empty workbook object with three blank sheets and all the empty
+     * fields.  Use this to create a workbook from scratch.
+     */
+    public static InternalWorkbook createWorkbook()
+    {
+        if (log.check( POILogger.DEBUG ))
+            log.log( DEBUG, "creating new workbook from scratch" );
+        InternalWorkbook retval = new InternalWorkbook();
+        List<Record> records = new ArrayList<Record>( 30 );
+        retval.records.setRecords(records);
+        List<FormatRecord> formats = retval.formats;
+
+        records.add(retval.createBOF());
+        records.add(retval.createInterfaceHdr());
+        records.add(retval.createMMS());
+        records.add(retval.createInterfaceEnd());
+        records.add(retval.createWriteAccess());
+        records.add(retval.createCodepage());
+        records.add(retval.createDSF());
+        records.add(retval.createTabId());
+        retval.records.setTabpos(records.size() - 1);
+        records.add(retval.createFnGroupCount());
+        records.add(createWindowProtect());
+        records.add(createProtect());
+        retval.records.setProtpos(records.size() - 1);
+        records.add(createPassword());
+        records.add(createProtectionRev4());
+        records.add(retval.createPasswordRev4());
+        retval.windowOne = createWindowOne();
+        records.add(retval.windowOne);
+        records.add(retval.createBackup());
+        retval.records.setBackuppos(records.size() - 1);
+        records.add(retval.createHideObj());
+        records.add(retval.createDateWindow1904());
+        records.add(retval.createPrecision());
+        records.add(createRefreshAll());
+        records.add(retval.createBookBool());
+        records.add(retval.createFont());
+        records.add(retval.createFont());
+        records.add(retval.createFont());
+        records.add(retval.createFont());
+        retval.records.setFontpos( records.size() - 1 );   // last font record position
+        retval.numfonts = 4;
+
+        // set up format records
+        for (int i = 0; i <= 7; i++) {
+            FormatRecord rec = createFormat(i);
+            retval.maxformatid = retval.maxformatid >= rec.getIndexCode() ? retval.maxformatid : rec.getIndexCode();
+            formats.add(rec);
+            records.add(rec);
+        }
+
+        for (int k = 0; k < 21; k++) {
+            records.add(retval.createExtendedFormat(k));
+            retval.numxfs++;
+        }
+        retval.records.setXfpos( records.size() - 1 );
+        for (int k = 0; k < 6; k++) {
+            records.add(retval.createStyle(k));
+        }
+        records.add(retval.createUseSelFS());
+
+        int nBoundSheets = 1; // now just do 1
+        for (int k = 0; k < nBoundSheets; k++) {
+            BoundSheetRecord bsr = createBoundSheet(k);
+
+            records.add(bsr);
+            retval.boundsheets.add(bsr);
+            retval.records.setBspos(records.size() - 1);
+        }
+        records.add( retval.createCountry() );
+        for ( int k = 0; k < nBoundSheets; k++ ) {
+            retval.getOrCreateLinkTable().checkExternSheet(k);
+        }
+        retval.sst = new SSTRecord();
+        records.add(retval.sst);
+        records.add(retval.createExtendedSST());
+
+        records.add(EOFRecord.instance);
+        if (log.check( POILogger.DEBUG ))
+            log.log( DEBUG, "exit create new workbook from scratch" );
+        return retval;
+    }
+
+
+    /**Retrieves the Builtin NameRecord that matches the name and index
+     * There shouldn't be too many names to make the sequential search too slow
+     * @param name byte representation of the builtin name to match
+     * @param sheetNumber 1-based sheet number
+     * @return null if no builtin NameRecord matches
+     */
+    public NameRecord getSpecificBuiltinRecord(byte name, int sheetNumber)
+    {
+        return getOrCreateLinkTable().getSpecificBuiltinRecord(name, sheetNumber);
+    }
+
+    /**
+     * Removes the specified Builtin NameRecord that matches the name and index
+     * @param name byte representation of the builtin to match
+     * @param sheetIndex zero-based sheet reference
+     */
+    public void removeBuiltinRecord(byte name, int sheetIndex) {
+        linkTable.removeBuiltinRecord(name, sheetIndex);
+        // TODO - do we need "this.records.remove(...);" similar to that in this.removeName(int namenum) {}?
+    }
+
+    public int getNumRecords() {
+        return records.size();
+    }
+
+    /**
+     * gets the font record at the given index in the font table.  Remember
+     * "There is No Four" (someone at M$ must have gone to Rocky Horror one too
+     * many times)
+     *
+     * @param idx the index to look at (0 or greater but NOT 4)
+     * @return FontRecord located at the given index
+     */
+
+    public FontRecord getFontRecordAt(int idx) {
+        int index = idx;
+
+        if (index > 4) {
+            index -= 1;   // adjust for "There is no 4"
+        }
+        if (index > (numfonts - 1)) {
+            throw new ArrayIndexOutOfBoundsException(
+            "There are only " + numfonts
+            + " font records, you asked for " + idx);
+        }
+        FontRecord retval =
+        ( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + index);
+
+        return retval;
+    }
+
+    /**
+     * Retrieves the index of the given font
+     */
+    public int getFontIndex(FontRecord font) {
+        for(int i=0; i<=numfonts; i++) {
+            FontRecord thisFont =
+                ( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + i);
+            if(thisFont == font) {
+                // There is no 4!
+                if(i > 3) {
+                    return (i+1);
+                }
+                return i;
+            }
+        }
+        throw new IllegalArgumentException("Could not find that font!");
+    }
+
+    /**
+     * creates a new font record and adds it to the "font table".  This causes the
+     * boundsheets to move down one, extended formats to move down (so this function moves
+     * those pointers as well)
+     *
+     * @return FontRecord that was just created
+     */
+
+    public FontRecord createNewFont() {
+        FontRecord rec = createFont();
+
+        records.add(records.getFontpos()+1, rec);
+        records.setFontpos( records.getFontpos() + 1 );
+        numfonts++;
+        return rec;
+    }
+
+    /**
+     * Removes the given font record from the
+     *  file's list. This will make all
+     *  subsequent font indicies drop by one,
+     *  so you'll need to update those yourself!
+     */
+    public void removeFontRecord(FontRecord rec) {
+        records.remove(rec); // this updates FontPos for us
+        numfonts--;
+    }
+
+    /**
+     * gets the number of font records
+     *
+     * @return   number of font records in the "font table"
+     */
+
+    public int getNumberOfFontRecords() {
+        return numfonts;
+    }
+
+    /**
+     * Sets the BOF for a given sheet
+     *
+     * @param sheetIndex the number of the sheet to set the positing of the bof for
+     * @param pos the actual bof position
+     */
+
+    public void setSheetBof(int sheetIndex, int pos) {
+        if (log.check( POILogger.DEBUG ))
+            log.log(DEBUG, "setting bof for sheetnum =", Integer.valueOf(sheetIndex),
+                " at pos=", Integer.valueOf(pos));
+        checkSheets(sheetIndex);
+        getBoundSheetRec(sheetIndex)
+        .setPositionOfBof(pos);
+    }
+
+    private BoundSheetRecord getBoundSheetRec(int sheetIndex) {
+        return boundsheets.get(sheetIndex);
+    }
+
+    /**
+     * Returns the position of the backup record.
+     */
+
+    public BackupRecord getBackupRecord() {
+        return ( BackupRecord ) records.get(records.getBackuppos());
+    }
+
+
+    /**
+     * sets the name for a given sheet.  If the boundsheet record doesn't exist and
+     * its only one more than we have, go ahead and create it.  If it's > 1 more than
+     * we have, except
+     *
+     * @param sheetnum the sheet number (0 based)
+     * @param sheetname the name for the sheet
+     */
+    public void setSheetName(int sheetnum, String sheetname) {
+        checkSheets(sheetnum);
+        BoundSheetRecord sheet = boundsheets.get(sheetnum);
+        sheet.setSheetname(sheetname);
+    }
+
+    /**
+     * Determines whether a workbook contains the provided sheet name.  For the purpose of
+     * comparison, long names are truncated to 31 chars.
+     *
+     * @param name the name to test (case insensitive match)
+     * @param excludeSheetIdx the sheet to exclude from the check or -1 to include all sheets in the check.
+     * @return true if the sheet contains the name, false otherwise.
+     */
+    public boolean doesContainsSheetName(String name, int excludeSheetIdx) {
+        String aName = name;
+        if (aName.length() > MAX_SENSITIVE_SHEET_NAME_LEN) {
+            aName = aName.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN);
+        }
+        for (int i = 0; i < boundsheets.size(); i++) {
+            BoundSheetRecord boundSheetRecord = getBoundSheetRec(i);
+            if (excludeSheetIdx == i) {
+                continue;
+            }
+            String bName = boundSheetRecord.getSheetname();
+            if (bName.length() > MAX_SENSITIVE_SHEET_NAME_LEN) {
+                bName = bName.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN);
+            }
+            if (aName.equalsIgnoreCase(bName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * sets the order of appearance for a given sheet.
+     *
+     * @param sheetname the name of the sheet to reorder
+     * @param pos the position that we want to insert the sheet into (0 based)
+     */
+
+    public void setSheetOrder(String sheetname, int pos ) {
+    int sheetNumber = getSheetIndex(sheetname);
+    //remove the sheet that needs to be reordered and place it in the spot we want
+    boundsheets.add(pos, boundsheets.remove(sheetNumber));
+    }
+
+    /**
+     * gets the name for a given sheet.
+     *
+     * @param sheetIndex the sheet number (0 based)
+     * @return sheetname the name for the sheet
+     */
+    public String getSheetName(int sheetIndex) {
+        return getBoundSheetRec(sheetIndex).getSheetname();
+    }
+
+    /**
+     * Gets the hidden flag for a given sheet.
+     * Note that a sheet could instead be
+     *  set to be very hidden, which is different
+     *  ({@link #isSheetVeryHidden(int)})
+     *
+     * @param sheetnum the sheet number (0 based)
+     * @return True if sheet is hidden
+     */
+    public boolean isSheetHidden(int sheetnum) {
+        return getBoundSheetRec(sheetnum).isHidden();
+    }
+
+    /**
+     * Gets the very hidden flag for a given sheet.
+     * This is different from the normal
+     *  hidden flag
+     *  ({@link #isSheetHidden(int)})
+     *
+     * @param sheetnum the sheet number (0 based)
+     * @return True if sheet is very hidden
+     */
+    public boolean isSheetVeryHidden(int sheetnum) {
+        return getBoundSheetRec(sheetnum).isVeryHidden();
+    }
+
+    /**
+     * Hide or unhide a sheet
+     *
+     * @param sheetnum The sheet number
+     * @param hidden True to mark the sheet as hidden, false otherwise
+     */
+    public void setSheetHidden(int sheetnum, boolean hidden) {
+        getBoundSheetRec(sheetnum).setHidden(hidden);
+    }
+
+    /**
+     * Hide or unhide a sheet.
+     *  0 = not hidden
+     *  1 = hidden
+     *  2 = very hidden.
+     *
+     * @param sheetnum The sheet number
+     * @param hidden 0 for not hidden, 1 for hidden, 2 for very hidden
+     */
+    public void setSheetHidden(int sheetnum, int hidden) {
+        BoundSheetRecord bsr = getBoundSheetRec(sheetnum);
+        boolean h = false;
+        boolean vh = false;
+        if(hidden == 0) {
+        } else if(hidden == 1) {
+            h = true;
+        } else if(hidden == 2) {
+            vh = true;
+        } else {
+            throw new IllegalArgumentException("Invalid hidden flag " + hidden + " given, must be 0, 1 or 2");
+        }
+        bsr.setHidden(h);
+        bsr.setVeryHidden(vh);
+    }
+
+
+    /**
+     * get the sheet's index
+     * @param name  sheet name
+     * @return sheet index or -1 if it was not found.
+     */
+    public int getSheetIndex(String name) {
+        int retval = -1;
+
+        for (int k = 0; k < boundsheets.size(); k++) {
+            String sheet = getSheetName(k);
+
+            if (sheet.equalsIgnoreCase(name)) {
+                retval = k;
+                break;
+            }
+        }
+        return retval;
+    }
+
+    /**
+     * if we're trying to address one more sheet than we have, go ahead and add it!  if we're
+     * trying to address >1 more than we have throw an exception!
+     */
+    private void checkSheets(int sheetnum) {
+        if ((boundsheets.size()) <= sheetnum) {   // if we're short one add another..
+            if ((boundsheets.size() + 1) <= sheetnum) {
+                throw new RuntimeException("Sheet number out of bounds!");
+            }
+            BoundSheetRecord bsr = createBoundSheet(sheetnum);
+
+            records.add(records.getBspos()+1, bsr);
+            records.setBspos( records.getBspos() + 1 );
+            boundsheets.add(bsr);
+            getOrCreateLinkTable().checkExternSheet(sheetnum);
+            fixTabIdRecord();
+        }
+    }
+
+    /**
+     * @param sheetIndex zero based sheet index
+     */
+    public void removeSheet(int sheetIndex) {
+        if (boundsheets.size() > sheetIndex) {
+            records.remove(records.getBspos() - (boundsheets.size() - 1) + sheetIndex);
+            boundsheets.remove(sheetIndex);
+            fixTabIdRecord();
+        }
+
+        // Within NameRecords, it's ok to have the formula
+        //  part point at deleted sheets. It's also ok to
+        //  have the ExternSheetNumber point at deleted
+        //  sheets.
+        // However, the sheet index must be adjusted, or
+        //  excel will break. (Sheet index is either 0 for
+        //  global, or 1 based index to sheet)
+        int sheetNum1Based = sheetIndex + 1;
+        for(int i=0; i<getNumNames(); i++) {
+            NameRecord nr = getNameRecord(i);
+
+            if(nr.getSheetNumber() == sheetNum1Based) {
+                // Excel re-writes these to point to no sheet
+                nr.setSheetNumber(0);
+            } else if(nr.getSheetNumber() > sheetNum1Based) {
+                // Bump down by one, so still points
+                //  at the same sheet
+                nr.setSheetNumber(nr.getSheetNumber()-1);
+            }
+        }
+    }
+
+    /**
+     * make the tabid record look like the current situation.
+     *
+     */
+    private void fixTabIdRecord() {
+        TabIdRecord tir = ( TabIdRecord ) records.get(records.getTabpos());
+        short[]     tia = new short[ boundsheets.size() ];
+
+        for (short k = 0; k < tia.length; k++) {
+            tia[ k ] = k;
+        }
+        tir.setTabIdArray(tia);
+    }
+
+    /**
+     * returns the number of boundsheet objects contained in this workbook.
+     *
+     * @return number of BoundSheet records
+     */
+
+    public int getNumSheets() {
+        if (log.check( POILogger.DEBUG ))
+            log.log(DEBUG, "getNumSheets=", Integer.valueOf(boundsheets.size()));
+        return boundsheets.size();
+    }
+
+    /**
+     * get the number of ExtendedFormat records contained in this workbook.
+     *
+     * @return int count of ExtendedFormat records
+     */
+
+    public int getNumExFormats() {
+        if (log.check( POILogger.DEBUG ))
+            log.log(DEBUG, "getXF=", Integer.valueOf(numxfs));
+        return numxfs;
+    }
+
+    /**
+     * gets the ExtendedFormatRecord at the given 0-based index
+     *
+     * @param index of the Extended format record (0-based)
+     * @return ExtendedFormatRecord at the given index
+     */
+
+    public ExtendedFormatRecord getExFormatAt(int index) {
+        int xfptr = records.getXfpos() - (numxfs - 1);
+
+        xfptr += index;
+        ExtendedFormatRecord retval =
+        ( ExtendedFormatRecord ) records.get(xfptr);
+
+        return retval;
+    }
+
+    /**
+     * Removes the given ExtendedFormatRecord record from the
+     *  file's list. This will make all
+     *  subsequent font indicies drop by one,
+     *  so you'll need to update those yourself!
+     */
+    public void removeExFormatRecord(ExtendedFormatRecord rec) {
+        records.remove(rec); // this updates XfPos for us
+        numxfs--;
+    }
+
+
+    /**
+     * creates a new Cell-type Extneded Format Record and adds it to the end of
+     *  ExtendedFormatRecords collection
+     *
+     * @return ExtendedFormatRecord that was created
+     */
+
+    public ExtendedFormatRecord createCellXF() {
+        ExtendedFormatRecord xf = createExtendedFormat();
+
+        records.add(records.getXfpos()+1, xf);
+        records.setXfpos( records.getXfpos() + 1 );
+        numxfs++;
+        return xf;
+    }
+
+    /**
+     * Returns the StyleRecord for the given
+     *  xfIndex, or null if that ExtendedFormat doesn't
+     *  have a Style set.
+     */
+    public StyleRecord getStyleRecord(int xfIndex) {
+        // Style records always follow after
+        //  the ExtendedFormat records
+        for(int i=records.getXfpos(); i<records.size(); i++) {
+            Record r = records.get(i);
+            if(r instanceof ExtendedFormatRecord) {
+                continue;
+            }
+            if(!(r instanceof StyleRecord)) {
+                return null;
+            }
+            StyleRecord sr = (StyleRecord)r;
+            if(sr.getXFIndex() == xfIndex) {
+                return sr;
+            }
+        }
+        return null;
+    }
+    /**
+     * Creates a new StyleRecord, for the given Extended
+     *  Format index, and adds it onto the end of the
+     *  records collection
+     */
+    public StyleRecord createStyleRecord(int xfIndex) {
+        // Style records always follow after
+        //  the ExtendedFormat records
+        StyleRecord newSR = new StyleRecord();
+        newSR.setXFIndex(xfIndex);
+
+        // Find the spot
+        int addAt = -1;
+        for(int i=records.getXfpos(); i<records.size() &&
+                addAt == -1; i++) {
+            Record r = records.get(i);
+            if(r instanceof ExtendedFormatRecord ||
+                    r instanceof StyleRecord) {
+                // Keep going
+            } else {
+                addAt = i;
+            }
+        }
+        if(addAt == -1) {
+            throw new IllegalStateException("No XF Records found!");
+        }
+        records.add(addAt, newSR);
+
+        return newSR;
+    }
+
+    /**
+     * Adds a string to the SST table and returns its index (if its a duplicate
+     * just returns its index and update the counts) ASSUMES compressed unicode
+     * (meaning 8bit)
+     *
+     * @param string the string to be added to the SSTRecord
+     *
+     * @return index of the string within the SSTRecord
+     */
+
+    public int addSSTString(UnicodeString string) {
+        if (log.check( POILogger.DEBUG ))
+          log.log(DEBUG, "insert to sst string='", string);
+        if (sst == null) {
+            insertSST();
+        }
+      return sst.addString(string);
+    }
+
+    /**
+     * given an index into the SST table, this function returns the corresponding String value
+     * @return String containing the SST String
+     */
+
+    public UnicodeString getSSTString(int str) {
+        if (sst == null) {
+            insertSST();
+        }
+        UnicodeString retval = sst.getString(str);
+
+        if (log.check( POILogger.DEBUG ))
+            log.log(DEBUG, "Returning SST for index=", Integer.valueOf(str),
+                " String= ", retval);
+        return retval;
+    }
+
+    /**
+     * use this function to add a Shared String Table to an existing sheet (say
+     * generated by a different java api) without an sst....
+     * @see #createExtendedSST()
+     * @see org.apache.poi.hssf.record.SSTRecord
+     */
+
+    public void insertSST() {
+        if (log.check( POILogger.DEBUG ))
+            log.log(DEBUG, "creating new SST via insertSST!");
+        sst = new SSTRecord();
+        records.add(records.size() - 1, createExtendedSST());
+        records.add(records.size() - 2, sst);
+    }
+
+    /**
+     * Serializes all records int the worksheet section into a big byte array. Use
+     * this to write the Workbook out.
+     *
+     * @return byte array containing the HSSF-only portions of the POIFS file.
+     */
+     // GJS: Not used so why keep it.
+//    public byte [] serialize() {
+//        log.log(DEBUG, "Serializing Workbook!");
+//        byte[] retval    = null;
+//
+////         ArrayList bytes     = new ArrayList(records.size());
+//        int    arraysize = getSize();
+//        int    pos       = 0;
+//
+//        retval = new byte[ arraysize ];
+//        for (int k = 0; k < records.size(); k++) {
+//
+//            Record record = records.get(k);
+////             Let's skip RECALCID records, as they are only use for optimization
+//        if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) {
+//                pos += record.serialize(pos, retval);   // rec.length;
+//        }
+//        }
+//        log.log(DEBUG, "Exiting serialize workbook");
+//        return retval;
+//    }
+
+    /**
+     * Serializes all records int the worksheet section into a big byte array. Use
+     * this to write the Workbook out.
+     * @param offset of the data to be written
+     * @param data array of bytes to write this to
+     */
+
+    public int serialize( int offset, byte[] data )
+    {
+        if (log.check( POILogger.DEBUG ))
+            log.log( DEBUG, "Serializing Workbook with offsets" );
+
+        int pos = 0;
+
+        SSTRecord sst = null;
+        int sstPos = 0;
+        boolean wroteBoundSheets = false;
+        for ( int k = 0; k < records.size(); k++ )
+        {
+
+            Record record = records.get( k );
+            // Let's skip RECALCID records, as they are only use for optimization
+            if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
+            {
+                int len = 0;
+                if (record instanceof SSTRecord)
+                {
+                    sst = (SSTRecord)record;
+                    sstPos = pos;
+                }
+                if (record.getSid() == ExtSSTRecord.sid && sst != null)
+                {
+                    record = sst.createExtSSTRecord(sstPos + offset);
+                }
+                if (record instanceof BoundSheetRecord) {
+                     if(!wroteBoundSheets) {
+                        for (int i = 0; i < boundsheets.size(); i++) {
+                            len+= getBoundSheetRec(i)
+                                             .serialize(pos+offset+len, data);
+                        }
+                        wroteBoundSheets = true;
+                     }
+                } else {
+                   len = record.serialize( pos + offset, data );
+                }
+                /////  DEBUG BEGIN /////
+//                if (len != record.getRecordSize())
+//                    throw new IllegalStateException("Record size does not match serialized bytes.  Serialized size = " + len + " but getRecordSize() returns " + record.getRecordSize());
+                /////  DEBUG END /////
+                pos += len;   // rec.length;
+            }
+        }
+        if (log.check( POILogger.DEBUG ))
+            log.log( DEBUG, "Exiting serialize workbook" );
+        return pos;
+    }
+
+    public int getSize()
+    {
+        int retval = 0;
+
+        SSTRecord sst = null;
+        for ( int k = 0; k < records.size(); k++ )
+        {
+            Record record = records.get( k );
+            // Let's skip RECALCID records, as they are only use for optimization
+            if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
+            {
+                if (record instanceof SSTRecord)
+                    sst = (SSTRecord)record;
+                if (record.getSid() == ExtSSTRecord.sid && sst != null)
+                    retval += sst.calcExtSSTRecordSize();
+                else
+                    retval += record.getRecordSize();
+            }
+        }
+        return retval;
+    }
+
+    private static BOFRecord createBOF() {
+        BOFRecord retval = new BOFRecord();
+
+        retval.setVersion(( short ) 0x600);
+        retval.setType(BOFRecord.TYPE_WORKBOOK);
+        retval.setBuild(( short ) 0x10d3);
+        retval.setBuildYear(( short ) 1996);
+        retval.setHistoryBitMask(0x41);   // was c1 before verify
+        retval.setRequiredVersion(0x6);
+        return retval;
+    }
+
+    private static InterfaceHdrRecord createInterfaceHdr() {
+        InterfaceHdrRecord retval = new InterfaceHdrRecord();
+
+        retval.setCodepage(CODEPAGE);
+        return retval;
+    }
+
+    private static MMSRecord createMMS() {
+        MMSRecord retval = new MMSRecord();
+
+        retval.setAddMenuCount(( byte ) 0);
+        retval.setDelMenuCount(( byte ) 0);
+        return retval;
+    }
+
+    private static InterfaceEndRecord createInterfaceEnd() {
+        return new InterfaceEndRecord();
+    }
+
+    /**
+     * creates the WriteAccess record containing the logged in user's name
+     */
+    private static WriteAccessRecord createWriteAccess() {
+        WriteAccessRecord retval = new WriteAccessRecord();
+
+        try {
+            retval.setUsername(System.getProperty("user.name"));
+        } catch (AccessControlException e) {
+                // AccessControlException can occur in a restricted context
+                // (client applet/jws application or restricted security server)
+                retval.setUsername("POI");
+        }
+        return retval;
+    }
+
+    private static CodepageRecord createCodepage() {
+        CodepageRecord retval = new CodepageRecord();
+
+        retval.setCodepage(CODEPAGE);
+        return retval;
+    }
+
+    private static DSFRecord createDSF() {
+        return new DSFRecord(false); // we don't even support double stream files
+    }
+
+    /**
+     * creates the TabId record containing an array
+     */
+    private static TabIdRecord createTabId() {
+        return new TabIdRecord();
+    }
+
+    /**
+     * creates the FnGroupCount record containing the Magic number constant of 14.
+     */
+    private static FnGroupCountRecord createFnGroupCount() {
+        FnGroupCountRecord retval = new FnGroupCountRecord();
+
+        retval.setCount(( short ) 14);
+        return retval;
+    }
+
+    /**
+     * @return a new WindowProtect record with protect set to false.
+     */
+    private static WindowProtectRecord createWindowProtect() {
+        // by default even when we support it we won't
+        // want it to be protected
+        return new WindowProtectRecord(false);
+    }
+
+    /**
+     * @return a new Protect record with protect set to false.
+     */
+    private static ProtectRecord createProtect() {
+        // by default even when we support it we won't
+        // want it to be protected
+        return new ProtectRecord(false);
+    }
+
+    /**
+     * @return a new Password record with password set to 0x0000 (no password).
+     */
+    private static PasswordRecord createPassword() {
+        return new PasswordRecord(0x0000); // no password by default!
+    }
+
+    /**
+     * @return a new ProtectionRev4 record with protect set to false.
+     */
+    private static ProtectionRev4Record createProtectionRev4() {
+        return new ProtectionRev4Record(false);
+    }
+
+    /**
+     * @return a new PasswordRev4 record with password set to 0.
+     */
+    private static PasswordRev4Record createPasswordRev4() {
+        return new PasswordRev4Record(0x0000);
+    }
+
+    /**
+     * creates the WindowOne record with the following magic values: <P>
+     * horizontal hold - 0x168 <P>
+     * vertical hold   - 0x10e <P>
+     * width           - 0x3a5c <P>
+     * height          - 0x23be <P>
+     * options         - 0x38 <P>
+     * selected tab    - 0 <P>
+     * displayed tab   - 0 <P>
+     * num selected tab- 0 <P>
+     * tab width ratio - 0x258 <P>
+     */
+    private static WindowOneRecord createWindowOne() {
+        WindowOneRecord retval = new WindowOneRecord();
+
+        retval.setHorizontalHold(( short ) 0x168);
+        retval.setVerticalHold(( short ) 0x10e);
+        retval.setWidth(( short ) 0x3a5c);
+        retval.setHeight(( short ) 0x23be);
+        retval.setOptions(( short ) 0x38);
+        retval.setActiveSheetIndex( 0x0);
+        retval.setFirstVisibleTab(0x0);
+        retval.setNumSelectedTabs(( short ) 1);
+        retval.setTabWidthRatio(( short ) 0x258);
+        return retval;
+    }
+
+    /**
+     * creates the Backup record with backup set to 0. (loose the data, who cares)
+     */
+    private static BackupRecord createBackup() {
+        BackupRecord retval = new BackupRecord();
+
+        retval.setBackup(( short ) 0);   // by default DONT save backups of files...just loose data
+        return retval;
+    }
+
+    /**
+     * creates the HideObj record with hide object set to 0. (don't hide)
+     */
+    private static HideObjRecord createHideObj() {
+        HideObjRecord retval = new HideObjRecord();
+        retval.setHideObj(( short ) 0);   // by default set hide object off
+        return retval;
+    }
+
+    /**
+     * creates the DateWindow1904 record with windowing set to 0. (don't window)
+     */
+    private static DateWindow1904Record createDateWindow1904() {
+        DateWindow1904Record retval = new DateWindow1904Record();
+
+        retval.setWindowing(( short ) 0);   // don't EVER use 1904 date windowing...tick tock..
+        return retval;
+    }
+
+    /**
+     * creates the Precision record with precision set to true. (full precision)
+     */
+    private static PrecisionRecord createPrecision() {
+        PrecisionRecord retval = new PrecisionRecord();
+        retval.setFullPrecision(true);   // always use real numbers in calculations!
+        return retval;
+    }
+
+    /**
+     * @return a new RefreshAll record with refreshAll set to false. (do not refresh all calcs)
+     */
+    private static RefreshAllRecord createRefreshAll() {
+        return new RefreshAllRecord(false);
+    }
+
+    /**
+     * creates the BookBool record with saveLinkValues set to 0. (don't save link values)
+     */
+    private static BookBoolRecord createBookBool() {
+        BookBoolRecord retval = new BookBoolRecord();
+        retval.setSaveLinkValues(( short ) 0);
+        return retval;
+    }
+
+    /**
+     * creates a Font record with the following magic values: <P>
+     * fontheight           = 0xc8<P>
+     * attributes           = 0x0<P>
+     * color palette index  = 0x7fff<P>
+     * bold weight          = 0x190<P>
+     * Font Name Length     = 5 <P>
+     * Font Name            = Arial <P>
+     */
+    private static FontRecord createFont() {
+        FontRecord retval = new FontRecord();
+
+        retval.setFontHeight(( short ) 0xc8);
+        retval.setAttributes(( short ) 0x0);
+        retval.setColorPaletteIndex(( short ) 0x7fff);
+        retval.setBoldWeight(( short ) 0x190);
+        retval.setFontName("Arial");
+        return retval;
+    }
+
+    /**
+     * Creates a FormatRecord object
+     * @param id    the number of the format record to create (meaning its position in
+     *        a file as M$ Excel would create it.)
+     */
+    private static FormatRecord createFormat(int id) {
+        // we'll need multiple editions for
+        // the different formats
+
+        switch (id) {
+            case 0: return new FormatRecord(5, "\"$\"#,##0_);\\(\"$\"#,##0\\)");
+            case 1: return new FormatRecord(6, "\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)");
+            case 2: return new FormatRecord(7, "\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)");
+            case 3: return new FormatRecord(8, "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)");
+            case 4: return new FormatRecord(0x2a, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)");
+            case 5: return new FormatRecord(0x29, "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)");
+            case 6: return new FormatRecord(0x2c, "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)");
+            case 7: return new FormatRecord(0x2b, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)");
+        }
+        throw new  IllegalArgumentException("Unexpected id " + id);
+    }
+
+    /**
+     * Creates an ExtendedFormatRecord object
+     * @param id    the number of the extended format record to create (meaning its position in
+     *        a file as MS Excel would create it.)
+     */
+    private static ExtendedFormatRecord createExtendedFormat(int id) {   // we'll need multiple editions
+        ExtendedFormatRecord retval = new ExtendedFormatRecord();
+
+        switch (id) {
+
+            case 0 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 1 :
+                retval.setFontIndex(( short ) 1);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 2 :
+                retval.setFontIndex(( short ) 1);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 3 :
+                retval.setFontIndex(( short ) 2);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 4 :
+                retval.setFontIndex(( short ) 2);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 5 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 6 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 7 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 8 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 9 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 10 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 11 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 12 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 13 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 14 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff400);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+                // cell records
+            case 15 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0);
+                retval.setCellOptions(( short ) 0x1);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0x0);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+                // style
+            case 16 :
+                retval.setFontIndex(( short ) 1);
+                retval.setFormatIndex(( short ) 0x2b);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff800);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 17 :
+                retval.setFontIndex(( short ) 1);
+                retval.setFormatIndex(( short ) 0x29);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff800);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 18 :
+                retval.setFontIndex(( short ) 1);
+                retval.setFormatIndex(( short ) 0x2c);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff800);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 19 :
+                retval.setFontIndex(( short ) 1);
+                retval.setFormatIndex(( short ) 0x2a);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff800);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 20 :
+                retval.setFontIndex(( short ) 1);
+                retval.setFormatIndex(( short ) 0x9);
+                retval.setCellOptions(( short ) 0xfffffff5);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0xfffff800);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+                // unused from this point down
+            case 21 :
+                retval.setFontIndex(( short ) 5);
+                retval.setFormatIndex(( short ) 0x0);
+                retval.setCellOptions(( short ) 0x1);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0x800);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 22 :
+                retval.setFontIndex(( short ) 6);
+                retval.setFormatIndex(( short ) 0x0);
+                retval.setCellOptions(( short ) 0x1);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0x5c00);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 23 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0x31);
+                retval.setCellOptions(( short ) 0x1);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0x5c00);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 24 :
+                retval.setFontIndex(( short ) 0);
+                retval.setFormatIndex(( short ) 0x8);
+                retval.setCellOptions(( short ) 0x1);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0x5c00);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+
+            case 25 :
+                retval.setFontIndex(( short ) 6);
+                retval.setFormatIndex(( short ) 0x8);
+                retval.setCellOptions(( short ) 0x1);
+                retval.setAlignmentOptions(( short ) 0x20);
+                retval.setIndentionOptions(( short ) 0x5c00);
+                retval.setBorderOptions(( short ) 0);
+                retval.setPaletteOptions(( short ) 0);
+                retval.setAdtlPaletteOptions(( short ) 0);
+                retval.setFillPaletteOptions(( short ) 0x20c0);
+                break;
+        }
+        return retval;
+    }
+
+    /**
+     * creates an default cell type ExtendedFormatRecord object.
+     * @return ExtendedFormatRecord with intial defaults (cell-type)
+     */
+    private static ExtendedFormatRecord createExtendedFormat() {
+        ExtendedFormatRecord retval = new ExtendedFormatRecord();
+
+        retval.setFontIndex(( short ) 0);
+        retval.setFormatIndex(( short ) 0x0);
+        retval.setCellOptions(( short ) 0x1);
+        retval.setAlignmentOptions(( short ) 0x20);
+        retval.setIndentionOptions(( short ) 0);
+        retval.setBorderOptions(( short ) 0);
+        retval.setPaletteOptions(( short ) 0);
+        retval.setAdtlPaletteOptions(( short ) 0);
+        retval.setFillPaletteOptions(( short ) 0x20c0);
+        retval.setTopBorderPaletteIdx(HSSFColor.BLACK.index);
+        retval.setBottomBorderPaletteIdx(HSSFColor.BLACK.index);
+        retval.setLeftBorderPaletteIdx(HSSFColor.BLACK.index);
+        retval.setRightBorderPaletteIdx(HSSFColor.BLACK.index);
+        return retval;
+    }
+
+    /**
+     * Creates a StyleRecord object
+     * @param id        the number of the style record to create (meaning its position in
+     *                  a file as MS Excel would create it.
+     */
+    private static StyleRecord createStyle(int id) {   // we'll need multiple editions
+        StyleRecord retval = new StyleRecord();
+
+        switch (id) {
+
+            case 0 :
+                retval.setXFIndex(0x010);
+                retval.setBuiltinStyle(3);
+                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
+                break;
+
+            case 1 :
+                retval.setXFIndex(0x011);
+                retval.setBuiltinStyle(6);
+                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
+                break;
+
+            case 2 :
+                retval.setXFIndex(0x012);
+                retval.setBuiltinStyle(4);
+                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
+                break;
+
+            case 3 :
+                retval.setXFIndex(0x013);
+                retval.setBuiltinStyle(7);
+                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
+                break;
+
+            case 4 :
+                retval.setXFIndex(0x000);
+                retval.setBuiltinStyle(0);
+                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
+                break;
+
+            case 5 :
+                retval.setXFIndex(0x014);
+                retval.setBuiltinStyle(5);
+                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
+                break;
+        }
+        return retval;
+    }
+
+    /**
+     * Creates a palette record initialized to the default palette
+     */
+    private static PaletteRecord createPalette() {
+        return new PaletteRecord();
+    }
+
+    /**
+     * @return a new UseSelFS object with the use natural language flag set to 0 (false)
+     */
+    private static UseSelFSRecord createUseSelFS() {
+        return new UseSelFSRecord(false);
+    }
+
+    /**
+     * create a "bound sheet" or "bundlesheet" (depending who you ask) record
+     * Always sets the sheet's bof to 0.  You'll need to set that yourself.
+     * @param id either sheet 0,1 or 2.
+     * @return record containing a BoundSheetRecord
+     * @see org.apache.poi.hssf.record.BoundSheetRecord
+     * @see org.apache.poi.hssf.record.Record
+     */
+    private static BoundSheetRecord createBoundSheet(int id) {
+        return new BoundSheetRecord("Sheet" + (id+1));
+    }
+
+    /**
+     * Creates the Country record with the default country set to 1
+     * and current country set to 7 in case of russian locale ("ru_RU") and 1 otherwise
+     */
+    private static CountryRecord createCountry() {
+        CountryRecord retval = new CountryRecord();
+
+        retval.setDefaultCountry(( short ) 1);
+
+        // from Russia with love ;)
+        if ( Locale.getDefault().toString().equals( "ru_RU" ) ) {
+            retval.setCurrentCountry(( short ) 7);
+        }
+        else {
+            retval.setCurrentCountry(( short ) 1);
+        }
+
+        return retval;
+    }
+
+    /**
+     * Creates the ExtendedSST record with numstrings per bucket set to 0x8.  HSSF
+     * doesn't yet know what to do with this thing, but we create it with nothing in
+     * it hardly just to make Excel happy and our sheets look like Excel's
+     */
+    private static ExtSSTRecord createExtendedSST() {
+        ExtSSTRecord retval = new ExtSSTRecord();
+        retval.setNumStringsPerBucket(( short ) 0x8);
+        return retval;
+    }
+
+    /**
+     * lazy initialization
+     * Note - creating the link table causes creation of 1 EXTERNALBOOK and 1 EXTERNALSHEET record
+     */
+    private LinkTable getOrCreateLinkTable() {
+        if(linkTable == null) {
+            linkTable = new LinkTable((short) getNumSheets(), records);
+        }
+        return linkTable;
+    }
+
+    /** finds the sheet name by his extern sheet index
+     * @param externSheetIndex extern sheet index
+     * @return sheet name.
+     */
+    public String findSheetNameFromExternSheet(int externSheetIndex){
+
+        int indexToSheet = linkTable.getIndexToInternalSheet(externSheetIndex);
+        if (indexToSheet < 0) {
+            // TODO - what does '-1' mean here?
+            //error check, bail out gracefully!
+            return "";
+        }
+        if (indexToSheet >= boundsheets.size()) {
+            // Not sure if this can ever happen (See bug 45798)
+            return ""; // Seems to be what excel would do in this case
+        }
+        return getSheetName(indexToSheet);
+    }
+    public ExternalSheet getExternalSheet(int externSheetIndex) {
+        String[] extNames = linkTable.getExternalBookAndSheetName(externSheetIndex);
+        if (extNames == null) {
+            return null;
+        }
+        return new ExternalSheet(extNames[0], extNames[1]);
+    }
+
+    /**
+     * Finds the sheet index for a particular external sheet number.
+     * @param externSheetNumber     The external sheet number to convert
+     * @return  The index to the sheet found.
+     */
+    public int getSheetIndexFromExternSheetIndex(int externSheetNumber)
+    {
+        return linkTable.getSheetIndexFromExternSheetIndex(externSheetNumber);
+    }
+
+    /** returns the extern sheet number for specific sheet number ,
+     *  if this sheet doesn't exist in extern sheet , add it
+     * @param sheetNumber sheet number
+     * @return index to extern sheet
+     */
+    public short checkExternSheet(int sheetNumber){
+        return (short)getOrCreateLinkTable().checkExternSheet(sheetNumber);
+    }
+
+    public int getExternalSheetIndex(String workbookName, String sheetName) {
+        return getOrCreateLinkTable().getExternalSheetIndex(workbookName, sheetName);
+    }
+
+
+    /** gets the total number of names
+     * @return number of names
+     */
+    public int getNumNames(){
+        if(linkTable == null) {
+            return 0;
+        }
+        return linkTable.getNumNames();
+    }
+
+    /** gets the name record
+     * @param index name index
+     * @return name record
+     */
+    public NameRecord getNameRecord(int index){
+        return linkTable.getNameRecord(index);
+    }
+
+    /** creates new name
+     * @return new name record
+     */
+    public NameRecord createName(){
+        return addName(new NameRecord());
+    }
+
+
+    /** creates new name
+     * @return new name record
+     */
+    public NameRecord addName(NameRecord name)
+    {
+
+        LinkTable linkTable = getOrCreateLinkTable();
+        if(linkTable.nameAlreadyExists(name)) {
+            throw new IllegalArgumentException(
+                "You are trying to assign a duplicated name record: "
+                + name.getNameText());
+        }
+        linkTable.addName(name);
+
+        return name;
+    }
+
+    /**
+     * Generates a NameRecord to represent a built-in region
+     * @return a new NameRecord
+     */
+    public NameRecord createBuiltInName(byte builtInName, int sheetNumber) {
+        if (sheetNumber < 0 || sheetNumber+1 > Short.MAX_VALUE) {
+            throw new IllegalArgumentException("Sheet number ["+sheetNumber+"]is not valid ");
+        }
+
+        NameRecord name = new NameRecord(builtInName, sheetNumber);
+
+        while(linkTable.nameAlreadyExists(name)) {
+            throw new RuntimeException("Builtin (" + builtInName
+                    + ") already exists for sheet (" + sheetNumber + ")");
+        }
+        addName(name);
+        return name;
+    }
+
+
+    /** removes the name
+     * @param nameIndex name index
+     */
+    public void removeName(int nameIndex){
+
+        if (linkTable.getNumNames() > nameIndex) {
+            int idx = findFirstRecordLocBySid(NameRecord.sid);
+            records.remove(idx + nameIndex);
+            linkTable.removeName(nameIndex);
+        }
+    }
+
+    /**
+     * Returns a format index that matches the passed in format.  It does not tie into HSSFDataFormat.
+     * @param format the format string
+     * @param createIfNotFound creates a new format if format not found
+     * @return the format id of a format that matches or -1 if none found and createIfNotFound
+     */
+    public short getFormat(String format, boolean createIfNotFound) {
+    Iterator iterator;
+    for (iterator = formats.iterator(); iterator.hasNext();) {
+        FormatRecord r = (FormatRecord)iterator.next();
+        if (r.getFormatString().equals(format)) {
+        return (short)r.getIndexCode();
+        }
+    }
+
+    if (createIfNotFound) {
+        return (short)createFormat(format);
+    }
+
+    return -1;
+    }
+
+    /**
+     * Returns the list of FormatRecords in the workbook.
+     * @return ArrayList of FormatRecords in the notebook
+     */
+    public List getFormats() {
+    return formats;
+    }
+
+    /**
+     * Creates a FormatRecord, inserts it, and returns the index code.
+     * @param formatString the format string
+     * @return the index code of the format record.
+     * @see org.apache.poi.hssf.record.FormatRecord
+     * @see org.apache.poi.hssf.record.Record
+     */
+    public int createFormat(String formatString) {
+
+        maxformatid = maxformatid >= 0xa4 ? maxformatid + 1 : 0xa4; //Starting value from M$ empircal study.
+        FormatRecord rec = new FormatRecord(maxformatid, formatString);
+
+        int pos = 0;
+        while ( pos < records.size() && records.get( pos ).getSid() != FormatRecord.sid )
+            pos++;
+        pos += formats.size();
+        formats.add( rec );
+        records.add( pos, rec );
+        return maxformatid;
+    }
+
+
+
+    /**
+     * Returns the first occurance of a record matching a particular sid.
+     */
+    public Record findFirstRecordBySid(short sid) {
+        for (Iterator iterator = records.iterator(); iterator.hasNext(); ) {
+            Record record = ( Record ) iterator.next();
+
+            if (record.getSid() == sid) {
+                return record;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the index of a record matching a particular sid.
+     * @param sid   The sid of the record to match
+     * @return      The index of -1 if no match made.
+     */
+    public int findFirstRecordLocBySid(short sid) {
+        int index = 0;
+        for (Iterator iterator = records.iterator(); iterator.hasNext(); ) {
+            Record record = ( Record ) iterator.next();
+
+            if (record.getSid() == sid) {
+                return index;
+            }
+            index ++;
+        }
+        return -1;
+    }
+
+    /**
+     * Returns the next occurance of a record matching a particular sid.
+     */
+    public Record findNextRecordBySid(short sid, int pos) {
+        int matches = 0;
+        for (Iterator iterator = records.iterator(); iterator.hasNext(); ) {
+            Record record = ( Record ) iterator.next();
+
+            if (record.getSid() == sid) {
+                if (matches++ == pos)
+                    return record;
+            }
+        }
+        return null;
+    }
+
+    public List getHyperlinks()
+    {
+        return hyperlinks;
+    }
+
+    public List<Record> getRecords() {
+        return records.getRecords();
+    }
+
+    /**
+    * Whether date windowing is based on 1/2/1904 or 1/1/1900.
+    * Some versions of Excel (Mac) can save workbooks using 1904 date windowing.
+    *
+    * @return true if using 1904 date windowing
+    */
+    public boolean isUsing1904DateWindowing() {
+        return uses1904datewindowing;
+    }
+
+    /**
+     * Returns the custom palette in use for this workbook; if a custom palette record
+     * does not exist, then it is created.
+     */
+    public PaletteRecord getCustomPalette()
+    {
+      PaletteRecord palette;
+      int palettePos = records.getPalettepos();
+      if (palettePos != -1) {
+        Record rec = records.get(palettePos);
+        if (rec instanceof PaletteRecord) {
+          palette = (PaletteRecord) rec;
+        } else throw new RuntimeException("InternalError: Expected PaletteRecord but got a '"+rec+"'");
+      }
+      else
+      {
+          palette = createPalette();
+          //Add the palette record after the bof which is always the first record
+          records.add(1, palette);
+          records.setPalettepos(1);
+      }
+      return palette;
+    }
+
+    /**
+     * Finds the primary drawing group, if one already exists
+     */
+    public void findDrawingGroup() {
+        // Need to find a DrawingGroupRecord that
+        //  contains a EscherDggRecord
+        for(Iterator<Record> rit = records.iterator(); rit.hasNext();) {
+            Record r = rit.next();
+
+            if(r instanceof DrawingGroupRecord) {
+                DrawingGroupRecord dg = (DrawingGroupRecord)r;
+                dg.processChildRecords();
+
+                EscherContainerRecord cr =
+                    dg.getEscherContainer();
+                if(cr == null) {
+                    continue;
+                }
+
+                EscherDggRecord dgg = null;
+                for(Iterator<EscherRecord> it = cr.getChildIterator(); it.hasNext();) {
+                    Object er = it.next();
+                    if(er instanceof EscherDggRecord) {
+                        dgg = (EscherDggRecord)er;
+                    }
+                }
+
+                if(dgg != null) {
+                    drawingManager = new DrawingManager2(dgg);
+                    return;
+                }
+            }
+        }
+
+        // Look for the DrawingGroup record
+        int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
+
+        // If there is one, does it have a EscherDggRecord?
+        if(dgLoc != -1) {
+            DrawingGroupRecord dg = (DrawingGroupRecord)records.get(dgLoc);
+            EscherDggRecord dgg = null;
+            for(Iterator it = dg.getEscherRecords().iterator(); it.hasNext();) {
+                Object er = it.next();
+                if(er instanceof EscherDggRecord) {
+                    dgg = (EscherDggRecord)er;
+                }
+            }
+
+            if(dgg != null) {
+                drawingManager = new DrawingManager2(dgg);
+            }
+        }
+    }
+
+    /**
+     * Creates a primary drawing group record.  If it already
+     *  exists then it's modified.
+     */
+    public void createDrawingGroup() {
+        if (drawingManager == null) {
+            EscherContainerRecord dggContainer = new EscherContainerRecord();
+            EscherDggRecord dgg = new EscherDggRecord();
+            EscherOptRecord opt = new EscherOptRecord();
+            EscherSplitMenuColorsRecord splitMenuColors = new EscherSplitMenuColorsRecord();
+
+            dggContainer.setRecordId((short) 0xF000);
+            dggContainer.setOptions((short) 0x000F);
+            dgg.setRecordId(EscherDggRecord.RECORD_ID);
+            dgg.setOptions((short)0x0000);
+            dgg.setShapeIdMax(1024);
+            dgg.setNumShapesSaved(0);
+            dgg.setDrawingsSaved(0);
+            dgg.setFileIdClusters(new EscherDggRecord.FileIdCluster[] {} );
+            drawingManager = new DrawingManager2(dgg);
+            EscherContainerRecord bstoreContainer = null;
+            if (escherBSERecords.size() > 0)
+            {
+                bstoreContainer = new EscherContainerRecord();
+                bstoreContainer.setRecordId( EscherContainerRecord.BSTORE_CONTAINER );
+                bstoreContainer.setOptions( (short) ( (escherBSERecords.size() << 4) | 0xF ) );
+                for ( Iterator iterator = escherBSERecords.iterator(); iterator.hasNext(); )
+                {
+                    EscherRecord escherRecord = (EscherRecord) iterator.next();
+                    bstoreContainer.addChildRecord( escherRecord );
+                }
+            }
+            opt.setRecordId((short) 0xF00B);
+            opt.setOptions((short) 0x0033);
+            opt.addEscherProperty( new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 524296) );
+            opt.addEscherProperty( new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 0x08000041) );
+            opt.addEscherProperty( new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, 134217792) );
+            splitMenuColors.setRecordId((short) 0xF11E);
+            splitMenuColors.setOptions((short) 0x0040);
+            splitMenuColors.setColor1(0x0800000D);
+            splitMenuColors.setColor2(0x0800000C);
+            splitMenuColors.setColor3(0x08000017);
+            splitMenuColors.setColor4(0x100000F7);
+
+            dggContainer.addChildRecord(dgg);
+            if (bstoreContainer != null)
+                dggContainer.addChildRecord( bstoreContainer );
+            dggContainer.addChildRecord(opt);
+            dggContainer.addChildRecord(splitMenuColors);
+
+            int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
+            if (dgLoc == -1) {
+                DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
+                drawingGroup.addEscherRecord(dggContainer);
+                int loc = findFirstRecordLocBySid(CountryRecord.sid);
+
+                getRecords().add(loc+1, drawingGroup);
+            } else {
+                DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
+                drawingGroup.addEscherRecord(dggContainer);
+                getRecords().set(dgLoc, drawingGroup);
+            }
+
+        }
+    }
+
+    public WindowOneRecord getWindowOne() {
+        return windowOne;
+    }
+
+    public EscherBSERecord getBSERecord(int pictureIndex) {
+        return escherBSERecords.get(pictureIndex-1);
+    }
+
+    public int addBSERecord(EscherBSERecord e) {
+        createDrawingGroup();
+
+        // maybe we don't need that as an instance variable anymore
+        escherBSERecords.add( e );
+
+        int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
+        DrawingGroupRecord drawingGroup = (DrawingGroupRecord) getRecords().get( dgLoc );
+
+        EscherContainerRecord dggContainer = (EscherContainerRecord) drawingGroup.getEscherRecord( 0 );
+        EscherContainerRecord bstoreContainer;
+        if (dggContainer.getChild( 1 ).getRecordId() == EscherContainerRecord.BSTORE_CONTAINER )
+        {
+            bstoreContainer = (EscherContainerRecord) dggContainer.getChild( 1 );
+        }
+        else
+        {
+            bstoreContainer = new EscherContainerRecord();
+            bstoreContainer.setRecordId( EscherContainerRecord.BSTORE_CONTAINER );
+            List<EscherRecord> childRecords = dggContainer.getChildRecords();
+            childRecords.add(1, bstoreContainer);
+            dggContainer.setChildRecords(childRecords);
+        }
+        bstoreContainer.setOptions( (short) ( (escherBSERecords.size() << 4) | 0xF ) );
+
+        bstoreContainer.addChildRecord( e );
+
+        return escherBSERecords.size();
+    }
+
+    public DrawingManager2 getDrawingManager()
+    {
+        return drawingManager;
+    }
+
+    public WriteProtectRecord getWriteProtect() {
+        if (writeProtect == null) {
+           writeProtect = new WriteProtectRecord();
+           int i = 0;
+           for (i = 0;
+                i < records.size() && !(records.get(i) instanceof BOFRecord);
+                i++) {
+           }
+           records.add(i+1, writeProtect);
+        }
+        return this.writeProtect;
+    }
+
+    public WriteAccessRecord getWriteAccess() {
+        if (writeAccess == null) {
+           writeAccess = createWriteAccess();
+           int i = 0;
+           for (i = 0;
+                i < records.size() && !(records.get(i) instanceof InterfaceEndRecord);
+                i++) {
+           }
+           records.add(i+1, writeAccess);
+        }
+        return writeAccess;
+    }
+
+    public FileSharingRecord getFileSharing() {
+        if (fileShare == null) {
+           fileShare = new FileSharingRecord();
+           int i = 0;
+           for (i = 0;
+                i < records.size() && !(records.get(i) instanceof WriteAccessRecord);
+                i++) {
+           }
+           records.add(i+1, fileShare);
+        }
+        return fileShare;
+    }
+
+    /**
+     * is the workbook protected with a password (not encrypted)?
+     */
+    public boolean isWriteProtected() {
+        if (fileShare == null) {
+            return false;
+        }
+        FileSharingRecord frec = getFileSharing();
+        return frec.getReadOnly() == 1;
+    }
+
+    /**
+     * protect a workbook with a password (not encypted, just sets writeprotect
+     * flags and the password.
+     * @param password to set
+     */
+    public void writeProtectWorkbook( String password, String username ) {
+        int protIdx = -1;
+        FileSharingRecord frec = getFileSharing();
+        WriteAccessRecord waccess = getWriteAccess();
+        WriteProtectRecord wprotect = getWriteProtect();
+        frec.setReadOnly((short)1);
+        frec.setPassword(FileSharingRecord.hashPassword(password));
+        frec.setUsername(username);
+        waccess.setUsername(username);
+    }
+
+    /**
+     * removes the write protect flag
+     */
+    public void unwriteProtectWorkbook() {
+        records.remove(fileShare);
+        records.remove(writeProtect);
+        fileShare = null;
+        writeProtect = null;
+    }
+
+    /**
+     * @param refIndex Index to REF entry in EXTERNSHEET record in the Link Table
+     * @param definedNameIndex zero-based to DEFINEDNAME or EXTERNALNAME record
+     * @return the string representation of the defined or external name
+     */
+    public String resolveNameXText(int refIndex, int definedNameIndex) {
+        return linkTable.resolveNameXText(refIndex, definedNameIndex);
+    }
+
+    public NameXPtg getNameXPtg(String name) {
+        return getOrCreateLinkTable().getNameXPtg(name);
+    }
+
+    /**
+     * Check if the cloned sheet has drawings. If yes, then allocate a new drawing group ID and
+     * re-generate shape IDs
+     *
+     * @param sheet the cloned sheet
+     */
+    public void cloneDrawings(Sheet sheet){
+
+        findDrawingGroup();
+
+        if(drawingManager == null) {
+            //this workbook does not have drawings
+            return;
+        }
+
+        //check if the cloned sheet has drawings
+        int aggLoc = sheet.aggregateDrawingRecords(drawingManager, false);
+        if(aggLoc != -1) {
+            EscherAggregate agg = (EscherAggregate) sheet.findFirstRecordBySid(EscherAggregate.sid);
+            EscherContainerRecord escherContainer = agg.getEscherContainer();
+            if (escherContainer == null) {
+                return;
+            }
+
+            EscherDggRecord dgg = drawingManager.getDgg();
+
+            //register a new drawing group for the cloned sheet
+            int dgId = drawingManager.findNewDrawingGroupId();
+            dgg.addCluster( dgId, 0 );
+            dgg.setDrawingsSaved(dgg.getDrawingsSaved() + 1);
+
+            EscherDgRecord dg = null;
+            for(Iterator<EscherRecord> it = escherContainer.getChildIterator(); it.hasNext();) {
+                EscherRecord er = it.next();
+                if(er instanceof EscherDgRecord) {
+                    dg = (EscherDgRecord)er;
+                    //update id of the drawing in the cloned sheet
+                    dg.setOptions( (short) ( dgId << 4 ) );
+                } else if (er instanceof EscherContainerRecord){
+                    //recursively find shape records and re-generate shapeId
+                    List<EscherRecord> spRecords = new ArrayList<EscherRecord>();
+                    EscherContainerRecord cp = (EscherContainerRecord)er;
+                    cp.getRecordsById(EscherSpRecord.RECORD_ID,  spRecords);
+                    for(Iterator<EscherRecord> spIt = spRecords.iterator(); spIt.hasNext();) {
+                        EscherSpRecord sp = (EscherSpRecord)spIt.next();
+                        int shapeId = drawingManager.allocateShapeId((short)dgId, dg);
+                        //allocateShapeId increments the number of shapes. roll back to the previous value
+                        dg.setNumShapes(dg.getNumShapes()-1);
+                        sp.setShapeId(shapeId);
+                    }
+                }
+            }
+
+        }
+    }
+
+    /**
+     * Updates named ranges due to moving of cells
+     */
+    public void updateNamesAfterCellShift(FormulaShifter shifter) {
+        for (int i = 0 ; i < getNumNames() ; ++i){
+            NameRecord nr = getNameRecord(i);
+            Ptg[] ptgs = nr.getNameDefinition();
+            if (shifter.adjustFormula(ptgs, nr.getSheetNumber())) {
+                nr.setNameDefinition(ptgs);
+            }
+        }
+    }
+
+}
index 9bb93a603ecbc315c8a545d22cda5a764634553c..90a9a109ed5642b29b625457fd8989a8eaae2d7c 100644 (file)
@@ -91,7 +91,7 @@ import org.apache.poi.util.POILogger;
  * @author  Brian Sanders (kestrel at burdell dot org) Active Cell support
  * @author  Jean-Pierre Paris (jean-pierre.paris at m4x dot org) (Just a little)
  *
- * @see org.apache.poi.hssf.model.Workbook
+ * @see org.apache.poi.hssf.model.InternalWorkbook
  * @see org.apache.poi.hssf.usermodel.HSSFSheet
  */
 public final class Sheet {
@@ -151,7 +151,7 @@ public final class Sheet {
      *
      * @return Sheet object with all values set to those read from the file
      *
-     * @see org.apache.poi.hssf.model.Workbook
+     * @see org.apache.poi.hssf.model.InternalWorkbook
      * @see org.apache.poi.hssf.record.Record
      */
     public static Sheet createSheet(RecordStream rs) {
diff --git a/src/java/org/apache/poi/hssf/model/Workbook.java b/src/java/org/apache/poi/hssf/model/Workbook.java
deleted file mode 100644 (file)
index eba4d10..0000000
+++ /dev/null
@@ -1,2338 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-
-package org.apache.poi.hssf.model;
-
-import java.security.AccessControlException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-
-import org.apache.poi.ddf.EscherBSERecord;
-import org.apache.poi.ddf.EscherBoolProperty;
-import org.apache.poi.ddf.EscherContainerRecord;
-import org.apache.poi.ddf.EscherDgRecord;
-import org.apache.poi.ddf.EscherDggRecord;
-import org.apache.poi.ddf.EscherOptRecord;
-import org.apache.poi.ddf.EscherProperties;
-import org.apache.poi.ddf.EscherRGBProperty;
-import org.apache.poi.ddf.EscherRecord;
-import org.apache.poi.ddf.EscherSpRecord;
-import org.apache.poi.ddf.EscherSplitMenuColorsRecord;
-import org.apache.poi.hssf.record.BOFRecord;
-import org.apache.poi.hssf.record.BackupRecord;
-import org.apache.poi.hssf.record.BookBoolRecord;
-import org.apache.poi.hssf.record.BoundSheetRecord;
-import org.apache.poi.hssf.record.CodepageRecord;
-import org.apache.poi.hssf.record.CountryRecord;
-import org.apache.poi.hssf.record.DSFRecord;
-import org.apache.poi.hssf.record.DateWindow1904Record;
-import org.apache.poi.hssf.record.DrawingGroupRecord;
-import org.apache.poi.hssf.record.EOFRecord;
-import org.apache.poi.hssf.record.EscherAggregate;
-import org.apache.poi.hssf.record.ExtSSTRecord;
-import org.apache.poi.hssf.record.ExtendedFormatRecord;
-import org.apache.poi.hssf.record.ExternSheetRecord;
-import org.apache.poi.hssf.record.FileSharingRecord;
-import org.apache.poi.hssf.record.FnGroupCountRecord;
-import org.apache.poi.hssf.record.FontRecord;
-import org.apache.poi.hssf.record.FormatRecord;
-import org.apache.poi.hssf.record.HideObjRecord;
-import org.apache.poi.hssf.record.HyperlinkRecord;
-import org.apache.poi.hssf.record.InterfaceEndRecord;
-import org.apache.poi.hssf.record.InterfaceHdrRecord;
-import org.apache.poi.hssf.record.MMSRecord;
-import org.apache.poi.hssf.record.NameRecord;
-import org.apache.poi.hssf.record.PaletteRecord;
-import org.apache.poi.hssf.record.PasswordRecord;
-import org.apache.poi.hssf.record.PasswordRev4Record;
-import org.apache.poi.hssf.record.PrecisionRecord;
-import org.apache.poi.hssf.record.ProtectRecord;
-import org.apache.poi.hssf.record.ProtectionRev4Record;
-import org.apache.poi.hssf.record.RecalcIdRecord;
-import org.apache.poi.hssf.record.Record;
-import org.apache.poi.hssf.record.RefreshAllRecord;
-import org.apache.poi.hssf.record.SSTRecord;
-import org.apache.poi.hssf.record.StyleRecord;
-import org.apache.poi.hssf.record.SupBookRecord;
-import org.apache.poi.hssf.record.TabIdRecord;
-import org.apache.poi.hssf.record.UnicodeString;
-import org.apache.poi.hssf.record.UseSelFSRecord;
-import org.apache.poi.hssf.record.WindowOneRecord;
-import org.apache.poi.hssf.record.WindowProtectRecord;
-import org.apache.poi.hssf.record.WriteAccessRecord;
-import org.apache.poi.hssf.record.WriteProtectRecord;
-import org.apache.poi.hssf.record.formula.NameXPtg;
-import org.apache.poi.hssf.record.formula.FormulaShifter;
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.util.HSSFColor;
-import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-
-/**
- * Low level model implementation of a Workbook.  Provides creational methods
- * for settings and objects contained in the workbook object.
- * <P>
- * This file contains the low level binary records starting at the workbook's BOF and
- * ending with the workbook's EOF.  Use HSSFWorkbook for a high level representation.
- * <P>
- * The structures of the highlevel API use references to this to perform most of their
- * operations.  Its probably unwise to use these low level structures directly unless you
- * really know what you're doing.  I recommend you read the Microsoft Excel 97 Developer's
- * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf
- * before even attempting to use this.
- *
- *
- * @author  Luc Girardin (luc dot girardin at macrofocus dot com)
- * @author  Sergei Kozello (sergeikozello at mail.ru)
- * @author  Shawn Laubach (slaubach at apache dot org) (Data Formats)
- * @author  Andrew C. Oliver (acoliver at apache dot org)
- * @author  Brian Sanders (bsanders at risklabs dot com) - custom palette
- * @author  Dan Sherman (dsherman at isisph.com)
- * @author  Glen Stampoultzis (glens at apache.org)
- * @see org.apache.poi.hssf.usermodel.HSSFWorkbook
- */
-public final class Workbook {
-    /**
-     * Excel silently truncates long sheet names to 31 chars.
-     * This constant is used to ensure uniqueness in the first 31 chars
-     */
-    private static final int MAX_SENSITIVE_SHEET_NAME_LEN = 31;
-
-
-    private static final POILogger log = POILogFactory.getLogger(Workbook.class);
-    private static final int DEBUG = POILogger.DEBUG;
-
-    /**
-     * constant used to set the "codepage" wherever "codepage" is set in records
-     * (which is duplicated in more than one record)
-     */
-    private final static short CODEPAGE = 0x04B0;
-
-    /**
-     * this contains the Worksheet record objects
-     */
-    private final WorkbookRecordList records;
-
-    /**
-     * this contains a reference to the SSTRecord so that new stings can be added
-     * to it.
-     */
-    protected SSTRecord sst;
-
-
-    private LinkTable linkTable; // optionally occurs if there are  references in the document. (4.10.3)
-
-    /**
-     * holds the "boundsheet" records (aka bundlesheet) so that they can have their
-     * reference to their "BOF" marker
-     */
-    private final List<BoundSheetRecord> boundsheets;
-    private final List<FormatRecord> formats;
-    private final List<HyperlinkRecord> hyperlinks;
-
-    /** the number of extended format records */
-       private int numxfs;
-    /** the number of font records */
-       private int numfonts;
-    /** holds the max format id */
-       private int maxformatid;
-    /** whether 1904 date windowing is being used */
-    private boolean uses1904datewindowing;
-    private DrawingManager2 drawingManager;
-    private List<EscherBSERecord> escherBSERecords;
-    private WindowOneRecord windowOne;
-    private FileSharingRecord fileShare;
-    private WriteAccessRecord writeAccess;
-    private WriteProtectRecord writeProtect;
-
-    private Workbook() {
-       records     = new WorkbookRecordList();
-
-               boundsheets = new ArrayList<BoundSheetRecord>();
-               formats = new ArrayList<FormatRecord>();
-               hyperlinks = new ArrayList<HyperlinkRecord>();
-               numxfs = 0;
-               numfonts = 0;
-               maxformatid = -1;
-               uses1904datewindowing = false;
-               escherBSERecords = new ArrayList<EscherBSERecord>();
-    }
-
-    /**
-     * read support  for low level
-     * API.  Pass in an array of Record objects, A Workbook
-     * object is constructed and passed back with all of its initialization set
-     * to the passed in records and references to those records held. Unlike Sheet
-     * workbook does not use an offset (its assumed to be 0) since its first in a file.
-     * If you need an offset then construct a new array with a 0 offset or write your
-     * own ;-p.
-     *
-     * @param recs an array of Record objects
-     * @return Workbook object
-     */
-    public static Workbook createWorkbook(List<Record> recs) {
-        if (log.check( POILogger.DEBUG ))
-            log.log(DEBUG, "Workbook (readfile) created with reclen=",
-                    Integer.valueOf(recs.size()));
-        Workbook retval = new Workbook();
-        List<Record> records = new ArrayList<Record>(recs.size() / 3);
-        retval.records.setRecords(records);
-
-        int k;
-        for (k = 0; k < recs.size(); k++) {
-            Record rec = recs.get(k);
-
-            if (rec.getSid() == EOFRecord.sid) {
-                records.add(rec);
-                if (log.check( POILogger.DEBUG ))
-                    log.log(DEBUG, "found workbook eof record at " + k);
-                break;
-            }
-            switch (rec.getSid()) {
-
-                case BoundSheetRecord.sid :
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found boundsheet record at " + k);
-                    retval.boundsheets.add((BoundSheetRecord) rec);
-                    retval.records.setBspos( k );
-                    break;
-
-                case SSTRecord.sid :
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found sst record at " + k);
-                    retval.sst = ( SSTRecord ) rec;
-                    break;
-
-                case FontRecord.sid :
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found font record at " + k);
-                    retval.records.setFontpos( k );
-                    retval.numfonts++;
-                    break;
-
-                case ExtendedFormatRecord.sid :
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found XF record at " + k);
-                    retval.records.setXfpos( k );
-                    retval.numxfs++;
-                    break;
-
-                case TabIdRecord.sid :
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found tabid record at " + k);
-                    retval.records.setTabpos( k );
-                    break;
-
-                case ProtectRecord.sid :
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found protect record at " + k);
-                    retval.records.setProtpos( k );
-                    break;
-
-                case BackupRecord.sid :
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found backup record at " + k);
-                    retval.records.setBackuppos( k );
-                    break;
-                case ExternSheetRecord.sid :
-                    throw new RuntimeException("Extern sheet is part of LinkTable");
-                case NameRecord.sid :
-                case SupBookRecord.sid :
-                    // LinkTable can start with either of these
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found SupBook record at " + k);
-                    retval.linkTable = new LinkTable(recs, k, retval.records);
-                    k+=retval.linkTable.getRecordCount() - 1;
-                    continue;
-                case FormatRecord.sid :
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found format record at " + k);
-                    retval.formats.add((FormatRecord) rec);
-                    retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode();
-                    break;
-                case DateWindow1904Record.sid :
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found datewindow1904 record at " + k);
-                    retval.uses1904datewindowing = ((DateWindow1904Record)rec).getWindowing() == 1;
-                    break;
-                case PaletteRecord.sid:
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found palette record at " + k);
-                    retval.records.setPalettepos( k );
-                    break;
-                case WindowOneRecord.sid:
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found WindowOneRecord at " + k);
-                    retval.windowOne = (WindowOneRecord) rec;
-                    break;
-                case WriteAccessRecord.sid:
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found WriteAccess at " + k);
-                    retval.writeAccess = (WriteAccessRecord) rec;
-                    break;
-                case WriteProtectRecord.sid:
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found WriteProtect at " + k);
-                    retval.writeProtect = (WriteProtectRecord) rec;
-                    break;
-                case FileSharingRecord.sid:
-                    if (log.check( POILogger.DEBUG ))
-                        log.log(DEBUG, "found FileSharing at " + k);
-                    retval.fileShare = (FileSharingRecord) rec;
-                default :
-            }
-            records.add(rec);
-        }
-        //What if we dont have any ranges and supbooks
-        //        if (retval.records.supbookpos == 0) {
-        //            retval.records.supbookpos = retval.records.bspos + 1;
-        //            retval.records.namepos    = retval.records.supbookpos + 1;
-        //        }
-
-        // Look for other interesting values that
-        //  follow the EOFRecord
-        for ( ; k < recs.size(); k++) {
-            Record rec = recs.get(k);
-            switch (rec.getSid()) {
-                case HyperlinkRecord.sid:
-                    retval.hyperlinks.add((HyperlinkRecord)rec);
-                    break;
-            }
-        }
-
-        if (retval.windowOne == null) {
-            retval.windowOne = createWindowOne();
-        }
-        if (log.check( POILogger.DEBUG ))
-            log.log(DEBUG, "exit create workbook from existing file function");
-        return retval;
-    }
-
-    /**
-     * Creates an empty workbook object with three blank sheets and all the empty
-     * fields.  Use this to create a workbook from scratch.
-     */
-    public static Workbook createWorkbook()
-    {
-        if (log.check( POILogger.DEBUG ))
-            log.log( DEBUG, "creating new workbook from scratch" );
-        Workbook retval = new Workbook();
-        List<Record> records = new ArrayList<Record>( 30 );
-        retval.records.setRecords(records);
-        List<FormatRecord> formats = retval.formats;
-
-        records.add(retval.createBOF());
-        records.add(retval.createInterfaceHdr());
-        records.add(retval.createMMS());
-        records.add(retval.createInterfaceEnd());
-        records.add(retval.createWriteAccess());
-        records.add(retval.createCodepage());
-        records.add(retval.createDSF());
-        records.add(retval.createTabId());
-        retval.records.setTabpos(records.size() - 1);
-        records.add(retval.createFnGroupCount());
-        records.add(createWindowProtect());
-        records.add(createProtect());
-        retval.records.setProtpos(records.size() - 1);
-        records.add(createPassword());
-        records.add(createProtectionRev4());
-        records.add(retval.createPasswordRev4());
-        retval.windowOne = createWindowOne();
-        records.add(retval.windowOne);
-        records.add(retval.createBackup());
-        retval.records.setBackuppos(records.size() - 1);
-        records.add(retval.createHideObj());
-        records.add(retval.createDateWindow1904());
-        records.add(retval.createPrecision());
-        records.add(createRefreshAll());
-        records.add(retval.createBookBool());
-        records.add(retval.createFont());
-        records.add(retval.createFont());
-        records.add(retval.createFont());
-        records.add(retval.createFont());
-        retval.records.setFontpos( records.size() - 1 );   // last font record position
-        retval.numfonts = 4;
-
-        // set up format records
-        for (int i = 0; i <= 7; i++) {
-            FormatRecord rec = createFormat(i);
-            retval.maxformatid = retval.maxformatid >= rec.getIndexCode() ? retval.maxformatid : rec.getIndexCode();
-            formats.add(rec);
-            records.add(rec);
-        }
-
-        for (int k = 0; k < 21; k++) {
-            records.add(retval.createExtendedFormat(k));
-            retval.numxfs++;
-        }
-        retval.records.setXfpos( records.size() - 1 );
-        for (int k = 0; k < 6; k++) {
-            records.add(retval.createStyle(k));
-        }
-        records.add(retval.createUseSelFS());
-
-        int nBoundSheets = 1; // now just do 1
-        for (int k = 0; k < nBoundSheets; k++) {
-            BoundSheetRecord bsr = createBoundSheet(k);
-
-            records.add(bsr);
-            retval.boundsheets.add(bsr);
-            retval.records.setBspos(records.size() - 1);
-        }
-        records.add( retval.createCountry() );
-        for ( int k = 0; k < nBoundSheets; k++ ) {
-            retval.getOrCreateLinkTable().checkExternSheet(k);
-        }
-        retval.sst = new SSTRecord();
-        records.add(retval.sst);
-        records.add(retval.createExtendedSST());
-
-        records.add(EOFRecord.instance);
-        if (log.check( POILogger.DEBUG ))
-            log.log( DEBUG, "exit create new workbook from scratch" );
-        return retval;
-    }
-
-
-    /**Retrieves the Builtin NameRecord that matches the name and index
-     * There shouldn't be too many names to make the sequential search too slow
-     * @param name byte representation of the builtin name to match
-     * @param sheetNumber 1-based sheet number
-     * @return null if no builtin NameRecord matches
-     */
-    public NameRecord getSpecificBuiltinRecord(byte name, int sheetNumber)
-    {
-        return getOrCreateLinkTable().getSpecificBuiltinRecord(name, sheetNumber);
-    }
-
-    /**
-     * Removes the specified Builtin NameRecord that matches the name and index
-     * @param name byte representation of the builtin to match
-     * @param sheetIndex zero-based sheet reference
-     */
-    public void removeBuiltinRecord(byte name, int sheetIndex) {
-        linkTable.removeBuiltinRecord(name, sheetIndex);
-        // TODO - do we need "this.records.remove(...);" similar to that in this.removeName(int namenum) {}?
-    }
-
-    public int getNumRecords() {
-        return records.size();
-    }
-
-    /**
-     * gets the font record at the given index in the font table.  Remember
-     * "There is No Four" (someone at M$ must have gone to Rocky Horror one too
-     * many times)
-     *
-     * @param idx the index to look at (0 or greater but NOT 4)
-     * @return FontRecord located at the given index
-     */
-
-    public FontRecord getFontRecordAt(int idx) {
-        int index = idx;
-
-        if (index > 4) {
-            index -= 1;   // adjust for "There is no 4"
-        }
-        if (index > (numfonts - 1)) {
-            throw new ArrayIndexOutOfBoundsException(
-            "There are only " + numfonts
-            + " font records, you asked for " + idx);
-        }
-        FontRecord retval =
-        ( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + index);
-
-        return retval;
-    }
-
-    /**
-     * Retrieves the index of the given font
-     */
-    public int getFontIndex(FontRecord font) {
-        for(int i=0; i<=numfonts; i++) {
-            FontRecord thisFont =
-                ( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + i);
-            if(thisFont == font) {
-                // There is no 4!
-                if(i > 3) {
-                    return (i+1);
-                }
-                return i;
-            }
-        }
-        throw new IllegalArgumentException("Could not find that font!");
-    }
-
-    /**
-     * creates a new font record and adds it to the "font table".  This causes the
-     * boundsheets to move down one, extended formats to move down (so this function moves
-     * those pointers as well)
-     *
-     * @return FontRecord that was just created
-     */
-
-    public FontRecord createNewFont() {
-        FontRecord rec = createFont();
-
-        records.add(records.getFontpos()+1, rec);
-        records.setFontpos( records.getFontpos() + 1 );
-        numfonts++;
-        return rec;
-    }
-
-    /**
-     * Removes the given font record from the
-     *  file's list. This will make all
-     *  subsequent font indicies drop by one,
-     *  so you'll need to update those yourself!
-     */
-    public void removeFontRecord(FontRecord rec) {
-        records.remove(rec); // this updates FontPos for us
-        numfonts--;
-    }
-
-    /**
-     * gets the number of font records
-     *
-     * @return   number of font records in the "font table"
-     */
-
-    public int getNumberOfFontRecords() {
-        return numfonts;
-    }
-
-    /**
-     * Sets the BOF for a given sheet
-     *
-     * @param sheetIndex the number of the sheet to set the positing of the bof for
-     * @param pos the actual bof position
-     */
-
-    public void setSheetBof(int sheetIndex, int pos) {
-        if (log.check( POILogger.DEBUG ))
-            log.log(DEBUG, "setting bof for sheetnum =", Integer.valueOf(sheetIndex),
-                " at pos=", Integer.valueOf(pos));
-        checkSheets(sheetIndex);
-        getBoundSheetRec(sheetIndex)
-        .setPositionOfBof(pos);
-    }
-
-    private BoundSheetRecord getBoundSheetRec(int sheetIndex) {
-        return boundsheets.get(sheetIndex);
-    }
-
-    /**
-     * Returns the position of the backup record.
-     */
-
-    public BackupRecord getBackupRecord() {
-        return ( BackupRecord ) records.get(records.getBackuppos());
-    }
-
-
-    /**
-     * sets the name for a given sheet.  If the boundsheet record doesn't exist and
-     * its only one more than we have, go ahead and create it.  If it's > 1 more than
-     * we have, except
-     *
-     * @param sheetnum the sheet number (0 based)
-     * @param sheetname the name for the sheet
-     */
-    public void setSheetName(int sheetnum, String sheetname) {
-        checkSheets(sheetnum);
-        BoundSheetRecord sheet = boundsheets.get(sheetnum);
-        sheet.setSheetname(sheetname);
-    }
-
-    /**
-     * Determines whether a workbook contains the provided sheet name.  For the purpose of
-     * comparison, long names are truncated to 31 chars.
-     *
-     * @param name the name to test (case insensitive match)
-     * @param excludeSheetIdx the sheet to exclude from the check or -1 to include all sheets in the check.
-     * @return true if the sheet contains the name, false otherwise.
-     */
-    public boolean doesContainsSheetName(String name, int excludeSheetIdx) {
-        String aName = name;
-        if (aName.length() > MAX_SENSITIVE_SHEET_NAME_LEN) {
-            aName = aName.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN);
-        }
-        for (int i = 0; i < boundsheets.size(); i++) {
-            BoundSheetRecord boundSheetRecord = getBoundSheetRec(i);
-            if (excludeSheetIdx == i) {
-                continue;
-            }
-            String bName = boundSheetRecord.getSheetname();
-            if (bName.length() > MAX_SENSITIVE_SHEET_NAME_LEN) {
-                bName = bName.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN);
-            }
-            if (aName.equalsIgnoreCase(bName)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * sets the order of appearance for a given sheet.
-     *
-     * @param sheetname the name of the sheet to reorder
-     * @param pos the position that we want to insert the sheet into (0 based)
-     */
-
-    public void setSheetOrder(String sheetname, int pos ) {
-    int sheetNumber = getSheetIndex(sheetname);
-    //remove the sheet that needs to be reordered and place it in the spot we want
-    boundsheets.add(pos, boundsheets.remove(sheetNumber));
-    }
-
-    /**
-     * gets the name for a given sheet.
-     *
-     * @param sheetIndex the sheet number (0 based)
-     * @return sheetname the name for the sheet
-     */
-    public String getSheetName(int sheetIndex) {
-        return getBoundSheetRec(sheetIndex).getSheetname();
-    }
-
-    /**
-     * Gets the hidden flag for a given sheet.
-     * Note that a sheet could instead be
-     *  set to be very hidden, which is different
-     *  ({@link #isSheetVeryHidden(int)})
-     *
-     * @param sheetnum the sheet number (0 based)
-     * @return True if sheet is hidden
-     */
-    public boolean isSheetHidden(int sheetnum) {
-        return getBoundSheetRec(sheetnum).isHidden();
-    }
-
-    /**
-     * Gets the very hidden flag for a given sheet.
-     * This is different from the normal
-     *  hidden flag
-     *  ({@link #isSheetHidden(int)})
-     *
-     * @param sheetnum the sheet number (0 based)
-     * @return True if sheet is very hidden
-     */
-    public boolean isSheetVeryHidden(int sheetnum) {
-        return getBoundSheetRec(sheetnum).isVeryHidden();
-    }
-
-    /**
-     * Hide or unhide a sheet
-     *
-     * @param sheetnum The sheet number
-     * @param hidden True to mark the sheet as hidden, false otherwise
-     */
-    public void setSheetHidden(int sheetnum, boolean hidden) {
-        getBoundSheetRec(sheetnum).setHidden(hidden);
-    }
-
-    /**
-     * Hide or unhide a sheet.
-     *  0 = not hidden
-     *  1 = hidden
-     *  2 = very hidden.
-     *
-     * @param sheetnum The sheet number
-     * @param hidden 0 for not hidden, 1 for hidden, 2 for very hidden
-     */
-    public void setSheetHidden(int sheetnum, int hidden) {
-        BoundSheetRecord bsr = getBoundSheetRec(sheetnum);
-        boolean h = false;
-        boolean vh = false;
-        if(hidden == 0) {
-        } else if(hidden == 1) {
-            h = true;
-        } else if(hidden == 2) {
-            vh = true;
-        } else {
-            throw new IllegalArgumentException("Invalid hidden flag " + hidden + " given, must be 0, 1 or 2");
-        }
-        bsr.setHidden(h);
-        bsr.setVeryHidden(vh);
-    }
-
-
-    /**
-     * get the sheet's index
-     * @param name  sheet name
-     * @return sheet index or -1 if it was not found.
-     */
-    public int getSheetIndex(String name) {
-        int retval = -1;
-
-        for (int k = 0; k < boundsheets.size(); k++) {
-            String sheet = getSheetName(k);
-
-            if (sheet.equalsIgnoreCase(name)) {
-                retval = k;
-                break;
-            }
-        }
-        return retval;
-    }
-
-    /**
-     * if we're trying to address one more sheet than we have, go ahead and add it!  if we're
-     * trying to address >1 more than we have throw an exception!
-     */
-    private void checkSheets(int sheetnum) {
-        if ((boundsheets.size()) <= sheetnum) {   // if we're short one add another..
-            if ((boundsheets.size() + 1) <= sheetnum) {
-                throw new RuntimeException("Sheet number out of bounds!");
-            }
-            BoundSheetRecord bsr = createBoundSheet(sheetnum);
-
-            records.add(records.getBspos()+1, bsr);
-            records.setBspos( records.getBspos() + 1 );
-            boundsheets.add(bsr);
-            getOrCreateLinkTable().checkExternSheet(sheetnum);
-            fixTabIdRecord();
-        }
-    }
-
-    /**
-     * @param sheetIndex zero based sheet index
-     */
-    public void removeSheet(int sheetIndex) {
-        if (boundsheets.size() > sheetIndex) {
-            records.remove(records.getBspos() - (boundsheets.size() - 1) + sheetIndex);
-            boundsheets.remove(sheetIndex);
-            fixTabIdRecord();
-        }
-
-        // Within NameRecords, it's ok to have the formula
-        //  part point at deleted sheets. It's also ok to
-        //  have the ExternSheetNumber point at deleted
-        //  sheets.
-        // However, the sheet index must be adjusted, or
-        //  excel will break. (Sheet index is either 0 for
-        //  global, or 1 based index to sheet)
-        int sheetNum1Based = sheetIndex + 1;
-        for(int i=0; i<getNumNames(); i++) {
-            NameRecord nr = getNameRecord(i);
-
-            if(nr.getSheetNumber() == sheetNum1Based) {
-                // Excel re-writes these to point to no sheet
-                nr.setSheetNumber(0);
-            } else if(nr.getSheetNumber() > sheetNum1Based) {
-                // Bump down by one, so still points
-                //  at the same sheet
-                nr.setSheetNumber(nr.getSheetNumber()-1);
-            }
-        }
-    }
-
-    /**
-     * make the tabid record look like the current situation.
-     *
-     */
-    private void fixTabIdRecord() {
-        TabIdRecord tir = ( TabIdRecord ) records.get(records.getTabpos());
-        short[]     tia = new short[ boundsheets.size() ];
-
-        for (short k = 0; k < tia.length; k++) {
-            tia[ k ] = k;
-        }
-        tir.setTabIdArray(tia);
-    }
-
-    /**
-     * returns the number of boundsheet objects contained in this workbook.
-     *
-     * @return number of BoundSheet records
-     */
-
-    public int getNumSheets() {
-        if (log.check( POILogger.DEBUG ))
-            log.log(DEBUG, "getNumSheets=", Integer.valueOf(boundsheets.size()));
-        return boundsheets.size();
-    }
-
-    /**
-     * get the number of ExtendedFormat records contained in this workbook.
-     *
-     * @return int count of ExtendedFormat records
-     */
-
-    public int getNumExFormats() {
-        if (log.check( POILogger.DEBUG ))
-            log.log(DEBUG, "getXF=", Integer.valueOf(numxfs));
-        return numxfs;
-    }
-
-    /**
-     * gets the ExtendedFormatRecord at the given 0-based index
-     *
-     * @param index of the Extended format record (0-based)
-     * @return ExtendedFormatRecord at the given index
-     */
-
-    public ExtendedFormatRecord getExFormatAt(int index) {
-        int xfptr = records.getXfpos() - (numxfs - 1);
-
-        xfptr += index;
-        ExtendedFormatRecord retval =
-        ( ExtendedFormatRecord ) records.get(xfptr);
-
-        return retval;
-    }
-
-    /**
-     * Removes the given ExtendedFormatRecord record from the
-     *  file's list. This will make all
-     *  subsequent font indicies drop by one,
-     *  so you'll need to update those yourself!
-     */
-    public void removeExFormatRecord(ExtendedFormatRecord rec) {
-        records.remove(rec); // this updates XfPos for us
-        numxfs--;
-    }
-
-
-    /**
-     * creates a new Cell-type Extneded Format Record and adds it to the end of
-     *  ExtendedFormatRecords collection
-     *
-     * @return ExtendedFormatRecord that was created
-     */
-
-    public ExtendedFormatRecord createCellXF() {
-        ExtendedFormatRecord xf = createExtendedFormat();
-
-        records.add(records.getXfpos()+1, xf);
-        records.setXfpos( records.getXfpos() + 1 );
-        numxfs++;
-        return xf;
-    }
-
-    /**
-     * Returns the StyleRecord for the given
-     *  xfIndex, or null if that ExtendedFormat doesn't
-     *  have a Style set.
-     */
-    public StyleRecord getStyleRecord(int xfIndex) {
-        // Style records always follow after
-        //  the ExtendedFormat records
-        for(int i=records.getXfpos(); i<records.size(); i++) {
-            Record r = records.get(i);
-            if(r instanceof ExtendedFormatRecord) {
-                continue;
-            }
-            if(!(r instanceof StyleRecord)) {
-                return null;
-            }
-            StyleRecord sr = (StyleRecord)r;
-            if(sr.getXFIndex() == xfIndex) {
-                return sr;
-            }
-        }
-        return null;
-    }
-    /**
-     * Creates a new StyleRecord, for the given Extended
-     *  Format index, and adds it onto the end of the
-     *  records collection
-     */
-    public StyleRecord createStyleRecord(int xfIndex) {
-        // Style records always follow after
-        //  the ExtendedFormat records
-        StyleRecord newSR = new StyleRecord();
-        newSR.setXFIndex(xfIndex);
-
-        // Find the spot
-        int addAt = -1;
-        for(int i=records.getXfpos(); i<records.size() &&
-                addAt == -1; i++) {
-            Record r = records.get(i);
-            if(r instanceof ExtendedFormatRecord ||
-                    r instanceof StyleRecord) {
-                // Keep going
-            } else {
-                addAt = i;
-            }
-        }
-        if(addAt == -1) {
-            throw new IllegalStateException("No XF Records found!");
-        }
-        records.add(addAt, newSR);
-
-        return newSR;
-    }
-
-    /**
-     * Adds a string to the SST table and returns its index (if its a duplicate
-     * just returns its index and update the counts) ASSUMES compressed unicode
-     * (meaning 8bit)
-     *
-     * @param string the string to be added to the SSTRecord
-     *
-     * @return index of the string within the SSTRecord
-     */
-
-    public int addSSTString(UnicodeString string) {
-        if (log.check( POILogger.DEBUG ))
-          log.log(DEBUG, "insert to sst string='", string);
-        if (sst == null) {
-            insertSST();
-        }
-      return sst.addString(string);
-    }
-
-    /**
-     * given an index into the SST table, this function returns the corresponding String value
-     * @return String containing the SST String
-     */
-
-    public UnicodeString getSSTString(int str) {
-        if (sst == null) {
-            insertSST();
-        }
-        UnicodeString retval = sst.getString(str);
-
-        if (log.check( POILogger.DEBUG ))
-            log.log(DEBUG, "Returning SST for index=", Integer.valueOf(str),
-                " String= ", retval);
-        return retval;
-    }
-
-    /**
-     * use this function to add a Shared String Table to an existing sheet (say
-     * generated by a different java api) without an sst....
-     * @see #createExtendedSST()
-     * @see org.apache.poi.hssf.record.SSTRecord
-     */
-
-    public void insertSST() {
-        if (log.check( POILogger.DEBUG ))
-            log.log(DEBUG, "creating new SST via insertSST!");
-        sst = new SSTRecord();
-        records.add(records.size() - 1, createExtendedSST());
-        records.add(records.size() - 2, sst);
-    }
-
-    /**
-     * Serializes all records int the worksheet section into a big byte array. Use
-     * this to write the Workbook out.
-     *
-     * @return byte array containing the HSSF-only portions of the POIFS file.
-     */
-     // GJS: Not used so why keep it.
-//    public byte [] serialize() {
-//        log.log(DEBUG, "Serializing Workbook!");
-//        byte[] retval    = null;
-//
-////         ArrayList bytes     = new ArrayList(records.size());
-//        int    arraysize = getSize();
-//        int    pos       = 0;
-//
-//        retval = new byte[ arraysize ];
-//        for (int k = 0; k < records.size(); k++) {
-//
-//            Record record = records.get(k);
-////             Let's skip RECALCID records, as they are only use for optimization
-//        if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) {
-//                pos += record.serialize(pos, retval);   // rec.length;
-//        }
-//        }
-//        log.log(DEBUG, "Exiting serialize workbook");
-//        return retval;
-//    }
-
-    /**
-     * Serializes all records int the worksheet section into a big byte array. Use
-     * this to write the Workbook out.
-     * @param offset of the data to be written
-     * @param data array of bytes to write this to
-     */
-
-    public int serialize( int offset, byte[] data )
-    {
-        if (log.check( POILogger.DEBUG ))
-            log.log( DEBUG, "Serializing Workbook with offsets" );
-
-        int pos = 0;
-
-        SSTRecord sst = null;
-        int sstPos = 0;
-        boolean wroteBoundSheets = false;
-        for ( int k = 0; k < records.size(); k++ )
-        {
-
-            Record record = records.get( k );
-            // Let's skip RECALCID records, as they are only use for optimization
-            if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
-            {
-                int len = 0;
-                if (record instanceof SSTRecord)
-                {
-                    sst = (SSTRecord)record;
-                    sstPos = pos;
-                }
-                if (record.getSid() == ExtSSTRecord.sid && sst != null)
-                {
-                    record = sst.createExtSSTRecord(sstPos + offset);
-                }
-                if (record instanceof BoundSheetRecord) {
-                     if(!wroteBoundSheets) {
-                        for (int i = 0; i < boundsheets.size(); i++) {
-                            len+= getBoundSheetRec(i)
-                                             .serialize(pos+offset+len, data);
-                        }
-                        wroteBoundSheets = true;
-                     }
-                } else {
-                   len = record.serialize( pos + offset, data );
-                }
-                /////  DEBUG BEGIN /////
-//                if (len != record.getRecordSize())
-//                    throw new IllegalStateException("Record size does not match serialized bytes.  Serialized size = " + len + " but getRecordSize() returns " + record.getRecordSize());
-                /////  DEBUG END /////
-                pos += len;   // rec.length;
-            }
-        }
-        if (log.check( POILogger.DEBUG ))
-            log.log( DEBUG, "Exiting serialize workbook" );
-        return pos;
-    }
-
-    public int getSize()
-    {
-        int retval = 0;
-
-        SSTRecord sst = null;
-        for ( int k = 0; k < records.size(); k++ )
-        {
-            Record record = records.get( k );
-            // Let's skip RECALCID records, as they are only use for optimization
-            if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
-            {
-                if (record instanceof SSTRecord)
-                    sst = (SSTRecord)record;
-                if (record.getSid() == ExtSSTRecord.sid && sst != null)
-                    retval += sst.calcExtSSTRecordSize();
-                else
-                    retval += record.getRecordSize();
-            }
-        }
-        return retval;
-    }
-
-    private static BOFRecord createBOF() {
-        BOFRecord retval = new BOFRecord();
-
-        retval.setVersion(( short ) 0x600);
-        retval.setType(BOFRecord.TYPE_WORKBOOK);
-        retval.setBuild(( short ) 0x10d3);
-        retval.setBuildYear(( short ) 1996);
-        retval.setHistoryBitMask(0x41);   // was c1 before verify
-        retval.setRequiredVersion(0x6);
-        return retval;
-    }
-
-    private static InterfaceHdrRecord createInterfaceHdr() {
-        InterfaceHdrRecord retval = new InterfaceHdrRecord();
-
-        retval.setCodepage(CODEPAGE);
-        return retval;
-    }
-
-    private static MMSRecord createMMS() {
-        MMSRecord retval = new MMSRecord();
-
-        retval.setAddMenuCount(( byte ) 0);
-        retval.setDelMenuCount(( byte ) 0);
-        return retval;
-    }
-
-    private static InterfaceEndRecord createInterfaceEnd() {
-        return new InterfaceEndRecord();
-    }
-
-    /**
-     * creates the WriteAccess record containing the logged in user's name
-     */
-    private static WriteAccessRecord createWriteAccess() {
-        WriteAccessRecord retval = new WriteAccessRecord();
-
-        try {
-            retval.setUsername(System.getProperty("user.name"));
-        } catch (AccessControlException e) {
-                // AccessControlException can occur in a restricted context
-                // (client applet/jws application or restricted security server)
-                retval.setUsername("POI");
-        }
-        return retval;
-    }
-
-    private static CodepageRecord createCodepage() {
-        CodepageRecord retval = new CodepageRecord();
-
-        retval.setCodepage(CODEPAGE);
-        return retval;
-    }
-
-    private static DSFRecord createDSF() {
-        return new DSFRecord(false); // we don't even support double stream files
-    }
-
-    /**
-     * creates the TabId record containing an array
-     */
-    private static TabIdRecord createTabId() {
-        return new TabIdRecord();
-    }
-
-    /**
-     * creates the FnGroupCount record containing the Magic number constant of 14.
-     */
-    private static FnGroupCountRecord createFnGroupCount() {
-        FnGroupCountRecord retval = new FnGroupCountRecord();
-
-        retval.setCount(( short ) 14);
-        return retval;
-    }
-
-    /**
-     * @return a new WindowProtect record with protect set to false.
-     */
-    private static WindowProtectRecord createWindowProtect() {
-        // by default even when we support it we won't
-        // want it to be protected
-        return new WindowProtectRecord(false);
-    }
-
-    /**
-     * @return a new Protect record with protect set to false.
-     */
-    private static ProtectRecord createProtect() {
-        // by default even when we support it we won't
-        // want it to be protected
-        return new ProtectRecord(false);
-    }
-
-    /**
-     * @return a new Password record with password set to 0x0000 (no password).
-     */
-    private static PasswordRecord createPassword() {
-        return new PasswordRecord(0x0000); // no password by default!
-    }
-
-    /**
-     * @return a new ProtectionRev4 record with protect set to false.
-     */
-    private static ProtectionRev4Record createProtectionRev4() {
-        return new ProtectionRev4Record(false);
-    }
-
-    /**
-     * @return a new PasswordRev4 record with password set to 0.
-     */
-    private static PasswordRev4Record createPasswordRev4() {
-        return new PasswordRev4Record(0x0000);
-    }
-
-    /**
-     * creates the WindowOne record with the following magic values: <P>
-     * horizontal hold - 0x168 <P>
-     * vertical hold   - 0x10e <P>
-     * width           - 0x3a5c <P>
-     * height          - 0x23be <P>
-     * options         - 0x38 <P>
-     * selected tab    - 0 <P>
-     * displayed tab   - 0 <P>
-     * num selected tab- 0 <P>
-     * tab width ratio - 0x258 <P>
-     */
-    private static WindowOneRecord createWindowOne() {
-        WindowOneRecord retval = new WindowOneRecord();
-
-        retval.setHorizontalHold(( short ) 0x168);
-        retval.setVerticalHold(( short ) 0x10e);
-        retval.setWidth(( short ) 0x3a5c);
-        retval.setHeight(( short ) 0x23be);
-        retval.setOptions(( short ) 0x38);
-        retval.setActiveSheetIndex( 0x0);
-        retval.setFirstVisibleTab(0x0);
-        retval.setNumSelectedTabs(( short ) 1);
-        retval.setTabWidthRatio(( short ) 0x258);
-        return retval;
-    }
-
-    /**
-     * creates the Backup record with backup set to 0. (loose the data, who cares)
-     */
-    private static BackupRecord createBackup() {
-        BackupRecord retval = new BackupRecord();
-
-        retval.setBackup(( short ) 0);   // by default DONT save backups of files...just loose data
-        return retval;
-    }
-
-    /**
-     * creates the HideObj record with hide object set to 0. (don't hide)
-     */
-    private static HideObjRecord createHideObj() {
-        HideObjRecord retval = new HideObjRecord();
-        retval.setHideObj(( short ) 0);   // by default set hide object off
-        return retval;
-    }
-
-    /**
-     * creates the DateWindow1904 record with windowing set to 0. (don't window)
-     */
-    private static DateWindow1904Record createDateWindow1904() {
-        DateWindow1904Record retval = new DateWindow1904Record();
-
-        retval.setWindowing(( short ) 0);   // don't EVER use 1904 date windowing...tick tock..
-        return retval;
-    }
-
-    /**
-     * creates the Precision record with precision set to true. (full precision)
-     */
-    private static PrecisionRecord createPrecision() {
-        PrecisionRecord retval = new PrecisionRecord();
-        retval.setFullPrecision(true);   // always use real numbers in calculations!
-        return retval;
-    }
-
-    /**
-     * @return a new RefreshAll record with refreshAll set to false. (do not refresh all calcs)
-     */
-    private static RefreshAllRecord createRefreshAll() {
-        return new RefreshAllRecord(false);
-    }
-
-    /**
-     * creates the BookBool record with saveLinkValues set to 0. (don't save link values)
-     */
-    private static BookBoolRecord createBookBool() {
-        BookBoolRecord retval = new BookBoolRecord();
-        retval.setSaveLinkValues(( short ) 0);
-        return retval;
-    }
-
-    /**
-     * creates a Font record with the following magic values: <P>
-     * fontheight           = 0xc8<P>
-     * attributes           = 0x0<P>
-     * color palette index  = 0x7fff<P>
-     * bold weight          = 0x190<P>
-     * Font Name Length     = 5 <P>
-     * Font Name            = Arial <P>
-     */
-    private static FontRecord createFont() {
-        FontRecord retval = new FontRecord();
-
-        retval.setFontHeight(( short ) 0xc8);
-        retval.setAttributes(( short ) 0x0);
-        retval.setColorPaletteIndex(( short ) 0x7fff);
-        retval.setBoldWeight(( short ) 0x190);
-        retval.setFontName("Arial");
-        return retval;
-    }
-
-    /**
-     * Creates a FormatRecord object
-     * @param id    the number of the format record to create (meaning its position in
-     *        a file as M$ Excel would create it.)
-     */
-    private static FormatRecord createFormat(int id) {
-        // we'll need multiple editions for
-        // the different formats
-
-        switch (id) {
-            case 0: return new FormatRecord(5, "\"$\"#,##0_);\\(\"$\"#,##0\\)");
-            case 1: return new FormatRecord(6, "\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)");
-            case 2: return new FormatRecord(7, "\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)");
-            case 3: return new FormatRecord(8, "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)");
-            case 4: return new FormatRecord(0x2a, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)");
-            case 5: return new FormatRecord(0x29, "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)");
-            case 6: return new FormatRecord(0x2c, "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)");
-            case 7: return new FormatRecord(0x2b, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)");
-        }
-        throw new  IllegalArgumentException("Unexpected id " + id);
-    }
-
-    /**
-     * Creates an ExtendedFormatRecord object
-     * @param id    the number of the extended format record to create (meaning its position in
-     *        a file as MS Excel would create it.)
-     */
-    private static ExtendedFormatRecord createExtendedFormat(int id) {   // we'll need multiple editions
-        ExtendedFormatRecord retval = new ExtendedFormatRecord();
-
-        switch (id) {
-
-            case 0 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 1 :
-                retval.setFontIndex(( short ) 1);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 2 :
-                retval.setFontIndex(( short ) 1);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 3 :
-                retval.setFontIndex(( short ) 2);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 4 :
-                retval.setFontIndex(( short ) 2);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 5 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 6 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 7 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 8 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 9 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 10 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 11 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 12 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 13 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 14 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff400);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-                // cell records
-            case 15 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0);
-                retval.setCellOptions(( short ) 0x1);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0x0);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-                // style
-            case 16 :
-                retval.setFontIndex(( short ) 1);
-                retval.setFormatIndex(( short ) 0x2b);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff800);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 17 :
-                retval.setFontIndex(( short ) 1);
-                retval.setFormatIndex(( short ) 0x29);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff800);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 18 :
-                retval.setFontIndex(( short ) 1);
-                retval.setFormatIndex(( short ) 0x2c);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff800);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 19 :
-                retval.setFontIndex(( short ) 1);
-                retval.setFormatIndex(( short ) 0x2a);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff800);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 20 :
-                retval.setFontIndex(( short ) 1);
-                retval.setFormatIndex(( short ) 0x9);
-                retval.setCellOptions(( short ) 0xfffffff5);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0xfffff800);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-                // unused from this point down
-            case 21 :
-                retval.setFontIndex(( short ) 5);
-                retval.setFormatIndex(( short ) 0x0);
-                retval.setCellOptions(( short ) 0x1);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0x800);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 22 :
-                retval.setFontIndex(( short ) 6);
-                retval.setFormatIndex(( short ) 0x0);
-                retval.setCellOptions(( short ) 0x1);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0x5c00);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 23 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0x31);
-                retval.setCellOptions(( short ) 0x1);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0x5c00);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 24 :
-                retval.setFontIndex(( short ) 0);
-                retval.setFormatIndex(( short ) 0x8);
-                retval.setCellOptions(( short ) 0x1);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0x5c00);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-
-            case 25 :
-                retval.setFontIndex(( short ) 6);
-                retval.setFormatIndex(( short ) 0x8);
-                retval.setCellOptions(( short ) 0x1);
-                retval.setAlignmentOptions(( short ) 0x20);
-                retval.setIndentionOptions(( short ) 0x5c00);
-                retval.setBorderOptions(( short ) 0);
-                retval.setPaletteOptions(( short ) 0);
-                retval.setAdtlPaletteOptions(( short ) 0);
-                retval.setFillPaletteOptions(( short ) 0x20c0);
-                break;
-        }
-        return retval;
-    }
-
-    /**
-     * creates an default cell type ExtendedFormatRecord object.
-     * @return ExtendedFormatRecord with intial defaults (cell-type)
-     */
-    private static ExtendedFormatRecord createExtendedFormat() {
-        ExtendedFormatRecord retval = new ExtendedFormatRecord();
-
-        retval.setFontIndex(( short ) 0);
-        retval.setFormatIndex(( short ) 0x0);
-        retval.setCellOptions(( short ) 0x1);
-        retval.setAlignmentOptions(( short ) 0x20);
-        retval.setIndentionOptions(( short ) 0);
-        retval.setBorderOptions(( short ) 0);
-        retval.setPaletteOptions(( short ) 0);
-        retval.setAdtlPaletteOptions(( short ) 0);
-        retval.setFillPaletteOptions(( short ) 0x20c0);
-        retval.setTopBorderPaletteIdx(HSSFColor.BLACK.index);
-        retval.setBottomBorderPaletteIdx(HSSFColor.BLACK.index);
-        retval.setLeftBorderPaletteIdx(HSSFColor.BLACK.index);
-        retval.setRightBorderPaletteIdx(HSSFColor.BLACK.index);
-        return retval;
-    }
-
-    /**
-     * Creates a StyleRecord object
-     * @param id        the number of the style record to create (meaning its position in
-     *                  a file as MS Excel would create it.
-     */
-    private static StyleRecord createStyle(int id) {   // we'll need multiple editions
-        StyleRecord retval = new StyleRecord();
-
-        switch (id) {
-
-            case 0 :
-                retval.setXFIndex(0x010);
-                retval.setBuiltinStyle(3);
-                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
-                break;
-
-            case 1 :
-                retval.setXFIndex(0x011);
-                retval.setBuiltinStyle(6);
-                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
-                break;
-
-            case 2 :
-                retval.setXFIndex(0x012);
-                retval.setBuiltinStyle(4);
-                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
-                break;
-
-            case 3 :
-                retval.setXFIndex(0x013);
-                retval.setBuiltinStyle(7);
-                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
-                break;
-
-            case 4 :
-                retval.setXFIndex(0x000);
-                retval.setBuiltinStyle(0);
-                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
-                break;
-
-            case 5 :
-                retval.setXFIndex(0x014);
-                retval.setBuiltinStyle(5);
-                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
-                break;
-        }
-        return retval;
-    }
-
-    /**
-     * Creates a palette record initialized to the default palette
-     */
-    private static PaletteRecord createPalette() {
-        return new PaletteRecord();
-    }
-
-    /**
-     * @return a new UseSelFS object with the use natural language flag set to 0 (false)
-     */
-    private static UseSelFSRecord createUseSelFS() {
-        return new UseSelFSRecord(false);
-    }
-
-    /**
-     * create a "bound sheet" or "bundlesheet" (depending who you ask) record
-     * Always sets the sheet's bof to 0.  You'll need to set that yourself.
-     * @param id either sheet 0,1 or 2.
-     * @return record containing a BoundSheetRecord
-     * @see org.apache.poi.hssf.record.BoundSheetRecord
-     * @see org.apache.poi.hssf.record.Record
-     */
-    private static BoundSheetRecord createBoundSheet(int id) {
-        return new BoundSheetRecord("Sheet" + (id+1));
-    }
-
-    /**
-     * Creates the Country record with the default country set to 1
-     * and current country set to 7 in case of russian locale ("ru_RU") and 1 otherwise
-     */
-    private static CountryRecord createCountry() {
-        CountryRecord retval = new CountryRecord();
-
-        retval.setDefaultCountry(( short ) 1);
-
-        // from Russia with love ;)
-        if ( Locale.getDefault().toString().equals( "ru_RU" ) ) {
-            retval.setCurrentCountry(( short ) 7);
-        }
-        else {
-            retval.setCurrentCountry(( short ) 1);
-        }
-
-        return retval;
-    }
-
-    /**
-     * Creates the ExtendedSST record with numstrings per bucket set to 0x8.  HSSF
-     * doesn't yet know what to do with this thing, but we create it with nothing in
-     * it hardly just to make Excel happy and our sheets look like Excel's
-     */
-    private static ExtSSTRecord createExtendedSST() {
-        ExtSSTRecord retval = new ExtSSTRecord();
-        retval.setNumStringsPerBucket(( short ) 0x8);
-        return retval;
-    }
-
-    /**
-     * lazy initialization
-     * Note - creating the link table causes creation of 1 EXTERNALBOOK and 1 EXTERNALSHEET record
-     */
-    private LinkTable getOrCreateLinkTable() {
-        if(linkTable == null) {
-            linkTable = new LinkTable((short) getNumSheets(), records);
-        }
-        return linkTable;
-    }
-
-    /** finds the sheet name by his extern sheet index
-     * @param externSheetIndex extern sheet index
-     * @return sheet name.
-     */
-    public String findSheetNameFromExternSheet(int externSheetIndex){
-
-        int indexToSheet = linkTable.getIndexToInternalSheet(externSheetIndex);
-        if (indexToSheet < 0) {
-            // TODO - what does '-1' mean here?
-            //error check, bail out gracefully!
-            return "";
-        }
-        if (indexToSheet >= boundsheets.size()) {
-            // Not sure if this can ever happen (See bug 45798)
-            return ""; // Seems to be what excel would do in this case
-        }
-        return getSheetName(indexToSheet);
-    }
-    public ExternalSheet getExternalSheet(int externSheetIndex) {
-        String[] extNames = linkTable.getExternalBookAndSheetName(externSheetIndex);
-        if (extNames == null) {
-            return null;
-        }
-        return new ExternalSheet(extNames[0], extNames[1]);
-    }
-
-    /**
-     * Finds the sheet index for a particular external sheet number.
-     * @param externSheetNumber     The external sheet number to convert
-     * @return  The index to the sheet found.
-     */
-    public int getSheetIndexFromExternSheetIndex(int externSheetNumber)
-    {
-        return linkTable.getSheetIndexFromExternSheetIndex(externSheetNumber);
-    }
-
-    /** returns the extern sheet number for specific sheet number ,
-     *  if this sheet doesn't exist in extern sheet , add it
-     * @param sheetNumber sheet number
-     * @return index to extern sheet
-     */
-    public short checkExternSheet(int sheetNumber){
-        return (short)getOrCreateLinkTable().checkExternSheet(sheetNumber);
-    }
-
-    public int getExternalSheetIndex(String workbookName, String sheetName) {
-        return getOrCreateLinkTable().getExternalSheetIndex(workbookName, sheetName);
-    }
-
-
-    /** gets the total number of names
-     * @return number of names
-     */
-    public int getNumNames(){
-        if(linkTable == null) {
-            return 0;
-        }
-        return linkTable.getNumNames();
-    }
-
-    /** gets the name record
-     * @param index name index
-     * @return name record
-     */
-    public NameRecord getNameRecord(int index){
-        return linkTable.getNameRecord(index);
-    }
-
-    /** creates new name
-     * @return new name record
-     */
-    public NameRecord createName(){
-        return addName(new NameRecord());
-    }
-
-
-    /** creates new name
-     * @return new name record
-     */
-    public NameRecord addName(NameRecord name)
-    {
-
-        LinkTable linkTable = getOrCreateLinkTable();
-        if(linkTable.nameAlreadyExists(name)) {
-            throw new IllegalArgumentException(
-                "You are trying to assign a duplicated name record: "
-                + name.getNameText());
-        }
-        linkTable.addName(name);
-
-        return name;
-    }
-
-    /**
-     * Generates a NameRecord to represent a built-in region
-     * @return a new NameRecord
-     */
-    public NameRecord createBuiltInName(byte builtInName, int sheetNumber) {
-        if (sheetNumber < 0 || sheetNumber+1 > Short.MAX_VALUE) {
-            throw new IllegalArgumentException("Sheet number ["+sheetNumber+"]is not valid ");
-        }
-
-        NameRecord name = new NameRecord(builtInName, sheetNumber);
-
-        while(linkTable.nameAlreadyExists(name)) {
-            throw new RuntimeException("Builtin (" + builtInName
-                    + ") already exists for sheet (" + sheetNumber + ")");
-        }
-        addName(name);
-        return name;
-    }
-
-
-    /** removes the name
-     * @param nameIndex name index
-     */
-    public void removeName(int nameIndex){
-
-        if (linkTable.getNumNames() > nameIndex) {
-            int idx = findFirstRecordLocBySid(NameRecord.sid);
-            records.remove(idx + nameIndex);
-            linkTable.removeName(nameIndex);
-        }
-    }
-
-    /**
-     * Returns a format index that matches the passed in format.  It does not tie into HSSFDataFormat.
-     * @param format the format string
-     * @param createIfNotFound creates a new format if format not found
-     * @return the format id of a format that matches or -1 if none found and createIfNotFound
-     */
-    public short getFormat(String format, boolean createIfNotFound) {
-    Iterator iterator;
-    for (iterator = formats.iterator(); iterator.hasNext();) {
-        FormatRecord r = (FormatRecord)iterator.next();
-        if (r.getFormatString().equals(format)) {
-        return (short)r.getIndexCode();
-        }
-    }
-
-    if (createIfNotFound) {
-        return (short)createFormat(format);
-    }
-
-    return -1;
-    }
-
-    /**
-     * Returns the list of FormatRecords in the workbook.
-     * @return ArrayList of FormatRecords in the notebook
-     */
-    public List getFormats() {
-    return formats;
-    }
-
-    /**
-     * Creates a FormatRecord, inserts it, and returns the index code.
-     * @param formatString the format string
-     * @return the index code of the format record.
-     * @see org.apache.poi.hssf.record.FormatRecord
-     * @see org.apache.poi.hssf.record.Record
-     */
-    public int createFormat(String formatString) {
-
-        maxformatid = maxformatid >= 0xa4 ? maxformatid + 1 : 0xa4; //Starting value from M$ empircal study.
-        FormatRecord rec = new FormatRecord(maxformatid, formatString);
-
-        int pos = 0;
-        while ( pos < records.size() && records.get( pos ).getSid() != FormatRecord.sid )
-            pos++;
-        pos += formats.size();
-        formats.add( rec );
-        records.add( pos, rec );
-        return maxformatid;
-    }
-
-
-
-    /**
-     * Returns the first occurance of a record matching a particular sid.
-     */
-    public Record findFirstRecordBySid(short sid) {
-        for (Iterator iterator = records.iterator(); iterator.hasNext(); ) {
-            Record record = ( Record ) iterator.next();
-
-            if (record.getSid() == sid) {
-                return record;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns the index of a record matching a particular sid.
-     * @param sid   The sid of the record to match
-     * @return      The index of -1 if no match made.
-     */
-    public int findFirstRecordLocBySid(short sid) {
-        int index = 0;
-        for (Iterator iterator = records.iterator(); iterator.hasNext(); ) {
-            Record record = ( Record ) iterator.next();
-
-            if (record.getSid() == sid) {
-                return index;
-            }
-            index ++;
-        }
-        return -1;
-    }
-
-    /**
-     * Returns the next occurance of a record matching a particular sid.
-     */
-    public Record findNextRecordBySid(short sid, int pos) {
-        int matches = 0;
-        for (Iterator iterator = records.iterator(); iterator.hasNext(); ) {
-            Record record = ( Record ) iterator.next();
-
-            if (record.getSid() == sid) {
-                if (matches++ == pos)
-                    return record;
-            }
-        }
-        return null;
-    }
-
-    public List getHyperlinks()
-    {
-        return hyperlinks;
-    }
-
-    public List<Record> getRecords() {
-        return records.getRecords();
-    }
-
-    /**
-    * Whether date windowing is based on 1/2/1904 or 1/1/1900.
-    * Some versions of Excel (Mac) can save workbooks using 1904 date windowing.
-    *
-    * @return true if using 1904 date windowing
-    */
-    public boolean isUsing1904DateWindowing() {
-        return uses1904datewindowing;
-    }
-
-    /**
-     * Returns the custom palette in use for this workbook; if a custom palette record
-     * does not exist, then it is created.
-     */
-    public PaletteRecord getCustomPalette()
-    {
-      PaletteRecord palette;
-      int palettePos = records.getPalettepos();
-      if (palettePos != -1) {
-        Record rec = records.get(palettePos);
-        if (rec instanceof PaletteRecord) {
-          palette = (PaletteRecord) rec;
-        } else throw new RuntimeException("InternalError: Expected PaletteRecord but got a '"+rec+"'");
-      }
-      else
-      {
-          palette = createPalette();
-          //Add the palette record after the bof which is always the first record
-          records.add(1, palette);
-          records.setPalettepos(1);
-      }
-      return palette;
-    }
-
-    /**
-     * Finds the primary drawing group, if one already exists
-     */
-    public void findDrawingGroup() {
-        // Need to find a DrawingGroupRecord that
-        //  contains a EscherDggRecord
-        for(Iterator<Record> rit = records.iterator(); rit.hasNext();) {
-            Record r = rit.next();
-
-            if(r instanceof DrawingGroupRecord) {
-                DrawingGroupRecord dg = (DrawingGroupRecord)r;
-                dg.processChildRecords();
-
-                EscherContainerRecord cr =
-                    dg.getEscherContainer();
-                if(cr == null) {
-                    continue;
-                }
-
-                EscherDggRecord dgg = null;
-                for(Iterator<EscherRecord> it = cr.getChildIterator(); it.hasNext();) {
-                    Object er = it.next();
-                    if(er instanceof EscherDggRecord) {
-                        dgg = (EscherDggRecord)er;
-                    }
-                }
-
-                if(dgg != null) {
-                    drawingManager = new DrawingManager2(dgg);
-                    return;
-                }
-            }
-        }
-
-        // Look for the DrawingGroup record
-        int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
-
-        // If there is one, does it have a EscherDggRecord?
-        if(dgLoc != -1) {
-            DrawingGroupRecord dg = (DrawingGroupRecord)records.get(dgLoc);
-            EscherDggRecord dgg = null;
-            for(Iterator it = dg.getEscherRecords().iterator(); it.hasNext();) {
-                Object er = it.next();
-                if(er instanceof EscherDggRecord) {
-                    dgg = (EscherDggRecord)er;
-                }
-            }
-
-            if(dgg != null) {
-                drawingManager = new DrawingManager2(dgg);
-            }
-        }
-    }
-
-    /**
-     * Creates a primary drawing group record.  If it already
-     *  exists then it's modified.
-     */
-    public void createDrawingGroup() {
-        if (drawingManager == null) {
-            EscherContainerRecord dggContainer = new EscherContainerRecord();
-            EscherDggRecord dgg = new EscherDggRecord();
-            EscherOptRecord opt = new EscherOptRecord();
-            EscherSplitMenuColorsRecord splitMenuColors = new EscherSplitMenuColorsRecord();
-
-            dggContainer.setRecordId((short) 0xF000);
-            dggContainer.setOptions((short) 0x000F);
-            dgg.setRecordId(EscherDggRecord.RECORD_ID);
-            dgg.setOptions((short)0x0000);
-            dgg.setShapeIdMax(1024);
-            dgg.setNumShapesSaved(0);
-            dgg.setDrawingsSaved(0);
-            dgg.setFileIdClusters(new EscherDggRecord.FileIdCluster[] {} );
-            drawingManager = new DrawingManager2(dgg);
-            EscherContainerRecord bstoreContainer = null;
-            if (escherBSERecords.size() > 0)
-            {
-                bstoreContainer = new EscherContainerRecord();
-                bstoreContainer.setRecordId( EscherContainerRecord.BSTORE_CONTAINER );
-                bstoreContainer.setOptions( (short) ( (escherBSERecords.size() << 4) | 0xF ) );
-                for ( Iterator iterator = escherBSERecords.iterator(); iterator.hasNext(); )
-                {
-                    EscherRecord escherRecord = (EscherRecord) iterator.next();
-                    bstoreContainer.addChildRecord( escherRecord );
-                }
-            }
-            opt.setRecordId((short) 0xF00B);
-            opt.setOptions((short) 0x0033);
-            opt.addEscherProperty( new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 524296) );
-            opt.addEscherProperty( new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 0x08000041) );
-            opt.addEscherProperty( new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, 134217792) );
-            splitMenuColors.setRecordId((short) 0xF11E);
-            splitMenuColors.setOptions((short) 0x0040);
-            splitMenuColors.setColor1(0x0800000D);
-            splitMenuColors.setColor2(0x0800000C);
-            splitMenuColors.setColor3(0x08000017);
-            splitMenuColors.setColor4(0x100000F7);
-
-            dggContainer.addChildRecord(dgg);
-            if (bstoreContainer != null)
-                dggContainer.addChildRecord( bstoreContainer );
-            dggContainer.addChildRecord(opt);
-            dggContainer.addChildRecord(splitMenuColors);
-
-            int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
-            if (dgLoc == -1) {
-                DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
-                drawingGroup.addEscherRecord(dggContainer);
-                int loc = findFirstRecordLocBySid(CountryRecord.sid);
-
-                getRecords().add(loc+1, drawingGroup);
-            } else {
-                DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
-                drawingGroup.addEscherRecord(dggContainer);
-                getRecords().set(dgLoc, drawingGroup);
-            }
-
-        }
-    }
-
-    public WindowOneRecord getWindowOne() {
-        return windowOne;
-    }
-
-    public EscherBSERecord getBSERecord(int pictureIndex) {
-        return escherBSERecords.get(pictureIndex-1);
-    }
-
-    public int addBSERecord(EscherBSERecord e) {
-        createDrawingGroup();
-
-        // maybe we don't need that as an instance variable anymore
-        escherBSERecords.add( e );
-
-        int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
-        DrawingGroupRecord drawingGroup = (DrawingGroupRecord) getRecords().get( dgLoc );
-
-        EscherContainerRecord dggContainer = (EscherContainerRecord) drawingGroup.getEscherRecord( 0 );
-        EscherContainerRecord bstoreContainer;
-        if (dggContainer.getChild( 1 ).getRecordId() == EscherContainerRecord.BSTORE_CONTAINER )
-        {
-            bstoreContainer = (EscherContainerRecord) dggContainer.getChild( 1 );
-        }
-        else
-        {
-            bstoreContainer = new EscherContainerRecord();
-            bstoreContainer.setRecordId( EscherContainerRecord.BSTORE_CONTAINER );
-            List<EscherRecord> childRecords = dggContainer.getChildRecords();
-            childRecords.add(1, bstoreContainer);
-            dggContainer.setChildRecords(childRecords);
-        }
-        bstoreContainer.setOptions( (short) ( (escherBSERecords.size() << 4) | 0xF ) );
-
-        bstoreContainer.addChildRecord( e );
-
-        return escherBSERecords.size();
-    }
-
-    public DrawingManager2 getDrawingManager()
-    {
-        return drawingManager;
-    }
-
-    public WriteProtectRecord getWriteProtect() {
-        if (writeProtect == null) {
-           writeProtect = new WriteProtectRecord();
-           int i = 0;
-           for (i = 0;
-                i < records.size() && !(records.get(i) instanceof BOFRecord);
-                i++) {
-           }
-           records.add(i+1, writeProtect);
-        }
-        return this.writeProtect;
-    }
-
-    public WriteAccessRecord getWriteAccess() {
-        if (writeAccess == null) {
-           writeAccess = createWriteAccess();
-           int i = 0;
-           for (i = 0;
-                i < records.size() && !(records.get(i) instanceof InterfaceEndRecord);
-                i++) {
-           }
-           records.add(i+1, writeAccess);
-        }
-        return writeAccess;
-    }
-
-    public FileSharingRecord getFileSharing() {
-        if (fileShare == null) {
-           fileShare = new FileSharingRecord();
-           int i = 0;
-           for (i = 0;
-                i < records.size() && !(records.get(i) instanceof WriteAccessRecord);
-                i++) {
-           }
-           records.add(i+1, fileShare);
-        }
-        return fileShare;
-    }
-
-    /**
-     * is the workbook protected with a password (not encrypted)?
-     */
-    public boolean isWriteProtected() {
-        if (fileShare == null) {
-            return false;
-        }
-        FileSharingRecord frec = getFileSharing();
-        return frec.getReadOnly() == 1;
-    }
-
-    /**
-     * protect a workbook with a password (not encypted, just sets writeprotect
-     * flags and the password.
-     * @param password to set
-     */
-    public void writeProtectWorkbook( String password, String username ) {
-        int protIdx = -1;
-        FileSharingRecord frec = getFileSharing();
-        WriteAccessRecord waccess = getWriteAccess();
-        WriteProtectRecord wprotect = getWriteProtect();
-        frec.setReadOnly((short)1);
-        frec.setPassword(FileSharingRecord.hashPassword(password));
-        frec.setUsername(username);
-        waccess.setUsername(username);
-    }
-
-    /**
-     * removes the write protect flag
-     */
-    public void unwriteProtectWorkbook() {
-        records.remove(fileShare);
-        records.remove(writeProtect);
-        fileShare = null;
-        writeProtect = null;
-    }
-
-    /**
-     * @param refIndex Index to REF entry in EXTERNSHEET record in the Link Table
-     * @param definedNameIndex zero-based to DEFINEDNAME or EXTERNALNAME record
-     * @return the string representation of the defined or external name
-     */
-    public String resolveNameXText(int refIndex, int definedNameIndex) {
-        return linkTable.resolveNameXText(refIndex, definedNameIndex);
-    }
-
-    public NameXPtg getNameXPtg(String name) {
-        return getOrCreateLinkTable().getNameXPtg(name);
-    }
-
-    /**
-     * Check if the cloned sheet has drawings. If yes, then allocate a new drawing group ID and
-     * re-generate shape IDs
-     *
-     * @param sheet the cloned sheet
-     */
-    public void cloneDrawings(Sheet sheet){
-
-        findDrawingGroup();
-
-        if(drawingManager == null) {
-            //this workbook does not have drawings
-            return;
-        }
-
-        //check if the cloned sheet has drawings
-        int aggLoc = sheet.aggregateDrawingRecords(drawingManager, false);
-        if(aggLoc != -1) {
-            EscherAggregate agg = (EscherAggregate) sheet.findFirstRecordBySid(EscherAggregate.sid);
-            EscherContainerRecord escherContainer = agg.getEscherContainer();
-            if (escherContainer == null) {
-                return;
-            }
-
-            EscherDggRecord dgg = drawingManager.getDgg();
-
-            //register a new drawing group for the cloned sheet
-            int dgId = drawingManager.findNewDrawingGroupId();
-            dgg.addCluster( dgId, 0 );
-            dgg.setDrawingsSaved(dgg.getDrawingsSaved() + 1);
-
-            EscherDgRecord dg = null;
-            for(Iterator<EscherRecord> it = escherContainer.getChildIterator(); it.hasNext();) {
-                EscherRecord er = it.next();
-                if(er instanceof EscherDgRecord) {
-                    dg = (EscherDgRecord)er;
-                    //update id of the drawing in the cloned sheet
-                    dg.setOptions( (short) ( dgId << 4 ) );
-                } else if (er instanceof EscherContainerRecord){
-                    //recursively find shape records and re-generate shapeId
-                    List<EscherRecord> spRecords = new ArrayList<EscherRecord>();
-                    EscherContainerRecord cp = (EscherContainerRecord)er;
-                    cp.getRecordsById(EscherSpRecord.RECORD_ID,  spRecords);
-                    for(Iterator<EscherRecord> spIt = spRecords.iterator(); spIt.hasNext();) {
-                        EscherSpRecord sp = (EscherSpRecord)spIt.next();
-                        int shapeId = drawingManager.allocateShapeId((short)dgId, dg);
-                        //allocateShapeId increments the number of shapes. roll back to the previous value
-                        dg.setNumShapes(dg.getNumShapes()-1);
-                        sp.setShapeId(shapeId);
-                    }
-                }
-            }
-
-        }
-    }
-
-    /**
-     * Updates named ranges due to moving of cells
-     */
-    public void updateNamesAfterCellShift(FormulaShifter shifter) {
-        for (int i = 0 ; i < getNumNames() ; ++i){
-            NameRecord nr = getNameRecord(i);
-            Ptg[] ptgs = nr.getNameDefinition();
-            if (shifter.adjustFormula(ptgs, nr.getSheetNumber())) {
-                nr.setNameDefinition(ptgs);
-            }
-        }
-    }
-
-}
index 2d2f238c5162aaaad6a0eb88f491a9d622d0640f..f587d57c91cfb10338aa0c3f8767f9800ad6a44f 100644 (file)
@@ -58,7 +58,7 @@ public final class FormatRecord extends StandardRecord {
      * get the format index code (for built in formats)
      *
      * @return the format index code
-     * @see org.apache.poi.hssf.model.Workbook
+     * @see org.apache.poi.hssf.model.InternalWorkbook
      */
     public int getIndexCode() {
         return field_1_index_code;
index a58eea67d46b3233dbfae14f8b3084a7ebc9850e..2f222465b66f597f64f27f5692eab73850e084b6 100644 (file)
@@ -34,35 +34,32 @@ public final class PaletteRecord extends StandardRecord {
     public final static byte STANDARD_PALETTE_SIZE = (byte) 56;
     /** The byte index of the first color */
     public final static short FIRST_COLOR_INDEX = (short) 0x8;
-    
-    private List<PColor>  field_2_colors;
 
-    public PaletteRecord()
-    {
+    private final List<PColor>  _colors;
+
+    public PaletteRecord() {
       PColor[] defaultPalette = createDefaultPalette();
-      field_2_colors    = new ArrayList<PColor>(defaultPalette.length);
+      _colors    = new ArrayList<PColor>(defaultPalette.length);
       for (int i = 0; i < defaultPalette.length; i++) {
-        field_2_colors.add(defaultPalette[i]);
+        _colors.add(defaultPalette[i]);
       }
     }
 
-    public PaletteRecord(RecordInputStream in)
-    {
+    public PaletteRecord(RecordInputStream in) {
        int field_1_numcolors = in.readShort();
-       field_2_colors    = new ArrayList<PColor>(field_1_numcolors);
+       _colors    = new ArrayList<PColor>(field_1_numcolors);
        for (int k = 0; k < field_1_numcolors; k++) {
-           field_2_colors.add(new PColor(in));
-       } 
+           _colors.add(new PColor(in));
+       }
     }
 
-    public String toString()
-    {
+    public String toString() {
         StringBuffer buffer = new StringBuffer();
 
         buffer.append("[PALETTE]\n");
-        buffer.append("  numcolors     = ").append(field_2_colors.size()).append('\n');
-        for (int i = 0; i < field_2_colors.size(); i++) {
-            PColor c = field_2_colors.get(i);
+        buffer.append("  numcolors     = ").append(_colors.size()).append('\n');
+        for (int i = 0; i < _colors.size(); i++) {
+            PColor c = _colors.get(i);
             buffer.append("* colornum      = ").append(i).append('\n');
             buffer.append(c.toString());
             buffer.append("/*colornum      = ").append(i).append('\n');
@@ -71,20 +68,18 @@ public final class PaletteRecord extends StandardRecord {
         return buffer.toString();
     }
 
-    public void serialize(LittleEndianOutput out)
-    {
-        out.writeShort(field_2_colors.size());
-        for (int i = 0; i < field_2_colors.size(); i++) {
-          field_2_colors.get(i).serialize(out);
+    public void serialize(LittleEndianOutput out) {
+        out.writeShort(_colors.size());
+        for (int i = 0; i < _colors.size(); i++) {
+          _colors.get(i).serialize(out);
         }
     }
 
     protected int getDataSize() {
-        return 2 + field_2_colors.size() * PColor.ENCODED_SIZE;
+        return 2 + _colors.size() * PColor.ENCODED_SIZE;
     }
 
-    public short getSid()
-    {
+    public short getSid() {
         return sid;
     }
 
@@ -94,16 +89,14 @@ public final class PaletteRecord extends StandardRecord {
      * @return the RGB triplet for the color, or <code>null</code> if the specified index
      * does not exist
      */
-    public byte[] getColor(short byteIndex) {
+    public byte[] getColor(int byteIndex) {
         int i = byteIndex - FIRST_COLOR_INDEX;
-        if (i < 0 || i >= field_2_colors.size())
-        {
+        if (i < 0 || i >= _colors.size()) {
             return null;
         }
-        PColor color =  field_2_colors.get(i);
-        return new byte[] { color.red, color.green, color.blue };
+        return _colors.get(i).getTriplet();
     }
-    
+
     /**
      * Sets the color value at a given index
      *
@@ -120,18 +113,16 @@ public final class PaletteRecord extends StandardRecord {
         {
             return;
         }
-        // may need to grow - fill intervening pallette entries with black
-        while (field_2_colors.size() <= i) {
-            field_2_colors.add(new PColor(0, 0, 0));
+        // may need to grow - fill intervening palette entries with black
+        while (_colors.size() <= i) {
+            _colors.add(new PColor(0, 0, 0));
         }
         PColor custColor = new PColor(red, green, blue);
-        field_2_colors.set(i, custColor);
+        _colors.set(i, custColor);
     }
-    
+
     /**
      * Creates the default palette as PaletteRecord binary data
-     *
-     * @see org.apache.poi.hssf.model.Workbook#createPalette
      */
     private static PColor[] createDefaultPalette()
     {
@@ -199,41 +190,45 @@ public final class PaletteRecord extends StandardRecord {
         return new PColor(r, g, b);
     }
 
-/**
- * PColor - element in the list of colors - consider it a "struct"
- */
-private static final class PColor {
-  public static final short ENCODED_SIZE = 4;
-  public byte red;
-  public byte green;
-  public byte blue;
-
-  public PColor(int red, int green, int blue) {
-    this.red=(byte) red;
-    this.green=(byte) green;
-    this.blue=(byte) blue;
-  }
-
-  public PColor(RecordInputStream in) {
-    red=in.readByte();
-    green=in.readByte();
-    blue=in.readByte();
-    in.readByte(); // unused
-  }
-
-  public void serialize(LittleEndianOutput out) {
-      out.writeByte(red);
-      out.writeByte(green);
-      out.writeByte(blue);
-      out.writeByte(0);
-  }
-
-  public String toString() {
-        StringBuffer buffer = new StringBuffer();
-        buffer.append("  red           = ").append(red & 0xff).append('\n');
-        buffer.append("  green         = ").append(green & 0xff).append('\n');
-        buffer.append("  blue          = ").append(blue & 0xff).append('\n');
-        return buffer.toString();
-  }
+    /**
+     * PColor - element in the list of colors
+     */
+    private static final class PColor {
+        public static final short ENCODED_SIZE = 4;
+        private int _red;
+        private int _green;
+        private int _blue;
+
+        public PColor(int red, int green, int blue) {
+            _red = red;
+            _green = green;
+            _blue = blue;
+        }
+
+        public byte[] getTriplet() {
+            return new byte[] { (byte) _red, (byte) _green, (byte) _blue };
+        }
+
+        public PColor(RecordInputStream in) {
+            _red = in.readByte();
+            _green = in.readByte();
+            _blue = in.readByte();
+            in.readByte(); // unused
+        }
+
+        public void serialize(LittleEndianOutput out) {
+            out.writeByte(_red);
+            out.writeByte(_green);
+            out.writeByte(_blue);
+            out.writeByte(0);
+        }
+
+        public String toString() {
+            StringBuffer buffer = new StringBuffer();
+            buffer.append("  red   = ").append(_red & 0xff).append('\n');
+            buffer.append("  green = ").append(_green & 0xff).append('\n');
+            buffer.append("  blue  = ").append(_blue & 0xff).append('\n');
+            return buffer.toString();
+        }
+    }
 }
-}
\ No newline at end of file
index c336e14d30777c34802aa9e1e34bfebde3c5c460..e938552c64e8688e33e7b32da457d6c004519379 100644 (file)
@@ -25,12 +25,10 @@ import org.apache.poi.util.LittleEndianOutput;
  * Description:  This record contains an ID that marks when a worksheet was last
  *               recalculated. It's an optimization Excel uses to determine if it
  *               needs to  recalculate the spreadsheet when it's opened. So far, only
- *               the two engine ids <code>0x80 0x38 0x01 0x00</code> 
+ *               the two engine ids <code>0x80 0x38 0x01 0x00</code>
  *               and <code>0x60 0x69 0x01 0x00</code> have been seen.<p/>
  * REFERENCE:  http://chicago.sourceforge.net/devel/docs/excel/biff8.html<p/>
  * @author Luc Girardin (luc dot girardin at macrofocus dot com)
- *
- * @see org.apache.poi.hssf.model.Workbook
  */
 public final class RecalcIdRecord extends StandardRecord {
     public final static short sid = 0x01C1;
index 551d503560edb8b37db7380e4b92d8135c3216e4..6557a812268c7371227afd6d159b4ad9d596ac6c 100644 (file)
@@ -23,7 +23,7 @@ import java.util.*;
 
 import org.apache.poi.hssf.model.HSSFFormulaParser;
 import org.apache.poi.hssf.model.Sheet;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.BlankRecord;
 import org.apache.poi.hssf.record.BoolErrRecord;
 import org.apache.poi.hssf.record.CellValueRecordInterface;
@@ -229,7 +229,7 @@ public class HSSFCell implements Cell {
     /**
      * Returns the Workbook that this Cell is bound to
      */
-    protected Workbook getBoundWorkbook() {
+    protected InternalWorkbook getBoundWorkbook() {
         return _book.getWorkbook();
     }
 
index 606fe3c5fdc9270b674eff7163f449639088518a..92642b30ebe4475ac6db80eb50d4ec618316e572 100644 (file)
@@ -18,7 +18,7 @@
 
 package org.apache.poi.hssf.usermodel;
 
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.ExtendedFormatRecord;
 import org.apache.poi.hssf.record.FontRecord;
 import org.apache.poi.hssf.record.StyleRecord;
@@ -38,7 +38,7 @@ import org.apache.poi.ss.usermodel.Font;
 public final class HSSFCellStyle implements CellStyle {
     private ExtendedFormatRecord _format                     = null;
     private short                _index                      = 0;
-    private Workbook             _workbook                   = null;
+    private InternalWorkbook             _workbook                   = null;
 
 
     /** Creates new HSSFCellStyle why would you want to do this?? */
@@ -46,7 +46,7 @@ public final class HSSFCellStyle implements CellStyle {
     {
        this(index, rec, workbook.getWorkbook());
     }
-    protected HSSFCellStyle(short index, ExtendedFormatRecord rec, Workbook workbook)
+    protected HSSFCellStyle(short index, ExtendedFormatRecord rec, InternalWorkbook workbook)
     {
         _workbook = workbook;
         _index = index;
@@ -125,7 +125,7 @@ public final class HSSFCellStyle implements CellStyle {
      *  the DataFormat against the supplied low level workbook
      * @see org.apache.poi.hssf.usermodel.HSSFDataFormat
      */
-    public String getDataFormatString(org.apache.poi.hssf.model.Workbook workbook) {
+    public String getDataFormatString(org.apache.poi.hssf.model.InternalWorkbook workbook) {
        HSSFDataFormat format = new HSSFDataFormat( workbook );
 
         return format.getFormat(getDataFormat());
index 28fd8e05570b350d9751ea46c73c606568edcf3d..f18f377387fbeea7425ea106de6d4078fa917c64 100644 (file)
@@ -29,7 +29,7 @@ import java.util.List;
 import java.util.ListIterator;
 import java.util.Vector;
 
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.FormatRecord;
 import org.apache.poi.ss.usermodel.BuiltinFormats;
 import org.apache.poi.ss.usermodel.DataFormat;
@@ -37,15 +37,15 @@ import org.apache.poi.ss.usermodel.DataFormat;
 /**
  * Identifies both built-in and user defined formats within a workbook.<p/>
  * See {@link BuiltinFormats} for a list of supported built-in formats.<p/>
- * 
+ *
  * <b>International Formats</b><br/>
- * Since version 2003 Excel has supported international formats.  These are denoted 
+ * Since version 2003 Excel has supported international formats.  These are denoted
  * with a prefix "[$-xxx]" (where xxx is a 1-7 digit hexadecimal number).
- * See the Microsoft article 
+ * See the Microsoft article
  * <a href="http://office.microsoft.com/assistance/hfws.aspx?AssetID=HA010346351033&CTT=6&Origin=EC010272491033">
  *   Creating international number formats
  * </a> for more details on these codes.
- * 
+ *
  * @author  Andrew C. Oliver (acoliver at apache dot org)
  * @author  Shawn M. Laubach (slaubach at apache dot org)
  */
@@ -53,7 +53,7 @@ public final class HSSFDataFormat implements DataFormat {
        private static final String[] _builtinFormats = BuiltinFormats.getAll();
 
        private final Vector<String> _formats = new Vector<String>();
-       private final Workbook _workbook;
+       private final InternalWorkbook _workbook;
        private boolean _movedBuiltins = false;  // Flag to see if need to
        // check the built in list
        // or if the regular list
@@ -64,7 +64,7 @@ public final class HSSFDataFormat implements DataFormat {
         * access to the workbooks format records.
         * @param workbook the workbook the formats are tied to.
         */
-       public HSSFDataFormat(Workbook workbook) {
+       HSSFDataFormat(InternalWorkbook workbook) {
                _workbook = workbook;
 
                @SuppressWarnings("unchecked")
index 7b55d81db74abf043f1901dab75630fabf076ab1..1f10a926ad12cfb8c6b07725601dc0e1fec7d1d0 100644 (file)
@@ -18,7 +18,7 @@
 package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.NameRecord;
 import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
 import org.apache.poi.hssf.record.formula.NamePtg;
@@ -42,7 +42,7 @@ import org.apache.poi.ss.formula.FormulaType;
 public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook {
 
        private final HSSFWorkbook _uBook;
-       private final Workbook _iBook;
+       private final InternalWorkbook _iBook;
 
        public static HSSFEvaluationWorkbook create(HSSFWorkbook book) {
                if (book == null) {
index 662ec2e1aae2bd7c68781e7b7bf6101a69dfb33e..579d3494e9f54b08bc4e1ad62d3e228174229334 100644 (file)
@@ -18,7 +18,7 @@
 package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.NameRecord;
 import org.apache.poi.hssf.record.formula.Ptg;
 import org.apache.poi.ss.formula.FormulaType;
@@ -114,7 +114,7 @@ public final class HSSFName implements Name {
     public void setNameName(String nameName){
         validateName(nameName);
 
-        Workbook wb = _book.getWorkbook();
+        InternalWorkbook wb = _book.getWorkbook();
         _definedNameRec.setNameText(nameName);
 
         int sheetNumber = _definedNameRec.getSheetNumber();
@@ -135,7 +135,7 @@ public final class HSSFName implements Name {
 
     private static void validateName(String name){
         if(name.length() == 0)  throw new IllegalArgumentException("Name cannot be blank");
-        
+
         char c = name.charAt(0);
         if(!(c == '_' || Character.isLetter(c)) || name.indexOf(' ') != -1) {
             throw new IllegalArgumentException("Invalid name: '"+name+"'; Names must begin with a letter or underscore and not contain spaces");
@@ -249,9 +249,7 @@ public final class HSSFName implements Name {
      *
      * @param value <code>true</code> indicates the name refers to a function.
      */
-       public void setFunction(boolean value) {
-               _definedNameRec.setFunction(value);
-               
-       }
-
+    public void setFunction(boolean value) {
+        _definedNameRec.setFunction(value);
+    }
 }
index 269cabe423c74cd964e55e23c50a9a9c6784c905..e69a203b9f8fcfb6d34b3e2771a2d6ceafa295f0 100644 (file)
@@ -19,7 +19,7 @@ package org.apache.poi.hssf.usermodel;
 
 import java.util.Iterator;
 
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.LabelSSTRecord;
 import org.apache.poi.hssf.record.UnicodeString;
 import org.apache.poi.ss.usermodel.Font;
@@ -74,7 +74,7 @@ public final class HSSFRichTextString implements Comparable<HSSFRichTextString>,
     public static final short NO_FONT = 0;
 
     private UnicodeString _string;
-    private Workbook _book;
+    private InternalWorkbook _book;
     private LabelSSTRecord _record;
 
     public HSSFRichTextString()
@@ -90,7 +90,7 @@ public final class HSSFRichTextString implements Comparable<HSSFRichTextString>,
         }
     }
 
-    HSSFRichTextString(Workbook book, LabelSSTRecord record) {
+    HSSFRichTextString(InternalWorkbook book, LabelSSTRecord record) {
       setWorkbookReferences(book, record);
 
       _string = book.getSSTString(record.getSSTIndex());
@@ -99,7 +99,7 @@ public final class HSSFRichTextString implements Comparable<HSSFRichTextString>,
     /** This must be called to setup the internal work book references whenever
      * a RichTextString is added to a cell
      */
-    void setWorkbookReferences(Workbook book, LabelSSTRecord record) {
+    void setWorkbookReferences(InternalWorkbook book, LabelSSTRecord record) {
       _book = book;
       _record = record;
     }
index c7972ecc932c04f6ba8eb720662a36a1ff4ba2a6..6fa9b68dd6d5e3b3f1a0e8b42bca832d0ddfa284 100644 (file)
@@ -32,7 +32,7 @@ import java.util.TreeMap;
 
 import org.apache.poi.ddf.EscherRecord;
 import org.apache.poi.hssf.model.Sheet;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.CellValueRecordInterface;
 import org.apache.poi.hssf.record.DVRecord;
 import org.apache.poi.hssf.record.EscherAggregate;
@@ -82,7 +82,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
     private final Sheet _sheet;
     /** stores rows by zero-based row number */
     private final TreeMap<Integer, HSSFRow> _rows;
-    protected final Workbook _book;
+    protected final InternalWorkbook _book;
     protected final HSSFWorkbook _workbook;
     private int _firstrow;
     private int _lastrow;
@@ -636,7 +636,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
 
     /**
      * Sets whether the worksheet is displayed from right to left instead of from left to right.
-     * 
+     *
      * @param value true for right to left, false otherwise.
      */
     public void setRightToLeft(boolean value)
@@ -1693,7 +1693,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
 
         FontRenderContext frc = new FontRenderContext(null, true, true);
 
-        HSSFWorkbook wb = new HSSFWorkbook(_book);
+        HSSFWorkbook wb = HSSFWorkbook.create(_book); // TODO - is it important to not use _workbook?
         HSSFFont defaultFont = wb.getFontAt((short) 0);
 
         str = new AttributedString("" + defaultChar);
index ca10a6f8743e2c1ecfeb671895604c9cb31b2e43..bd8fa768fc3d5bdd2f48f419a5a35b433f20f072 100644 (file)
@@ -38,7 +38,7 @@ import org.apache.poi.hssf.OldExcelFormatException;
 import org.apache.poi.hssf.model.HSSFFormulaParser;
 import org.apache.poi.hssf.model.RecordStream;
 import org.apache.poi.hssf.model.Sheet;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.AbstractEscherHolderRecord;
 import org.apache.poi.hssf.record.BackupRecord;
 import org.apache.poi.hssf.record.DrawingGroupRecord;
@@ -78,13 +78,13 @@ import org.apache.poi.util.POILogger;
  * will construct whether they are reading or writing a workbook.  It is also the
  * top level object for creating new sheets/etc.
  *
- * @see org.apache.poi.hssf.model.Workbook
+ * @see org.apache.poi.hssf.model.InternalWorkbook
  * @see org.apache.poi.hssf.usermodel.HSSFSheet
  * @author  Andrew C. Oliver (acoliver at apache dot org)
  * @author  Glen Stampoultzis (glens at apache.org)
  * @author  Shawn Laubach (slaubach at apache dot org)
  */
-public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook {
+public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook {
     private static final Pattern COMMA_PATTERN = Pattern.compile(",");
     private static final int MAX_ROW = 0xFFFF;
     private static final short MAX_COLUMN = (short)0x00FF;
@@ -104,7 +104,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
      * this is the reference to the low level Workbook object
      */
 
-    private Workbook workbook;
+    private InternalWorkbook workbook;
 
     /**
      * this holds the HSSFSheet objects attached to this workbook
@@ -162,25 +162,26 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
 
     private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class);
 
+    public static HSSFWorkbook create(InternalWorkbook book) {
+       return new HSSFWorkbook(book);
+    }
     /**
      * Creates new HSSFWorkbook from scratch (start here!)
      *
      */
-    public HSSFWorkbook()
-    {
-        this(Workbook.createWorkbook());
+    public HSSFWorkbook() {
+        this(InternalWorkbook.createWorkbook());
     }
 
-    protected HSSFWorkbook( Workbook book )
-    {
-        super(null, null);
-        workbook = book;
-        _sheets = new ArrayList( INITIAL_CAPACITY );
-        names = new ArrayList( INITIAL_CAPACITY );
-    }
+       private HSSFWorkbook(InternalWorkbook book) {
+               super(null, null);
+               workbook = book;
+               _sheets = new ArrayList(INITIAL_CAPACITY);
+               names = new ArrayList(INITIAL_CAPACITY);
+       }
 
     public HSSFWorkbook(POIFSFileSystem fs) throws IOException {
-      this(fs,true);
+        this(fs,true);
     }
 
     /**
@@ -275,7 +276,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
 
         List records = RecordFactory.createRecords(stream);
 
-        workbook = Workbook.createWorkbook(records);
+        workbook = InternalWorkbook.createWorkbook(records);
         setPropertiesFromWorkbook(workbook);
         int recOffset = workbook.getNumRecords();
         int sheetNum = 0;
@@ -321,7 +322,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
      * used internally to set the workbook properties.
      */
 
-    private void setPropertiesFromWorkbook(Workbook book)
+    private void setPropertiesFromWorkbook(InternalWorkbook book)
     {
         this.workbook = book;
 
@@ -1225,7 +1226,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
      * @return byte[] array containing the binary representation of this workbook and all contained
      *         sheets, rows, cells, etc.
      *
-     * @see org.apache.poi.hssf.model.Workbook
+     * @see org.apache.poi.hssf.model.InternalWorkbook
      * @see org.apache.poi.hssf.model.Sheet
      */
     public byte[] getBytes() {
@@ -1290,8 +1291,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
         return workbook.getSSTString(index).getString();
     }
 
-    protected Workbook getWorkbook()
-    {
+    InternalWorkbook getWorkbook() {
         return workbook;
     }
 
index 2c56ea57a17283c0c388ccbeab47743e0a011b41..483a38d75547f3a9be09902abcb14039fd37c192 100644 (file)
@@ -27,7 +27,7 @@ import junit.framework.TestCase;
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder.SheetRecordCollectingListener;
 import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.FormulaRecord;
 import org.apache.poi.hssf.record.Record;
 import org.apache.poi.hssf.record.formula.Ptg;
@@ -41,13 +41,13 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 public final class TestEventWorkbookBuilder extends TestCase {
        private MockHSSFListener mockListen;
        private SheetRecordCollectingListener listener;
-       
+
        public void setUp() {
                HSSFRequest req = new HSSFRequest();
                mockListen = new MockHSSFListener();
                listener = new SheetRecordCollectingListener(mockListen);
                req.addListenerForAllRecords(listener);
-               
+
                HSSFEventFactory factory = new HSSFEventFactory();
                try {
                        InputStream is = HSSFTestDataSamples.openSampleFileStream("3dFormulas.xls");
@@ -56,94 +56,94 @@ public final class TestEventWorkbookBuilder extends TestCase {
                } catch (IOException e) {
                        throw new RuntimeException(e);
                }
-       } 
-       
+       }
+
        public void testBasics() {
                assertNotNull(listener.getSSTRecord());
                assertNotNull(listener.getBoundSheetRecords());
                assertNotNull(listener.getExternSheetRecords());
        }
-       
+
        public void testGetStubWorkbooks() {
                assertNotNull(listener.getStubWorkbook());
                assertNotNull(listener.getStubHSSFWorkbook());
        }
-       
+
        public void testContents() {
                assertEquals(2, listener.getSSTRecord().getNumStrings());
                assertEquals(3, listener.getBoundSheetRecords().length);
                assertEquals(1, listener.getExternSheetRecords().length);
-               
+
                assertEquals(3, listener.getStubWorkbook().getNumSheets());
-               
-               Workbook ref = listener.getStubWorkbook();
+
+               InternalWorkbook ref = listener.getStubWorkbook();
                assertEquals("Sh3", ref.findSheetNameFromExternSheet(0));
                assertEquals("Sheet1", ref.findSheetNameFromExternSheet(1));
                assertEquals("S2", ref.findSheetNameFromExternSheet(2));
        }
-       
+
        public void testFormulas() {
-               
+
                FormulaRecord[] fRecs = mockListen.getFormulaRecords();
-               
+
                // Check our formula records
                assertEquals(6, fRecs.length);
-               
-               Workbook stubWB = listener.getStubWorkbook();
+
+               InternalWorkbook stubWB = listener.getStubWorkbook();
                assertNotNull(stubWB);
                HSSFWorkbook stubHSSF = listener.getStubHSSFWorkbook();
                assertNotNull(stubHSSF);
-               
+
                // Check these stubs have the right stuff on them
                assertEquals("Sheet1", stubWB.getSheetName(0));
                assertEquals("S2", stubWB.getSheetName(1));
                assertEquals("Sh3", stubWB.getSheetName(2));
-               
+
                // Check we can get the formula without breaking
                for(int i=0; i<fRecs.length; i++) {
                        HSSFFormulaParser.toFormulaString(stubHSSF, fRecs[i].getParsedExpression());
                }
-               
+
                // Peer into just one formula, and check that
                //  all the ptgs give back the right things
                Ptg[] ptgs = fRecs[0].getParsedExpression();
                assertEquals(1, ptgs.length);
                assertTrue(ptgs[0] instanceof Ref3DPtg);
-               
+
                Ref3DPtg ptg = (Ref3DPtg)ptgs[0];
                HSSFEvaluationWorkbook book = HSSFEvaluationWorkbook.create(stubHSSF);
                assertEquals("Sheet1!A1", ptg.toFormulaString(book));
-               
-               
+
+
                // Now check we get the right formula back for
                //  a few sample ones
                FormulaRecord fr;
-               
+
                // Sheet 1 A2 is on same sheet
                fr = fRecs[0];
                assertEquals(1, fr.getRow());
                assertEquals(0, fr.getColumn());
                assertEquals("Sheet1!A1", HSSFFormulaParser.toFormulaString(stubHSSF, fr.getParsedExpression()));
-               
+
                // Sheet 1 A5 is to another sheet
                fr = fRecs[3];
                assertEquals(4, fr.getRow());
                assertEquals(0, fr.getColumn());
                assertEquals("'S2'!A1", HSSFFormulaParser.toFormulaString(stubHSSF, fr.getParsedExpression()));
-               
+
                // Sheet 1 A7 is to another sheet, range
                fr = fRecs[5];
                assertEquals(6, fr.getRow());
                assertEquals(0, fr.getColumn());
                assertEquals("SUM(Sh3!A1:A4)", HSSFFormulaParser.toFormulaString(stubHSSF, fr.getParsedExpression()));
-               
-               
+
+
                // Now, load via Usermodel and re-check
                HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("3dFormulas.xls");
                assertEquals("Sheet1!A1", wb.getSheetAt(0).getRow(1).getCell(0).getCellFormula());
                assertEquals("SUM(Sh3!A1:A4)", wb.getSheetAt(0).getRow(6).getCell(0).getCellFormula());
        }
-       
+
        private static final class MockHSSFListener implements HSSFListener {
                public MockHSSFListener() {}
                private final List _records = new ArrayList();
@@ -161,4 +161,4 @@ public final class TestEventWorkbookBuilder extends TestCase {
                        return result;
                }
        }
-}
\ No newline at end of file
+}
index c7939e33a57a2b8f950e9afba2de352f36f055f2..d6f1e7c90be3fc02e3c002224e2fba3eb4c6a5b5 100644 (file)
 
 package org.apache.poi.hssf.model;
 
+import junit.framework.TestCase;
+
 import org.apache.poi.hssf.record.FontRecord;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-import junit.framework.TestCase;
+import org.apache.poi.hssf.usermodel.TestHSSFWorkbook;
 
 /**
  * Unit test for the Workbook class.
@@ -29,7 +30,7 @@ import junit.framework.TestCase;
  */
 public final class TestWorkbook extends TestCase {
        public void testFontStuff() {
-               Workbook wb = (new HW()).getWorkbook();
+               InternalWorkbook wb = TestHSSFWorkbook.getInternalWorkbook(new HSSFWorkbook());
 
                assertEquals(4, wb.getNumberOfFontRecords());
                assertEquals(68, wb.getRecords().size());
@@ -82,13 +83,4 @@ public final class TestWorkbook extends TestCase {
                assertEquals(6, wb.getFontIndex(n7));
                assertEquals(n7, wb.getFontRecordAt(6));
        }
-
-       private static final class HW extends HSSFWorkbook {
-               public HW() {
-                       super();
-               }
-               protected Workbook getWorkbook() {
-                       return super.getWorkbook();
-               }
-       }
 }
index 8da432fa7e23dbb2b17851cf773a00c7ff709f21..2453575d446697ad30cb1956a347f6cdbff5e991 100644 (file)
@@ -21,7 +21,7 @@ package org.apache.poi.hssf.usermodel;
 
 import junit.framework.Assert;
 import org.apache.poi.hssf.model.Sheet;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.*;
 import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
 
@@ -208,7 +208,7 @@ public class SanityChecker
         new CheckRecord(EOFRecord.class, '1')
     };
 
-    private void checkWorkbookRecords(Workbook workbook)
+    private void checkWorkbookRecords(InternalWorkbook workbook)
     {
         List records = workbook.getRecords();
         assertTrue(records.get(0) instanceof BOFRecord);
index df3f2348821d770cf60a32efb2c38a38f9649a9b..c0f639d41224275a91cb39972ad82070c2dd20a2 100644 (file)
@@ -31,7 +31,7 @@ import junit.framework.AssertionFailedError;
 import org.apache.poi.hssf.HSSFITestDataProvider;
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.hssf.OldExcelFormatException;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.CellValueRecordInterface;
 import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
 import org.apache.poi.hssf.record.NameRecord;
@@ -171,7 +171,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
     public void test15375_2() {
         baseTest15375(6000);
     }
-    
+
     /**Double byte strings*/
     public void test15556() {
 
@@ -844,7 +844,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
 
         // Check all names fit within range, and use
         //  DeletedArea3DPtg
-        Workbook w = wb.getWorkbook();
+        InternalWorkbook w = wb.getWorkbook();
         for(int i=0; i<w.getNumNames(); i++) {
             NameRecord r = w.getNameRecord(i);
             assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
@@ -1249,7 +1249,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
     /**
      * The resolution for bug 45777 assumed that the maximum text length in a header / footer
      * record was 256 bytes.  This assumption appears to be wrong.  Since the fix for bug 47244,
-     * POI now supports header / footer text lengths beyond 256 bytes.  
+     * POI now supports header / footer text lengths beyond 256 bytes.
      */
     public void test45777() {
         HSSFWorkbook wb = new HSSFWorkbook();
@@ -1375,7 +1375,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
         HSSFWorkbook wb = openSample("45290.xls");
         assertEquals(1, wb.getNumberOfSheets());
     }
-    
+
     /**
      * In POI-2.5 user reported exception when parsing a name with a custom VBA function:
      *  =MY_VBA_FUNCTION("lskdjflsk")
@@ -1455,7 +1455,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
         wb.write(out);
         out.close();
         int size1 = out.size();
-        
+
         out = new ByteArrayOutputStream();
         wb.write(out);
         out.close();
@@ -1469,7 +1469,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
         assertEquals(size2, size3);
 
     }
-    
+
     /**
      * java.io.IOException: block[ 0 ] already removed
      * (is an excel 95 file though)
@@ -1484,7 +1484,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
             ));
         }
     }
-    
+
     /**
      * java.lang.NegativeArraySizeException reading long
      *  non-unicode data for a name record
@@ -1514,7 +1514,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
      */
     public void test48180() {
         HSSFWorkbook wb = openSample("48180.xls");
-        
+
        HSSFSheet s = wb.getSheetAt(0);
         HSSFCell cell1 = s.getRow(0).getCell(0);
         assertEquals("test ", cell1.getStringCellValue().toString());
@@ -1524,12 +1524,12 @@ public final class TestBugs extends BaseTestBugzillaIssues {
     }
 
     /**
-     * POI 3.5 beta 7 can not read excel file contain list box (Form Control)  
+     * POI 3.5 beta 7 can not read excel file contain list box (Form Control)
      */
     public void test47701() {
         openSample("47701.xls");
     }
-    
+
     public void test48026() {
         openSample("48026.xls");
     }
index 0f9c7ae0f1c4ca53c59c99cca25c1344a76407a9..02113fd6c2a2608c1c53f1746580118bedf88227 100644 (file)
@@ -25,7 +25,7 @@ import java.util.TimeZone;
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 
 /**
  * Class TestHSSFDateUtil
@@ -306,7 +306,7 @@ public final class TestHSSFDateUtil extends TestCase {
 
         HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("DateFormats.xls");
         HSSFSheet sheet       = workbook.getSheetAt(0);
-        Workbook wb           = workbook.getWorkbook();
+        InternalWorkbook wb           = workbook.getWorkbook();
 
         HSSFRow  row;
         HSSFCell cell;
index 39a911c53ed0d137bc2d3ff40b251cbcaefe1adf..360dc7cb46b8bf44419a0b51330d1dda822c0f72 100644 (file)
@@ -25,6 +25,7 @@ import junit.framework.AssertionFailedError;
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.hssf.HSSFITestDataProvider;
 import org.apache.poi.hssf.model.HSSFFormulaParser;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.model.Sheet;
 import org.apache.poi.hssf.record.NameRecord;
 import org.apache.poi.hssf.record.Record;
@@ -48,6 +49,13 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         return HSSFITestDataProvider.getInstance();
     }
 
+    /**
+     * gives test code access to the {@link InternalWorkbook} within {@link HSSFWorkbook}
+     */
+    public static InternalWorkbook getInternalWorkbook(HSSFWorkbook wb) {
+       return wb.getWorkbook();
+    }
+
     public void testSetRepeatingRowsAndColumns() {
         // Test bug 29747
         HSSFWorkbook b = new HSSFWorkbook( );
index 15682a074b49991a235eff4a6fcceb0dec37befc..fde71790807634efca232a688a5e42b695305abc 100644 (file)
@@ -25,7 +25,7 @@ import java.io.IOException;
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.BackupRecord;
 import org.apache.poi.hssf.record.LabelSSTRecord;
 import org.apache.poi.hssf.record.Record;
@@ -449,7 +449,7 @@ public final class TestWorkbook extends TestCase {
     public void testBackupRecord() {
         HSSFWorkbook wb = new HSSFWorkbook();
                wb.createSheet();
-               Workbook workbook = wb.getWorkbook();
+               InternalWorkbook workbook = wb.getWorkbook();
         BackupRecord record   = workbook.getBackupRecord();
 
         assertEquals(0, record.getBackup());
index 4a15ac0eee10e1a99e5a2e20b3123a7557530abd..b17872922f6f76ca1384f212400593af80c17534 100644 (file)
 
 package org.apache.poi.hssf.util;
 
-import java.io.IOException;
 import java.io.InputStream;
 
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.NameRecord;
 import org.apache.poi.hssf.record.formula.Area3DPtg;
 import org.apache.poi.hssf.record.formula.MemFuncPtg;
@@ -36,10 +35,11 @@ import org.apache.poi.hssf.usermodel.HSSFName;
 import org.apache.poi.hssf.usermodel.HSSFRow;
 import org.apache.poi.hssf.usermodel.HSSFSheet;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.usermodel.TestHSSFWorkbook;
 import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellReference;
 /**
- * 
+ *
  */
 public final class TestAreaReference extends TestCase {
 
@@ -52,54 +52,54 @@ public final class TestAreaReference extends TestCase {
         assertTrue("row is abs",cf.isRowAbsolute());
         assertTrue("col is abs",cf.isColAbsolute());
         assertTrue("string is $A$1",cf.formatAsString().equals("$A$1"));
-        
+
         cf = ar.getLastCell();
         assertTrue("row is 4",cf.getRow()==1);
         assertTrue("col is 1",cf.getCol()==1);
         assertTrue("row is abs",cf.isRowAbsolute());
         assertTrue("col is abs",cf.isColAbsolute());
         assertTrue("string is $B$2",cf.formatAsString().equals("$B$2"));
-        
+
         CellReference[] refs = ar.getAllReferencedCells();
         assertEquals(4, refs.length);
-        
+
         assertEquals(0, refs[0].getRow());
         assertEquals(0, refs[0].getCol());
         assertNull(refs[0].getSheetName());
-        
+
         assertEquals(0, refs[1].getRow());
         assertEquals(1, refs[1].getCol());
         assertNull(refs[1].getSheetName());
-        
+
         assertEquals(1, refs[2].getRow());
         assertEquals(0, refs[2].getCol());
         assertNull(refs[2].getSheetName());
-        
+
         assertEquals(1, refs[3].getRow());
         assertEquals(1, refs[3].getCol());
         assertNull(refs[3].getSheetName());
     }
-    
+
     /**
      * References failed when sheet names were being used
      * Reported by Arne.Clauss@gedas.de
      */
     public void testReferenceWithSheet() {
         AreaReference ar;
-        
+
         ar = new AreaReference("Tabelle1!B5:B5");
         assertTrue(ar.isSingleCell());
         TestCellReference.confirmCell(ar.getFirstCell(), "Tabelle1", 4, 1, false, false, "Tabelle1!B5");
-        
+
         assertEquals(1, ar.getAllReferencedCells().length);
-        
-        
+
+
         ar = new AreaReference("Tabelle1!$B$5:$B$7");
         assertFalse(ar.isSingleCell());
-        
+
         TestCellReference.confirmCell(ar.getFirstCell(), "Tabelle1", 4, 1, true, true, "Tabelle1!$B$5");
         TestCellReference.confirmCell(ar.getLastCell(), "Tabelle1", 6, 1, true, true, "Tabelle1!$B$7");
-        
+
         // And all that make it up
         CellReference[] allCells = ar.getAllReferencedCells();
         assertEquals(3, allCells.length);
@@ -108,16 +108,6 @@ public final class TestAreaReference extends TestCase {
         TestCellReference.confirmCell(allCells[2], "Tabelle1", 6, 1, true, true, "Tabelle1!$B$7");
     }
 
-    // TODO - remove this sub-class
-    private static final class HSSFWB extends HSSFWorkbook {
-        public HSSFWB(InputStream in) throws IOException {
-            super(in);
-        }
-        public Workbook getWorkbook() {
-            return super.getWorkbook();
-        }
-    }
-
     public void testContiguousReferences() {
         String refSimple = "$C$10:$C$10";
         String ref2D = "$C$10:$D$11";
@@ -138,15 +128,21 @@ public final class TestAreaReference extends TestCase {
         try {
             new AreaReference(refDCSimple);
             fail();
-        } catch(IllegalArgumentException e) {}
+        } catch(IllegalArgumentException e) {
+               // expected during successful test
+        }
         try {
             new AreaReference(refDC2D);
             fail();
-        } catch(IllegalArgumentException e) {}
+        } catch(IllegalArgumentException e) {
+               // expected during successful test
+        }
         try {
             new AreaReference(refDC3D);
             fail();
-        } catch(IllegalArgumentException e) {}
+        } catch(IllegalArgumentException e) {
+               // expected during successful test
+        }
 
         // Test that we split as expected
         AreaReference[] refs;
@@ -193,8 +189,8 @@ public final class TestAreaReference extends TestCase {
 
     public void testDiscontinousReference() throws Exception {
         InputStream is = HSSFTestDataSamples.openSampleFileStream("44167.xls");
-        HSSFWB wb = new HSSFWB(is);
-        Workbook workbook = wb.getWorkbook();
+        HSSFWorkbook wb = new HSSFWorkbook(is);
+        InternalWorkbook workbook = TestHSSFWorkbook.getInternalWorkbook(wb);
         HSSFEvaluationWorkbook eb = HSSFEvaluationWorkbook.create(wb);
 
         assertEquals(1, wb.getNumberOfNames());
@@ -252,18 +248,18 @@ public final class TestAreaReference extends TestCase {
         HSSFCell c = r.getCell((int)cref.getCol());
         assertNotNull(c);
     }
-    
+
     public void testSpecialSheetNames() {
         AreaReference ar;
         ar = new AreaReference("'Sheet A'!A1:A1");
         confirmAreaSheetName(ar, "Sheet A", "'Sheet A'!A1");
-        
+
         ar = new AreaReference("'Hey! Look Here!'!A1:A1");
         confirmAreaSheetName(ar, "Hey! Look Here!", "'Hey! Look Here!'!A1");
-        
+
         ar = new AreaReference("'O''Toole'!A1:B2");
         confirmAreaSheetName(ar, "O'Toole", "'O''Toole'!A1:B2");
-        
+
         ar = new AreaReference("'one:many'!A1:B2");
         confirmAreaSheetName(ar, "one:many", "'one:many'!A1:B2");
     }
@@ -273,25 +269,24 @@ public final class TestAreaReference extends TestCase {
         assertEquals(sheetName, cells[0].getSheetName());
         assertEquals(expectedFullText, ar.formatAsString());
     }
-    
+
     public void testWholeColumnRefs() {
-               confirmWholeColumnRef("A:A", 0, 0, false, false);
-               confirmWholeColumnRef("$C:D", 2, 3, true, false);
-               confirmWholeColumnRef("AD:$AE", 29, 30, false, true);
-               
-       }
-
-       private static void confirmWholeColumnRef(String ref, int firstCol, int lastCol, boolean firstIsAbs, boolean lastIsAbs) {
-               AreaReference ar = new AreaReference(ref);
-               confirmCell(ar.getFirstCell(), 0, firstCol, true, firstIsAbs);
-               confirmCell(ar.getLastCell(), 0xFFFF, lastCol, true, lastIsAbs);
-       }
-
-       private static void confirmCell(CellReference cell, int row, int col, boolean isRowAbs,
-                       boolean isColAbs) {
-               assertEquals(row, cell.getRow());
-               assertEquals(col, cell.getCol());
-               assertEquals(isRowAbs, cell.isRowAbsolute());
-               assertEquals(isColAbs, cell.isColAbsolute());
-       }
+        confirmWholeColumnRef("A:A", 0, 0, false, false);
+        confirmWholeColumnRef("$C:D", 2, 3, true, false);
+        confirmWholeColumnRef("AD:$AE", 29, 30, false, true);
+    }
+
+    private static void confirmWholeColumnRef(String ref, int firstCol, int lastCol, boolean firstIsAbs, boolean lastIsAbs) {
+        AreaReference ar = new AreaReference(ref);
+        confirmCell(ar.getFirstCell(), 0, firstCol, true, firstIsAbs);
+        confirmCell(ar.getLastCell(), 0xFFFF, lastCol, true, lastIsAbs);
+    }
+
+    private static void confirmCell(CellReference cell, int row, int col, boolean isRowAbs,
+            boolean isColAbs) {
+        assertEquals(row, cell.getRow());
+        assertEquals(col, cell.getCol());
+        assertEquals(isRowAbs, cell.isRowAbsolute());
+        assertEquals(isColAbs, cell.isColAbsolute());
+    }
 }