diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index e7a4463ef..f5781c101 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -125,6 +125,7 @@ type const AValue: string; ACell: PCell); override; procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Cardinal; const AFormula: TsRPNFormula; ACell: PCell); override; + function WriteString_8bitLen(AStream: TStream; AString: String): Integer; override; procedure WriteStringRecord(AStream: TStream; AString: string); procedure WriteStyle(AStream: TStream); procedure WriteWindow2(AStream: TStream; ASheet: TsWorksheet); @@ -927,12 +928,16 @@ begin INT_EXCEL_TOKEN_TSTR: { fekString } begin // string constant is stored as widestring in BIFF8 + // Writing is done by the virtual method WriteString_8bitLen. + Inc(RPNLength, WriteString_8bitLen(AStream, AFormula[i].StringValue)); + { wideStr := UTF8Decode(AFormula[i].StringValue); len := Length(wideStr); AStream.WriteByte(len); // char count in 1 byte AStream.WriteByte(1); // Widestring flags, 1=regular unicode LE string AStream.WriteBuffer(WideStringToLE(wideStr)[1], len * Sizeof(WideChar)); Inc(RPNLength, 1 + 1 + len*SizeOf(WideChar)); + } end; INT_EXCEL_TOKEN_TBOOL: { fekBool } @@ -990,6 +995,24 @@ begin WriteStringRecord(AStream, ACell^.UTF8StringValue); end; +{ Helper function for writing a string with 8-bit length. Overridden version + for BIFF8. Called for writing rpn formula string tokens. + Returns the count of bytes written} +function TsSpreadBIFF8Writer.WriteString_8BitLen(AStream: TStream; + AString: String): Integer; +var + len: Integer; + wideStr: WideString; +begin + // string constant is stored as widestring in BIFF8 + wideStr := UTF8Decode(AString); + len := Length(wideStr); + AStream.WriteByte(len); // char count in 1 byte + AStream.WriteByte(1); // Widestring flags, 1=regular unicode LE string + AStream.WriteBuffer(WideStringToLE(wideStr)[1], len * Sizeof(WideChar)); + Result := 1 + 1 + len * SizeOf(WideChar); +end; + procedure TsSpreadBIFF8Writer.WriteStringRecord(AStream: TStream; AString: String); var diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index b81468d8f..8343bb41d 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -448,6 +448,8 @@ type procedure GetLastColCallback(ACell: PCell; AStream: TStream); function GetLastColIndex(AWorksheet: TsWorksheet): Word; function FormulaElementKindToExcelTokenID(AElementKind: TFEKind; out ASecondaryID: Word): Word; + // Helper function for writing a string with 8-bit length } + function WriteString_8BitLen(AStream: TStream; AString: String): Integer; virtual; // Write out BLANK cell record procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal; @@ -2141,6 +2143,23 @@ begin AStream.WriteWord(WordToLE(flags)); end; +{ Helper function for writing a string with 8-bit length. Here, we implement the + version for ansistrings since it is valid for all BIFF versions except BIFF8 + where it has to overridden. Is called for writing a string rpn token. + Returns the count of bytes written. } +function TsSpreadBIFFWriter.WriteString_8bitLen(AStream: TStream; + AString: String): Integer; +var + len: Byte; + s: ansistring; +begin + s := AString; + len := Length(s); + AStream.WriteByte(len); + AStream.WriteBuffer(s[1], len); + Result := 1 + len; +end; + { Writes an Excel 5/8 WINDOW1 record This record contains general settings for the document window and global workbook settings.