数据库
首页 > 数据库> > 搬家第四天-89.Wincc V7.3 用户归档深入8-用户归档结合数据库控件使用vbs脚本模拟从ERP任务表到控制系统配方

搬家第四天-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