2011-04-15 168 views
10

我想將TQuery的內容導出爲CSV文件,而不使用三維零件組件(Delphi 7)。據我所知,這不能用Delphi標準組件完成。Delphi TQuery保存爲csv文件

我的解決方案是將內容保存爲CSV格式的StringList,並將其保存到文件中。

有沒有什麼舒適的解決方案?我不想使用JvCsvDataSet或其他組件。問題是:這隻能使用Delphi 7或更高版本的標準組件才能實現?

預先感謝您!

+4

編寫CSV文件發射器非常簡單。由於您無法找到內置的功能,並且由於您不需要第三方解決方案,因此您可能需要沿着這條路線走下去。 – 2011-04-15 17:05:45

+0

由於我們在談論CSV,因此有一篇關於設計模式的漂亮文章,使用CSV解析器作爲示例 - http://conferences.embarcadero.com/article/32129 – Najem 2011-04-16 17:10:28

回答

12

當然可以。

你只需要做的工作,以正確輸出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; 
+3

有關如何轉義sTemp的一些信息:http:// www.csvreader.com/csv_format.php – jachguate 2011-04-15 17:59:51

9

原始問題要求使用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; 

您可以添加選項來更改分隔符類型或其他。

1

Delphi不提供對.csv數據的任何內置訪問。 但是,遵循VCL TXMLTransform範例,我編寫了一個TCsvTransform類幫助程序,它可以將.csv結構轉換爲TClientDataSet或從TClientDataSet轉換。 至於最初的問題是將TQuery導出爲.csv,一個簡單的TDataSetProvider將使TQuery和TClientDataSet之間的鏈接成爲可能。 有關TCsvTransform詳情,CF http://didier.cabale.free.fr/delphi.htm#uCsvTransform

1

這就好比羅布麥克唐納溶液但也有一些改進:報頭,逃生字符,外殼僅在需要時,和「;」分隔器。 如果不需要,您可以輕鬆禁用此增強功能。

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;