internal FormulaRecord(Record formulaRecord, Record stringRecord) : base() { _rid = formulaRecord.RID; _data = formulaRecord.Data; _continues = formulaRecord.Continues; StringRecord = stringRecord; }
internal static string Read(Record record, int lengthBits, ref int continueIndex, ref ushort offset) { string text = string.Empty; ReadState state = new ReadState(record, lengthBits, continueIndex, offset); Read(state); continueIndex = state.ContinueIndex; offset = state.Offset; return new string(state.CharactersRead.ToArray()); }
private Bytes INDEX(int baseLength) { Bytes index = new Bytes(); //Not used index.Append(new byte[] { 0x00, 0x00, 0x00, 0x00 }); //Index to first used row (0-based) index.Append(BitConverter.GetBytes(_rows.MinRow - 1)); //Index to first row of unused tail of sheet(last row + 1, 0-based) index.Append(BitConverter.GetBytes(_rows.MaxRow)); //Absolute stream position of the DEFCOLWIDTH record //TODO: Implement Worksheet.INDEX Absolute stream position of the DEFCOLWIDTH record (not necessary) index.Append(BitConverter.GetBytes((uint)0)); for (int i = 1; i < _dbCellOffsets.Length; i++) { index.Append(BitConverter.GetBytes((uint)(baseLength + _dbCellOffsets[i]))); } return(Record.GetBytes(RID.INDEX, index)); }
private static string Read(Record record, int lengthBits, ushort offset) { int continueIndex = -1; //throw away return Read(record, lengthBits, ref continueIndex, ref offset); }
public ReadState(Record record, int lengthBits, int continueIndex, ushort offset) { LengthBits = lengthBits; Record = record; ContinueIndex = continueIndex; Offset = offset; Bytes data = GetRecordData(); if (LengthBits == 8) { TotalCharacters = data.Get(offset, 1).ByteArray[0]; Offset++; } else { TotalCharacters = data.Get(offset, 2).GetBits().ToUInt16(); Offset += 2; } ReadOptionsFlags(); HasAsianPhonetics = (OptionsFlags & 0x04) == 0x04; HasRichTextSettings = (OptionsFlags & 0x08) == 0x08; if (HasRichTextSettings) { FormattingRunCount = BitConverter.ToUInt16(data.Get(Offset, 2).ByteArray, 0); Offset += 2; //bytesRemaining += (ushort)(4 * formattingRuns); //NOTE: When implementing Rich Text, remember to add total length of formating runs to bytesRead //throw new NotSupportedException("Rich Text text values in cells are not yet supported"); } if (HasAsianPhonetics) { PhoneticSettingsByteCount = BitConverter.ToUInt32(data.Get(Offset, 4).ByteArray, 0); Offset += 4; //NOTE: When implementing Asian Text, remember to add total length of Asian Phonetic Settings Block to bytesRead //throw new NotSupportedException("Asian Phonetic text values in cells are not yet supported"); } }
internal static string Read(Bytes bytes, int lengthBits) { Record record = new Record(RID.Empty, bytes); return Read(record, lengthBits, 0); }
internal Worksheet(XlsDocument doc, Record boundSheet, List<Record> sheetRecords) : this(doc) { byte[] byteArray = boundSheet.Data.ByteArray; byte visibility = byteArray[4]; if (visibility == 0x00) _visibility = WorksheetVisibilities.Visible; else if (visibility == 0x01) _visibility = WorksheetVisibilities.Hidden; else if (visibility == 0x02) _visibility = WorksheetVisibilities.StrongHidden; else throw new Exception(string.Format("Unknown Visibility {0}", visibility)); byte type = byteArray[5]; if (type == 0x00) _sheettype = WorksheetTypes.Worksheet; else if (type == 0x02) _sheettype = WorksheetTypes.Chart; else if (type == 0x06) _sheettype = WorksheetTypes.VBModule; else throw new Exception(string.Format("Unknown Sheet Type {0}", type)); List<Record> rowRecords = new List<Record>(); List<Record> cellRecords = new List<Record>(); List<Record> noteRecords = new List<Record>(); for (int i = 0; i < sheetRecords.Count; i++) { Record record = sheetRecords[i]; if (record.IsCellRecord()) { if (record.RID == RID.FORMULA) { Record formulaStringRecord = null; if ((i + i) < sheetRecords.Count) { formulaStringRecord = sheetRecords[i + 1]; if (formulaStringRecord.RID != RID.STRING) formulaStringRecord = null; } record = new FormulaRecord(record, formulaStringRecord); } cellRecords.Add(record); } else if (record.RID == RID.ROW) rowRecords.Add(record); else if (record.RID == RID.NOTE) noteRecords.Add(record); } //Add the Rows first so they exist for adding the Cells foreach (Record rowRecord in rowRecords) { Bytes rowBytes = rowRecord.Data; ushort rowIndex = rowBytes.Get(0, 2).GetBits().ToUInt16(); Row row = Rows.AddRow(rowIndex); bool isDefaultHeight = rowBytes.Get(6, 2).GetBits().Values[15]; ushort height = 0; if (!isDefaultHeight) { height = rowBytes.Get(6, 2).GetBits().Get(0, 14).ToUInt16(); //TODO: Set height on Row when reading (after Row Height implemented) } bool defaultsWritten = (rowBytes.Get(10, 1).ByteArray[0] == 0x01); if (defaultsWritten) { //TODO: Read ROW record defaults } } foreach (Record record in cellRecords) AddCells(record); foreach (Record record in noteRecords) AddNote(record); _name = UnicodeBytes.Read(boundSheet.Data.Get(6, boundSheet.Data.Length - 6), 8); }
private void AddNote(Record record) { Bytes bytes = record.Data; ushort rowIndex = bytes.Get(0, 2).GetBits().ToUInt16(); ushort colIndex = bytes.Get(2, 2).GetBits().ToUInt16(); Bytes options = bytes.Get(4, 2); ushort objId = bytes.Get(6, 2).GetBits().ToUInt16(); string authorName = UnicodeBytes.Read(bytes.Get(8, bytes.Length - 8), 16); Debugger.Break(); }
private void ReadBytes(Bytes bytes, BytesReadCallback bytesReadCallback) { if (bytes == null) { throw new ArgumentNullException("bytes"); } if (bytes.Length == 0) { throw new ArgumentException("can't be zero-length", "bytes"); } //The XF's read in won't necessarily have the same ID (index) once added to this Workbook, //so we need to keep the cross-reference list for re-assignment as we read in the cell records later SortedList <ushort, ushort> xfIdLookups = new SortedList <ushort, ushort>(); List <Record> records = Record.GetAll(bytes); List <Record> fontRecords = new List <Record>(); List <Record> formatRecords = new List <Record>(); List <Record> xfRecords = new List <Record>(); List <Record> boundSheetRecords = new List <Record>(); Record sstRecord = Record.Empty; SortedList <int, List <Record> > sheetRecords = new SortedList <int, List <Record> >(); int sheetIndex = -1; foreach (Record record in records) { if (sheetIndex >= 0) { if (!sheetRecords.ContainsKey(sheetIndex)) { sheetRecords[sheetIndex] = new List <Record>(); } sheetRecords[sheetIndex].Add(record); if (record.RID == RID.EOF) { sheetIndex++; } } else if (record.RID == RID.FONT) { fontRecords.Add(record); } else if (record.RID == RID.FORMAT) { formatRecords.Add(record); } else if (record.RID == RID.XF) { xfRecords.Add(record); } else if (record.RID == RID.BOUNDSHEET) { boundSheetRecords.Add(record); } else if (record.RID == RID.SST) { sstRecord = record; } else if (record.RID == RID.EOF) { sheetIndex++; } } SortedList <ushort, string> formats = new SortedList <ushort, string>(); ushort index = 0; foreach (Record record in fontRecords) { Font font = new Font(_doc, record.Data); this.Fonts.Add(font); } foreach (Record record in formatRecords) { Bytes recordData = record.Data; string format = UnicodeBytes.Read(recordData.Get(2, recordData.Length - 2), 16); index = BitConverter.ToUInt16(recordData.Get(2).ByteArray, 0); formats[index] = format; this.Formats.Add(format); } index = 0; for (index = 0; index < xfRecords.Count; index++) { Record record = xfRecords[index]; Bytes recordData = record.Data; ushort fontIndex = BitConverter.ToUInt16(recordData.Get(0, 2).ByteArray, 0); ushort formatIndex = BitConverter.ToUInt16(recordData.Get(2, 2).ByteArray, 0); //ushort styleIndex = BitConverter.ToUInt16(recordData.Get(4, 2)) //TODO: Defaults to default font. Should it? NOTE: This is encountered with TestReferenceFile BlankBudgetWorksheet.xls Font font = fontIndex < _fonts.Count ? _fonts[fontIndex] : _fonts[0]; string format; if (formats.ContainsKey(formatIndex)) { format = formats[formatIndex]; } else if (_formats.ContainsKey(formatIndex)) { format = _formats[formatIndex]; } else { throw new Exception(string.Format("Format {0} not found in read FORMAT records or standard/default FORMAT records.", formatIndex)); } xfIdLookups[index] = this.XFs.Add(new XF(_doc, record.Data, font, format)); } this.XFs.XfIdxLookups = xfIdLookups; if (sstRecord != Record.Empty) { this.SharedStringTable.ReadBytes(sstRecord); } if (bytesReadCallback != null) { bytesReadCallback(records); } for (int i = 0; i < boundSheetRecords.Count; i++) { _worksheets.Add(boundSheetRecords[i], sheetRecords[i]); } }
internal Worksheet(XlsDocument doc, Record boundSheet, List <Record> sheetRecords) : this(doc) { byte[] byteArray = boundSheet.Data.ByteArray; byte visibility = byteArray[4]; if (visibility == 0x00) { _visibility = WorksheetVisibilities.Visible; } else if (visibility == 0x01) { _visibility = WorksheetVisibilities.Hidden; } else if (visibility == 0x02) { _visibility = WorksheetVisibilities.StrongHidden; } else { throw new ApplicationException(string.Format("Unknown Visibility {0}", visibility)); } byte type = byteArray[5]; if (type == 0x00) { _sheettype = WorksheetTypes.Worksheet; } else if (type == 0x02) { _sheettype = WorksheetTypes.Chart; } else if (type == 0x06) { _sheettype = WorksheetTypes.VBModule; } else { throw new ApplicationException(string.Format("Unknown Sheet Type {0}", type)); } List <Record> rowRecords = new List <Record>(); List <Record> cellRecords = new List <Record>(); for (int i = 0; i < sheetRecords.Count; i++) { Record record = sheetRecords[i]; if (record.IsCellRecord()) { if (record.RID == RID.FORMULA) { Record formulaStringRecord = null; if ((i + i) < sheetRecords.Count) { formulaStringRecord = sheetRecords[i + 1]; if (formulaStringRecord.RID != RID.STRING) { formulaStringRecord = null; } } record = new FormulaRecord(record, formulaStringRecord); } cellRecords.Add(record); } else if (record.RID == RID.ROW) { rowRecords.Add(record); } } //Add the Rows first so they exist for adding the Cells foreach (Record rowRecord in rowRecords) { Bytes rowBytes = rowRecord.Data; ushort rowIndex = rowBytes.Get(0, 2).GetBits().ToUInt16(); Row row = Rows.AddRow(rowIndex); bool isDefaultHeight = rowBytes.Get(6, 2).GetBits().Values[15]; ushort height = 0; if (!isDefaultHeight) { height = rowBytes.Get(6, 2).GetBits().Get(0, 14).ToUInt16(); //TODO: Set height on Row when reading (after Row Height implemented) } bool defaultsWritten = (rowBytes.Get(10, 1).ByteArray[0] == 0x01); if (defaultsWritten) { //TODO: Read ROW record defaults } } foreach (Record record in cellRecords) { AddCells(record); } _name = UnicodeBytes.Read(boundSheet.Data.Get(6, boundSheet.Data.Length - 6), 8); }
private void AddCells(Record record) { Bytes bytes = record.Data; ushort rowIndex = bytes.Get(0, 2).GetBits().ToUInt16(); ushort colIndex = bytes.Get(2, 2).GetBits().ToUInt16(); ushort lastColIndex = colIndex; ushort offset = 4; byte[] rid = record.RID; bool isMulti = false; if (rid == RID.MULBLANK) { isMulti = true; rid = RID.BLANK; } else if (rid == RID.MULRK) { isMulti = true; rid = RID.RK; } if (isMulti) { lastColIndex = bytes.Get(bytes.Length - 2, 2).GetBits().ToUInt16(); } while (colIndex <= lastColIndex) { Cell cell = Cells.Add((ushort)(rowIndex + 1), (ushort)(colIndex + 1)); ushort xfIndex = bytes.Get(offset, 2).GetBits().ToUInt16(); offset += 2; Bytes data; if (rid == RID.BLANK) { data = new Bytes(); } else if (rid == RID.RK) { data = bytes.Get(offset, 4); offset += 4; cell.SetValue(rid, data); } else { data = bytes.Get(offset, bytes.Length - offset); if (rid == RID.FORMULA) { FormulaRecord formulaRecord = record as FormulaRecord; cell.SetFormula(data, formulaRecord.StringRecord); } else { cell.SetValue(rid, data); } } colIndex++; } }
private void DecodeFORMULA(Bytes data, Record stringRecord) { //TODO: Read in formula properties if (stringRecord != null) _value = UnicodeBytes.Read(stringRecord.Data, 16); _type = CellTypes.Formula; }
internal void SetFormula(Bytes data, Record stringRecord) { DecodeFORMULA(data, stringRecord); }
// Token: 0x06000151 RID: 337 RVA: 0x000076F2 File Offset: 0x000066F2 internal void SetFormula(Bytes data, Record stringRecord) { this.DecodeFORMULA(data, stringRecord); }
private void AddCells(Record record) { Bytes bytes = record.Data; ushort rowIndex = bytes.Get(0, 2).GetBits().ToUInt16(); ushort colIndex = bytes.Get(2, 2).GetBits().ToUInt16(); ushort lastColIndex = colIndex; ushort offset = 4; byte[] rid = record.RID; bool isMulti = false; if (rid == RID.MULBLANK) { isMulti = true; rid = RID.BLANK; } else if (rid == RID.MULRK) { isMulti = true; rid = RID.RK; } if (isMulti) lastColIndex = bytes.Get(bytes.Length - 2, 2).GetBits().ToUInt16(); while (colIndex <= lastColIndex) { Cell cell = Cells.Add((ushort)(rowIndex + 1), (ushort)(colIndex + 1)); ushort xfIndex = bytes.Get(offset, 2).GetBits().ToUInt16(); ushort index = _doc.Workbook.XFs.XfIdxLookups[xfIndex]; cell.SetXfIndex(index); offset += 2; Bytes data; if (rid == RID.BLANK) data = new Bytes(); else if (rid == RID.RK) { data = bytes.Get(offset, 4); offset += 4; cell.SetValue(rid, data); } else { data = bytes.Get(offset, bytes.Length - offset); if (rid == RID.FORMULA) { FormulaRecord formulaRecord = record as FormulaRecord; cell.SetFormula(data, formulaRecord.StringRecord); } else cell.SetValue(rid, data); } colIndex++; } }
/// <summary> /// /// </summary> /// <param name="stream"></param> /// <returns></returns> public static List<Record> GetAll(Bytes stream) { int i = 0; List<Record> records = new List<Record>(); Record lastNonContinue = Record.Empty; while (i < (stream.Length - 4)) { byte[] rid = org.in2bits.MyXls.RID.ByteArray(stream.Get(i, 2).ByteArray); Bytes data = new Bytes(); if (rid == MyXls.RID.Empty) break; int length = BitConverter.ToUInt16(stream.Get(i + 2, 2).ByteArray, 0); data = stream.Get(i + 4, length); Record record = new Record(rid, data); i += (4 + length); if (rid == MyXls.RID.CONTINUE) { if (lastNonContinue == Record.Empty) throw new Exception("Found CONTINUE record without previous/parent record."); lastNonContinue.Continues.Add(record); } else { lastNonContinue = record; records.Add(record); } } return records; }
//TODO: Implement Rich Text Value support //TODO: Implement Asian Text Value support internal void ReadBytes(Record sstRecord) { uint totalStrings = sstRecord.Data.Get(0, 4).GetBits().ToUInt32(); uint uniqueStrings = sstRecord.Data.Get(4, 4).GetBits().ToUInt32(); int stringIndex = 0; ushort offset = 8; int continueIndex = -1; while (stringIndex < uniqueStrings) { string sharedString = UnicodeBytes.Read(sstRecord, 16, ref continueIndex, ref offset); Add(sharedString); stringIndex++; } _countAll = totalStrings; }