You've already forked lazarus-ccr
fpspreadsheet: Fix writing rich-text to xlsx (Error when Excel opens this file). Fix writing multiline cell texts containing a CR as line ending which is not accepted by xls.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4226 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@@ -52,7 +52,7 @@ function WordLEtoN(AValue: Word): Word;
|
|||||||
function DWordLEtoN(AValue: Cardinal): Cardinal;
|
function DWordLEtoN(AValue: Cardinal): Cardinal;
|
||||||
function WideStringLEToN(const AValue: WideString): WideString;
|
function WideStringLEToN(const AValue: WideString): WideString;
|
||||||
|
|
||||||
// Other routines
|
// Cell, column and row strings
|
||||||
function ParseIntervalString(const AStr: string;
|
function ParseIntervalString(const AStr: string;
|
||||||
out AFirstCellRow, AFirstCellCol, ACount: Cardinal;
|
out AFirstCellRow, AFirstCellCol, ACount: Cardinal;
|
||||||
out ADirection: TsSelectionDirection): Boolean;
|
out ADirection: TsSelectionDirection): Boolean;
|
||||||
@@ -1534,6 +1534,7 @@ begin
|
|||||||
'"': Result := Result + '"';
|
'"': Result := Result + '"';
|
||||||
'''':Result := Result + ''';
|
'''':Result := Result + ''';
|
||||||
'%': Result := Result + '%';
|
'%': Result := Result + '%';
|
||||||
|
{ this breaks multi-line labels in xlsx
|
||||||
#10: begin
|
#10: begin
|
||||||
Result := Result + '<br />';
|
Result := Result + '<br />';
|
||||||
if (idx < Length(AText)) and (AText[idx+1] = #13) then inc(idx);
|
if (idx < Length(AText)) and (AText[idx+1] = #13) then inc(idx);
|
||||||
@@ -1542,6 +1543,7 @@ begin
|
|||||||
Result := Result + '<br />';
|
Result := Result + '<br />';
|
||||||
if (idx < Length(AText)) and (AText[idx+1] = #10) then inc(idx);
|
if (idx < Length(AText)) and (AText[idx+1] = #10) then inc(idx);
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
#10: WrkStr := WrkStr + ' ';
|
#10: WrkStr := WrkStr + ' ';
|
||||||
#13: WrkStr := WrkStr + ' ';
|
#13: WrkStr := WrkStr + ' ';
|
||||||
|
@@ -1836,7 +1836,7 @@ begin
|
|||||||
|
|
||||||
if AValue = '' then Exit; // Writing an empty text doesn't work
|
if AValue = '' then Exit; // Writing an empty text doesn't work
|
||||||
|
|
||||||
AnsiText := UTF8ToISO_8859_1(AValue);
|
AnsiText := UTF8ToISO_8859_1(FixLineEnding(AValue));
|
||||||
|
|
||||||
if Length(AnsiText) > MAXBYTES then begin
|
if Length(AnsiText) > MAXBYTES then begin
|
||||||
// BIFF 5 does not support labels/text bigger than 255 chars,
|
// BIFF 5 does not support labels/text bigger than 255 chars,
|
||||||
|
@@ -1465,7 +1465,7 @@ begin
|
|||||||
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
|
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
ansiValue := ConvertEncoding(AValue, encodingUTF8, FCodePage);
|
ansiValue := ConvertEncoding(FixLineEnding(AValue), encodingUTF8, FCodePage);
|
||||||
if AnsiValue = '' then begin
|
if AnsiValue = '' then begin
|
||||||
// Bad formatted UTF8String (maybe ANSI?)
|
// Bad formatted UTF8String (maybe ANSI?)
|
||||||
if Length(AValue) <> 0 then begin
|
if Length(AValue) <> 0 then begin
|
||||||
|
@@ -141,7 +141,7 @@ type
|
|||||||
procedure WriteHyperlinks(AStream: TStream; AWorksheet: TsWorksheet);
|
procedure WriteHyperlinks(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
procedure WriteHyperlinkToolTip(AStream: TStream; const ARow, ACol: Cardinal;
|
procedure WriteHyperlinkToolTip(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
const ATooltip: String);
|
const ATooltip: String);
|
||||||
procedure WriteIndex(AStream: TStream);
|
procedure WriteINDEX(AStream: TStream);
|
||||||
procedure WriteLABEL(AStream: TStream; const ARow, ACol: Cardinal;
|
procedure WriteLABEL(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
const AValue: string; ACell: PCell); override;
|
const AValue: string; ACell: PCell); override;
|
||||||
procedure WriteMergedCells(AStream: TStream; AWorksheet: TsWorksheet);
|
procedure WriteMergedCells(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
@@ -2613,7 +2613,7 @@ end;
|
|||||||
|
|
||||||
nm = (rl - rf - 1) / 32 + 1 (using integer division)
|
nm = (rl - rf - 1) / 32 + 1 (using integer division)
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsSpreadBIFF8Writer.WriteIndex(AStream: TStream);
|
procedure TsSpreadBIFF8Writer.WriteINDEX(AStream: TStream);
|
||||||
begin
|
begin
|
||||||
{ BIFF Record header }
|
{ BIFF Record header }
|
||||||
WriteBIFFHeader(AStream, INT_EXCEL_ID_INDEX, 16);
|
WriteBIFFHeader(AStream, INT_EXCEL_ID_INDEX, 16);
|
||||||
@@ -2664,7 +2664,7 @@ begin
|
|||||||
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
|
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
WideValue := UTF8Decode(AValue); //to UTF16
|
WideValue := UTF8Decode(FixLineEnding(AValue)); //to UTF16
|
||||||
if WideValue = '' then begin
|
if WideValue = '' then begin
|
||||||
// Badly formatted UTF8String (maybe ANSI?)
|
// Badly formatted UTF8String (maybe ANSI?)
|
||||||
if Length(AValue)<>0 then begin
|
if Length(AValue)<>0 then begin
|
||||||
|
@@ -460,6 +460,7 @@ type
|
|||||||
FPalette: TsPalette;
|
FPalette: TsPalette;
|
||||||
procedure AddBuiltinNumFormats; override;
|
procedure AddBuiltinNumFormats; override;
|
||||||
function FindXFIndex(ACell: PCell): Integer; virtual;
|
function FindXFIndex(ACell: PCell): Integer; virtual;
|
||||||
|
function FixLineEnding(const AText: String): String;
|
||||||
function GetLastRowIndex(AWorksheet: TsWorksheet): Integer;
|
function GetLastRowIndex(AWorksheet: TsWorksheet): Integer;
|
||||||
function GetLastColIndex(AWorksheet: TsWorksheet): Word;
|
function GetLastColIndex(AWorksheet: TsWorksheet): Word;
|
||||||
function GetPrintOptions: Word; virtual;
|
function GetPrintOptions: Word; virtual;
|
||||||
@@ -2414,6 +2415,28 @@ begin
|
|||||||
Result := LAST_BUILTIN_XF + ACell^.FormatIndex;
|
Result := LAST_BUILTIN_XF + ACell^.FormatIndex;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
The line separator for multi-line text in label cells is accepted by xls
|
||||||
|
to be either CRLF or LF, CR does not work.
|
||||||
|
This procedure replaces accidentally used single CR characters by LF.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function TsSpreadBIFFWriter.FixLineEnding(const AText: String): String;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := AText;
|
||||||
|
if Result = '' then
|
||||||
|
exit;
|
||||||
|
// if the last character is a #13 it cannot be part of a CRLF --> replace by #10
|
||||||
|
if Result[Length(Result)] = #13 then
|
||||||
|
Result[Length(Result)] := #10;
|
||||||
|
// In the rest of the string replace all #13 (which are not followed by a #10)
|
||||||
|
// by #10.
|
||||||
|
for i:=1 to Length(Result)-1 do
|
||||||
|
if (Result[i] = #13) and (Result[i+1] <> #10) then
|
||||||
|
Result[i] := #10;
|
||||||
|
end;
|
||||||
|
|
||||||
function TsSpreadBIFFWriter.GetLastRowIndex(AWorksheet: TsWorksheet): Integer;
|
function TsSpreadBIFFWriter.GetLastRowIndex(AWorksheet: TsWorksheet): Integer;
|
||||||
begin
|
begin
|
||||||
Result := AWorksheet.GetLastRowIndex;
|
Result := AWorksheet.GetLastRowIndex;
|
||||||
|
@@ -3853,7 +3853,7 @@ begin
|
|||||||
// unformatted string
|
// unformatted string
|
||||||
AppendToStream(FSSharedStrings,
|
AppendToStream(FSSharedStrings,
|
||||||
'<si>' +
|
'<si>' +
|
||||||
'<t>' + txt + '</t>' +
|
'<t xml:space="preserve">' + txt + '</t>' +
|
||||||
'</si>')
|
'</si>')
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@@ -3868,7 +3868,7 @@ begin
|
|||||||
ValidXMLText(txt);
|
ValidXMLText(txt);
|
||||||
AppendToStream(FSSharedStrings,
|
AppendToStream(FSSharedStrings,
|
||||||
'<r>' +
|
'<r>' +
|
||||||
'<t>' + txt + '</t>' +
|
'<t xml:space="preserve">' + txt + '</t>' +
|
||||||
'</r>'
|
'</r>'
|
||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
@@ -3883,7 +3883,7 @@ begin
|
|||||||
'<r>');
|
'<r>');
|
||||||
WriteFont(FSSharedStrings, fnt, false); // <rPr> ... font data ... </rPr>
|
WriteFont(FSSharedStrings, fnt, false); // <rPr> ... font data ... </rPr>
|
||||||
AppendToStream(FSSharedStrings,
|
AppendToStream(FSSharedStrings,
|
||||||
'<t>' + txt + '</t>' +
|
'<t xml:space="preserve">' + txt + '</t>' +
|
||||||
'</r>'
|
'</r>'
|
||||||
);
|
);
|
||||||
if (rtParam.EndIndex < L) and (i = High(ACell^.RichTextParams)) then
|
if (rtParam.EndIndex < L) and (i = High(ACell^.RichTextParams)) then
|
||||||
@@ -3892,7 +3892,7 @@ begin
|
|||||||
ValidXMLText(txt);
|
ValidXMLText(txt);
|
||||||
AppendToStream(FSSharedStrings,
|
AppendToStream(FSSharedStrings,
|
||||||
'<r>' +
|
'<r>' +
|
||||||
'<t>' + txt + '</t>' +
|
'<t xml:space="preserve">' + txt + '</t>' +
|
||||||
'</r>'
|
'</r>'
|
||||||
)
|
)
|
||||||
end else
|
end else
|
||||||
@@ -3903,7 +3903,7 @@ begin
|
|||||||
ValidXMLText(txt);
|
ValidXMLText(txt);
|
||||||
AppendToStream(FSSharedStrings,
|
AppendToStream(FSSharedStrings,
|
||||||
'<r>' +
|
'<r>' +
|
||||||
'<t>' + txt + '</t>' +
|
'<t xml:space="preserve">' + txt + '</t>' +
|
||||||
'</r>'
|
'</r>'
|
||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
Reference in New Issue
Block a user