VBA 单链表

链表很重要,可以看做其他复杂数据结构的基础。

首先需要建立一个结点,这个结点是一个类,每个节点中包含数据和指向下一个结点的变量。建立如下代码

建立链表类,这个类包含头部结点变量,当前结点变量,还有结点的个数,代码如下

定位函数,我们要获取或者修改某一个结点,必须把pCurrent变量指向这个结点。

添加代码如下

添加结点代码

删除结点代码

获取结点值

至此一个简单的链表实现了

具体代码如下

结点类代码

Option Explicit

 

Public data As String ‘数据

Public pNext As Node ‘引用,指向下一个接点

 

‘构造函数

Private Sub Class_Initialize()

data = “”

Set pNext = Nothing

End Sub

 

‘析构函数

Private Sub Class_Terminate()

Set pNext = Nothing

End Sub

链表类代码

Option Explicit

 

Public pHead As Node

Public pCurrent As Node

Public intSize As Integer

 

Private Sub Class_Initialize()

Set pHead = New Node

Set pCurrent = pHead

End Sub

 

Private Sub Class_Terminate()

Set pHead = Nothing

Set pCurrent = Nothing

End Sub

 

Public Sub index(i As Integer)

Dim j As Integer

If i < -1 Or i > intSize – 1 Then

MsgBox “Parameter out of range”

Exit Sub

End If

Set pCurrent = pHead

j = -1

If i = -1 Then

Exit Sub

End If

Do While j < i

Set pCurrent = pCurrent.pNext

j = j + 1

Loop

End Sub

 

Public Sub insert(i As Integer, strData As String)

If i < -1 Or i > intSize Then

MsgBox “Parameter out of range”

Exit Sub

End If

Dim j As Integer

Dim p As Node

Call index(i – 1)

Set p = New Node

p.data = strData

Set p.pNext = pCurrent.pNext

Set pCurrent.pNext = p

intSize = intSize + 1

Set p = Nothing

End Sub

 

Public Sub delete(i As Integer)

If intSize = 0 Then

MsgBox “Empty list”

Exit Sub

End If

If i < -1 Or i > intSize – 1 Then

MsgBox “Parameter out of range”

Exit Sub

End If

Call index(i – 1)

Set pCurrent.pNext = pCurrent.pNext.pNext

intSize = intSize – 1

End Sub

 

Public Function getData(i As Integer) As String

If i < -1 Or i > intSize – 1 Then

MsgBox “Parameter out of range”

Exit Function

End If

Call index(i)

getData = pCurrent.data

End Function

我们在窗口中看一看这个链表的使用

参考代码如下

Option Explicit

 

Dim List1 As LinkList

 

Private Sub CommandButton1_Click()

Set List1 = New LinkList

Dim i As Integer

For i = 0 To 50

Call List1.insert(i, CStr(Rnd * 100))

Next i

For i = 0 To 50

Me.ListBox1.AddItem (List1.getData(i))

Next i

End Sub

这个代码只是示例学习用的,还可以改进的,比如intSize变量可以做属性封装,只允许读取不允许写入,index函数应该定义成私有函数,这里就不再讨论了。

徐大军

Application的事件

之前我在帮助文档中看到这个对象有事件,模仿了Excel的使用方法,结果不起作用,联系了GE的技术支持,回复说事件不起作用,是手册写错了。

这里只是Excel做的示例

添加类模块

添加按钮,执行代码

点击按钮之后,添加新的工作表会触发事件

徐大军

VBA 类与实例

我们常说VB是基于对象的编程语言,这个面向对象语言是有区别的,面向对象的语言有三个特征:封装,继承,多态。VB不支持继承,多态,目前来看也足够我们用了。我们先来学习一下类,类是数据和方法的封装,类就是一个模板,用它来创建具体的变量实例。

我们创建一个人的类,人具有姓名和年龄的属性,具有说话的能力也就是方法,对事物刺激的反应也就是事件。

创建类

进入到VBA界面编辑器,点击画面右键,选择”类模块”

更改名称”类1″为 “Person”

添加私有变量,参见下图,strName和intAge属于私有变量,我们是不能访问的

接下来,添加构造函数,也就是实例化的时候,可以给这个人个名字,因为VB不支持带参数的构造函数,我们实例化的时候,可以给姓名和年龄赋初值

然后我们要添加属性,人名和年龄都允许读写

这里还有一点不完善的地方,比如设置的年龄超过了150岁,这样就不合理了,我们可以做个限制

再给这个类添加一个说话的功能,也就是方法,可以说出自己的姓名和年龄

事件的学习是个棘手的概念,比如说有人要修改我的年龄了,我应该告诉关心这件事情的人或者物,而且事件的代码并没有封装到类中,而是写到了别处,暂时没有好的解释办法,先看代码吧。注意年龄修改属性代码中添加脚本,别漏掉

创建实例

我们像添加类模块的模式,添加一个用户窗口

窗口中添加一个按钮

进入到代码窗口,添加代码,这里实现了类,并调用了实例的方法

点击运行按钮

点击窗口中的按钮

到这里,我们还有事件代码没有添加,我们选择对象下拉列表,选中P,会自动添加事件代码

我们在实践中添加如下代码

运行效果如下

类和实例是很复杂的概念,这里的描述没能结合具体的实际应用,只是讲了一些基本的概念,在实现复杂的数据结构的时候,我们必须使用类,这里面还牵扯到堆栈,引用等概念,可能后续会讲到。

徐大军

VBA 过程

VBA过程分为有返回值和无返回值的,有返回值的叫函数,无返回值的叫子过程,我也不明白为什么要这么分,感觉应该是一个东西。

过程可以放在grf页面窗口,frm页面窗口,模块中。

子过程定义示例如下

函数定义示例如下

函数的参数是可选的,但是要放在必选参数之后

徐大军

VBA 数据类型

VBA的数据类型与VB相同,这里不做详细的说明。

需要注意的是关于两个赋值的关键字,Let和Set,看下面的定义

Let是用来给值类型的变量赋值的,这个关键词可以省略,Set是用来给引用类型赋值的,而且不允许省略。

徐大军

iFIX VisiconX控件的使用

VisiconX控件主要是方便我们对数据库的访问,不用使用代码,不用使用SQL语句。

主要包含以下几个控件

vxCombo对象

vxData对象

vxGrid对象

vxList对象

其中vxData是获取数据的,剩下的三个主要用来显示获取的数据。

vxData对象

添加vxData对象到画面

双击vxData,选中如下数据库接口程序

选择实数数据库,也就是PDB数据库,点击测试连接按钮

转到纪录源的页面,点击”Run SQL Wizard”按钮

点击下一步

点击”SQL Select”

添加可用表,然后下一步

添加标签名,然后下一步

创建行过滤,我们这里把有”ALM”字符的标签提取出来

排序不需要设置

生成查询语句


确定之后返回主画面

画面中添加vxList控件

关联vxList控件的动画

切换到运行模式,我们把包含ALM字符的标签全部读取到了xvList中

提供一个典型应用的例子,之前实现过一个功能,就是获取当前所有的用户名,根据用户名和时间段,查询用户的操作记录,里面牵扯到使用控件的P属性

我这里使用的是SQLserver数据库,用户权限管理和操作记录功能都是编程实现的,这里只做简单的介绍,知道怎么用控件查询数据即可。

用户登录表

操作记录表,这里是测试用的数据

先获取所有用户名到下拉列表中

添加DTPicker控件,也就是时间设定


徐大军

iFIX定时器

iFIX定时器控件和VB中的定时器有一些区别,主要在启动这一块。我们添加一个long型的局部变量var1

在窗体中做数据戳显示这个变量

我们在定时器脚本中写下如下代码

切换到运行画面,var1变量每隔一秒自动加一

我们添加定时器停止的代码

再添加定时器的启动按钮,注意启动必须使用方法,只设置属性是不起作用的

徐大军

iFIX标签组

标签组主要用来替换画面中关联的标签,打开画面的时候,可以选择不同的标签组,就可以显示关联不同标签的画面。

比如一个画面要显示很多阀门的状态,我们可以做一幅画面,多个阀门的标签组,点击不同的阀门,打开关联不同标签组的同一幅画面。

我在这里演示个简单的例子。

先设置虚拟Modbus从站,界面如下,我们使用00001开始的线圈。

建立PDB数据库中的标签,如下图,我们建变量的时候要在”高级”选择”启用输出”

新建一个名为Main的画面,添加两个按钮,如下图所示

再建一个名为lab的画面,如下

添加一个指示灯和一个按钮

双击指示灯,做如下设置,注意标签中的名称Fix32.FIX.@tihuan@.F_CV

按钮我们使用如下设置,主要是输入专家的设置,也要注意标签

为了区分我们打开的是哪个标签,我们把按钮的显示值也做个替换

设置完成后,打开标签组编辑器

填入如下内容,然后保存为lab1

再新建一个标签组,填入如下内容,保存为lab2

返回main界面

点击DI1按钮,使用打开画面专家,设置如下

点击DI2按钮,使用打开画面专家,设置如下

切换到运行模式

点击不同的按钮,出现不同的画面,可以关联控制不同的对象。

标签组就讲这些内容吧。

徐大军

iFIX语言切换

iFIX可以做多种语言切换,这里只做中文和英文切换的示例。

先了解两个语言的设置,点击”首页””‘–>”设置”–>”用户首选项”,弹出如下界面,选择”画面自定义”,其中”语言”设置就是新建画面时的默认语言

点击画面右键,在菜单中选择”属性窗口”,可以查看画面的当前语言,目前是中文。

下面开始讲解如何做画面的中英文切换

在系统树中,参见下图,找到”翻译工具栏”,然后双击,弹出翻译工具栏

我们在画面中添加一个文字标签,标签内容”中文标签”,然后再添加两个按钮,按钮的caption属性分别设置为中文和英文,参见下图,并保存画面

在”翻译工具栏”中,点击”导出多个语言文件”,先导出中文,设置如下,然后点击导出

再导出英文

打开画面所在文件夹,我们会发现导出的中文和英文的语言文件(CSV格式)

我们用Excel打开英文语言文件,文件里面列出了各个控件的属性,里面包含一个标签,两个按钮,按照下图所示修改其中的”翻译文字”为英文

分别给两个按钮添加事件,代码如下

其中的数字代表不同的语言,可参见帮助手册

切换到运行模式,点击不同的按钮即可实现页面语言的切换

注意:上述的方法只是实现了自身画面语言的切换,其实还有一个函数实现所有画面语言的切换,但是对已打开的画面不起作用。

设置成英文模式

SetLanguage LANG_English

设置成中文模式

SetLanguage LANG_Chinese_PRC

可以把上述代码放到起始画面或者登陆画面中,这样在系统运行初期即可切换中英文系统。

徐大军

iFIX过程数据库(PDB数据库)

过程数据库也叫PDB数据库,它是一个实时性的数据库。

点击”首页”—>”选项”,这里面有个刷新周期,也就是我们打开PDB数据库的时候,如果通信正常的话,每隔5S刷新一次各标签的值

点击”首页”—>”属性”,为了使用方便,我通常会把常用的列显示出来,我这里添加几项

设置后

设置后显示的PDB数据库

另外两个有用的功能是导入和导出,我们在添加标签的时候,一个个的添加和设置会很麻烦,尤其是变量特别多的时候。我这里做个示范,现在PDB中添加一个AI类型的标签,还是使用虚拟的Modbus从站

我们导出PDB数据库文件,文件格式是CSV,我们用Excel打开这个文件

在添加一个标签,修改一下标签名和地址,其它相同的设置要复制一下

 

然后导入,导入后的效果

 

徐大军