![]() |
Datenbank: Pervasive SQL • Version: 8.x-9.x • Zugriff über: ODBC
SQL-Abfrage so "direkt" wie möglich in csv-Datei s
Hallo zusammen,
nun bin ich schon eine ganze Weile am suchen... :( Ich möchte ein Progrämmchen erstellen, welches jeden Tag 2-6 mal zu einer festgelegten Uhrzeit durch den Windows Taskplaner aufgerufen werden soll. Dieses Progrämmchen soll dann aus einer Ini-Datei einen oder auch mehrere dort hinterlegte SQL-Abfrage(n) absetzen und das Ergebnis in eine csv-Datei schreiben. Pro SQL-Abfrage soll dann das Ergebnis in eine Datei an einen in der ini-Datei hinterlegten Pfad gespeichert werden. Im Prinzip soll der Benutzer davon gar nichts mitbekommen; es soll über den beschriebenen Weg völlig autom. laufen; möglichst ohne große "Umwege". Ich bin jetzt soweit, dass ich die Ergebnisse habe (im Moment in einem DBGrid), mit der ini-Datei auch alles funktioniert, aber ich nun nicht weiter weiß, wie ich die Ergebnisse in eine csv-Datei abspeichern kann. Jetzt hatte ich schon mehrere Varianten gefunden. Mein derzeitiger Favorit: - ein DBGrid (wäre eine kostenpflichtige Komponente), welche direkt SaveToFile-mäßig parametriert werden kann. Gibt es Alternativen? Also vllt. ohne den "Umweg" über ein DBGrid. Gibt es Empfehlungen für eine Komponente, welche dieses Vorhaben unterstützt? Da ich mich bis jetzt noch gar nicht mit DB beschäftigt habe, hoffe ich, dass diese Frage nicht zu trivial ist... :mrgreen: Bin für jeden Hinweis dankbar! |
Re: SQL-Abfrage so "direkt" wie möglich in csv-Dat
Ich denk eine recht geschickte Lösung wäre der Weg über Class Helper
Delphi-Quellcode:
Danach steht dir in allen TDataset Erben (TADOQuery usw.) direkt die Methode Save zur Verfügung. Du musst nicht mal casten.
TYourDataset = class helper for TDataset
public procedure Save (Filename : string) ; end; Save musst du halt nur noch implementieren, aber das sollte nicht so kompliziert sein. |
Re: SQL-Abfrage so "direkt" wie möglich in csv-Dat
Hallo, ich habe vor Jahren mal eine Unit erstellt, die die Daten eines DBGrid als *.csv exportiert. Sie ist mit einiger Sicherheit ziemlich buggy, aber vielleicht reicht es Dir ja so. Ansonsten steht es Dir (und anderen) frei, sie zu verbessern.
Delphi-Quellcode:
unit DetDBExport;
interface uses Windows, Classes, FileCtrl, SysUtils, DBGrids, DB, DBTables; procedure ExportDBGridToCSV(TheGrid: TDBGrid; ShowFieldNames: Boolean; const FileName, Trenner: string);overload; procedure ExportDBGridToCSV(TheGrid: TDBGrid; ShowFieldNames: Boolean; const FileName, Trenner: string; QuoteStrings: Boolean);overload; procedure ExportDBGridToCSV(TheGrid: TDBGrid; ShowFieldNames: Boolean; const FileName, Trenner: string; QuoteStrings: Boolean; DeleteLastLimiter: Boolean);overload; procedure ExportDBGridToCSV(TheGrid: TDBGrid; ShowFieldNames: Boolean; const FileName, Trenner: string; QuoteStrings: Boolean; DeleteLastLimiter: Boolean; ForceDestDir: Boolean);overload; procedure ExportDBGridToCSV(TheGrid: TDBGrid; ShowFieldNames: Boolean; const FileName, Trenner: string; QuoteStrings: Boolean; DeleteLastLimiter: Boolean; ForceDestDir: Boolean; AskUser: Boolean);overload; procedure ExportDBGridToXML(TheGrid: TDBGrid; const FileName, DataDescription: string); implementation function GetNiceName(const sDir: string): string; begin Result := ''; if Length(sDir) = 0 then exit; if AnsiLastChar(sDir) = '\' then Result := Copy(sDir,1,Length(sDir) - 1) else Result := sDir; end; procedure ExportDBGridToCSV(TheGrid: TDBGrid; ShowFieldNames: Boolean; const FileName, Trenner: string); var i, j: integer; Liste: TStringList; Zeile, Feld: string; begin if not(Assigned(TheGrid) and Assigned(TheGrid.DataSource)) then exit; Liste := TStringList.Create; with TheGrid.DataSource.DataSet do try First; if ShowFieldNames then begin for j := 0 to TheGrid.FieldCount - 1 do begin Feld := Fields[j].FieldName; Zeile := Zeile + Feld + Trenner; end; Liste.Add(Zeile); end; for i := 0 to RecordCount - 1 do begin Zeile := ''; for j := 0 to TheGrid.FieldCount - 1 do begin Feld := Fields[j].AsString; Zeile := Zeile + Feld + Trenner; end; Liste.Add(Zeile); Next; end; finally Liste.SaveToFile(FileName); Liste.Free; end; end; procedure ExportDBGridToCSV(TheGrid: TDBGrid; ShowFieldNames: Boolean; const FileName, Trenner: string; QuoteStrings: Boolean); var i, j: integer; Liste: TStringList; Zeile, Feld: string; begin if not(Assigned(TheGrid) and Assigned(TheGrid.DataSource)) then exit; Liste := TStringList.Create; with TheGrid.DataSource.DataSet do try First; if ShowFieldNames then begin for j := 0 to TheGrid.FieldCount - 1 do begin Feld := Fields[j].FieldName; Zeile := Zeile + Feld + Trenner; end; Liste.Add(Zeile); end; for i := 0 to RecordCount - 1 do begin Zeile := ''; for j := 0 to TheGrid.FieldCount - 1 do begin Feld := Fields[j].AsString; if QuoteStrings and (Fields[j] is TStringField) then Feld := '"' + Feld + '"'; Zeile := Zeile + Feld + Trenner; end; Liste.Add(Zeile); Next; end; finally Liste.SaveToFile(FileName); Liste.Free; end; end; procedure ExportDBGridToCSV(TheGrid: TDBGrid; ShowFieldNames: Boolean; const FileName, Trenner: string; QuoteStrings: Boolean; DeleteLastLimiter: Boolean); var i, j: integer; Liste: TStringList; Zeile, Feld: string; begin if not(Assigned(TheGrid) and Assigned(TheGrid.DataSource)) then exit; Liste := TStringList.Create; with TheGrid.DataSource.DataSet do try First; if ShowFieldNames then begin for j := 0 to TheGrid.FieldCount - 1 do begin Feld := Fields[j].FieldName; Zeile := Zeile + Feld + Trenner; end; Liste.Add(Zeile); end; for i := 0 to RecordCount - 1 do begin Zeile := ''; for j := 0 to TheGrid.FieldCount - 1 do begin Feld := Fields[j].AsString; if QuoteStrings and (Fields[j] is TStringField) then Feld := '"' + Feld + '"'; Zeile := Zeile + Feld + Trenner; end; if DeleteLastLimiter then System.Delete(Zeile,Length(Zeile) - Pred(Length(Trenner)),Length(Zeile)); Liste.Add(Zeile); Next; end; finally Liste.SaveToFile(FileName); Liste.Free; end; end; procedure ExportDBGridToCSV(TheGrid: TDBGrid; ShowFieldNames: Boolean; const FileName, Trenner: string; QuoteStrings: Boolean; DeleteLastLimiter: Boolean; ForceDestDir: Boolean); var i, j: integer; Liste: TStringList; Zeile, Feld: string; begin if not(Assigned(TheGrid) and Assigned(TheGrid.DataSource)) then exit; if not DirectoryExists(ExtractFilePath(FileName)) then begin if ForceDestDir then begin ForceDirectories(ExtractFilePath(FileName)); if not DirectoryExists(ExtractFilePath(FileName)) then begin MessageBox(0, PChar(Format('Das Verzeichnis %s konnte nicht angelegt' +#13#10+' werden.', [GetNiceName(ExtractFilePath(FileName))])), 'Fehler', MB_OK or MB_ICONERROR); exit; end; end else begin MessageBox(0, PChar(Format('Das Verzeichnis %s existiert nicht.', [GetNiceName(ExtractFilePath(FileName))])), 'Fehler', MB_OK or MB_ICONERROR); exit; end; end; Liste := TStringList.Create; with TheGrid.DataSource.DataSet do try First; if ShowFieldNames then begin for j := 0 to TheGrid.FieldCount - 1 do begin Feld := Fields[j].FieldName; Zeile := Zeile + Feld + Trenner; end; Liste.Add(Zeile); end; for i := 0 to RecordCount - 1 do begin Zeile := ''; for j := 0 to TheGrid.FieldCount - 1 do begin Feld := Fields[j].AsString; if QuoteStrings and (Fields[j] is TStringField) then Feld := '"' + Feld + '"'; Zeile := Zeile + Feld + Trenner; end; if DeleteLastLimiter then System.Delete(Zeile,Length(Zeile) - Pred(Length(Trenner)),Length(Zeile)); Liste.Add(Zeile); Next; end; finally Liste.SaveToFile(FileName); Liste.Free; end; end; procedure ExportDBGridToCSV(TheGrid: TDBGrid; ShowFieldNames: Boolean; const FileName, Trenner: string; QuoteStrings: Boolean; DeleteLastLimiter: Boolean; ForceDestDir: Boolean; AskUser: Boolean); var i, j: integer; Liste: TStringList; Zeile, Feld: string; begin if not(Assigned(TheGrid) and Assigned(TheGrid.DataSource)) then exit; if not DirectoryExists(ExtractFilePath(FileName)) then begin if (MessageBox(0, PChar(Format('Das Verzeichnis %s existiert nicht.' +#13#10+ 'Soll es angelegt werden?', [GetNiceName(ExtractFilePath(FileName))])), 'Verzeichnis nicht gefunden', MB_OKCANCEL or MB_ICONQUESTION) = idOK) and ForceDestDir then begin ForceDirectories(ExtractFilePath(FileName)); if not DirectoryExists(ExtractFilePath(FileName)) then begin MessageBox(0, PChar(Format('Das Verzeichnis %s konnte nicht' + ' angelegt werden.', [GetNiceName(ExtractFilePath(FileName))])), 'Fehler', MB_OK or MB_ICONERROR); exit; end; end else begin if not ForceDestDir then MessageBox(0, PChar(Format('Das Verzeichnis %s existiert nicht.', [GetNiceName(ExtractFilePath(FileName))])), 'Fehler', MB_OK or MB_ICONERROR); exit; end; end; Liste := TStringList.Create; with TheGrid.DataSource.DataSet do try if ShowFieldNames then begin for j := 0 to TheGrid.FieldCount - 1 do begin Feld := Fields[j].FieldName; Zeile := Zeile + Feld + Trenner; end; Liste.Add(Zeile); end; First; for i := 0 to RecordCount - 1 do begin Zeile := ''; for j := 0 to TheGrid.FieldCount - 1 do begin Feld := Fields[j].AsString; if QuoteStrings and (Fields[j] is TStringField) then Feld := '"' + Feld + '"'; Zeile := Zeile + Feld + Trenner; end; if DeleteLastLimiter then System.Delete(Zeile,Length(Zeile) - Pred(Length(Trenner)),Length(Zeile)); Liste.Add(Zeile); Next; end; finally Liste.SaveToFile(FileName); Liste.Free; end; end; procedure ExportDBGridToXML(TheGrid: TDBGrid; const FileName, DataDescription: string); var i, j: integer; Liste: TStringList; Zeile, Feld, Desc: string; begin if not(Assigned(TheGrid) and Assigned(TheGrid.DataSource)) then exit; if Length(trim(DataDescription)) < 1 then exit; Liste := TStringList.Create; Liste.Add('<?xml version="1.0" encoding="ISO-8859-1" ?>'); try Desc := TDBDataSet(TheGrid.DataSource.DataSet).DataBaseName; except Desc := 'Datensatz'; end; Liste.Add(Format('<%s>',[Desc])); with TheGrid.DataSource.DataSet do try First; for i := 0 to RecordCount - 1 do begin Liste.Add(Format(' <%s>',[DataDescription])); for j := 0 to TheGrid.FieldCount - 1 do begin Zeile := Format(' <%s>',[Fields[j].FieldName]); Feld := Fields[j].AsString; Feld := StringReplace(Feld,'&','&',[rfReplaceAll]); Feld := StringReplace(Feld,'>','>',[rfReplaceAll]); Feld := StringReplace(Feld,'<','<',[rfReplaceAll]); Feld := StringReplace(Feld,'"','"',[rfReplaceAll]); Feld := StringReplace(Feld,'''',''',[rfReplaceAll]); Zeile := Zeile + Feld + Format('</%s>',[Fields[j].FieldName]); Liste.Add(Zeile); end; Liste.Add(Format(' </%s>',[DataDescription])); Next; end; Liste.Add(Format('</%s>',[Desc])); finally Liste.SaveToFile(FileName); Liste.Free; end; end; end. |
Re: SQL-Abfrage so "direkt" wie möglich in csv-Dat
@ Jelly,
vielen Dank für deinen Hinweis! Leider verstehe ich es nicht ganz. Habe da ca. 4 Seiten über Class Helper gelesen, aber nicht so wirklich schlau draus geworden. Ich hätte dann also eine neue Methode. Und hier müsste ich Save implementieren. Save würde dann sowas sein wie in DeddyH seiner Unit? :gruebel: Wo liegen bei deinem Vorschlag die Vorteile gegenüber z.B. der Unit von DeddyH? Das ist mir halt nicht ganz klar. @ DeddyH, vielen Dank! Das hilft mir auf die Schnelle schon mal sehr viel! Ich finde, dass sieht richtig gut aus! Werde es testen und falls mir Fehler auffallen, diese hier posten. Also, vielen Dank und :thumb: Good Night! |
Re: SQL-Abfrage so "direkt" wie möglich in csv-Dat
Hab auch noch nie wirklich mit Class Helper gearbeitet, aber wie ich es verstanden hab, erweitert ein Class Helper eine bestehende Klasse, in diesem Fall TDataset.
Jeder Abkömmling von TDataset erhält damit also die in der Class Helper definierten Methoden gleich mit. Nutzt du z.B. TADOQuery, das ja auch von TDataset erbt, so kannst du dort direkt die Methoden aus deiner Class Helper Klasse aufrufen.
Delphi-Quellcode:
Du musst also keine externe Funktion deklarieren, der du dann ein Dataset als Parameter übergibst. Class Helper ist demnach etwas objektorientierter.
qry := TADOQuery.Create (Self) ;
qry.connectionstring := 'sss' ; qry.Save ('c:\test.csv') ; Würd mich interessieren, obs damit jetzt auch wirklich klappt, denn ich habs ja selbst noch nie wirklich benutzt. |
Re: SQL-Abfrage so "direkt" wie möglich in csv-Dat
Der Datenexport von einer Datenmenge in eine CSV-Datei hat zunächst mal nichts mit einem DBGrid zu tun.
Ein DBGrid dient lediglich als visuelles Steuerelement (Control) um Daten anzuzeigen. Also kann die Quelle der Daten nur ein TDataSet sein und das Ziel ist ein Stream oder eine Datei:
Delphi-Quellcode:
Es macht Sinn den eigentlichen Datenexport in einen Stream vorzunehmen. Der Export in ein File kann dann die Stream-Procedure mitbenutzen.
procedure ExportDataset2CsvStream(ds:TDataSet; stream:TStream; delimiter, quotechar:Char);
procedure ExportDataset2CsvFile(ds:TDataSet; const filename:string; delimiter, quotechar:Char); |
Re: SQL-Abfrage so "direkt" wie möglich in csv-Dat
Hallo shmia,
ich denke, dass ist genau das was ich gesucht habe (halt so direkt wie möglich). :thumb: Naja, dann muss ich mich mit dem füllen des Streams und dem eigentlichem Export aus diesem beschäftigen. Erst mal vielen Dank! Gruß Jürgen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:34 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz