예제 #1
0
        /// <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));
        }
예제 #2
0
        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);
        }
예제 #3
0
        /// <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);
            }
        }
예제 #4
0
        /// <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);
        }
예제 #6
0
        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;
                }
            }
        }
예제 #7
0
        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);
        }
예제 #8
0
        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;
            }
        }
예제 #9
0
        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);
        }