Delphi TQuery сохранить в CSV-файл
Я хочу экспортировать содержимое TQuery в файл CSV без использования компонента 3D-детали (Delphi 7). Насколько мне известно, это невозможно сделать с помощью стандартных компонентов Delphi.
Моим решением было сохранить контент в StringList в формате CSV и сохранить его в файл.
Есть ли удобное решение?
PS: я не хочу использовать JvCsvDataSet или любой другой компонент. Вопрос в том, может ли это быть достигнуто только с помощью Delphi 7 или более высоких стандартных компонентов?
Заранее спасибо!
5 ответов
Конечно может.
Вам просто нужно выполнить работу для правильного вывода содержимого CSV (правильное цитирование, обработка встроенных кавычек и запятых и т. Д.). Вы можете легко написать вывод, используя TFileStream
и получить данные, используя TQuery.Fields
а также TQuery.FieldCount
должным образом.
Я оставлю вам необычные цитаты из CSV и специальную обработку для вас. Это позаботится о легкой части:
var
Stream: TFileStream;
i: Integer;
OutLine: string;
sTemp: string;
begin
Stream := TFileStream.Create('C:\Data\YourFile.csv', fmCreate);
try
while not Query1.Eof do
begin
// You'll need to add your special handling here where OutLine is built
OutLine := '';
for i := 0 to Query.FieldCount - 1 do
begin
sTemp := Query.Fields[i].AsString;
// Special handling to sTemp here
OutLine := OutLine + sTemp + ',';
end;
// Remove final unnecessary ','
SetLength(OutLine, Length(OutLine) - 1);
// Write line to file
Stream.Write(OutLine[1], Length(OutLine) * SizeOf(Char));
// Write line ending
Stream.Write(sLineBreak, Length(sLineBreak));
Query1.Next;
end;
finally
Stream.Free; // Saves the file
end;
end;
В первоначальном вопросе было предложено решение с использованием StringList. Так что было бы что-то вроде этого. Он будет работать с любым TDataSet, а не только с TQuery.
procedure WriteDataSetToCSV(DataSet: TDataSet, FileName: String);
var
List: TStringList;
S: String;
I: Integer;
begin
List := TStringList.Create;
try
DataSet.First;
while not DataSet.Eof do
begin
S := '';
for I := 0 to DataSet.FieldCount - 1 do
begin
if S > '' then
S := S + ',';
S := S + '"' + DataSet.Fields[I].AsString + '"';
end;
List.Add(S);
DataSet.Next;
end;
finally
List.SaveToFile(FileName);
List.Free;
end;
end;
Вы можете добавить параметры для изменения типа разделителя или чего-либо еще.
Это похоже на решение Rob McDonell, но с некоторыми улучшениями: заголовок, escape-символы, вложение только при необходимости и ";" разделитель. Вы можете легко отключить это улучшение, если не требуется.
procedure SaveToCSV(DataSet: TDataSet; FileName: String);
const
Delimiter: Char = ';'; // In order to be automatically recognized in Microsoft Excel use ";", not ","
Enclosure: Char = '"';
var
List: TStringList;
S: String;
I: Integer;
function EscapeString(s: string): string;
var
i: Integer;
begin
Result := StringReplace(s,Enclosure,Enclosure+Enclosure,[rfReplaceAll]);
if (Pos(Delimiter,s) > 0) OR (Pos(Enclosure,s) > 0) then // Comment this line for enclosure in every fields
Result := Enclosure+Result+Enclosure;
end;
procedure AddHeader;
var
I: Integer;
begin
S := '';
for I := 0 to DataSet.FieldCount - 1 do begin
if S > '' then
S := S + Delimiter;
S := S + EscapeString(DataSet.Fields[I].FieldName);
end;
List.Add(S);
end;
procedure AddRecord;
var
I: Integer;
begin
S := '';
for I := 0 to DataSet.FieldCount - 1 do begin
if S > '' then
S := S + Delimiter;
S := S + EscapeString(DataSet.Fields[I].AsString);
end;
List.Add(S);
end;
begin
List := TStringList.Create;
try
DataSet.DisableControls;
DataSet.First;
AddHeader; // Comment if header not required
while not DataSet.Eof do begin
AddRecord;
DataSet.Next;
end;
finally
List.SaveToFile(FileName);
DataSet.First;
DataSet.EnableControls;
List.Free;
end;
end;
Delphi не предоставляет никакого встроенного доступа к данным.csv. Однако, следуя парадигме VCL TXMLTransform, я написал помощник класса TCsvTransform, который будет преобразовывать структуру.csv в / из TClientDataSet. Что касается первоначального вопроса, который заключался в экспорте TQuery в.csv, простой TDataSetProvider установит связь между TQuery и TClientDataSet. Для получения дополнительной информации о TCsvTransform, см. Http://didier.cabale.free.fr/delphi.htm#uCsvTransform
Извините, что отвечаю на вопрос семилетней давности, но если кто-то наткнется на него (как я) и не захочет реализовывать и поддерживать свой собственный модуль записи CSV, следующий код демонстрирует, как использовать компоненты FireDAC (которые устанавливаются вместе с Delphi с тех пор, как XE5), чтобы сохранить набор данных в CSV всего за несколько основных шагов:
uses
FireDAC.Comp.BatchMove,
FireDAC.Comp.BatchMove.Text,
FireDAC.Comp.BatchMove.DataSet;
procedure SaveDatasetToCSV(IncludeFieldNames : Boolean; Dataset : TDataset; Filename : String);
var
TextWriter : TFDBatchMoveTextWriter;
DataSetReader : TFDBatchMoveDataSetReader;
BatchMove : TFDBatchMove;
begin
BatchMove := nil;
try
BatchMove := TFDBatchMove.Create(nil);
TextWriter := TFDBatchMoveTextWriter.Create(BatchMove);
DataSetReader := TFDBatchMoveDataSetReader.Create(BatchMove);
DataSetReader.DataSet := Dataset;
TextWriter.FileName := Filename;
TextWriter.DataDef.WithFieldNames := IncludeFieldNames;
BatchMove.Reader := DataSetReader;
BatchMove.Writer := TextWriter;
BatchMove.Options := BatchMove.Options + [poClearDest]; //Overrides file if it already exists
BatchMove.Execute;
finally
BatchMove.Free;
end;
end;