Smile 笑容

delphi中克隆录入记录:实现添加记录的“携带”实现

在数据库管理系统中,数据录入是数据处理的基本功能,录入操作方便与否是衡量数据库应用程序交互良莠的指标之一。录入中除了应要对录入数据进行合法检验外,还应为用户提供更多的方便操作,即对于“规范性”数据,如:性别、职称等字段的数据,应尽可能供用户“选择”录入,而非直接文字输入,另外,如:出生年月、联系电话、邮编等类似名称的字段,程序应设置数据录入格式,这可以从一定程度上“规范”数据,并提高录入速度。除此以外,在较大数据量的录入中,用户还希望更快速地进行相似数
据的批量录入,实现高效数据处理。本文只介绍“批量数据”的录入处理。

  针对大多数的要录入的记录数据都与现有(即已录入)数据具有或多或少的相同内容,因此,修改记录的少量字段数据无疑要比逐个字段内容录入快得多。由于此方法源自Foxbase系统的“Set carry on”命令,因此取名为记录“携带”。以下具体介绍这种录入数据时采用的“携带”功能的实现方法。

  一、建立一动态数组,用来存放整条记录的所有字段值(不含“备注型”等类型),定义如下:

MyDynamic_Record: Variant; //定义一个动态可变数组,来存放当前记录各字段值

  注意此处不限定数组单元数和单元值类型,更具有通用性。

  二、在表对象的InsertBefore事件中,完成源数据的读取并存入动态数组MyDynamic_Record中。

  具体是,用户定位到要作为源的记录位置(可以是末记录或中间某一记录),使用Insert插入键(或其它应用程序提供的按键或按钮)进行插入操作前,为表对象的InsertBefore事件加入读取当前记录的各字段值的代码(见以下MyRecordScatTo()自定义函数),存入MyDynamic_Record中。

  三、在表对象的InsertAfter事件中将MyDynamic_Record数组值写入新增的记录的各字段值(代码见以下My_GathFrom自定义函数)。

四、由用户对当前新增的“克隆”记录进行修改,确定时“保存”,否则“取消”。

  以下创建一演示实例,并给出具体步骤:

  1、新建一工程项目,取名为Project1,表单取名为Form1;在该表单中先后加入如下图中对象,并设置各相应属性,调整好各控件对象位置:

  其中,对应的Salary(工资表)的结构定义如下:

  说明:结构中虽然有“备注”字段,但类型并非“备注型”,而设置为“字符型”,因此该字段可参与
“携带”。

  2、在单元Unit1的type部分作相应的说明及变量的定义:

type
TForm1 = class(TForm)

procedure FormCreate(Sender: TObject);
procedure Table1BeforeInsert(DataSet: TDataSet);
procedure Table1AfterInsert(DataSet: TDataSet);
procedure Table1PostError(DataSet: TDataSet; E: EDatabaseError; var Action: TDataAction);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);

//以下为自定义过程与函数的说明
function MyRecordScatTo(DataSet0:TDataSet;var MyDynamic_Record0:Variant):boolean;
function MyRecordGatherFrom(DataSet0:TDataSet;var MyDynamic_Record0:Variant):boolean;
procedure My_TablePostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction;sFieldName:string);

private
{ Private declarations }
MyDynamic_Record:Variant; //定义动态数组
public
{ Public declarations }
end;

3、在表单的OnCreate事件中,加入Table1表的初始设置:
procedure TForm1.FormCreate(Sender: TObject);
var s:string;
begin
s:=ExtractFilePath(Application.ExeName);
Table1.DatabaseName:=s; //设置Table1的源数据路径
Table1.Open;
end; //初始设置

分别在表Table1的BeforeInsert,AfterInsert,OnPostError事件中加入如下代码:
procedure TForm1.Table1BeforeInsert(DataSet: TDataSet);
begin
if CheckBox1.Checked //使用"携带"功能时,调用"获取"
then
if not MyRecordScatTo(Table1,MyDynamic_Record) //出错时,取消"携带"
then CheckBox1.Checked:=false;
procedure TForm1.Table1AfterInsert(DataSet: TDataSet);
begin
if CheckBox1.Checked //使用"携带"功能时,调用"赋值"
then MyRecordGatherFrom(Table1,MyDynamic_Record);
end; //添加记录后的数据处理

procedure TForm1.Table1PostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction);
begin
//调用通用表数据处理模块:主关键字'编号'
My_TablePostError(DataSet,E,Action,'编号');
end;

分别在Button1、Button2的OnClick事件中加入如下代码:
procedure TForm1.Button1Click(Sender: TObject);
begin
Table1.Insert;
if DBGrid1.CanFocus
then DBGrid1.SetFocus
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Table1.Refresh;
Table1.Close;
Close;
end; //关闭表单

4、以上调用的过程及函数——MyRecordScatTo、MyRecordGatherFrom、My_TablePostError的代码如
下:


function TForm1.MyRecordScatTo(DataSet0:TDataSet;var MyDynamic_Record0:Variant):boolean; //正确
返回TRUE,否则为FALSE
//功能:读取(当前记录)字段值存入动态数组中
var i:integer;
begin
try
i:=DataSet0.FieldCount; //取字段数
MyDynamic_Record0:=VarArrayCreate([0,i],varVariant); //MyVariant
if (not DataSet0.Active) //or(DataSet0.eof)
then begin
MessageBeep(MB_OK);
MessageDlg('当前为空记录,无法使用"携带"!',mtError, [mbOk], 0);
Result:=false;
Exit;
end;
with DataSet0 do //DBGrid0
begin
for i:=0 to FieldCount-1 do
begin
if Fields[i].DataType<>ftMemo //非"备注"型数据
then MyDynamic_Record0[i]:=Fields[i].Value;
end; //for i:
end;
Result:=true;
except
Result:=false
end //try
end; // MyRecordScatTo

function TForm1.MyRecordGatherFrom(DataSet0:TDataSet;var MyDynamic_Record0:Variant):boolean; //
正确返回TRUE,否则为FALSE
//功能:从动态数组中获取相应值,来更改(当前记录)字段值
var i:integer;
begin
Result:=true;
with DataSet0 do //
begin
try
for i:=0 to FieldCount-1 do
begin //Edit;
if (Fields[i].DataType<>ftMemo) //非"备注"型数据
then Fields[i].Value:=MyDynamic_Record0[i];
end; //for i
except
Result:=false;
end //try
end;
end; // MyRecordGatherFrom

procedure TForm1.My_TablePostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction;sFieldName:string);
//功能:保存时数据错误信息捕捉
var sMes:string;
begin
MessageBeep(0);
//以下捕捉"错误信息"
sMes:='当前记录非法!更正后再保存。';
if Pos(UpperCase('key violation'),UpperCase(e.Message))<>0
then sMes:='"'+sFieldName+'"内容重复,请更改后再保存!';
if Pos(UpperCase('must have a value'),UpperCase(e.Message))<>0
then sMes:='当前栏目必须输入值!';// '"'+sFieldName+'"字段必须输入值!';
sMes:=sMes+Chr(13)+Chr(10)+'(Esc键取消操作)';
MessageDlg(sMes,mtError, [mbOk], 0);
Action:=daAbort; //放弃编辑且不显示错误信息
end; //调用通用表数据处理模块

  5、运行程序,选择<使用“携带”> 后,按<添加>(或按[Insert]键)出现的画面如下图所示(以第2条记录为源):

  以上代码在下述环境中调试通过:中文Win2000 Pro,Delphi 7.0。