搬家第四天-89.Wincc V7.3 用户归档深入8-用户归档结合数据库控件使用vbs脚本模拟从ERP任务表到控制系统配方
作者:互联网
一 任务背景描述
假设有这样一个车间,每天生产任务来自ERP系统任务表,现场控制计算机从系统中查询到任务表,然后根据设备实际情况选择任务表,并把这个配方任务每隔10秒逐条下载给控制系统,控制系统根据上级的指令完成生产任务。wincc查询、选择数据表的方法,前面的博客有较为介绍,本文不作重点介绍。
1. 假设ERP任务表存放在ERP数据库中,表名叫做Task。表的各字段如下图所示,各字段类型、长度、表结构是否最优不在本文讨论范围。CurDate表示生产任务的日期,Product表示配方名称,Pressure表示压力设定值,Tempreture表示温度设定值,finished记录任务是否完成(我们假定下载到控制系统的任务都能完成,只要下载了就把这个显示为“是”)。
2. 假定Task表格已经有下面一些记录了。
我们需要在画面上能够按照日期查询这些配方任务,可以筛选符合现场设备工艺状况的配方任务,然后每隔10秒把选中的配方任务下载到控制系统中,选中的记录在finished字段标注“是”,未选中的任务在finished字段标注“否”。我们选定好任务后,在人物下载到控制系统的过程中,还必须确保无论是在哪一个工艺画面,下载过程都能够顺利完成,不会因为画面切换而造成中断(实际生产中也会有这类需求)。
3. 在数据库ERP中新建一个用户任务表User_Task,用于记录用户选定的配方任务。
二 基本设置
1. 下位机硬件设置
这是一个模拟项目,没有实际的硬件,在simatic manager 插入一个s7 300 站点,配置好电源、CPU和简单的IO。
2. 插入一个DB1,里面定义Product、Pressure、Tempreture三个变量,设置这三个变量和DB块允许操作员监控,DB块S7_m_c属性为true.
3. simatic manager插入PC Station,配置硬件。
4. simatic manager的PC Station下OS右键编译,把标签上载到Wincc。
5. 在Wincc定义内部变量Index,32位浮点数,记录user_task的行号;Download 二进制变量;@MyUA_ID、@MyUA_JOB、@MyUA_Field、@MyUA_Value分别对应用户归档MyUA的四个属性。
6. 新建用户归档MyUA,下面三个归档变量Product,Pressure、Tempreture,分别对应上载上来的三个PLC变量。(详细设置参考其他博客)
二 画面设置和编程
1. 新建两个画面Task和UA,分别用于查询设置和查看用户归档
2. Task画面插入日期时间空间,名字修改为DTPicker;两个MSHFGrid控件,名字分别为ERP_Task和User_Task;一个查询按钮、一个上移按钮、一个下移按钮、一个下达任务按钮、一个跳转到用户贵党页面按钮。
3.查询按钮vbs脚本
Sub OnClick(ByVal Item)
Dim conn
Dim ssql
Dim ors
Dim ocom
Dim scon
Dim ERP_Task,User_Task,rowcount,i
Dim ADODC
Dim PCName,colscount
Dim sYear,sMonth,sDay,sDate,DTP
'以下代码规范查询日期的字符串格式
Set DTP=ScreenItems("DTPicker")
sYear=Year(DTP.value)
sMonth=Month(DTP.value)
sDay=Day(DTP.Value)
If sMonth<10 Then
sMonth="0" & CStr(sMonth)
End If
If sDay<10 Then
sDay="0" & CStr(sDay)
End If
sDate=CStr(sYear) & "-" & CStr(sMonth) & "-" & CStr(sDay)
'开始按照日期条件查询
PCName=HMIRuntime.Tags("@LocalMachineName").Read
scon="Provider = SQLOLEDB.1;Integrated Security=SSPI;Persist SecurityInfo=False;Initial Catalog =ERP;Data Source = " &PCName & "\WINCC"
ssql="select Curdate as '日期',product as N'配方代号',pressure as '压力设定',tempreture as '温度设定',finished as N'是否完成' from Task where Curdate='" & sDate & "'"
Set conn=CreateObject("ADODB.Connection")
conn.ConnectionString=scon
conn.Cursorlocation=3
conn.open
Set ors=CreateObject("ADODB.RecordSet")
Set ocom=CreateObject("ADODB.Command")
ocom.commandtype=1
Set ocom.ActiveConnection=conn
ocom.CommandText=ssql
Set ors=ocom.Execute
Set ERP_task=ScreenItems("ERP_Task")
Set ERP_task.DataSource=ors
ERP_task.Refresh
Set ors=Nothing
conn.close
Set conn=Nothing
' 增加一列用于勾选,一列记录临时表行号
colscount=ERP_task.Cols
ERP_task.Cols = colscount + 2
ERP_task.TextMatrix(0,colscount)="点击选择"
ERP_task.TextMatrix(0,colscount+1)="临时表行号"
ERP_task.colwidth(1)=1200
'如果已经设定过一次再次点击读取数据,则清空临时表
Set User_Task=ScreenItems("User_Task")
rowcount=User_Task.Rows
User_Task.Row=1
For i=1 To User_Task.Rows-2
User_Task.RemoveItem User_Task.Row
User_Task.Row=1
Next
End Sub
有中文显示的字段,前面加N避免显示成?
4. ERP_Task控件鼠标点击事件vbs脚本
Sub Click(ByVal Item)
Dim ERP_Task,User_Task
Dim hid,vid
Dim colcount
Dim i,UserTask_currow
Dim delrow
Set ERP_Task=ScreenItems("ERP_Task")
Set User_Task=ScreenItems("User_Task")
User_Task.colwidth(1)=1200
colcount=ERP_Task.cols-2
User_Task.Cols=colcount+1 '增加一列记录在原表中的行号
hid=ERP_Task.Row
vid=ERP_Task.col
'初始化临时表
For i=1 To colcount-1 '列标题
User_Task.TextMatrix(0,i)=ERP_Task.TextMatrix(0,i)
Next
User_Task.TextMatrix(0,User_Task.cols-1)="原始表行号"
If (hid>=1 And hid<=ERP_Task.rows-1) And vid=colcount Then
If ERP_Task.TextMatrix(hid,vid)="" Then
ERP_Task.TextMatrix(hid,vid)="x"
ERP_Task.ColAlignment(vid)=3 '居中
User_Task.AddItem ""
UserTask_currow=User_Task.Rows-2
For i=1 To colcount-1
User_Task.TextMatrix(UserTask_currow,i)=ERP_Task.TextMatrix(hid,i)
Next
User_Task.TextMatrix(UserTask_currow,0)="第" & CStr(UserTask_currow) & "步骤"
ERP_Task.TextMatrix(hid,colcount+1)=CStr(User_Task.Rows-2)
User_Task.TextMatrix(UserTask_currow,User_Task.Cols-1)=CStr(hid) '记录是原表哪一行
Else
delrow=ERP_Task.TextMatrix(hid,ERP_Task.Cols-1)
User_Task.RemoveItem delrow
ERP_Task.TextMatrix(hid,ERP_Task.Cols-1)=""
ERP_Task.TextMatrix(hid,ERP_Task.Cols-2)=""
'删除临时表相应行之后,原始表中相应列数字需要修改
For i=delrow To User_Task.Rows-2
ERP_Task.TextMatrix(User_Task.textmatrix(i,User_Task.cols-1),vid+1)=i
Next
End If
End If
End Sub
5. 上移按钮脚本
Sub OnClick(ByVal Item)
Dim currow,Erp_Task,User_Task
Dim colvalue
Dim selrow,selcol
Dim rowno1,rowno2 '这两个变量存放临时表中“原表行号”
Dim rowno3,rowno4 '这两个变量存放原表行号
Dim i,btn
Set Erp_Task=ScreenItems("Erp_Task")
Set User_Task=ScreenItems("User_Task")
Set btn=ScreenItems("btn_up")
selrow=User_Task.Row
selcol=User_Task.Col
For i=1 To User_Task.cols-1
colvalue=User_Task.TextMatrix(selrow,i)
User_Task.TextMatrix(selrow,i)=User_Task.TextMatrix(selrow-1,i)
User_Task.TextMatrix(selrow-1,i)=colvalue
Next
'改变原表中"临时表行号"字段
User_Task.Row=User_Task.Row-1
rowno1=User_Task.TextMatrix(User_Task.Row,User_Task.cols-1)
rowno2=User_Task.TextMatrix(User_Task.Row+1,User_Task.cols-1)
ERP_Task.TextMatrix(User_Task.TextMatrix(User_Task.Row,User_Task.Cols-1),ERP_Task.cols-1)=User_Task.Row
ERP_Task.TextMatrix(User_Task.TextMatrix(User_Task.Row+1,User_Task.Cols-1),ERP_Task.cols-1)=User_Task.Row+1
'如果移动到第一行,按钮失效
If User_Task.Row=1 Then
btn.Enabled=False
Else
btn.Enabled=True
End If
End Sub
6.下移按钮vbs脚本
Sub OnClick(ByVal Item)
Dim currow,Erp_Task,User_Task
Dim colvalue
Dim selrow,selcol
Dim i,btn
Set User_Task=ScreenItems("User_Task")
Set Erp_Task=screenitems("Erp_Task")
Set btn=ScreenItems("btn_Down")
selrow=User_Task.Row
selcol=User_Task.Col
For i=1 To User_Task.cols-1
colvalue=User_Task.TextMatrix(selrow,i)
User_Task.TextMatrix(selrow,i)=User_Task.TextMatrix(selrow+1,i)
User_Task.TextMatrix(selrow+1,i)=colvalue
Next
User_Task.Row=User_Task.Row+1
'改变原表中"临时表行号"字段
rowno1=User_Task.TextMatrix(selrow,User_Task.cols-1) '用户选中的那一行在Erp_Task表中的行号
rowno2=User_Task.TextMatrix(selrow+1,User_Task.cols-1) '用户选中的行紧邻下一行在Erp_Task表中的行号
Erp_Task.TextMatrix(rowno1,Erp_Task.cols-1)=selrow
Erp_Task.TextMatrix(rowno2,Erp_Task.cols-1)=selrow+1
If User_Task.Row>=User_Task.Row-2 Then
btn.Enabled=False
Else
btn.Enabled=True
End If
End Sub
7. 下达任务按钮vbs脚本
Sub OnClick(ByVal Item)
Dim Product(),Pressure(),Tempreture(),CurDate()'定义动态数组,事先不知道配方任务有多少条
Dim conn,con,ssql
Dim PCName
Dim UserTask,UATaskCount
Dim i,Download
PCName=HMIRuntime.Tags("@LocalMachineName").Read '数据库所在计算机名字
Set Download=HMIRuntime.Tags("Download")
Set UserTask=ScreenItems("User_Task")
UATaskCount=UserTask.rows-2
Redim CurDate(UATaskCount),Product(UATaskCount),Pressure(UATaskCount),Tempreture(UATaskCount)
For i=1 To UATaskCount
CurDate(i)=UserTask.TextMatrix(i,1)
Product(i)=UserTask.TextMatrix(i,2)
Pressure(i)=UserTask.TextMatrix(i,3)
Tempreture(i)=UserTask.TextMatrix(i,4)
Next
'先删除表格内容
con="Provider = SQLOLEDB.1;password = sa;user id = sa;Initial Catalog =ERP;Data Source = " & PCName & "\WINCC"
Set conn=CreateObject("ADODB.Connection")
conn.ConnectionString=con
conn.open
ssql="delete from usertask"
conn.Execute ssql
'逐行把usertask表格内容添加到sql数据表UserTask中
For i= 1 To UATaskcount
ssql="insert into UserTask(CurDate,Product,Pressure,Tempreture) values('" & CurDate(i) & "','" & Product(i) & "','" & CStr(Pressure(i)) & "','" & CStr(Tempreture(i)) & "')"
conn.Execute ssql
Next
conn.close
Set conn=Nothing
Download.Write 1
End Sub
8.新建全局vbs脚本,循环触发器10s触发一次
Option Explicit
Function action
Dim con,conn,ssql,ors,Rscount,PCName
Dim con1,conn1,ssql1,ors1
Dim Product,Pressure,Tempreture,Download
Dim id,job
Dim CurDate(),CP(),YL(),WD()
Dim i,Index
PCName=HMIRuntime.Tags("@LocalMachineName").Read '数据库所在计算机名字
Set Product=HMIRuntime.Tags("S7$程序(1)/DB1.Product")
Set Pressure=HMIRuntime.Tags("S7$程序(1)/DB1.Pressure")
Set Tempreture=HMIRuntime.Tags("S7$程序(1)/DB1.Tempreture")
Set Download=HMIRuntime.Tags("Download")
Set id=HMIRuntime.Tags("@MyUA_ID")
Set job=HMIRuntime.Tags("@MyUA_Job")
Set Index=HMIRuntime.Tags("Index")
If download.Read =1 Then
con="Provider = SQLOLEDB.1;password = sa;user id = sa;Initial Catalog =ERP;Data Source = " & PCName & "\WINCC"
Set conn=CreateObject("ADODB.Connection")
conn.ConnectionString=con
conn.open
ssql="select * from usertask"
conn.Execute ssql
Set ors=CreateObject("ADODB.RecordSet")
ors.open ssql, conn, 1,3
rscount=ors.recordcount
Redim Curdate(rscount),CP(rscount),YL(rscount),WD(rscount)
ors.movefirst
Curdate(1)=ors.fields("Curdate").value
CP(1)=ors.fields("Product").value
YL(1)=ors.fields("Pressure").value
WD(1)=ors.fields("Tempreture").value
For i=1 To rscount-1
ors.movenext
Curdate(i+1)=ors.fields("Curdate").value
CP(i+1)=ors.fieldS("Product").value
YL(i+1)=ors.fields("Pressure").value
WD(i+1)=ors.fields("Tempreture").value
Next
Set ors=Nothing
conn.close
Index.Write Index.Read + 1
'Msgbox Index.Read
If Index.read <=rscount Then
Product.Write CP(Index.read)
Pressure.Write YL(Index.read)
Tempreture.Write WD(Index.read)
' Msgbox Index.read
'写入用户归档
id.Write -1
job.Write 6
'Msgbox j
'把ERP_Task表格finished字段修改成‘已完成’
con1="Provider = SQLOLEDB.1;password = sa;user id = sa;Initial Catalog =ERP;Data Source = " & PCName & "\WINCC"
Set conn1=CreateObject("ADODB.Connection")
conn1.ConnectionString=con1
conn1.open
ssql1="update task set finished=N'是' where CurDate='" & CurDate(Index.read) & "' and Product='" & CP(Index.read) & "' and Pressure=" & CStr(YL(Index.read)) & " and Tempreture=" & CStr(WD(Index.read))
conn1.Execute ssql1
End If
If Index.read>=rscount Then
Index.Write 0
Download.Write 0
End If
End If
End Function
当“下达任务”按钮点击后,二进制内部变量download变成1,全局脚本有效,然后查询sql表ueser_task
,逐条读取记录,将值传给PLC变量,同时用户归档做记录。如果读完最后一条user_task表格记录,download恢复0,行序号index恢复0,如果切换到用户归档页面,就可以看到记录。
这样完成后,整个需求的基本功能就完全实现了。但是这种思路有不完善的地方:
1. 定时逐条给下位机传送配方参数,如果遇上上下位机通讯问题,配方不能及时下达,那么生产就会中断,实际使用可以考虑一次性把所有配方下载到PLC。
2. 我们在选择配方任务时,如果遇到标注已完成的,就没必要再次选择下达任务,这个在ERP_Task控件点击的脚本中可以再完善一下。
标签:控件,Task,ERP,用户,ors,Set,User,归档,TextMatrix 来源: https://www.cnblogs.com/fishingsriver/p/14356133.html