/// <summary>
        /// Creates a stub Workbook from the supplied records,
        /// suitable for use with the {@link HSSFFormulaParser}
        /// </summary>
        /// <param name="externs">The ExternSheetRecords in your file</param>
        /// <param name="bounds">The BoundSheetRecords in your file</param>
        /// <param name="sst">TThe SSTRecord in your file.</param>
        /// <returns>A stub Workbook suitable for use with HSSFFormulaParser</returns>
        public static InternalWorkbook CreateStubWorkbook(ExternSheetRecord[] externs,
                BoundSheetRecord[] bounds, SSTRecord sst)
        {
            List<Record> wbRecords = new List<Record>();

            // Core Workbook records go first
            if (bounds != null)
            {
                for (int i = 0; i < bounds.Length; i++)
                {
                    wbRecords.Add(bounds[i]);
                }
            }
            if (sst != null)
            {
                wbRecords.Add(sst);
            }

            // Now we can have the ExternSheetRecords,
            //  preceded by a SupBookRecord
            if (externs != null)
            {
                wbRecords.Add(SupBookRecord.CreateInternalReferences(
                        (short)externs.Length));
                for (int i = 0; i < externs.Length; i++)
                {
                    wbRecords.Add(externs[i]);
                }
            }

            // Finally we need an EoF record
            wbRecords.Add(EOFRecord.instance);

            return InternalWorkbook.CreateWorkbook(wbRecords);
        }
            /// <summary>
            /// Process an HSSF Record. Called when a record occurs in an HSSF file.
            /// </summary>
            /// <param name="record"></param>
            public void ProcessRecord(Record record)
            {
                String thisText = null;
                int thisRow = -1;

                switch (record.Sid)
                {
                    case BoundSheetRecord.sid:
                        BoundSheetRecord sr = (BoundSheetRecord)record;
                        sheetNames.Add(sr.Sheetname);
                        break;
                    case BOFRecord.sid:
                        BOFRecord bof = (BOFRecord)record;
                        if (bof.Type == BOFRecord.TYPE_WORKSHEET)
                        {
                            sheetNum++;
                            rowNum = -1;

                            if (includeSheetNames)
                            {
                                if (text.Length > 0) text.Append("\n");
                                text.Append(sheetNames[sheetNum]);
                            }
                        }
                        break;
                    case SSTRecord.sid:
                        sstRecord = (SSTRecord)record;
                        break;

                    case FormulaRecord.sid:
                        FormulaRecord frec = (FormulaRecord)record;
                        thisRow = frec.Row;

                        if (formulasNotResults)
                        {
                            thisText = HSSFFormulaParser.ToFormulaString((HSSFWorkbook)null, frec.ParsedExpression);
                        }
                        else
                        {
                            if (frec.HasCachedResultString)
                            {
                                // Formula result is a string
                                // This is stored in the next record
                                outputNextStringValue = true;
                                nextRow = frec.Row;
                            }
                            else
                            {
                                thisText = FormatNumberDateCell(frec, frec.Value);
                            }
                        }
                        break;
                    case StringRecord.sid:
                        if (outputNextStringValue)
                        {
                            // String for formula
                            StringRecord srec = (StringRecord)record;
                            thisText = srec.String;
                            thisRow = nextRow;
                            outputNextStringValue = false;
                        }
                        break;
                    case LabelRecord.sid:
                        LabelRecord lrec = (LabelRecord)record;
                        thisRow = lrec.Row;
                        thisText = lrec.Value;
                        break;
                    case LabelSSTRecord.sid:
                        LabelSSTRecord lsrec = (LabelSSTRecord)record;
                        thisRow = lsrec.Row;
                        if (sstRecord == null)
                        {
                            throw new Exception("No SST record found");
                        }
                        thisText = sstRecord.GetString(lsrec.SSTIndex).ToString();
                        break;
                    case NoteRecord.sid:
                        NoteRecord nrec = (NoteRecord)record;
                        thisRow = nrec.Row;
                        // TODO: Find object to match nrec.GetShapeId()
                        break;
                    case NumberRecord.sid:
                        NumberRecord numrec = (NumberRecord)record;
                        thisRow = numrec.Row;
                        thisText = FormatNumberDateCell(numrec, numrec.Value);
                        break;
                    default:
                        break;
                }

                if (thisText != null)
                {
                    if (thisRow != rowNum)
                    {
                        rowNum = thisRow;
                        if (text.Length > 0)
                            text.Append("\n");
                    }
                    else
                    {
                        text.Append("\t");
                    }
                    text.Append(thisText);
                }
            }
 /// <summary>
 /// Process the record ourselves, but do not
 /// pass it on to the child Listener.
 /// </summary>
 /// <param name="record">The record.</param>
 public void ProcessRecordInternally(Record record)
 {
     if (record is BoundSheetRecord)
     {
         boundSheetRecords.Add(record);
     }
     else if (record is ExternSheetRecord)
     {
         externSheetRecords.Add(record);
     }
     else if (record is SSTRecord)
     {
         sstRecord = (SSTRecord)record;
     }
 }