using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Drawing; using HH.WMS.Utils.ExcelLibrary.CompoundDocumentFormat; using HH.WMS.Utils.ExcelLibrary.SpreadSheet; namespace HH.WMS.Utils.ExcelLibrary.BinaryFileFormat { public class WorksheetDecoder { public static Worksheet Decode(Workbook book, Stream stream, SharedResource sharedResource) { Worksheet sheet = new Worksheet(); sheet.Book = book; List records = ReadRecords(stream, out sheet.Drawing); sheet.Cells = PopulateCells(records, sharedResource); sheet.Book.Records.AddRange(records); return sheet; } private static List ReadRecords(Stream stream, out MSODRAWING drawingRecord) { List records = new List(); drawingRecord = null; Record record = Record.Read(stream); Record last_record = record; Record last_formula_record = null; last_record.Decode(); if (record is BOF && ((BOF)record).StreamType == StreamType.Worksheet) { while (record.Type != RecordType.EOF) { if (record.Type == RecordType.CONTINUE) { last_record.ContinuedRecords.Add(record); } else { switch (record.Type) { case RecordType.STRING: // jetcat_au: use last_formula_record instead of last_record if (last_formula_record is FORMULA) { record.Decode(); (last_formula_record as FORMULA).StringRecord = record as STRING; } break; case RecordType.MSODRAWING: if (drawingRecord == null) { drawingRecord = record as MSODRAWING; records.Add(record); } else { drawingRecord.ContinuedRecords.Add(record); } break; default: records.Add(record); break; } // jetcat_au: see 4.8 Array Formulas and Shared Formulas if (record.Type == RecordType.FORMULA) { last_formula_record = record; } else if (record.Type != RecordType.SHRFMLA && record.Type != RecordType.ARRAY) { last_formula_record = null; } last_record = record; } record = Record.Read(stream); } records.Add(record); } return records; } private static CellCollection PopulateCells(List records, SharedResource sharedResource) { CellCollection cells = new CellCollection(); cells.SharedResource = sharedResource; foreach (Record record in records) { record.Decode(); switch (record.Type) { //case RecordType.DIMENSIONS: // DIMENSIONS dimensions = record as DIMENSIONS; // cells.FirstRowIndex = dimensions.FirstRow; // cells.FirstColIndex = dimensions.FirstColumn; // cells.LastRowIndex = dimensions.LastRow-1; // cells.LastColIndex = dimensions.LastColumn-1; // break; case RecordType.BOOLERR: BOOLERR boolerr = record as BOOLERR; cells.CreateCell(boolerr.RowIndex, boolerr.ColIndex, boolerr.GetValue(), boolerr.XFIndex); break; case RecordType.LABEL: LABEL label = record as LABEL; cells.CreateCell(label.RowIndex, label.ColIndex, label.Value, label.XFIndex); break; case RecordType.LABELSST: LABELSST labelsst = record as LABELSST; Cell cell = cells.CreateCell(labelsst.RowIndex, labelsst.ColIndex, sharedResource.GetStringFromSST(labelsst.SSTIndex), labelsst.XFIndex); cell.Style.RichTextFormat = sharedResource.SharedStringTable.RichTextFormatting[labelsst.SSTIndex]; break; case RecordType.NUMBER: NUMBER number = record as NUMBER; cells.CreateCell(number.RowIndex, number.ColIndex, number.Value, number.XFIndex); break; case RecordType.RK: RK rk = record as RK; cells.CreateCell(rk.RowIndex, rk.ColIndex, Record.DecodeRK(rk.Value), rk.XFIndex); break; case RecordType.MULRK: MULRK mulrk = record as MULRK; int row = mulrk.RowIndex; for (int col = mulrk.FirstColIndex; col <= mulrk.LastColIndex; col++) { int index = col - mulrk.FirstColIndex; object value = Record.DecodeRK(mulrk.RKList[index]); int XFindex = mulrk.XFList[index]; cells.CreateCell(row, col, value, XFindex); } break; case RecordType.FORMULA: FORMULA formula = record as FORMULA; cells.CreateCell(formula.RowIndex, formula.ColIndex, formula.DecodeResult(), formula.XFIndex); break; } } return cells; } /* * Page 171 of the OpenOffice documentation of the Excel File Format * * The font with index 4 is omitted in all BIFF versions. This means the first four fonts have zero-based indexes, * and the fifth font and all following fonts are referenced with one-based indexes. */ //public FONT getFontRecord(int index) private static FONT getFontRecord(SharedResource sharedResource, UInt16 index) { if (index >= 0 && index <= 3) { return sharedResource.Fonts[index]; } else if (index >= 5) { return sharedResource.Fonts[index - 1]; } else // index == 4 -> error { return null; } } /* * Sunil Shenoi, 8-25-2008 * * Assuming cell has a valid string vlaue, find the font record for a given characterIndex * into the stringValue of the cell */ public static FONT getFontForCharacter(Cell cell, UInt16 charIndex) { FONT f = null; int index = cell.Style.RichTextFormat.CharIndexes.BinarySearch(charIndex); List fontIndexList = cell.Style.RichTextFormat.FontIndexes; if (index >= 0) { // found the object, return the font record f = getFontRecord(cell.SharedResource, fontIndexList[index]); //Console.WriteLine("for charIndex={0}, fontIndex={1})", charIndex, fontIndexList[index]); //Console.WriteLine("Object: {0} found at [{1}]", o, index); } else { // would have been inserted before the returned value, so insert just before it if (~index == 0) { //f = getFontRecord(sheet,fontIndexList[0]); //Console.WriteLine("for charIndex={0}, fontIndex=CELL", charIndex); } else { f = getFontRecord(cell.SharedResource, fontIndexList[(~index) - 1]); //Console.WriteLine("for charIndex={0}, fontIndex={1})", charIndex, fontIndexList[(~index) - 1]); } //Console.WriteLine("Object: {0} not found. " // + "Next larger object found at [{1}].", o, ~index); } return f; } } }