用Delphi编写小型数据库(三)——项目的制作流程
编程爱好者
本章将通过一个项目制作过程的讲解来加深读者对数据库编程的认识。我们以攀钢热轧板厂纵切机组二级系统的上料程序为例,讲解如何进行项目的制作。
攀钢热轧板厂纵切机组是一条生产钢卷的生产线,整个生产流程见图1:

吊车把钢卷吊到入口步进梁上(总共有6个卷位,每个卷位可以放置一个钢卷),然后由现场操作人员开动步进梁设备,通过上料小车把钢卷送到开卷机上进行生产。生产完成后由卷取机把钢卷卷好,通过卸料小车把钢卷送到出口步进梁,现场操作人员开动步进梁到称重位置的电子秤称重后,把钢卷送到库房。
整个生产由一级系统(PLC)控制,二级系统不参与控制,但需要对整个生产流程的数据做记录并统计分析和备份,二级系统主要实现的功能有:1.接收计划,生产计划由三级系统下发,二级系统只要把生产计划接收下来;2.吊销计划;3.产品跟踪,现场生产的钢卷信息要实时反映到二级系统,指导现场操作人员生产;4.生成并上传给三级系统实绩,也就是把生产完成的卷的相应信息保存下来并做标签打印;5.计划和实绩的查询功能。
根据实际需要,二级系统由两个独立的应用程序构成:上料程序和主程序。由于篇幅的关系,这里只讲解上料程序的制作流程和逻辑思路。上料程序的界面如图2:

上料程序的功能:
1.上料操作
提供给操作人员一个界面,操作人员在接到生产计划后,把待生产的钢卷用吊车吊放到入口步进梁的卷位上,然后在画面中把实物所对应的信息从数据库的计划表中写到跟踪表中。比如把一个钢卷号为“41236704400”吊到入口步进梁的1号卷位后,在程序中做如下操作:根据轧制明细表,选择计划号“212067”后显示此计划下所有的合同号,点击合同号“J000000022”,显示此计划、此合同下的钢卷号,点击这个钢卷号,点击“上料”按钮,再点击“1号卷位”,系统就把此钢卷的信息(计划号、钢卷号)写到跟踪表中了。
2.卸料操作
由于操作失误或者某种原因,把刚才入口步进梁1号卷位的钢卷“41236704400”上到2号卷位,提供给操作人员一个“卸卷”按钮,当点击它后,就把跟踪表中的相关信息清除了,就可以重新执行上料操作了。
3.钢卷前进
当开动步进梁前进,由于步进梁是整体前进的,需要把跟踪表中的信息做相应修改,点击 “钢卷前进”按钮,就把5号卷位的信息写到6号卷位,4号卷位的信息写到5号卷位……1号卷位的信息写到2号卷位,同时1号卷位的信息清空。实际上,钢卷前进后,由工业HMI系统把数据库的信号表的某个字段值改变,通过扫描这个值的变化,修改跟踪表实现钢卷自动前进功能。如果实际设备动作后由于某种原因导致信号表相应字段的值没有发生变化,就需要手动点击“钢卷前进”按钮了。
一、设计数据库
使用Microsoft SQL Server2000,建立一个数据库,这里需要使用4张表:
1.接口表TB_ SplitCutPlan,三级系统下发计划的方式是直接写数据到此表中,当数据库检测到此表有数据后把所有数据插入到计划表中,并删除此表中的全部数据;方法是使用触发器,只有两句SQL语句:
insert into l2_splitcutplan select * from tb_splitcutplan
delete from tb_splitcutplan
2.计划表L2_SplitCutPlan,存放待生产钢卷的详细信息,由于钢卷号是唯一的,因此把钢卷号字段HOT_COIL_NO设置为主键。计划表和接口表的设计一模一样,把接口表复制后改名为计划表就可以了。
3.信号表Signal,当钢卷信息到了跟踪表的开卷机时,需要通知三级系统此卷上了生产线,也就是说需要把信号表中某个字段的值置1,由主程序去扫描这个值是否为1,当为1时把跟踪表的开卷机的钢卷信息写到三级系统的相关表中。
4.跟踪表L2_SplitCutMatTrack,存储钢卷信息,保持物流和信息流一致性。
二、程序编码难点
1.程序界面中,计划号、合同号、钢卷号等三个供操作人员进行选择的列表框为ListBox控件,随着数据量的增大,计划号在ListBox中必须按时间倒序排列,也就是三级系统最后下发的计划,其计划号是排列在ListBox的最顶部的,这样操作人员一眼就能找到最近需要生产的计划号。当然,为了让程序更加健壮,需要做一个计划号的查询,在界面的右下角输入计划号,点击“查询计划号”按钮,在ListBox中就自动把此计划号反选,并查询出此计划号所对应的合同号并显示在合同号列表框中。
在窗体的FormShow事件中加入下面代码:
procedure TMaterial.FormShow(Sender: TObject);
var
i:integer;
strPlanNo:string;
begin
//***计划刷新***//
Plan_No_ListBox.Items.Clear;//启动画面时清空计划号列表框
Plan_ADODataSet.Close;//关闭计划表数据集,这个数据集对应的是计划表L2_SplitCutPlan的数据
Plan_ADODataSet.CommandText := 'SELECT PlanNo from L2_SplitCutPlan group by planno,prg_start_time order by prg_start_time desc;';//关键就是这个SQL语句,它从计划表中选择计划号和时间字段,并按时间字段倒序排列,同时相同的计划号只显示一次。
Plan_ADODataSet.Open;//打开数据集
for i := 0 To (Plan_ADODataSet.RecordCount-1) do//把计划表的记录从头到尾扫描一遍,把每条记录的计划号字段读出来,赋给内部变量strPlanNo,然后把strPlanNo的值添加到ListBox中。
begin
strPlanNo := Plan_ADODataSet.FieldByName('PlanNo').AsString;
Plan_ADODataSet.Next;
Plan_No_ListBox.Items.Add(StrPlanNo);
end;
L2_TrackADODataSet.Active:=false;//当启动画面时刷新画面右侧的跟踪表格的数据,这个表格是DBGrid控件。
L2_TrackADODataSet.Active:=true;
end;
2.当点击合同号后,在钢卷号列表框中就显示了钢卷号,这里显示的钢卷号必须具备下面两点:1.显示的钢卷号所对应的计划号必须是前面选择的计划号;2.显示的钢卷号所对应的合同号必须是前面选择的合同号。如果要满足这两个要求,必须要使用到SQL语句。
3.如何把选择的钢卷号上料到步进梁上面?也就是说如何把计划表的计划号、钢卷号字段写到跟踪表中?根据工艺流程,设计的跟踪表如图3:

Coil_Number和Coil_Name字段的值是固定的,在程序中是静止的,只须把选择的计划号和钢卷号写给Coil_No和PlanNo即可。下面给出“1号卷位”按钮的代码,操作人员在选择一个钢卷号后,点击“上料”按钮,再点击“1号卷位”按钮就把从计划表中选择的钢卷号的信息写到跟踪表中了。
procedure TMaterial.Button5Click(Sender: TObject);
var
i:integer;
tmpCoil:string;
begin
if UpOrDown=1 then //上料,UpOrDown是全局变量,当点击“上料”按钮后,把这个值置为1,表示进行上料操作
begin
for i := 0 to (Coil_No_ListBox.Items.Count - 1) do//把选择的钢卷号的值赋给内部变量tmpCoil
begin
if Coil_No_ListBox.Selected[i] then
begin
tmpCoil:=Coil_No_ListBox.Items.Strings[i];
//***修改L2跟踪表***//
L2_TrackADODataSet.Active:=false;
L2_TrackADODataSet.Active:=true;
L2_TrackADODataSet.First;//由于是上料到1号卷位,就指向跟踪表的第一条记录
if L2_TrackADODataSet.FieldByName('Coil_No').AsString<>' ' then//如果字段Coil_Name的值不为空,就不应该上料到此处,给出提示信息并退出程序
begin
MessageDlg('此卷位有卷啦,请先卸卷', mtError,[mbOk], 0);
exit;
end;
L2_TrackADODataSet.Edit;//编辑跟踪表
L2_TrackADODataSet.FieldByName('Coil_No').AsString:= tmpCoil; //把选择的钢卷号写到跟踪表的第一条记录的Coil_No字段中。
L2_TrackADODataSet.FieldByName('PlanNo').AsString:=strPlanNo1; //把选择的钢卷号所对应的计划号写到跟踪表的第一条记录的PlanNo字段中。
L2_TrackADODataSet.Post;// 将数据集中修改的内容写回到数据库中
L2_TrackADODataSet.Active:=false;//刷新表格
L2_TrackADODataSet.Active:=true;
exit;//退出程序
end;
end;
end;
end;
编码完成后,需要不断离线测试,修改程序中的Bug,完善程序。如果没有大问题就可以上线运行了。