/// <summary> /// Returns an index into Workbook.Formats for the given cell and preceding ixfe record. /// </summary> private int GetFormatIndexForCell(XlsBiffBlankCell cell, XlsBiffRecord ixfe) { if (Workbook.BiffVersion == 2) { if (cell.XFormat == 63 && ixfe != null) { var xFormat = ixfe.ReadUInt16(0); return(Workbook.GetNumberFormatFromXF(xFormat)); } else if (cell.XFormat > 63) { // Invalid XF ref on cell in BIFF2 stream, default to built-in "General" return(0); } else if (cell.XFormat < Workbook.GetExtendedFormatCount()) { return(Workbook.GetNumberFormatFromXF(cell.XFormat)); } else { // Either the file has no XFs, or XF was out of range. Use the cell attributes' format reference. return(Workbook.GetNumberFormatFromFileIndex(cell.Format)); } } return(Workbook.GetNumberFormatFromXF(cell.XFormat)); }
private XlsRowBlock ReadNextBlock(XlsBiffStream biffStream, int startRow, int rows, int minOffset, int maxOffset) { var result = new XlsRowBlock { Rows = new Dictionary <int, Row>() }; // Ensure rows with physical records are initialized with height for (var i = 0; i < rows; i++) { if (RowOffsetMap.TryGetValue(startRow + i, out _)) { EnsureRow(result, startRow + i); } } if (minOffset == int.MaxValue) { return(result); } biffStream.Position = minOffset; XlsBiffRecord rec; XlsBiffRecord ixfe = null; while (biffStream.Position <= maxOffset && (rec = biffStream.Read()) != null) { if (rec.Id == BIFFRECORDTYPE.IXFE) { // BIFF2: If cell.xformat == 63, this contains the actual XF index >= 63 ixfe = rec; } if (rec.IsCell) { var cell = (XlsBiffBlankCell)rec; var currentRow = EnsureRow(result, cell.RowIndex); if (cell.Id == BIFFRECORDTYPE.MULRK) { var cellValues = ReadMultiCell(cell); currentRow.Cells.AddRange(cellValues); } else { var xfIndex = GetXfIndexForCell(cell, ixfe); var cellValue = ReadSingleCell(biffStream, cell, xfIndex); currentRow.Cells.Add(cellValue); } ixfe = null; } } return(result); }
/// <summary> /// Reads record under cursor and advances cursor position to next record /// </summary> /// <returns></returns> public XlsBiffRecord Read() { //add lock(this) as this is equivalent to [MethodImpl(MethodImplOptions.Synchronized)] on the method lock (this) { if ((uint)m_offset >= bytes.Length) { return(null); } XlsBiffRecord rec = XlsBiffRecord.GetRecord(bytes, (uint)m_offset, reader); m_offset += rec.Size; if (m_offset > m_size) { return(null); } return(rec); } }
/// <summary> /// Reads record at specified offset, does not change cursor position /// </summary> /// <param name="offset"></param> /// <returns></returns> public XlsBiffRecord ReadAt(int offset) { if ((uint)offset >= bytes.Length) { return(null); } XlsBiffRecord rec = XlsBiffRecord.GetRecord(bytes, (uint)offset, reader); //choose ReadOption.Loose to skip this check (e.g. sql reporting services) if (reader.ReadOption == ReadOption.Strict) { if (m_offset + rec.Size > m_size) { return(null); } } return(rec); }
/// <summary> /// Reads record under cursor and advances cursor position to next record /// </summary> /// <returns>The record -or- null.</returns> public XlsBiffRecord Read() { // Minimum record size is 4 if ((uint)Position + 4 >= _bytes.Length) { return(null); } var record = XlsBiffRecord.GetRecord(_bytes, (uint)Position, BiffVersion); if (record != null) { Position += record.Size; } if (Position > Size) { record = null; } return(record); }
private void ReadWorksheetGlobals() { using (var biffStream = new XlsBiffStream(Stream, (int)DataOffset, Workbook.BiffVersion, null, Workbook.SecretKey, Workbook.Encryption)) { // Check the expected BOF record was found in the BIFF stream if (biffStream.BiffVersion == 0 || biffStream.BiffType != BIFFTYPE.Worksheet) { return; } XlsBiffHeaderFooterString header = null; XlsBiffHeaderFooterString footer = null; // Handle when dimensions report less columns than used by cell records. int maxCellColumn = 0; int maxRowCount = 0; Dictionary <int, bool> previousBlocksObservedRows = new Dictionary <int, bool>(); Dictionary <int, bool> observedRows = new Dictionary <int, bool>(); var recordOffset = biffStream.Position; XlsBiffRecord rec = biffStream.Read(); while (rec != null && !(rec is XlsBiffEof)) { if (rec is XlsBiffDimensions dims) { FieldCount = dims.LastColumn; RowCount = (int)dims.LastRow; } if (rec.Id == BIFFRECORDTYPE.DEFAULTROWHEIGHT || rec.Id == BIFFRECORDTYPE.DEFAULTROWHEIGHT_V2) { var defaultRowHeightRecord = (XlsBiffDefaultRowHeight)rec; DefaultRowHeight = defaultRowHeightRecord.RowHeight; } if (rec.Id == BIFFRECORDTYPE.RECORD1904) { IsDate1904 = ((XlsBiffSimpleValueRecord)rec).Value == 1; } if (rec.Id == BIFFRECORDTYPE.XF_V2 || rec.Id == BIFFRECORDTYPE.XF_V3 || rec.Id == BIFFRECORDTYPE.XF_V4) { ExtendedFormats.Add(rec); } if (rec.Id == BIFFRECORDTYPE.FORMAT) { var fmt = (XlsBiffFormatString)rec; if (Workbook.BiffVersion >= 5) { // fmt.Index exists on BIFF5+ only Formats.Add(fmt.Index, fmt); } else { Formats.Add((ushort)Formats.Count, fmt); } } if (rec.Id == BIFFRECORDTYPE.FORMAT_V23) { var fmt = (XlsBiffFormatString)rec; Formats.Add((ushort)Formats.Count, fmt); } if (rec.Id == BIFFRECORDTYPE.CODEPAGE) { var codePage = (XlsBiffSimpleValueRecord)rec; Encoding = EncodingHelper.GetEncoding(codePage.Value); } if (rec.Id == BIFFRECORDTYPE.HEADER && rec.RecordSize > 0) { header = (XlsBiffHeaderFooterString)rec; } if (rec.Id == BIFFRECORDTYPE.FOOTER && rec.RecordSize > 0) { footer = (XlsBiffHeaderFooterString)rec; } if (rec.Id == BIFFRECORDTYPE.CODENAME) { var codeName = (XlsBiffCodeName)rec; CodeName = codeName.GetValue(Encoding); } if (rec.Id == BIFFRECORDTYPE.ROW) { var rowRecord = (XlsBiffRow)rec; SetMinMaxRowOffset(rowRecord.RowIndex, recordOffset); maxRowCount = Math.Max(maxRowCount, rowRecord.RowIndex + 1); } if (rec.IsCell) { var cell = (XlsBiffBlankCell)rec; SetMinMaxRowOffset(cell.RowIndex, recordOffset); maxCellColumn = Math.Max(maxCellColumn, cell.ColumnIndex + 1); maxRowCount = Math.Max(maxRowCount, cell.RowIndex + 1); } recordOffset = biffStream.Position; rec = biffStream.Read(); } if (header != null || footer != null) { HeaderFooter = new HeaderFooter(false, false) { OddHeader = header?.GetValue(Encoding), OddFooter = footer?.GetValue(Encoding), }; } if (FieldCount < maxCellColumn) { FieldCount = maxCellColumn; } if (RowCount < maxRowCount) { RowCount = maxRowCount; } } }
private XlsRowBlock ReadNextBlock(XlsBiffStream biffStream, int startRow, int rows) { var result = new XlsRowBlock { Rows = new Dictionary <int, Row>() }; XlsBiffRecord rec; XlsBiffRecord ixfe = null; if (!GetMinMaxOffsetsForRowBlock(startRow, rows, out var minOffset, out var maxOffset)) { return(result); } biffStream.Position = minOffset; while (biffStream.Position <= maxOffset && (rec = biffStream.Read()) != null) { if (rec.Id == BIFFRECORDTYPE.ROW || rec.Id == BIFFRECORDTYPE.ROW_V2) { var rowRecord = (XlsBiffRow)rec; var currentRow = EnsureRow(result, rowRecord.RowIndex); currentRow.Height = (rowRecord.UseDefaultRowHeight ? DefaultRowHeight : rowRecord.RowHeight) / 20.0; } if (rec.Id == BIFFRECORDTYPE.IXFE) { // BIFF2: If cell.xformat == 63, this contains the actual XF index >= 63 ixfe = rec; } if (rec.IsCell) { var cell = (XlsBiffBlankCell)rec; var currentRow = EnsureRow(result, cell.RowIndex); if (cell.Id == BIFFRECORDTYPE.MULRK) { var cellValues = ReadMultiCell(cell); currentRow.Cells.AddRange(cellValues); } else { ushort xFormat; if (Workbook.BiffVersion == 2 && cell.XFormat == 63 && ixfe != null) { xFormat = ixfe.ReadUInt16(0); } else { xFormat = cell.XFormat; } var cellValue = ReadSingleCell(biffStream, cell, xFormat); currentRow.Cells.Add(cellValue); } ixfe = null; } } return(result); }
private void ReadWorksheetGlobals() { var biffStream = new XlsBiffStream(Bytes, (int)DataOffset, Workbook.BiffVersion); // Check the expected BOF record was found in the BIFF stream if (biffStream.BiffVersion == 0 || biffStream.BiffType != BIFFTYPE.Worksheet) { return; } XlsBiffHeaderFooterString header = null; XlsBiffHeaderFooterString footer = null; // Handle when dimensions report less columns than used by cell records. int maxCellColumn = 0; Dictionary <int, bool> previousBlocksObservedRows = new Dictionary <int, bool>(); Dictionary <int, bool> observedRows = new Dictionary <int, bool>(); XlsBiffRecord rec = biffStream.Read(); while (rec != null && !(rec is XlsBiffEof)) { if (rec is XlsBiffDimensions dims) { FieldCount = dims.LastColumn; } if (rec.Id == BIFFRECORDTYPE.RECORD1904) { IsDate1904 = ((XlsBiffSimpleValueRecord)rec).Value == 1; } if (rec.Id == BIFFRECORDTYPE.XF_V2 || rec.Id == BIFFRECORDTYPE.XF_V3 || rec.Id == BIFFRECORDTYPE.XF_V4) { ExtendedFormats.Add(rec); } if (rec.Id == BIFFRECORDTYPE.FORMAT) { var fmt = (XlsBiffFormatString)rec; if (Workbook.BiffVersion >= 5) { // fmt.Index exists on BIFF5+ only Formats.Add(fmt.Index, fmt); } else { Formats.Add((ushort)Formats.Count, fmt); } } if (rec.Id == BIFFRECORDTYPE.FORMAT_V23) { var fmt = (XlsBiffFormatString)rec; Formats.Add((ushort)Formats.Count, fmt); } if (rec.Id == BIFFRECORDTYPE.CODEPAGE) { var codePage = (XlsBiffSimpleValueRecord)rec; Encoding = EncodingHelper.GetEncoding(codePage.Value); } if (rec.Id == BIFFRECORDTYPE.HEADER && rec.RecordSize > 0) { header = (XlsBiffHeaderFooterString)rec; } if (rec.Id == BIFFRECORDTYPE.FOOTER && rec.RecordSize > 0) { footer = (XlsBiffHeaderFooterString)rec; } if (rec.Id == BIFFRECORDTYPE.CODENAME) { var codeName = (XlsBiffCodeName)rec; CodeName = codeName.GetValue(Encoding); } if (!RowContentInMultipleBlocks && rec is XlsBiffDbCell) { foreach (int row in observedRows.Keys) { previousBlocksObservedRows[row] = true; } observedRows.Clear(); } if (rec is XlsBiffBlankCell cell) { maxCellColumn = Math.Max(maxCellColumn, cell.ColumnIndex + 1); if (!RowContentInMultipleBlocks) { if (previousBlocksObservedRows.ContainsKey(cell.RowIndex)) { RowContentInMultipleBlocks = true; previousBlocksObservedRows.Clear(); observedRows.Clear(); } observedRows[cell.RowIndex] = true; } } rec = biffStream.Read(); } if (header != null || footer != null) { HeaderFooter = new HeaderFooter(false, false) { OddHeader = header?.GetValue(Encoding), OddFooter = footer?.GetValue(Encoding), }; } if (FieldCount < maxCellColumn) { FieldCount = maxCellColumn; } }
private XlsRowBlock ReadNextBlock(XlsBiffStream biffStream) { var result = new XlsRowBlock { Rows = new Dictionary <int, object[]>() }; var currentRowIndex = -1; object[] currentRow = null; XlsBiffRecord rec; XlsBiffRecord ixfe = null; while ((rec = biffStream.Read()) != null) { if (rec is XlsBiffEof) { result.EndOfSheet = true; break; } if (rec is XlsBiffMSODrawing || (!RowContentInMultipleBlocks && rec is XlsBiffDbCell)) { break; } if (rec.Id == BIFFRECORDTYPE.IXFE) { // BIFF2: If cell.xformat == 63, this contains the actual XF index >= 63 ixfe = rec; } if (rec is XlsBiffBlankCell cell) { // In most cases cells are grouped by row if (currentRowIndex != cell.RowIndex) { if (!result.Rows.TryGetValue(cell.RowIndex, out currentRow)) { currentRow = new object[FieldCount]; result.Rows.Add(cell.RowIndex, currentRow); } currentRowIndex = cell.RowIndex; } ushort xFormat; if (Workbook.BiffVersion == 2 && cell.XFormat == 63 && ixfe != null) { xFormat = ixfe.ReadUInt16(0); } else { xFormat = cell.XFormat; } var additionalRecords = new List <XlsBiffRecord>(); while (!PushCellValue(currentRow, cell, xFormat, additionalRecords)) { var additionalRecord = biffStream.Read(); additionalRecords.Add(additionalRecord); } ixfe = null; } } return(result); }