From 04a58a17c75e70fec6a82c2a50a41eacc8f366d3 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Sat, 14 Jan 2023 21:54:41 +0000 Subject: [PATCH] fpspreadsheet: Extend TsWorksheetDataset.CopyFromDataset to support codepage conversion of the source dataset. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8678 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../source/dataset/fpsdataset.pas | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/components/fpspreadsheet/source/dataset/fpsdataset.pas b/components/fpspreadsheet/source/dataset/fpsdataset.pas index b00b7f624..278eab5c9 100644 --- a/components/fpspreadsheet/source/dataset/fpsdataset.pas +++ b/components/fpspreadsheet/source/dataset/fpsdataset.pas @@ -200,7 +200,8 @@ type procedure Clear(ClearDefs: Boolean); function CompareBookmarks(Bookmark1, Bookmark2: TBookmark): Longint; override; procedure CopyFromDataset(ADataset: TDataset; - const AWorkbookFileName, ASheetName: String); + const AWorkbookFileName, ASheetName: String; + ASourceCodePage: TSystemCodePage = CP_UTF8); function CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream; override; procedure CreateTable; procedure Flush; @@ -270,7 +271,7 @@ procedure Register; implementation uses - LazUTF8, LazUTF16, Math, TypInfo, Variants, FmtBCD, fpsNumFormat; + LazUTF8, LazUTF16, LConvEncoding, Math, TypInfo, Variants, FmtBCD, fpsNumFormat; const // This are the field types of FPC 3.3.x ftSupported = [ftString, ftSmallint, ftInteger, ftWord, ftBoolean, ftFloat, @@ -681,18 +682,44 @@ begin end; end; +function SystemCodePageToStr(ACodePage: TSystemCodePage): String; +begin + if (ACodePage = CP_UTF8) then + Result := 'utf8' + else + if (ACodePage < 1000) or ((ACodePage >= 1250) and (ACodePage <= 1258)) then + Result := 'cp' + IntToStr(ACodePage) + else + if (ACodePage >= 28591) and (ACodePage <= 28599) then + Result := 'iso88' + IntToStr(ACodePage-28000) + else + if (ACodePage >=28600) and (ACodePage <= 28605) then + Result := 'iso88561' + IntToStr(ACodePage-28600) + else + if (ACodePage = 20866) then + Result := 'koi8r' + else + if (ACodePage = 21866) then + Result := 'koi8u' + else + Result := ''; +end; + { Copies the specified dataset to the worksheet dataset: copies fielddefs as well as data. Important: In order to avoid data loss in the worksheet dataset it must be closed and FileName and SheetName must be empty; they will be set to the values passed as parameters. } procedure TsWorksheetDataset.CopyFromDataset(ADataset: TDataset; - const AWorkbookFileName, ASheetName: String); + const AWorkbookFileName, ASheetName: String; ASourceCodePage: TSystemCodePage = CP_UTF8); var i: Integer; fsrc, fdest: TField; stream: TMemoryStream; bm: TBookmark; + codepageStr: String; + s: RawByteString; + sUTF8: UTF8String; begin if Active then DatabaseError('Dataset must not be active when calling CopyFromDataset.'); @@ -701,6 +728,8 @@ begin if FSheetName <> '' then DatabaseError('SheetName must be empty when calling CopyFromDataset.'); + codepageStr := SystemCodePageToStr(ASourceCodepage); + FFileName := AWorkbookFileName; FSheetName := ASheetName; @@ -734,7 +763,7 @@ begin if not fsrc.IsNull then case fdest.DataType of ftString, ftFixedChar: - fdest.AsString := fsrc.AsString; + fdest.AsString := ConvertEncoding(fsrc.AsString, codepageStr, 'utf8'); ftWideString, ftFixedWideChar: fdest.AsWideString := fsrc.AsWideString; ftBoolean: @@ -761,6 +790,15 @@ begin begin stream.Clear; TBlobField(fsrc).SaveToStream(stream); + if (ASourceCodePage <> CP_UTF8) and (stream.Size > 0) then + begin + stream.Position := 0; + SetLength(s, stream.Size); + stream.Write(s[1], stream.Size); + sUTF8 := ConvertEncoding(s, codepageStr, 'utf8'); + stream.Clear; + stream.Read(sUTF8[1], Length(sUTF8)); + end; stream.Position := 0; TBlobField(fdest).LoadFromStream(stream); end;