Пример #1
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the INDEX record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public IndexRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Index)
            {
                Stream       stream = biff.GetDataStream();
                BinaryReader reader = new BinaryReader(stream);

                /* uint reserved = */ reader.ReadUInt32();
                _firstRow = reader.ReadUInt32();
                _lastRow  = reader.ReadUInt32();
                /* reserved = */ reader.ReadUInt32();

                int nrows = (int)(stream.Length - stream.Position) / 4;
                _rows = new uint[nrows];
                nrows = 0;
                while (stream.Position < stream.Length)
                {
                    _rows[nrows++] = reader.ReadUInt32();
                }

                Debug.Assert(stream.Position == stream.Length);
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Index);
            }
        }
Пример #2
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the FORMULA record.</param>
		/// <param name="recordsStream">The stream into the records to which the FORMULA record belongs to. The record stream must be positioned just after the FORMULA record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public FormulaRecord(GenericBiff biff, Stream recordsStream)
		{
			if(biff.Id == (ushort)RecordType.Formula)
			{
				Stream stream = biff.GetDataStream();
				BinaryReader reader = new BinaryReader(stream);
				
				ReadRowColXf(reader);
				FormulaValue val = new FormulaValue(reader.ReadDouble());
				
				_options = reader.ReadUInt16();
				_reserved = reader.ReadUInt32();
				_formulaLen = reader.ReadUInt16();
				_formulaData = reader.ReadBytes((int)(stream.Length - stream.Position));

				if(val.StringFollows)
				{
					GenericBiff r = new GenericBiff(recordsStream);
					while(r.Id != (ushort)RecordType.String)
					{
						r = new GenericBiff(recordsStream);
					}

					StringValueRecord stringValue = new StringValueRecord(r);
					_value = stringValue.Value;
				}
				else
					_value = val.Value;
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Formula);
		}
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the SST record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public StringValueRecord(GenericBiff biff) 
		{
			if(biff.Id == (ushort)RecordType.String)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());
				_value = Reader.ReadComplexString(reader);
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.String);
		}
Пример #4
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the XF record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public XfRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Xf)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                _fontIdx   = reader.ReadUInt16();
                _formatIdx = reader.ReadUInt16();

                ushort data = reader.ReadUInt16();
                _typeAndProtection = new TypeAndProtection(data & 0x000F);
                _parentIdx         = (ushort)((data & 0xFFF0) >> 8);

                byte data2 = reader.ReadByte();
                _horizontalAlignment = (HorizontalAlignment)(data2 & 0x07);
                _wrapped             = (data & 0x088) != 0;
                _verticalAlignment   = (VerticalAlignment)((data2 & 0x70) >> 4);

                data2     = reader.ReadByte();
                _rotation = new Rotation(data2);

                data2          = reader.ReadByte();
                _indentLevel   = new Nibble((byte)(data2 & 0x0F));
                _shrinkContent = (data2 & 0x10) == 1;

                _parentStyle = (ParentStyleAttributes)(reader.ReadByte());

                uint data3 = reader.ReadUInt32();
                _leftLineStyle   = (LineStyle)(data3 & 0x0000000F);
                _rightLineStyle  = (LineStyle)((data3 & 0x000000F0) >> 1);
                _topLineStyle    = (LineStyle)((data3 & 0x00000F00) >> 2);
                _bottomLineStyle = (LineStyle)((data3 & 0x0000F000) >> 3);
                _rightLineColor  = (ushort)((data3 & 0x007F0000) >> 4);
                _leftLineColor   = (ushort)((data3 & 0x3F800000) >> 5);
                _diagonalRightTopToLeftBottom = (data & 0x40000000) == 1;
                _diagonalLeftBottomToTopRight = (data & 0x80000000) == 1;

                data3              = reader.ReadUInt32();
                _topLineColor      = (ushort)(data3 & 0x0000007F);
                _bottomLineColor   = (ushort)((data3 & 0x00003F80) >> 1);
                _diagonalLineColor = (ushort)((data3 & 0x001FC000) >> 3);
                _diagonalLineStyle = (LineStyle)((data3 & 0x01E00000) >> 5);
                _fillPattern       = (FillPattern)((data3 & 0xFC000000) >> 6);

                data               = reader.ReadUInt16();
                _patternColor      = (ushort)(data & 0x007F);
                _patternBackground = (ushort)((data & 0x3F80) >> 7);

                Debug.Assert(reader.BaseStream.Position == reader.BaseStream.Length);
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Xf);
            }
        }
Пример #5
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the BLANK record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException if thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public BlankRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.Blank)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());
				
				ReadRowColXf(reader);
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Blank);
		}
Пример #6
0
 /// <summary>
 /// The constructor for the record.
 /// </summary>
 /// <param name="biff">The GenericBiff record that should contain the correct type and data for the SST record.</param>
 /// <exception cref="InvalidRecordIdException">
 /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
 /// </exception>
 public StringValueRecord(GenericBiff biff)
 {
     if (biff.Id == (ushort)RecordType.String)
     {
         BinaryReader reader = new BinaryReader(biff.GetDataStream());
         _value = Reader.ReadComplexString(reader);
     }
     else
     {
         throw new InvalidRecordIdException(biff.Id, RecordType.String);
     }
 }
Пример #7
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the FORMAT record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public FormatRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.Format)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				_index = reader.ReadUInt16();
				_format = Reader.ReadComplexString(reader);
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Format);
		}
Пример #8
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the RK record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public RkRecord(GenericBiff biff) 
		{
			if(biff.Id == (ushort)RecordType.Rk)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				ReadRowColXf(reader);
				_value = new RkValue(reader.ReadInt32());
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Rk);
		}
Пример #9
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the XF record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public XfRecord(GenericBiff biff) 
		{
			if(biff.Id == (ushort)RecordType.Xf)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());
				
				_fontIdx = reader.ReadUInt16();
				_formatIdx = reader.ReadUInt16();

				ushort data = reader.ReadUInt16();
				_typeAndProtection = new TypeAndProtection(data & 0x000F);
				_parentIdx = (ushort)((data & 0xFFF0) >> 8);

				byte data2 = reader.ReadByte();
				_horizontalAlignment = (HorizontalAlignment)(data2 & 0x07);
				_wrapped = (data & 0x088) != 0;
				_verticalAlignment = (VerticalAlignment)((data2 & 0x70) >> 4);
				
				data2 = reader.ReadByte();
				_rotation = new Rotation(data2);

				data2 = reader.ReadByte();
				_indentLevel = new Nibble((byte)(data2 & 0x0F));
				_shrinkContent = (data2 & 0x10) == 1;

				_parentStyle = (ParentStyleAttributes)(reader.ReadByte());
					
				uint data3 = reader.ReadUInt32();
				_leftLineStyle = (LineStyle)(data3 & 0x0000000F);
				_rightLineStyle = (LineStyle)((data3 & 0x000000F0) >> 1);
				_topLineStyle = (LineStyle)((data3 & 0x00000F00) >> 2);
				_bottomLineStyle = (LineStyle)((data3 & 0x0000F000) >> 3);
				_rightLineColor = (ushort)((data3 & 0x007F0000) >> 4);
				_leftLineColor = (ushort)((data3 & 0x3F800000) >> 5);
				_diagonalRightTopToLeftBottom = (data & 0x40000000) == 1;
				_diagonalLeftBottomToTopRight = (data & 0x80000000) == 1;

				data3 = reader.ReadUInt32();
				_topLineColor = (ushort)(data3 & 0x0000007F);
				_bottomLineColor = (ushort)((data3 & 0x00003F80) >> 1);
				_diagonalLineColor = (ushort)((data3 & 0x001FC000) >> 3);
				_diagonalLineStyle = (LineStyle)((data3 & 0x01E00000) >> 5);
				_fillPattern = (FillPattern)((data3 & 0xFC000000) >> 6);

				data = reader.ReadUInt16();
				_patternColor = (ushort)(data & 0x007F);
				_patternBackground = (ushort)((data & 0x3F80) >> 7);

				Debug.Assert(reader.BaseStream.Position == reader.BaseStream.Length);
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Xf);
		}
Пример #10
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the BLANK record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException if thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public BlankRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Blank)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                ReadRowColXf(reader);
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Blank);
            }
        }
Пример #11
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the LABEL record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public LabelRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.Label)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				ReadRowColXf(reader);

				_value = Reader.ReadSimpleUnicodeString(reader);
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Label);
		}
Пример #12
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the LABELSST record.</param>
		/// <param name="sst">A reference to the shared string table for the workbook.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public LabelSstRecord(GenericBiff biff, SstRecord sst)
		{
			if(biff.Id == (ushort)RecordType.LabelSst)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				ReadRowColXf(reader);
				_sstIndex = reader.ReadUInt32();		
				_value = sst.Strings[_sstIndex];
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.LabelSst);
		}
Пример #13
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the NUMBER record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public NumberRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Number)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                ReadRowColXf(reader);
                _value = reader.ReadDouble();
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Number);
            }
        }
Пример #14
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the FORMAT record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public FormatRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Format)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                _index  = reader.ReadUInt16();
                _format = Reader.ReadComplexString(reader);
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Format);
            }
        }
Пример #15
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the RK record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public RkRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Rk)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                ReadRowColXf(reader);
                _value = new RkValue(reader.ReadInt32());
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Rk);
            }
        }
Пример #16
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the BOOLERR record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public BoolErrRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.BoolErr)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				ReadRowColXf(reader);
				
				byte boolErr = reader.ReadByte();
				byte error = reader.ReadByte();
				_value = new BoolErrValue(boolErr, error);
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.BoolErr);
		}
Пример #17
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the MULBLANK record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public MulBlankRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.MulBlank)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				reader = ReadRowColInfo(reader);
				_xfIndex = new ushort[reader.BaseStream.Length / 2];
				for(int n = 0; n < _xfIndex.Length; ++n)
					_xfIndex[n] = reader.ReadUInt16();

			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.MulBlank);
		}
Пример #18
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the BOUNDSHEET record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public BoundSheetRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Boundsheet)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());
                _bofPos = reader.ReadUInt32();
                _visibility = (VisibilityType)reader.ReadByte();
                _type = (SheetType)reader.ReadByte();

                byte len = reader.ReadByte();
                _name = Reader.ReadPossibleCompressedString(reader, len);
            }
            else
                throw new InvalidRecordIdException(biff.Id, RecordType.Boundsheet);
        }
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the SHRFMLA record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public SharedFormulaRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.ShrFmla)
			{
				Stream stream = biff.GetDataStream();
				BinaryReader reader = new BinaryReader(stream);

				ReadRangeValues(reader);

				_reserved = reader.ReadUInt16();
				_data = reader.ReadBytes((int)(stream.Length - stream.Position));
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.ShrFmla);
		}
Пример #20
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the LABELSST record.</param>
        /// <param name="sst">A reference to the shared string table for the workbook.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public LabelSstRecord(GenericBiff biff, SstRecord sst)
        {
            if (biff.Id == (ushort)RecordType.LabelSst)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                ReadRowColXf(reader);
                _sstIndex = reader.ReadUInt32();
                _value    = sst.Strings[_sstIndex];
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.LabelSst);
            }
        }
Пример #21
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the LABEL record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public LabelRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Label)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                ReadRowColXf(reader);

                _value = Reader.ReadSimpleUnicodeString(reader);
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Label);
            }
        }
Пример #22
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the BOF record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public BofRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.Bof)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());
				_version = reader.ReadUInt16();
				_type = (SubstreamType)reader.ReadUInt16();
				_buildId = reader.ReadUInt16();
				_buildYear = reader.ReadUInt16();
				_history = reader.ReadUInt32();
				_lowestBiff = reader.ReadUInt32();
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Bof);
		}
Пример #23
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the ROW record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public RowRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.Row)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());
				_rowNumber = reader.ReadUInt16();
				_firstCol = reader.ReadUInt16();
				_lastCol = reader.ReadUInt16();
				_rowHeight = new RowHeight(reader.ReadUInt16());
				_optimizer = reader.ReadUInt16();
				_options = new RowOptionFlags(reader.ReadUInt16());
				_xf = reader.ReadUInt16();
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Row);
		}
Пример #24
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the PALETTE record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public PaletteRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.Palette)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				ushort numColors = reader.ReadUInt16();
				_colors = new int[numColors];
				for(ushort i = 0; i < numColors; ++i)
				{
					_colors[i] = reader.ReadInt32();
				}
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Palette);
		}
Пример #25
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the TABLE record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public TableRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.Table)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				ReadRangeValues(reader);

				_options = reader.ReadUInt16();
				_inputRowIdx = reader.ReadUInt16();
				_inputColIdx = reader.ReadUInt16();
				_inputRowIdxForColInp = reader.ReadUInt16();
				_inputColIdxForColInp = reader.ReadUInt16();
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Table);
		}
Пример #26
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the BOOLERR record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public BoolErrRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.BoolErr)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                ReadRowColXf(reader);

                byte boolErr = reader.ReadByte();
                byte error   = reader.ReadByte();
                _value = new BoolErrValue(boolErr, error);
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.BoolErr);
            }
        }
Пример #27
0
 /// <summary>
 /// The constructor for the record.
 /// </summary>
 /// <param name="biff">The GenericBiff record that should contain the correct type and data for the BOF record.</param>
 /// <exception cref="InvalidRecordIdException">
 /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
 /// </exception>
 public BofRecord(GenericBiff biff)
 {
     if (biff.Id == (ushort)RecordType.Bof)
     {
         BinaryReader reader = new BinaryReader(biff.GetDataStream());
         _version    = reader.ReadUInt16();
         _type       = (SubstreamType)reader.ReadUInt16();
         _buildId    = reader.ReadUInt16();
         _buildYear  = reader.ReadUInt16();
         _history    = reader.ReadUInt32();
         _lowestBiff = reader.ReadUInt32();
     }
     else
     {
         throw new InvalidRecordIdException(biff.Id, RecordType.Bof);
     }
 }
Пример #28
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the SHRFMLA record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public SharedFormulaRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.ShrFmla)
            {
                Stream       stream = biff.GetDataStream();
                BinaryReader reader = new BinaryReader(stream);

                ReadRangeValues(reader);

                _reserved = reader.ReadUInt16();
                _data     = reader.ReadBytes((int)(stream.Length - stream.Position));
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.ShrFmla);
            }
        }
Пример #29
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the BOUNDSHEET record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public BoundSheetRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Boundsheet)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());
                _bofPos     = reader.ReadUInt32();
                _visibility = (VisibilityType)reader.ReadByte();
                _type       = (SheetType)reader.ReadByte();

                byte len = reader.ReadByte();
                _name = Reader.ReadPossibleCompressedString(reader, len);
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Boundsheet);
            }
        }
Пример #30
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the PALETTE record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public PaletteRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Palette)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                ushort numColors = reader.ReadUInt16();
                _colors = new int[numColors];
                for (ushort i = 0; i < numColors; ++i)
                {
                    _colors[i] = reader.ReadInt32();
                }
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Palette);
            }
        }
Пример #31
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the MULBLANK record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public MulBlankRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.MulBlank)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                reader   = ReadRowColInfo(reader);
                _xfIndex = new ushort[reader.BaseStream.Length / 2];
                for (int n = 0; n < _xfIndex.Length; ++n)
                {
                    _xfIndex[n] = reader.ReadUInt16();
                }
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.MulBlank);
            }
        }
Пример #32
0
 /// <summary>
 /// The constructor for the record.
 /// </summary>
 /// <param name="biff">The GenericBiff record that should contain the correct type and data for the ROW record.</param>
 /// <exception cref="InvalidRecordIdException">
 /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
 /// </exception>
 public RowRecord(GenericBiff biff)
 {
     if (biff.Id == (ushort)RecordType.Row)
     {
         BinaryReader reader = new BinaryReader(biff.GetDataStream());
         _rowNumber = reader.ReadUInt16();
         _firstCol  = reader.ReadUInt16();
         _lastCol   = reader.ReadUInt16();
         _rowHeight = new RowHeight(reader.ReadUInt16());
         _optimizer = reader.ReadUInt16();
         _options   = new RowOptionFlags(reader.ReadUInt16());
         _xf        = reader.ReadUInt16();
     }
     else
     {
         throw new InvalidRecordIdException(biff.Id, RecordType.Row);
     }
 }
Пример #33
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the TABLE record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public TableRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Table)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                ReadRangeValues(reader);

                _options              = reader.ReadUInt16();
                _inputRowIdx          = reader.ReadUInt16();
                _inputColIdx          = reader.ReadUInt16();
                _inputRowIdxForColInp = reader.ReadUInt16();
                _inputColIdxForColInp = reader.ReadUInt16();
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Table);
            }
        }
Пример #34
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the MULRK record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public MulRkRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.MulRk)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				reader = ReadRowColInfo(reader);

				_values = new RkRec[reader.BaseStream.Length / 6];
				for(int n = 0; n < _values.Length; ++n)
				{
					ushort xf = reader.ReadUInt16();
					int rk = reader.ReadInt32();
					_values[n] = new RkRec(xf, rk);
				}
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.MulRk);
		}
Пример #35
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the DBCELL record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public DbCellRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.DbCell)
			{
				Stream stream = biff.GetDataStream();
				BinaryReader reader = new BinaryReader(stream);
				
				_rowOffset = reader.ReadUInt32();

				int noffsets = (int)(stream.Length - stream.Position) / 2;
				_streamOffsets = new ushort[noffsets];
				noffsets = 0;
				while(stream.Position < stream.Length)
					_streamOffsets[noffsets++] = reader.ReadUInt16();

				Debug.Assert(stream.Position == stream.Length);
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.DbCell);
		}
Пример #36
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the MULRK record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public MulRkRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.MulRk)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                reader = ReadRowColInfo(reader);

                _values = new RkRec[reader.BaseStream.Length / 6];
                for (int n = 0; n < _values.Length; ++n)
                {
                    ushort xf = reader.ReadUInt16();
                    int    rk = reader.ReadInt32();
                    _values[n] = new RkRec(xf, rk);
                }
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.MulRk);
            }
        }
Пример #37
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the FONT record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public FontRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.Font)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				_fontHeight = reader.ReadUInt16();
				_options = (FontOptions)reader.ReadUInt16();
				_colorIdx = reader.ReadUInt16();
				_boldness = new FontBoldness(reader.ReadUInt16());
				_escapement = (FontEscape)reader.ReadUInt16();
				_underline = (FontUnderline)reader.ReadByte();
				_fontFamily = (FontFamily)reader.ReadByte();
				_characterSet = (FontCharacterSet)reader.ReadByte();
				/* byte reserved = */ reader.ReadByte();
				byte len = reader.ReadByte();
				_fontName = Reader.ReadComplexString(reader, len);
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Font);
		}
Пример #38
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the INDEX record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public IndexRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.Index)
			{
				Stream stream = biff.GetDataStream();
				BinaryReader reader = new BinaryReader(stream);

				/* uint reserved = */ reader.ReadUInt32();
				_firstRow = reader.ReadUInt32();
				_lastRow = reader.ReadUInt32();
				/* reserved = */ reader.ReadUInt32();

				int nrows = (int)(stream.Length - stream.Position) / 4; 
				_rows = new uint[nrows];
				nrows = 0;
				while(stream.Position < stream.Length)
					_rows[nrows++] = reader.ReadUInt32();

				Debug.Assert(stream.Position == stream.Length);
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Index);
		}
Пример #39
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the FONT record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public FontRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Font)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                _fontHeight   = reader.ReadUInt16();
                _options      = (FontOptions)reader.ReadUInt16();
                _colorIdx     = reader.ReadUInt16();
                _boldness     = new FontBoldness(reader.ReadUInt16());
                _escapement   = (FontEscape)reader.ReadUInt16();
                _underline    = (FontUnderline)reader.ReadByte();
                _fontFamily   = (FontFamily)reader.ReadByte();
                _characterSet = (FontCharacterSet)reader.ReadByte();
                byte reserved = reader.ReadByte();
                byte len      = reader.ReadByte();
                _fontName = Reader.ReadComplexString(reader, len);
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Font);
            }
        }
Пример #40
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the FORMULA record.</param>
        /// <param name="recordsStream">The stream into the records to which the FORMULA record belongs to. The record stream must be positioned just after the FORMULA record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public FormulaRecord(GenericBiff biff, Stream recordsStream)
        {
            if (biff.Id == (ushort)RecordType.Formula)
            {
                Stream       stream = biff.GetDataStream();
                BinaryReader reader = new BinaryReader(stream);

                ReadRowColXf(reader);
                FormulaValue val = new FormulaValue(reader.ReadDouble());

                _options     = reader.ReadUInt16();
                _reserved    = reader.ReadUInt32();
                _formulaLen  = reader.ReadUInt16();
                _formulaData = reader.ReadBytes((int)(stream.Length - stream.Position));

                if (val.StringFollows)
                {
                    GenericBiff r = new GenericBiff(recordsStream);
                    while (r.Id != (ushort)RecordType.String)
                    {
                        r = new GenericBiff(recordsStream);
                    }

                    StringValueRecord stringValue = new StringValueRecord(r);
                    _value = stringValue.Value;
                }
                else
                {
                    _value = val.Value;
                }
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Formula);
            }
        }
Пример #41
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the DBCELL record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public DbCellRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.DbCell)
            {
                Stream       stream = biff.GetDataStream();
                BinaryReader reader = new BinaryReader(stream);

                _rowOffset = reader.ReadUInt32();

                int noffsets = (int)(stream.Length - stream.Position) / 2;
                _streamOffsets = new ushort[noffsets];
                noffsets       = 0;
                while (stream.Position < stream.Length)
                {
                    _streamOffsets[noffsets++] = reader.ReadUInt16();
                }

                Debug.Assert(stream.Position == stream.Length);
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.DbCell);
            }
        }
Пример #42
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the SST record.</param>
		/// <param name="recordStream">The stream into the records to which the SST record belongs to. The record stream must be positioned just after the SST record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public SstRecord(GenericBiff biff, Stream recordStream)
		{
			if(biff.Id == (ushort)RecordType.Sst)
			{
				Stream stream = biff.GetDataStream();
				BinaryReader reader = new BinaryReader(stream);
				/* uint totalStrings = */ reader.ReadUInt32();
				uint totalUniqueStrings = reader.ReadUInt32();

				_strings = new string[totalUniqueStrings];
				StringBuilder sb = new StringBuilder();
				for(int i = 0; i < totalUniqueStrings; ++i)
				{
					if(stream.Position >= stream.Length)
					{
						ContinueRecord cont = ReadContinue(recordStream);
						stream = cont.GetDataStream();
						reader = new BinaryReader(stream);
					}

					ushort len = reader.ReadUInt16();
					byte options = reader.ReadByte();
					bool compressed = (options & 0x01) == 0;
					bool farEast = (options & 0x04) != 0;
					bool richText = (options & 0x08) != 0;
					ushort rtSize = 0;
					uint farEastSize = 0;

					if(richText)
						rtSize = reader.ReadUInt16();
					if(farEast)
						farEastSize = reader.ReadUInt32();
		
					sb.Length = 0;
					sb.EnsureCapacity(len);
					for(ushort n = 0; n < len; ++n)
					{
						if(stream.Position >= stream.Length)
						{
							ContinueRecord cont = ReadContinue(recordStream);
							stream = cont.GetDataStream();
							reader = new BinaryReader(stream);
							compressed = (reader.ReadByte() & 0x01) == 0;
						}

						if(compressed)
							sb.Append(Convert.ToChar(reader.ReadByte()));
						else
							sb.Append(Convert.ToChar(reader.ReadUInt16()));
					}
					Debug.Assert(sb.Length == len);
					_strings[i] = sb.ToString();

					long skip = (rtSize * 4) + farEastSize;

					while(skip > 0)
					{
						if(stream.Position >= stream.Length)
						{
							ContinueRecord cont = ReadContinue(recordStream);
							stream = cont.GetDataStream();
							reader = new BinaryReader(stream);
						}

						long actualSkip = Math.Min(stream.Length - stream.Position, skip);

						stream.Seek(actualSkip, SeekOrigin.Current);

						skip -= actualSkip;
					}					
				}
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Sst);
		}
Пример #43
0
		/// <summary>
		/// The constructor for the record.
		/// </summary>
		/// <param name="biff">The GenericBiff record that should contain the correct type and data for the HLINK record.</param>
		/// <exception cref="InvalidRecordIdException">
		/// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
		/// </exception>
		public HyperLinkRecord(GenericBiff biff)
		{
			if(biff.Id == (ushort)RecordType.Hyperlink)
			{
				BinaryReader reader = new BinaryReader(biff.GetDataStream());

				_firstRow = reader.ReadUInt16();
				_lastRow = reader.ReadUInt16();
				_firstCol = reader.ReadUInt16();
				_lastCol = reader.ReadUInt16();

				_guid = reader.ReadBytes(16);

				/* uint unknown = */ reader.ReadUInt32();

				_options = new HyperLinkOptions(reader.ReadUInt32());

				if(_options.HasDescription)
				{
					_description = Reader.ReadSimpleUnicodeString(reader);
				}

				if(_options.HasTargetFrame)
				{
					_targetFrame = Reader.ReadSimpleUnicodeString(reader);
				}

				if(_options.HasFileLinkOrUrl)
				{
					_monikerGuid = reader.ReadBytes(16);

					if(IsUrlMoniker(_monikerGuid))
					{
						_link = Reader.ReadSimpleUnicodeString(reader);
					}
					else if(IsFileMoniker(_monikerGuid))
					{
						if(_options.HasUNCPath)
						{
							_link = Reader.ReadSimpleUnicodeString(reader);
						}
						else
						{
							/* int uplevelCount = */ reader.ReadUInt16();

							int shortFileLen = reader.ReadInt32();

							string shortFile = Reader.ReadSimpleAsciiString(reader, shortFileLen);

							/* byte[] unknownBytes = */ reader.ReadBytes(24);

							int fileLinkLen = reader.ReadInt32();

							if(fileLinkLen > 0)
							{
								int extendedFileLen = reader.ReadInt32();

								/* byte[] unknownBytes2 = */ reader.ReadBytes(2);

								string extendedFile = Reader.ReadSimpleUnicodeString(reader, extendedFileLen);

								_link = extendedFile;
							}
							else
								_link = shortFile;
						}
					}
				}

				if(_options.HasTextMark)
				{
                    try
                    {
                        _textMark = Reader.ReadSimpleUnicodeString(reader);
                    }
                    catch
                    {
                    }
				}
			}
			else
				throw new InvalidRecordIdException(biff.Id, RecordType.Hyperlink);
		}
Пример #44
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the HLINK record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public HyperLinkRecord(GenericBiff biff)
        {
            if (biff.Id == (ushort)RecordType.Hyperlink)
            {
                BinaryReader reader = new BinaryReader(biff.GetDataStream());

                _firstRow = reader.ReadUInt16();
                _lastRow  = reader.ReadUInt16();
                _firstCol = reader.ReadUInt16();
                _lastCol  = reader.ReadUInt16();

                _guid = reader.ReadBytes(16);

                uint unknown = reader.ReadUInt32();

                _options = new HyperLinkOptions(reader.ReadUInt32());

                if (_options.HasDescription)
                {
                    _description = Reader.ReadSimpleUnicodeString(reader);
                }

                if (_options.HasTargetFrame)
                {
                    _targetFrame = Reader.ReadSimpleUnicodeString(reader);
                }

                if (_options.HasFileLinkOrUrl)
                {
                    _monikerGuid = reader.ReadBytes(16);

                    if (IsUrlMoniker(_monikerGuid))
                    {
                        _link = Reader.ReadSimpleUnicodeString(reader);
                    }
                    else if (IsFileMoniker(_monikerGuid))
                    {
                        if (_options.HasUNCPath)
                        {
                            _link = Reader.ReadSimpleUnicodeString(reader);
                        }
                        else
                        {
                            int uplevelCount = reader.ReadUInt16();

                            int shortFileLen = reader.ReadInt32();

                            string shortFile = Reader.ReadSimpleAsciiString(reader, shortFileLen);

                            byte[] unknownBytes = reader.ReadBytes(24);

                            int fileLinkLen = reader.ReadInt32();

                            if (fileLinkLen > 0)
                            {
                                int extendedFileLen = reader.ReadInt32();

                                byte[] unknownBytes2 = reader.ReadBytes(2);

                                string extendedFile = Reader.ReadSimpleUnicodeString(reader, extendedFileLen);

                                _link = extendedFile;
                            }
                            else
                            {
                                _link = shortFile;
                            }
                        }
                    }
                }

                if (_options.HasTextMark)
                {
                    try
                    {
                        _textMark = Reader.ReadSimpleUnicodeString(reader);
                    }
                    catch
                    {
                    }
                }
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Hyperlink);
            }
        }
Пример #45
0
        /// <summary>
        /// The constructor for the record.
        /// </summary>
        /// <param name="biff">The GenericBiff record that should contain the correct type and data for the SST record.</param>
        /// <param name="recordStream">The stream into the records to which the SST record belongs to. The record stream must be positioned just after the SST record.</param>
        /// <exception cref="InvalidRecordIdException">
        /// An InvalidRecordIdException is thrown if biff contains an invalid type or invalid data.
        /// </exception>
        public SstRecord(GenericBiff biff, Stream recordStream)
        {
            if (biff.Id == (ushort)RecordType.Sst)
            {
                Stream       stream = biff.GetDataStream();
                BinaryReader reader = new BinaryReader(stream);
                /* uint totalStrings = */ reader.ReadUInt32();
                uint totalUniqueStrings = reader.ReadUInt32();

                _strings = new string[totalUniqueStrings];
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < totalUniqueStrings; ++i)
                {
                    if (stream.Position >= stream.Length)
                    {
                        ContinueRecord cont = ReadContinue(recordStream);
                        stream = cont.GetDataStream();
                        reader = new BinaryReader(stream);
                    }

                    ushort len         = reader.ReadUInt16();
                    byte   options     = reader.ReadByte();
                    bool   compressed  = (options & 0x01) == 0;
                    bool   farEast     = (options & 0x04) != 0;
                    bool   richText    = (options & 0x08) != 0;
                    ushort rtSize      = 0;
                    uint   farEastSize = 0;

                    if (richText)
                    {
                        rtSize = reader.ReadUInt16();
                    }
                    if (farEast)
                    {
                        farEastSize = reader.ReadUInt32();
                    }

                    sb.Length = 0;
                    sb.EnsureCapacity(len);
                    for (ushort n = 0; n < len; ++n)
                    {
                        if (stream.Position >= stream.Length)
                        {
                            ContinueRecord cont = ReadContinue(recordStream);
                            stream     = cont.GetDataStream();
                            reader     = new BinaryReader(stream);
                            compressed = (reader.ReadByte() & 0x01) == 0;
                        }

                        if (compressed)
                        {
                            sb.Append(Convert.ToChar(reader.ReadByte()));
                        }
                        else
                        {
                            sb.Append(Convert.ToChar(reader.ReadUInt16()));
                        }
                    }
                    Debug.Assert(sb.Length == len);
                    _strings[i] = sb.ToString();

                    long skip = (rtSize * 4) + farEastSize;

                    while (skip > 0)
                    {
                        if (stream.Position >= stream.Length)
                        {
                            ContinueRecord cont = ReadContinue(recordStream);
                            stream = cont.GetDataStream();
                            reader = new BinaryReader(stream);
                        }

                        long actualSkip = Math.Min(stream.Length - stream.Position, skip);

                        stream.Seek(actualSkip, SeekOrigin.Current);

                        skip -= actualSkip;
                    }
                }
            }
            else
            {
                throw new InvalidRecordIdException(biff.Id, RecordType.Sst);
            }
        }