Delphi TQuery save to csv file

后端 未结 4 2171
太阳男子
太阳男子 2021-02-08 06:44

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.

相关标签:
4条回答
  • 2021-02-08 07:30

    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;
    
    0 讨论(0)
  • 2021-02-08 07:35

    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.

    0 讨论(0)
  • 2021-02-08 07:45

    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

    0 讨论(0)
  • 2021-02-08 07:47

    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;
    
    0 讨论(0)
提交回复
热议问题