科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Delphi控件的“拿来主义”

Delphi控件的“拿来主义”

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

一个优秀的Delphi程序员,不仅要会使用控件,还要会写控件。

作者:xm4014 来源:论坛 2007年10月31日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
我们来看DataSetToCSV方法的实现代码(主要是注释部分):

procedure TPgCSV.CSVToDataSet;
var
 RecordString,
 Temp : string;
 i : Integer;
 C : LongInt;
 D : Boolean;
 F : Real;
 ErrorResponse : TPgCSVErrorResponse;
 Buffer : Pointer;
begin
 //create field cache
 FFieldCache:=TList.Create;
 //initiate map items
 FMapItems:=0;
 //allocate buffer size
 GetMem(Buffer,FBufferSize);
 //assign and open CSV file
 AssignFile(FFile,FCSVFile);
 SetTextBuf(FFile,Buffer^,FBufferSize);
 Reset(FFile);
 //open table if nessecary
 if FAutoOpen then
 begin
  if Assigned(FBeforeOpenTable) then
   FBeforeOpenTable(Self);
   FDataset.Open;
   if Assigned(FAfterOpenTable) then
    FAfterOpenTable(Self);
   end;
   //export to table from CSV file
   if Assigned(FBeforeExport) then
    FBeforeExport(Self);
    //set the counter to zero
    C:=0;
    Temp:=ShortDateFormat;
    ShortDateFormat:=FDateFormat;
    {**********以下是文本数据导入的核心代码部分,也是我要关心的部分********}
    FDataset.DisableControls;
    while (not Eof(FFile)) and (not FStop) do
    begin
     //read from CSV
     Readln(FFile,RecordString);
     //注意,这里好像差了一点什么东西
     //add new record
     try
      FDataset.Append;
      for i:=1 to CountMapItems do
       if Uppercase(GetMapItem(i,D)) <> Uppercase(FIgnoreStr) then
       case FDataset.FieldByName(GetMapItem(i,D)).DataType of

       ftInteger:
      FDataset.FieldByName(GetMapItem(i,D)).AsInteger:=
StrToIntDef(Trim(GetCSVRecordItem(i,RecordString)),FDefaultInt);
       ftFloat:
         begin

try

F:=StrToFloat(Trim(GetCSVRecordItem(i,RecordString)));

except

F:=FDefaultInt;

end;

FDataset.FieldByName(GetMapItem(i,D)).AsFloat:=F;

end;

else

if FTrimData then

FDataset.FieldByName(GetMapItem(i,D)).AsString:=
 Trim(GetCSVRecordItem(i,RecordString))

else

FDataset.FieldByName(GetMapItem(i,D)).AsString:=
 GetCSVRecordItem(i,RecordString);

end;

//post record

FDataset.Post;

except

on E:Exception do

if not FSilentExport then

raise

else

if Assigned(FExportError) then

begin

FExportError(Self,E.Message,C,ErrorResponse);

if ErrorResponse = pgcsvAbort then

Break;

end;

end;

if Assigned(FOnAddRecord) then

FOnAddRecord(Self);

if Assigned(FExportProgress) then

FExportProgress(Self, C, FStop);

Inc(C);

end;

FDataset.EnableControls;

{************以上是文本数据导入的核心代码部分**************}

if Assigned(FAfterExport) then

FAfterExport(Self);

//close table if nessecary

if FAutoOpen then

begin

if Assigned(FBeforeCloseTable) then

FBeforeCloseTable(Self);

FDataset.Close;

if Assigned(FAfterCloseTable) then

FAfterCloseTable(Self);

end;

//close CSV file

CloseFile(FFile);

//disallocate buffer

FreeMem(Buffer);

ShortDateFormat:=Temp;

//free cache

for i:=FFieldCache.Count - 1 downto 0 do

Dispose(FFieldCache.Items[i]);

FFieldCache.Free;

end;

  (这么长!看得我眼都花了.好在找到了我所关心的核心代码,其他的?别管了吧,我这个懒惰的人.)差的是什么呢?很明显,我们希望把这个时候的RecordString开放出去,经过处理之后再回来进行导入的操作.所以,这里差的只是一个事件处理过程,在这个过程中,我们需要通过Delphi把RecordString的值传出去让用户处理。

  既然没有提供这个接口,那就自己动手添加了。由于需要传参数,这个事件不能用标准的TNotifyEvent来定义,而需要重新声明。

  新的事件声明和事件属性如下:

type

...

TPgCSVRegulateStrEvent = procedure (Sender : TObject; var ARecordString: string) of object;

...

TPgCSV = class(TComponent)

Published

property RegulateString : TPgCSVRegulateStrEvent read FRegulateString write FRegulateString;

//写完后别忘了按一下ctrl+shift+c

...

End;

  好了,现在可以在我刚才注释的地方写事件调用方法的程序了.

...

while (not Eof(FFile)) and (not FStop) do

begin

//read from CSV

Readln(FFile,RecordString);

//xm4014's modification

if Assigned(FRegulateString) then

FRegulateString(self,RecordString);

//add new record

try

FDataset.Append;

...

  重新编译包文件通过后,你就会在TPgCSV控件的事件页面中发现RegulateString这个事件,双击它就可以添加你的处理代码了。这样一来,无论文本数据中有什么样怪异的字符或格式,我们都通过这个事件处理预先过滤一编,让控件放心的处理导入的操作。简单吧(也太简单了点,居然还写了这么长!汗)

  但是,这样就行了吗?
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章