Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi geöffnete CSV bearbeiten (https://www.delphipraxis.net/97951-geoeffnete-csv-bearbeiten.html)

Elliotx9 19. Aug 2007 16:40

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.

mkinzler 19. Aug 2007 19:37

Re: geöffnete CSV bearbeiten
 
Vielleicht wäre der Einsatz eines CSV-Dataset sinnvoll

grenzgaenger 19. Aug 2007 20:04

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

Elliotx9 20. Aug 2007 12:22

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.

mkinzler 20. Aug 2007 12:25

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, ...)

hoika 20. Aug 2007 12:38

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 08:37 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz