1

要するに、私はデルファイに不慣れであり、次のことを達成したいと思っています。

  • テーブルの定義は.cdsファイル{インデックス、データ、日付}で、一部のデータは.csv形式です。
  • .csvファイルをテーブルにロードし、その変更とエラーをログに表示したい(例:無効な日付形式)。

質問

このタスクをエレガントに解決するにはどうすればよいですか?

4

4 に答える 4

3

.csv から 1 行ずつ読み取り、各行を StringList の 'DelimitedText' に設定し、レコードをデータセットに追加し、文字列リストをループして各フィールドの値を設定してから、データセットに投稿できます。
「フィールド値の割り当て」/「投稿」を try-except ブロックに配置し、発生した例外のエラー メッセージを好きな情報 (たとえば、不正な形式のフィールド値/名前、行番号、および/または行全体など) と一緒にログに記録できます。 ) ファイル fi へ

(「変更」の意味がわかりません。私が理解したことから、.csv の行がデータセットに挿入されるため、すべての変更が挿入されます。)


編集:具体的なことについて議論できるようにする(タスクを把握するのに苦労しています:))

サンプル データ (CodeGear サンプル 'Clients.cds' の一部):

Davis;Jennifer;1023495,0000;100 Cranberry St.;Wellesley;MA;02181;516-292-3945;01.01.93 Jones;Arthur;2094056,0000;10 Hunnewell St;Los Altos;CA;94024;415-941 -4321;07.02.81 Parker;Debra;1209395,0000;74 South St;Atherton;CA;98765;916-213-2234;23.10.90 Sawyer;Dave;3094095,0000;101 Oakland St;Los Altos;CA; 94022;415-948-9998;21.12.89 White;Cindy;1024034,0000;1 Wentworth Dr;Los Altos;CA;94022;415-948-6547;01.10.92

procedure TForm1.FormCreate(Sender: TObject);
begin
  CDS.FieldDefs.Add('LAST_NAME', ftString, 20);
  CDS.FieldDefs.Add('FIRST_NAME', ftString, 20);
  CDS.FieldDefs.Add('ACCT_NBR', ftInteger);
  CDS.FieldDefs.Add('ADDRESS_1', ftString, 30);
  CDS.FieldDefs.Add('CITY', ftString, 15);
  CDS.FieldDefs.Add('STATE', ftString, 2);
  CDS.FieldDefs.Add('ZIP', ftString, 5);
  CDS.FieldDefs.Add('TELEPHONE', ftString, 12);
  CDS.FieldDefs.Add('DATE_OPEN', ftDate);
  CDS.CreateDataSet;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  csv: TextFile;
  Rec: string;
  Fields: TStringList;
  LineNo: Integer;
  i: Integer;
begin
  Fields := TStringList.Create;
  try
    Fields.StrictDelimiter := True;
    Fields.Delimiter := ';';

    AssignFile(csv, ExtractFilePath(Application.ExeName) + 'clients.csv');
    try
      Reset(csv);

      LineNo := 0;
      while not Eof(csv) do begin
        Inc(LineNo);
        Readln(csv, Rec);

        Fields.DelimitedText := Rec;
        CDS.Append;

        for i := 0 to Fields.Count - 1 do
          try
            CDS.Fields[i].Value := Fields[i];   // Variant conversion will raise
                                 // exception where conversion from string fails
          except
            on E:EDatabaseError do begin
              CDS.Cancel;        // Failed, discard the record

              // log the error instead of showing a message
              ShowMessage(Format('Cannot set field "%s" at line %d' + sLineBreak +
                  'Error: %s', [CDS.Fields[i].FieldName, LineNo, E.Message]));
              Break;             // Continue with next record
            end;
          end;

        if CDS.State = dsInsert then // It's not dsInsert if we Cancelled the Insert
          try
            CDS.Post;
          except
            on E:EDatabaseError do begin
              // log error instead of showing
              ShowMessage(Format('Cannot post line %d' + sLineBreak + 'Error: %s',
                  [LineNo, E.Message]));
              CDS.Cancel;
            end;
          end;

      end;
    finally
      CloseFile(csv);
    end;
  finally
    Fields.Free;
  end;
end;

procedure TForm1.CDSBeforePost(DataSet: TDataSet);
begin
  // Superficial posting error
  if CDS.FieldByName('LAST_NAME').AsString = '' then
    raise EDatabaseError.Create('LAST_NAME cannot be empty');
end;
于 2011-06-21T01:05:09.930 に答える
3

JvCsvDataSet (JEDI JVCL コンポーネント) は CSV ファイルを適切に解析するため、データ ポンプ コンポーネントを使用してデータをクライアント データセットに移動し、いくつかの検証を行います。

しかし、CSV ファイルをデータベース対応コントロールに提供するだけで本当に必要な場合は、ClientDataSet を完全に除外し、目的のために構築されたコンポーネントを使用するだけです。ネジを釘にしたり、釘をネジにしたりしないでください。どちらも金属製ですが、役割が異なります。

CSV ファイル テーブル定義は、目的が CDS テーブル定義とはまったく異なります。JvCsvDataSet は、メタデータ (整数、文字列、日時などのフィールド データ型、および関連するフィールド名、ヘッダー行がない CSV ファイルの場合)、ClientDatSet で行うよりも簡単です。

于 2011-06-21T15:15:03.753 に答える
2

私の知る限り、.csv データを .csv ファイルに直接ロードする方法はありませんTClientDataset

私が考えることができる最も簡単な方法は、TTextDataSetDemos\Delphi\Database\TextDataにあり、から入手可能Start->All Programs->Embarcadero RAD Studio XE->Samples)を使用することです。他の TDataSet と同じように使用できます。つまり、 から読み取ったり、 をFields使用したりでき、 、、、およびFieldByNameをサポートしています。BofEofNextPrior

単純に反復して CDS 列に割り当てようとすると、エラーが生成され、処理またはログに記録できます。

TTextDataset他のコンポーネントと同じようにインストールすることも、ユニットをuses句に追加して実行時に作成することもできます。readme.htmあまり説明されていないファイルがフォルダーにあります。主なプロパティはFileNameActiveです。:)

これには、事前に設計されたパッケージ ( TextPkg.dproj) とテスト アプリ ( TextTest.dproj) の両方が含まれています。プロジェクト グループ ( TextDataGroup.groupproj) もあります。これを IDE で開くだけで、TextPkgパッケージをビルドしてインストールし、テスト アプリをコンパイルして実行できます。テスト アプリのソースには、使用方法がよく示されています。

于 2011-06-20T23:09:54.900 に答える
1

データベースが DBISAM である可能性が低い場合は、単純に IMPORT SQL ステートメントを使用できます。

import table "tablename" from "myinputfile.csv" Delimiter ',';

他のデータベースにも同様の機能がある場合があります。

于 2011-06-21T15:21:06.183 に答える