1

简而言之,我是 delphi 新手,我想实现以下目标:

  • 我将表定义为 .cds 文件 {index, data, date},以及一些 .csv 格式的数据。
  • 我想将 .csv 文件加载到表中并显示日志它的更改和错误(例如:无效的日期格式)。

问题

如何优雅地解决这个任务?

4

4 回答 4

3

您可以从 .csv 中逐行读取,将每一行设置为 StringList 的“DelimitedText”,将记录附加到数据集,循环字符串列表以设置每个字段的值,然后发布到数据集。
您可以将 'field value assinging'/'posting' 放在 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

AFAIK,没有直接的方法将 .csv 数据加载到TClientDataset.

我能想到的最简单的方法是使用TTextDataSet(在 中找到Demos\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 回答