diff --git a/components/fpspreadsheet/examples/other/test_write_formatting.pas b/components/fpspreadsheet/examples/other/test_write_formatting.pas index 144937c77..58879b825 100644 --- a/components/fpspreadsheet/examples/other/test_write_formatting.pas +++ b/components/fpspreadsheet/examples/other/test_write_formatting.pas @@ -170,8 +170,8 @@ begin WriteSecondWorksheet(); // Save the spreadsheet to a file - MyWorkbook.WriteToFile(MyDir + 'test3.xls', sfExcel8, False); -// MyWorkbook.WriteToFile(MyDir + 'test3.odt', sfOpenDocument, False); +// MyWorkbook.WriteToFile(MyDir + 'test3.xls', sfExcel8, False); + MyWorkbook.WriteToFile(MyDir + 'test3.odt', sfOpenDocument, False); MyWorkbook.Free; end. diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas index fcba23689..db1c847ca 100755 --- a/components/fpspreadsheet/fpsopendocument.pas +++ b/components/fpspreadsheet/fpsopendocument.pas @@ -30,7 +30,9 @@ uses Classes, SysUtils, fpszipper, {NOTE: fpszipper is the latest zipper.pp Change to standard zipper when FPC 2.4 is released. Changed by JLJR} fpspreadsheet, - xmlread, DOM, AVL_Tree,math; + xmlread, DOM, AVL_Tree, + math, + fpsutils; type @@ -632,7 +634,7 @@ begin // The row should already be the correct one FContent := FContent + ' ' + LineEnding + - ' ' + AValue + '' + LineEnding + + ' ' + UTF8TextToXMLText(AValue) + '' + LineEnding + ' ' + LineEnding; end; diff --git a/components/fpspreadsheet/fpsutils.pas b/components/fpspreadsheet/fpsutils.pas index 070abefe0..b5abf488c 100644 --- a/components/fpspreadsheet/fpsutils.pas +++ b/components/fpspreadsheet/fpsutils.pas @@ -34,6 +34,7 @@ function ParseCellRowString(const AStr: string; var AResult: Integer): Boolean; function ParseCellColString(const AStr: string; var AResult: Integer): Boolean; +function UTF8TextToXMLText(AText: ansistring): ansistring; implementation @@ -264,5 +265,42 @@ begin Result := True; end; +{In XML files some chars must be translated} +function UTF8TextToXMLText(AText: ansistring): ansistring; +var + Idx:Integer; + WrkStr, AppoSt:ansistring; +begin + WrkStr:=''; + + for Idx:=1 to Length(AText) do + begin + case AText[Idx] of + '&': begin + AppoSt:=Copy(AText, Idx, 6); + + if (Pos('&', AppoSt) = 1) or + (Pos('<', AppoSt) = 1) or + (Pos('>', AppoSt) = 1) or + (Pos('"', AppoSt) = 1) or + (Pos(''', AppoSt) = 1) then begin + //'&' is the first char of a special chat, it must not be converted + WrkStr:=WrkStr + AText[Idx]; + end else begin + WrkStr:=WrkStr + '&'; + end; + end; + '<': WrkStr:=WrkStr + '<'; + '>': WrkStr:=WrkStr + '>'; + '"': WrkStr:=WrkStr + '"'; + '''':WrkStr:=WrkStr + '''; + else + WrkStr:=WrkStr + AText[Idx]; + end; + end; + + Result:=WrkStr; +end; + end.