![]() |
Datenbank: delphi • Version: 5 • Zugriff über: ODBC
geöffnete CSV bearbeiten
Hallo zusammen,
Ich habe mal eine Frage zur Überprüfung von CSV-Dateien. Ich würde gerne eine geöffnete CSV-Datei nach bestimmten Kriterien (z.B. Parameterfolge '1234') zeilenweise untersuchen. Wird in einer Zeile diese Parameterfolge nicht erfüllt, so soll eine Fehlermeldung in Form einer Liste mit entsprechenden Zeilennummern ausgegeben werden. Vielleicht habt Ihr ja eine Idee, wie man das am Besten realisieren kann. Hier ist erstmal der vorläufige Quellcode:
Delphi-Quellcode:
unit MainUnit;
interface {$ifdef VER140} {$define DELPHI6_UP} {$endif} {$ifdef VER150} {$define DELPHI6_UP} {$endif} {$ifdef VER160} {$define DELPHI6_UP} {$endif} {$ifdef VER170} {$define DELPHI6_UP} {$endif} {$ifdef VER180} {$define DELPHI6_UP} {$define BDS2006_UP} {$endif} uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TMainForm = class(TForm) TopPanel: TPanel; lbxRecords: TListBox; Splitter: TSplitter; lbxFields: TListBox; Label1: TLabel; FileEdit: TEdit; btnPickFile: TButton; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; stLineNo: TStaticText; stLineCount: TStaticText; stFieldCount: TStaticText; stFieldNo: TStaticText; gbParsing: TGroupBox; rbCustom: TRadioButton; rbCommaText: TRadioButton; rbDelimitedText: TRadioButton; Label6: TLabel; DelimEdit: TEdit; Label7: TLabel; QuoteEdit: TEdit; btnOpen: TButton; OpenDialog: TOpenDialog; NewlineEdit: TEdit; Label8: TLabel; cbEatWhitespace: TCheckBox; cbStrictDelimiter: TCheckBox; procedure btnPickFileClick(Sender: TObject); procedure btnOpenClick(Sender: TObject); procedure lbxRecordsClick(Sender: TObject); procedure lbxFieldsClick(Sender: TObject); procedure FormShow(Sender: TObject); private { Private declarations } FDelim: String; FQuote: String; FNewline: String; procedure ResetDisplay; procedure ParseRecord; procedure UpdateFieldNo; function OptionToText(S: String): String; function TextToOption(S: String): String; public { Public declarations } published procedure ParseOptionChange(Sender: TObject); end; var MainForm: TMainForm; implementation {$R *.dfm} uses llCSV; function TMainForm.OptionToText(S: String): String; var i: Integer; begin Result := S; if (Length(S) = 1) then begin i := Ord(S[1]); if (i < 32) or (i > 127) then Result := Format('%.3d', [i]); end; end; function TMainForm.TextToOption(S: String): String; var i: Integer; begin Result := S; if Length(S) = 3 then begin i := StrToIntDef(S, 0); if (i mod 256 = i) and (Format('%.3d', [i]) = S) then Result := Chr(i); end; end; procedure TMainForm.FormShow(Sender: TObject); begin {$ifndef DELPHI6_UP} rbDelimitedText.Enabled := False; {$endif} {$ifdef BDS2006_UP} cbStrictDelimiter.Enabled := not rbCustom.Checked; cbStrictDelimiter.Checked := lbxFields.Items.StrictDelimiter; {$else} cbStrictDelimiter.Enabled := False; {$endif} ResetDisplay; DelimEdit.Text := OptionToText(DefaultDelim); QuoteEdit.Text := OptionToText(DefaultQuote); NewlineEdit.Text := OptionToText(DefaultNewline); // Associate me with CSV files if you don't have Excel! if ParamCount > 0 then begin FileEdit.Text := ParamStr(1); btnOpenClick(Sender); end; end; procedure TMainForm.ResetDisplay; begin lbxRecords.Clear; lbxFields.Items.Text := 'Copyright ©2007 Ray Marron - www.raymarron.com'; stLineCount.Caption := '-'; stLineNo.Caption := '-'; stFieldCount.Caption := '-'; stFieldNo.Caption := '-'; stFieldCount.Color := clBtnFace; end; procedure TMainForm.btnPickFileClick(Sender: TObject); begin if FileEdit.Text <> '' then OpenDialog.InitialDir := ExtractFileDir(FileEdit.Text); if OpenDialog.Execute then begin FileEdit.Text := OpenDialog.FileName; btnOpenClick(Sender); end; end; procedure TMainForm.btnOpenClick(Sender: TObject); begin ResetDisplay; if FileEdit.Text = '' then Exit; if not FileExists(FileEdit.Text) then begin ShowMessage('File not found: ' + FileEdit.Text); Exit; end; lbxRecords.Items.LoadFromFile(FileEdit.Text); stLineCount.Caption := IntToStr(lbxRecords.Items.Count); if lbxRecords.Items.Count > 0 then begin lbxRecords.ItemIndex := 0; ParseOptionChange(Sender); end; end; procedure TMainForm.lbxRecordsClick(Sender: TObject); begin ParseRecord; end; procedure TMainForm.UpdateFieldNo; begin if lbxFields.ItemIndex >= 0 then stFieldNo.Caption := Format('%d (%d)', [lbxFields.ItemIndex + 1, Length(lbxFields.Items[lbxFields.ItemIndex])]) else stFieldNo.Caption := '-'; end; procedure TMainForm.lbxFieldsClick(Sender: TObject); begin UpdateFieldNo; end; procedure TMainForm.ParseOptionChange(Sender: TObject); begin DelimEdit.Enabled := not rbCommaText.Checked; QuoteEdit.Enabled := not rbCommaText.Checked; NewlineEdit.Enabled := rbCustom.Checked; cbEatWhitespace.Enabled := rbCustom.Checked; if DelimEdit.Text = '' then DelimEdit.Text := OptionToText(DefaultDelim); FDelim := TextToOption(DelimEdit.Text)[1]; if QuoteEdit.Text = '' then QuoteEdit.Text := OptionToText(DefaultQuote); FQuote := TextToOption(QuoteEdit.Text)[1]; if NewlineEdit.Text = '' then NewlineEdit.Text := OptionToText(DefaultNewline); FNewline := TextToOption(NewlineEdit.Text); {$ifdef DELPHI6_UP} lbxFields.Items.Delimiter := FDelim[1]; lbxFields.Items.QuoteChar := FQuote[1]; {$endif} {$ifdef BDS2006_UP} cbStrictDelimiter.Enabled := not rbCustom.Checked; lbxFields.Items.StrictDelimiter := cbStrictDelimiter.Checked; {$endif} ParseRecord; end; procedure TMainForm.ParseRecord; var i: Integer; MultiLine, GoodData: Boolean; begin stLineNo.Color := clBtnFace; stFieldCount.Color := clBtnFace; lbxFields.Items.BeginUpdate; try lbxFields.Items.Clear; i := lbxRecords.ItemIndex; if i < 0 then begin stFieldCount.Caption := '-'; stFieldNo.Caption := '-'; Exit; end; stLineNo.Caption := Format('%d (%d)', [i + 1, Length(lbxRecords.Items[i])]); if rbCustom.Checked then begin GoodData := True; MultiLine := False; repeat if not ParseCSVLine(lbxRecords.Items[i], lbxFields.Items, MultiLine, FQuote[1], FDelim[1], FNewline, cbEatWhitespace.Checked) then GoodData := False; Inc(i); if MultiLine then stLineNo.Color := clYellow; // Indicate a multi-line record with color until (not MultiLine) or (i = lbxRecords.Items.Count); if MultiLine or not GoodData then // If MultiLine is still true, we ran out of data! stFieldCount.Color := clRed; // Indicate bad data with color end else if rbCommaText.Checked then begin lbxFields.Items.CommaText := lbxRecords.Items[i]; {$ifdef DELPHI6_UP} end else if rbDelimitedText.Checked then begin lbxFields.Items.DelimitedText := lbxRecords.Items[i]; {$endif} end; if lbxFields.Items.Count > 0 then lbxFields.ItemIndex := 0; finally lbxFields.Items.EndUpdate; end; stFieldCount.Caption := IntToStr(lbxFields.Items.Count); UpdateFieldNo; end; end. Vielen Dank schon einmal im voraus für alle konstruktiven Vorschläge. |
Re: geöffnete CSV bearbeiten
Vielleicht wäre der Einsatz eines CSV-Dataset sinnvoll
|
Re: geöffnete CSV bearbeiten
standardmässig öffnet delphi auch TP bei einen reset mit dem filemode 02 (read und write). wenn du ein CSV, welches bereits geöffnet ist, noch mal öffnen möchtest, musst du den filemode vor dem öffnen auf read OF_READ (= 0; definiert in der unit windows) setzen. dann sollte es klappen.
grüss und noch viel erfolg. gg |
Re: geöffnete CSV bearbeiten
Danke erstmal für Eure Antworten.
CSV-Dataset ist mir eher unbekannt, daher versuche ich das Problem mit Hilfe von TStringGrid anstatt mit 'ListBox' zu lösen. Dann lassen sich vielleicht die einzelnen Zellkoordinaten besser miteinander vergleichen, überprüfen und zusammenfassend auswerten. Die Frage ist nur, wie ich eines der StringGrid-Fenster als .txt - Datei abspeichern kann. :wall: Wenn sonst noch jemanden etwas einfällt, so kann er dies natürlich gerne mitteilen (Thread ist also noch nicht geschlossen...). Wenn ich irgendwann mal fertig bin stelle ich sonst auch mal den kompletten Quellcode rein. |
Re: geöffnete CSV bearbeiten
Ein CSV-DataSet ist eine Komponente, die eine CSV-Datei als ein DataSet kapselt. So kann man wie auf eine Datenbank zugreifen (.First, .Next, .Locate, .Lookup, FieldByName, ...)
|
Re: geöffnete CSV bearbeiten
Hallo,
TStringList hat eine LoadFromFile Methode, du musst nur den Separator richtig einstellen. Und zum Speichern aus einem StringGrid kannst du du einfach TextFile benutzen.
Delphi-Quellcode:
var
TxtFile: TextFile; sLine: String; iCol, iRow: Integer; begin AssignFile(TxtFile, 'c:\bla.txt'); Rewrite(TxtFile); // try finally selber machen for iRow:= 0 to StrGrid.WorCount-1 do begin sLine:= ''; for iCol:= 0 to StrGrid.ColCount-1 do begin if iCol>0 then sLine:= sLine+';'; sLine:= sLine+StrGid.Cells[iCol,iRow]; end; Writeln(TxtFile, sLine); end; CloseFile(TxtFile); end; Heiko |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:55 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-2025 by Thomas Breitkreuz