/// <summary> /// Find how many rows to read at a time and their offset in the file. /// If rows are stored sequentially in the file, returns a block size of up to 32 rows. /// If rows are stored non-sequentially, the block size may extend up to the entire worksheet stream /// </summary> private void GetBlockSize(int startRow, out int blockRowCount, out int minOffset, out int maxOffset) { minOffset = int.MaxValue; maxOffset = int.MinValue; var i = 0; blockRowCount = Math.Min(32, RowCount - startRow); while (i < blockRowCount) { if (RowOffsetMap.TryGetValue(startRow + i, out var rowOffset)) { minOffset = Math.Min(rowOffset.MinCellOffset, minOffset); maxOffset = Math.Max(rowOffset.MaxCellOffset, maxOffset); if (rowOffset.MaxOverlapRowIndex != int.MinValue) { var maxOverlapRowCount = rowOffset.MaxOverlapRowIndex + 1; blockRowCount = Math.Max(blockRowCount, maxOverlapRowCount - startRow); } } i++; } }
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); }
private void SetMinMaxRow(int rowIndex, XlsBiffRow row) { if (!RowOffsetMap.TryGetValue(rowIndex, out var rowOffset)) { rowOffset = new XlsRowOffset(); rowOffset.MinCellOffset = int.MaxValue; rowOffset.MaxCellOffset = int.MinValue; rowOffset.MaxOverlapRowIndex = int.MinValue; RowOffsetMap.Add(rowIndex, rowOffset); } rowOffset.Record = row; }
private void SetMinMaxRowOffset(int rowIndex, int recordOffset, int maxOverlapRow) { if (!RowOffsetMap.TryGetValue(rowIndex, out var rowOffset)) { rowOffset = new XlsRowOffset(); rowOffset.MinCellOffset = int.MaxValue; rowOffset.MaxCellOffset = int.MinValue; rowOffset.MaxOverlapRowIndex = int.MinValue; RowOffsetMap.Add(rowIndex, rowOffset); } rowOffset.MinCellOffset = Math.Min(recordOffset, rowOffset.MinCellOffset); rowOffset.MaxCellOffset = Math.Max(recordOffset, rowOffset.MaxCellOffset); rowOffset.MaxOverlapRowIndex = Math.Max(maxOverlapRow, rowOffset.MaxOverlapRowIndex); }
private Row EnsureRow(XlsRowBlock result, int rowIndex) { if (!result.Rows.TryGetValue(rowIndex, out var currentRow)) { var height = DefaultRowHeight / 20.0; if (RowOffsetMap.TryGetValue(rowIndex, out var rowOffset) && rowOffset.Record != null) { height = (rowOffset.Record.UseDefaultRowHeight ? DefaultRowHeight : rowOffset.Record.RowHeight) / 20.0; } currentRow = new Row(rowIndex, height, new List <Cell>()); result.Rows.Add(rowIndex, currentRow); } return(currentRow); }