Всем привет. По своей необходимости написал юнит, который расширяет возможности TJvStringGrid так, чтобы можно было выбирать Encoding в LoadFromCSV и SaveToCSV. Может, кому полезно будет.
Код:
unit uJVStringGridMod;
interface
uses
Vcl.Graphics,
Vcl.Controls,
Vcl.Forms,
Vcl.Dialogs,
Vcl.Grids,
JvExGrids,
System.Classes,
System.SysUtils,
JvStringGrid;
type
// Запиливаем настройку кодировки
TJvStringGridMod = class(TJvStringGrid)
public
procedure LoadFromCSV(const FileName: string{$IFDEF UNICODE};
Encoding: TEncoding{$ENDIF}; Separator: Char = ';'; QuoteChar: Char = '"';
StripQuotes: Boolean = True);
procedure SaveToCSV(const FileName: string{$IFDEF UNICODE};
Encoding: TEncoding{$ENDIF}; Separator: Char = ';'; QuoteChar: Char = '"');
end;
implementation
procedure TJvStringGridMod.LoadFromCSV(const FileName: string{$IFDEF UNICODE};
Encoding: TEncoding{$ENDIF}; Separator: Char = ';'; QuoteChar: Char = '"';
StripQuotes: Boolean = True);
var
I: Longint;
Lines, Fields: TStringList;
procedure SplitLine(const Line: string; Result: TStrings;
Delimiter, QuoteChar: Char; StripQuotes: Boolean);
var
I, SLen, QuoteCount: Integer;
S: string;
IgnoreDelim: Boolean;
QuotedStr: PChar;
begin
S := '';
SLen := Length(Line);
IgnoreDelim := False;
QuoteCount := 0;
Result.Clear;
for I := 1 to SLen do
begin
if Line[I] = QuoteChar then
begin
Inc(QuoteCount);
{ * A Delimiter surrounded by a pair of QuoteChar has to be ignored.
See example above: "FirstName, LastName"
therefor: * }
IgnoreDelim := QuoteCount mod 2 <> 0;
end;
if IgnoreDelim then
S := S + Line[I]
else if Line[I] <> Delimiter then
S := S + Line[I]
else
begin
if S <> '' then
begin
if StripQuotes and (S[1] = QuoteChar) then
begin
QuotedStr := PChar(S);
Result.Add(AnsiExtractQuotedStr(QuotedStr, QuoteChar));
end
else
Result.Add(S);
end
else
Result.Add(S);
S := '';
end;
end;
if S <> '' then
begin
if StripQuotes and (S[1] = QuoteChar) then
begin
QuotedStr := PChar(S);
Result.Add(AnsiExtractQuotedStr(QuotedStr, QuoteChar));
end
else
Result.Add(S);
end
else
Result.Add(S);
end;
begin
Lines := TStringList.Create;
Fields := TStringList.Create;
try
Lines.LoadFromFile(FileName{$IFDEF UNICODE}, Encoding{$ENDIF});
DoLoadProgress(0, Lines.Count);
RowCount := Lines.Count;
ColCount := FixedCols + 1;
for I := 0 to Lines.Count - 1 do
begin
{ * added John * }
SplitLine(Lines[I], Fields, Separator, QuoteChar, StripQuotes);
DoLoadProgress(I, Lines.Count);
if Fields.Count > ColCount then
ColCount := Fields.Count;
Rows[I].Assign(Fields);
end;
DoLoadProgress(Lines.Count, Lines.Count);
finally
Fields.Free;
Lines.Free;
end;
end;
procedure TJvStringGridMod.SaveToCSV(const FileName: string{$IFDEF UNICODE};
Encoding: TEncoding{$ENDIF}; Separator: Char = ';'; QuoteChar: Char = '"');
var
I, J: Longint;
BufStr, Value: string;
Lines: TStringList;
begin
Lines := TStringList.Create;
DoSaveProgress(0, RowCount);
try
Lines.Clear;
for I := 0 to RowCount - 1 do
begin
BufStr := '';
DoSaveProgress(I, RowCount);
for J := 0 to ColCount - 1 do
begin
Value := Cells[J, I];
if Pos(Separator, Value) > 0 then
Value := AnsiQuotedStr(Value, QuoteChar);
BufStr := BufStr + Value;
if J <> (ColCount - 1) then
BufStr := BufStr + Separator;
end;
Lines.Add(BufStr);
end;
DoSaveProgress(RowCount, RowCount);
Lines.SaveToFile(FileName{$IFDEF UNICODE}, Encoding{$ENDIF});
finally
Lines.Free;
end;
end;
end.
По аналогии можно сделать так и с другими компонентами, которые имеют функцию LoadFromCSV/SaveToCSV.