Delphi TQuery 保存到 csv 文件

发布于 2024-11-01 23:33:40 字数 236 浏览 1 评论 0原文

我想将 TQuery 的内容导出到 CSV 文件,而不使用 3d 部件组件(Delphi 7)。据我所知,这不能用 Delphi 标准组件来完成。

我的解决方案是将内容保存在 CSV 格式的 StringList 中,并将其保存到文件中。

有什么舒服的解决办法吗?

PS:我不想使用 JvCsvDataSet 或任何组件。问题是:这只能用Delphi 7或更高标准的组件来完成吗?

先感谢您!

I want to export content of a TQuery to a CSV file without using a 3d part component(Delphi 7). From my knowledge this can not be accomplished with Delphi standard components.

My solution was to save the content in a StringList with a CSV format, and save it to a file.

Is there any comfortable solution?

PS:I don't want to use JvCsvDataSet or any component. Question is: can this be accomplished only with Delphi 7 or higher standard components?

Thank you in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

回心转意 2024-11-08 23:33:40

当然可以。

您只需完成正确输出 CSV 内容的工作(正确引用、处理嵌入的引号和逗号等)。您可以使用 TFileStream 轻松编写输出,并正确使用 TQuery.FieldsTQuery.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;

Of course it can.

You just have to do the work to properly output the CSV content (quoting properly, handling embedded quotes and commas, etc.). You can easily write the output using TFileStream, and get the data using the TQuery.Fields and TQuery.FieldCount properly.

I'll leave the fancy CSV quoting and special handling to you. This will take care of the easy part:

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;
不一样的天空 2024-11-08 23:33:40

最初的问题要求使用 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;

您可以添加选项来更改分隔符类型或其他内容。

The original question asked for a solution using a StringList. So it would be something more like this. It will work with any TDataSet, not just a 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;

You can add options to change the delimiter type or whatever.

如此安好 2024-11-08 23:33:40

这类似于 Rob McDonell 解决方案,但有一些增强功能:标头、转义字符、仅在需要时才包含以及“;”分隔符。
如果不需要,您可以轻松禁用此增强功能。

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;

This is like the Rob McDonell solution but with some enhancements: header, escape chars, enclosure only when required, and ";" separator.
You can easily disable this enhancements if not required.

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;
吃→可爱长大的 2024-11-08 23:33:40

Delphi 不提供对 .csv 数据的任何内置访问。
然而,按照 VCL TXMLTransform 范例,我编写了一个 TCsvTransform 类帮助器,它将 .csv 结构转换为 TClientDataSet 或从 TClientDataSet 转换。
至于最初的问题是将 TQuery 导出到 .csv,一个简单的 TDataSetProvider 将在 TQuery 和 TClientDataSet 之间建立链接。
有关 TCsvTransform 的更多详细信息,请参见 http://didier.cabale.free.fr/delphi。 htm#uCsvTransform

Delphi does not provide any built-in access to .csv data.
However, following the VCL TXMLTransform paradigm, I wrote a TCsvTransform class helper that will translate a .csv structure to /from a TClientDataSet.
As for the initial question that was to export a TQuery to .csv, a simple TDataSetProvider will make the link between TQuery and TClientDataSet.
For more details about TCsvTransform, cf http://didier.cabale.free.fr/delphi.htm#uCsvTransform

郁金香雨 2024-11-08 23:33:40

很抱歉回答一个七年前的问题,但如果有人偶然发现它(就像我一样)并且不想实现和维护自己的 CSV 编写器,下面的代码演示了如何使用 FireDAC 组件(自 Delphi 起就安装了 FireDAC 组件) 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;

Sorry to reply to a seven year old question but if anyone stumbles upon it (as I did) and doesn't want to implement and maintain their own CSV writer, the following code demonstrates how to use FireDAC components (which come installed with Delphi since XE5) to save a dataset to CSV in just a few basic steps:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文