科技行者

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

知识库

知识库 安全导航

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

Delphi控件的“拿来主义”

  • 扫一扫
    分享文章到微信

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

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

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

关键字:

  • 评论
  • 分享微博
  • 分享邮件
◆设计思路

  程序的关键在文本数据字段的分离。通常的做法,都是先将字符串进行处理(RegulateString),然后把串中每个字符同分割符(可以是空格,逗号等)比较,将不是分割符的字符追加到一个串中(GetRecordItem),得到一个字段的内容。通过一个循环(循环次数由GetItemNum来定),就可以将一个字符串分成几个字段。最后的工作就是将分离出来的数据对号入座加入数据库。

  按照上面的思路,利用Delphi提供的已有函数和过程,实现起来应该不难,但问题是,我可不想每次编文本导入程序的时候,都把什么这啊那的函数过程重新定义一遍,哎,最烦的就是重复性的工作了.那么有没有现成的控件将上述过程都封装起来呢?PS:又不用我编呢?

  答案是肯定的!前几天刚刚下了一个免费控件TPgCSV,据说可以实现文本的导入和导出.翻出来一看,正是我想要的。

  在深入到下面的内容之前,有必要对该控件的类声明部分作一定了解

//中文部分为笔者所作的注释

//注意:

//在该控件中,Export代表将文本数据导入到数据库,Import代表从数据库导出到文本。??? 怎么和我理解的

//导入导出概念刚好是反的 :)

type

//在处理数据产生异常时,可选择继续还是中止

TPgCSVErrorResponse = (pgcsvAbort, pgcsvIgnore);

//进程监控事件声明,可以将导入/导出的进度作为参数传出

TPgCSVProgressEvent = procedure (Sender : TObject; AProgress: LongInt; var StopIt: Boolean) of object;

//发生异常时的事件处理声明,异常信息通过该接口传给程序员。

TPgCSVExportErrorEvent = procedure (Sender : TObject; Mess: string; RecNo: LongInt; var Response:TPgCSVErrorResponse) of object;

TPgCSV = class(TComponent)

private

FDataset : TDataset;

FCSVMap,

FCSVFile,

FDateFormat,

FIgnoreStr : string;

FSeprator,

FDelimiter,

FFieldIndicator : Char;

FAutoOpen,

FUseDelimiter,

FSilentExport,

FTrimData,

FStop,

FEmptyTable : Boolean;

FBeforeOpenTable,

FAfterOpenTable,

FBeforeCloseTable,

FAfterCloseTable,

FBeforeEmptyTable,

FAfterEmptyTable,

FBeforeExport,

FAfterExport,

FBeforeImport,

FAfterImport,

FOnAddRecord : TNotifyEvent;

FExportProgress,

FImportProgress : TPgCSVProgressEvent;

FExportError : TPgCSVExportErrorEvent;

FMapItems,

FDefaultInt : Integer;

FBufferSize : LongInt;

FFieldCache : TList;

protected

FFile : TextFile;

//以下就是我所说的希望封装的部分

function CountMapItems:Integer;//计算映射字符串的字段个数

function GetMapItem(ItemIndex:Integer;var AField:Boolean):string;//提取映射字符串的字段

function GetCSVRecordItem(ItemIndex:Integer;CSVRecord:string):string;//提取CSV文件字符串中的某一字段

function BuildMap:string;//自动创建映射,如果CSVMap一栏为空的话,会由它来产生映射字符串

function ExtractWord(Item: Integer;S, WordDelim: string): string;//提取文本数据字符串/映射字符串中的某一字段

function WordCount(const S ,WordDelim: string): Integer;//计算文本数据字符串/映射字符串中的字段数目

function WordPosition(Item: Integer; const S, SubStr: string): Integer;//计算子字符串在字符串中的位置

public

constructor Create(AOwner: TComponent); override;

published

//properties

property Dataset : TDataset read FDataset write FDataset;

//设置要导入或导出的目标数据集.

property CSVMap : string read FCSVMap write FCSVMap;

//CSV 文本数据文件到数据库字段值的映射字符串.控件通过该映射决定文本中的哪些数据要导入及要导入哪个字段.

property CSVFile : string read FCSVFile write FCSVFile;

//CSV 文件格式,其实就是文本数据文件。CSV代表什么意思?呵呵,我也不知道

property Seprator : Char read FSeprator write FSeprator;

//分隔符,可以是空格,也可以是,、;、#等符号

property FieldIndicator : Char read FFieldIndicator write FFieldIndicator;

//字段标识符.

property AutoOpen : Boolean read FAutoOpen write FAutoOpen;

//将AutoOpen设为True可以在处理数据前自动打开要导入的数据表并在操作完毕后自动关掉它。

property IgnoreString : string read FIgnoreStr write FIgnoreStr;

//忽略纪录的标识串.

//举例来说

//IgnoreString:='(ignore)';

//CSVMap:='$Name,(ignore),$Age';

//在这种情况下,CSVToDataSet方法,即导入数据方法将忽略文本文件中的第二列的字段。

property Delimiter : Char read FDelimiter write FDelimiter;

//在某些CSV文档中标识字符串纪录的标识符,比如,"john","boy",12中的",在这种情况下,TPgCSV

//会忽略这些标识符。

property EmptyTable : Boolean read FEmptyTable write FEmptyTable;

//只在从数据库导出(DataSetToCSV)方法中有效,作用是创建一个新的CSV文件。

property UseDelimiter : Boolean read FUseDelimiter write FUseDelimiter;

//是否有Delimiter。

property SilentExport : Boolean read FSilentExport write FSilentExport;

//若该属性为True,应用程序将不显示数据操作时的异常,而将异常信息通过一个接口传给程序员处理.

property DateFormat : string read FDateFormat write FDateFormat;

//设定CSV文件中日期数据的格式。

property TrimData : Boolean read FTrimData write FTrimData;

//是否去掉数据头尾的空格.

property DefaultInt : Integer read FDefaultInt write FDefaultInt;

//整/实形数据转换出错后的默认值

property BufferSize : LongInt read FBufferSize write FBufferSize;

//CSV 文件的缓冲值,以字节为单位,可以加快导入和导出数据的速度。

//events

property BeforeOpenTable : TNotifyEvent read FBeforeOpenTable write FBeforeOpenTable;

property AfterOpenTable : TNotifyEvent read FAfterOpenTable write FAfterOpenTable;

property BeforeCloseTable : TNotifyEvent read FBeforeCloseTable write FBeforeCloseTable;

property AfterCloseTable : TNotifyEvent read FAfterCloseTable write FAfterCloseTable;

property BeforeEmptyTable : TNotifyEvent read FBeforeEmptyTable write FBeforeEmptyTable;

property AfterEmptyTable : TNotifyEvent read FAfterEmptyTable write FAfterEmptyTable;

property BeforeImport : TNotifyEvent read FBeforeImport write FBeforeImport;

property AfterImport : TNotifyEvent read FAfterImport write FAfterImport;

property BeforeExport : TNotifyEvent read FBeforeExport write FBeforeExport;

property AfterExport : TNotifyEvent read FAfterExport write FAfterExport;

property ExportProgress : TPgCSVProgressEvent read FExportProgress write FExportProgress;

//进程监控事件。每完成一条文本数据的导入就触发该事件。

property ImportProgress : TPgCSVProgressEvent read FImportProgress write FImportProgress;

property OnAddRecord : TNotifyEvent read FOnAddRecord write FOnAddRecord;

property ExportError : TPgCSVExportErrorEvent read FExportError write FExportError;

//发生异常时交由该事件处理,异常信息通过该接口传给程序员。

//methodes

//整个控件的核心内容

procedure CSVToDataset;//将文本导入到数据集的方法

procedure DatasetToCSV;//将数据集的数据导入到文本的方法

end;

procedure Register;

{略}

implementation

{略}
end.

  从声明部分中我们可以看到,TPgCSV将文本数据的导入导出全部封装到了CSVToDataSet(文本数据导入)和DataSetToCSV(文本数据导出)两个方法中.开发者可以在设计阶段直接将文本文件同要导入/出的数据库相连,然后在程序运行当中调用这两个方法就可以了,根本不用理会那些函数什么的,相当的方便.

  那我是不是可以直接拿来使用呢?这里就出现问题了.

  ----问题一及解决方案
  
  在该控件自带的Demo中,所使用的文本数据文件,格式如下


test.csv

"11","12","13","14"

"21","22","23","24"

"31","32","33","34"

...

  而ISO文件中的数据格式(部分)为

  sm01632.ISO

  ... a7507310175-b特精装-d¥1893"?1 -a毛泽东珍品典藏(上、下册)-f中共中央文献研究室编著?c中献-d011200"...

  ...-a7119029193-b平装- d¥20"?1 -a中国:加入WTO与经济改革-f王 梦 奎编著? -c外文-d011200"? ... -

  我们看到,同test.csv相比,sm01632.ISO文件中的纪录很不规则。

  我们所需要的是这样的纪录

  sm01632.ISO

  ... 7507310175,特精装,1893,1,毛泽东珍品典藏(上、下册),中共中央文献研究室编著,中献,011200...

  ...-7119029193,平装,20,1,中国:加入WTO与经济改革,王 梦 奎编著,外文,011200? ... -

  TPgCSV能否对这种情况进行自动的处理呢?哇噻,这种万能的控件好像不大可能有吧!(事实上也不需要)既然直接用TPgCSV处理无法实现正确导入的,我们就需要在每一条从文件中读取出来的纪录导入数据库之前,用程序对它们进行处理,转换之后再交由TPgCSV进行操作。怎么样处理这里就不赘述了。我们所关心的是TPgCSV有没有开放出这样一个处理的接口呢?
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

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

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