You are on page 1of 38

PML基础

王元
AVEVA中国

1
1
课程将包括...

▼ PML介绍
– PML概念
– PML功能
– PML构成
▼ PML程序语言
– 变量的定义及用法
– 循环Do、判断If、跳转Golabel
– 错误处理
– 文件处理
– 函数Functions、方法Method
– 对话框Forms和菜单Menu

课程结束后 ...

▼ 您会具有以下知识 …
– PML构成及功能
– 编写简单的宏
– PML变量的定义及应用
– PML函数/方法的定义及调用
– PML窗体/对象的定义及调用

2
2
PML - 功能强大的语言

▼ Programmable Macro Language可编程宏语言


▼ PML2基于面向对象(Object Oriented)概念的编程
语言
▼ 支持用户可自定义对象类型(Object Types)
▼ 简单易学,与PDMS无缝连接
▼ 丰富的内置函数,方法及对象
▼ 最简单的对话框,菜单编写语言

PML构成

▼ Macros
– Macros是包含PDMS 命令序列的ASCII文件
– Macros 在 PDMS 中通过 $m /FILENAME来执行
▼ PML
– 变量(Variables)
– 判断语句(if Constrcuct)
– 循环(Do loops)
– 错误处理(Error Handling)
– 文件处理(Files and Directories)
▼ 窗体和菜单
– PDMS大多数应用程序都由对话框 (Forms)和菜单
(Menus)来驱动

3
3
一个简单的 Macro

▼ 宏是包含PDMS 命令序列的一个文本文件

ASCII 文件
MYFILE NEW EQUIP /FRED
NEW BOX
XLEN 300 YLEN 400 ZLEN 600
NEW CYL DIA 400 HEI 600
CONN P1 TO P2 OF PREV
▼运行宏
$M /MyFile

参数化宏Parameterized Macro
一个简单的 Macro ,继续,
▼ 宏可以参数化

ASCII 文件
MYFILE NEW EQUIP /$1
NEW BOX
XLEN $2 YLEN $3 ZLEN $4
NEW CYL DIA $3 HEI $4
CONN P1 TO P2 OF PREV

▼文件名后面的字符串是参数(parameters)
$M /MyFile NEWEQUIP 300 400 600

4
4
宏的参数

▼ Macros 可以有多达 9 个由空格分隔的参数.


$M /MyFile PML TRAINING 55 66
▼ 文本字符串可以以单个参数输入
$M /MyFile $< PML TRAINING $> 55 66
和 $> 是分隔符,在它们之间的任何字符都被
▼ $<
认为是单个参数

变量Variables

▼ 变量基本概念
– 变量用于存储数值,变量必须有名字,变量的数值可以改
变,但变量名是固定的.
▼ PML变量
– 在PML2中变量是一个对象(Objects)
• 每一个对象(变量)有一个唯一的名字
• 每一个对象都有一套函数与之相关联,这些函数称为方法
(Methods).方法用于处理对象中的数据
• 生成对象时必须指明对象类型(Object type),不同的对
象类型对应不同的方法

5
5
对象(变量)类型Object Types

▼ 内置(Build-in)的对象类型
– 字符串类型(String).如‘Hello World’
– 实数类型(Real).整数类型包括在实数类型中,如99
– 布尔类型(Boolean).用于逻辑表达式,如True,False
– 数组类型(Array).可以存储任意类型的数据

▼ 系统定义(System-defined)的对象类型
– 指在PDMS中的变量类型,如Positon,Reference

▼ 用户自定义(User-defined)的对象类型

生成、查询、删除变量

▼ 通过赋值声明变量类型
!MyString = ‘Hello World’
Q var !MyString
显示<STRING> 'Hello World'

▼ 直接声明变量类型
!Length = Real()
Q Var !Length
显示<REAL> Unset

▼ 删除变量用到方法
!MyString.Delete()

6
6
变量命名规则(Naming Conventions)

▼ 局部变量(Local)和全局变量(Global)
!SurfaceArea ! 表示局部变量
!!Area !!表示全局变量
▼ 变量名最长 16 个字符(不包括!和!!),变量名可以
包含字母和数字
▼ 变量名不能用数字和点(.)开头
▼ 变量名的大小写不敏感
▼ 建议:一个变量一个用途,最好给变量名一个有意义
的名字,并且区分大小写
!!StartInUpperCase

PDMS属性类型-系统定义变量类型
▼ 字符串(String) 如Name,Description,Function
▼ 实数(Real) 如Angle,Temperature
▼ 布尔(Boolean) 如Lock,Shop,Built
▼ 数组(Array) 如Level
▼ 参考(Reference) 如Spref,Catref,Lstube

▼ 关键字(Word) 如Type,Purpose
▼ 位置(Position) 如Position,Hposition
▼ 方位(Orientation) 如Orientation

▼ 方向(Direction) 如HDirection

7
7
变量提取属性

▼ 用变量提取属性值,变量名=属性名
!Name = Name
!Desc = Description
!Pspec = Pspec
!Temp = Temp
!Purp = Purp
▼ 查询属性类型
!Ref = Ref
Q var !Ref

变量给PDMS属性赋值

▼ 属性名 $变量名,其中$表示将变量的值转换成字符
串,PDMS命令行只接受字符串的值
– 给名字赋值,第一个字符必须是/
Name $!Name
– 给字符串赋值,必须用单引号括起来
Desc ‘$!Desc’
– 给实数赋值
Temp $!Temp
– 给参考赋值,参考元素必须存在
Pspec $!Pspec
– 给关键字赋值,只提前四个字符,不用括号
Purp $!Purp

8
8
练习-变量给属性赋值

▼ 从Pipe提取下列属性
– Bore
– Desc
– Temp
– Pspec
– Purp
▼ 新建Pipe,相应属性与前一个Pipe一样
New Pipe

方法(Method)和函数(Function)

▼ 函数(Function)是执行特定功能的子程序
▼ 方法(Method)是对象(变量)的函数
– 在PML2中变量是一个对象(Objects)
• 每一个对象(变量)有一个唯一的名字
• 每一个对象都有一套函数与之相关联,这些函数称为方法
(Methods).方法用于处理对象中的数据
• 生成对象时必须指明对象类型(Object type),不同的对
象类型对应不同的方法
– 方法并不改变对象的类型和对象中的值
▼ 参考手册Cadcentre Software Customisation
Reference Manual

9
9
方法-字符串对象(String Object)

▼ 字符串长度 Length()
▼ 类型转换 Real(),Position(),Boolean()
▼ 大小写转换 LowCase(),UpCase()
▼ 两端截取 After(str2),Before(str2),Substring(index)
▼ 中间截取 Substring(index,nchars)
▼ 分隔符截取 Part(nth),Part(nth,delim)
▼ 替换 Replace(str2,str3)
▼ 匹配 Match(str2),MatchWild(str2)
▼ 分割 Split()
▼ 修剪 Trim(),Trim(option)

方法实例

!line = 'hello how are you'


!newline = !line.after(‘hello’).trim().upcase()
q var !newline
<String> ‘HOW ARE YOU’

10
10
PML表达式

▼表达式运算符(Expression operators)
– 算术运算符
+-* /
– 和并符
&
– 比较运算符
EQ NE LT LE GT GE
– 布尔运算符
NOT AND OR

表达式说明

▼表达式可以嵌套
▼表达式前后的类型必须一致
!X = 64
!Y = 32
!Z = !X + !Y !Z = 96
!A = ‘Hello ’
!B = ‘World’
!AB = !A + !B !AB = ‘Hello World’
!XY = !X & !Y !XY = ‘6432’

11
11
标准函数

▼ 标准函数(Function)
– SIN COS TAN ASIN ACOS ATAN
– SQR POW ABS 平方 开方 绝对值
– LOG ALOG 对数 反对数
– INT NINT 取整 四舍五入取整
– MATCH,DMATCH 匹配 中文字符匹配
– MAX,MIN 最大值 最小值
▼ 标准函数用法见Reference Manual
C.3.2 Numeric (Real) Functions

函数应用

!s = 30 * sin(45)
!len = Length(‘abcdef’)
!t = pow(20,2)
!sqr = sqr(4)
!m = match ( ’abcdef’ , ’cd’ )
!f = (match(Func of Zone,’Piping’) gt 0)

12
12
定义函数

▼ 函数定义成全局变量
define function !!Area( !Length is REAL, !Width is REAL ) is REAL
!Area = !Length * !Width
return !Area $*函数!!Area有两个参数一个返回值
Endfunction
▼ 文件命名和存放位置
Pmllib/NewPml

functions forms objects


area.pmlfnc xxx.pmlfrm xxx.pmlobj
文件名必须与函数名一样,后缀是小写的pmlfnc

PML通用功能-注释

▼ 单行注释
--This is a new-style PML comment
----------------------------- -
$* The following lines calculate the new angle
!Z = !X + !Y $* We are assuming both !X and !Y are REAL

▼ 段落注释
$(
skip if (!X EQ !Y)
$)

13
13
函数调用

▼ 将新建函数加到索引文件Pml.index中
Pml Rehash All
▼ 调用函数并且得到返回值
!MyArea = !!Area(6,4)

PML通用功能-打印等

▼ 打印
$P This text will be output to the screen
▼ 换行
$P This is an example of a much longer message $
that will be output to the screen

▼ 退出程序
if ( count EQ 0 ) then
return
endif

14
14
逻辑控制(Control Logic)

▼ 四种逻辑控制结构
– 条件判断语句 If…else…endif
– 循环语句 Do …enddo
– 跳转 Label Golabel
– 错误处理 Handle

条件判断语句(If Construct)

▼ 判断表达式中必须是布尔值
!Type = Type
!OwnType = Type of Owner
IF (!Type eq ‘BRAN’) THEN
$P CE is Branch.
ELSEIF (!OwnType eq ‘BRAN’) THEN
$P CE is Branch member.
ELSE
$P CE is $!Type,Pls select Branch.
ENDIF
▼ Elseif,else都是可选项

15
15
判断常用例程

▼ 判断变量值是否存在
!x =real()
用函数判断 用方法判断
If(Unset(!x)) then… if(!x.Unset()) then…
If(Set(!x)) then… if(!x.Set()) then…
▼ 判断布尔值
!MyString = ‘True’
If(!MyString.Boolean()) then

练习-条件判断

▼ 判断当前元素类型(Type),添加当前元素和连接元

– 如果是‘BRAN’,add Href和add Tref
– 如果是‘NOZZ’,add Cref
– 打印当前元素类型
– 打印加入的元素个数

16
16
循环(Do loops)

▼ 循环赋值
Do !x From 1 To 100 By 1
!Total = !Total + !x
Enddo
▼ 中断循环 Break
Do !x From 1 To 100
!Total = !Total + !x
If(!Total gt 500) then
Break 或者Break if(!Total gt 500)
Endif
Enddo

跳过循环(Skip)

▼ 用skip 跳过奇数
Do !x From 1 To 100
If(Int(!x / 2) NE (!x / 2)) then
Skip 或者Skip If(Int(!x / 2) NE (!x / 2))
Endif
!Total = !Total + !x
Enddo

17
17
跳转(Jump)

▼ 用golabel可以跳转到标记行,不限制前后顺序
Label /Start

GoLabel /Start
▼ Label名最长 16 个字符,不包括’/’
▼ 不允许跳转到Do循环中
golabel /illegal
do !x from 1 to 5
!Total = !Total + !x
label /illegal
enddo

错误提示

▼ 测试程序
Next
$p OK
▼ 可能出现的错误
(2,113) List exhausted
2 表示错误出现在PDMS中的哪个模块
113 是错误代码
▼ 出现错误通常有三种结果
– 出现一个警告框,用户必须确认
– 输出一个错误信息
– 从当前运行的程序中退出

18
18
错误处理(Error Handling)

▼ 处理特定错误,使程序继续执行
Next
Handle (2,113)
$p Last element.
EndHandle
$p OK
▼ 处理任何可能的错误
Next
Handle Any
EndHandle
$p OK

数组(Array)
▼ 从字符串创建数组
!Str = ‘Benz,Bmw,Audi’
!BestCar = !Str.Split(‘,’)
Q var ! BestCar
<ARRAY>
[1] <STRING> ‘Benz'
[2] <STRING> ‘Bmw‘
[3] <STRING> ‘Audi‘ $*数组元素,索引号
▼ 逐个元素添加
!BestCar[4] = ‘Cadillac’
▼ 数组追加
!BestCar.Append(‘Lincoln’) $*数组必须存在,否则提前声明

19
19
方法-数组对象(Array Object)

▼ 数组元素数量 Size()
▼ 追加元素 Append(value)
▼ 追加数组 AppendArray(Array)
▼ 删除全部元素 Clear()
▼ 删除单个元素 !MyArray[N].Delete()
▼ 删除数组 Delete()
▼ 压缩数组 Compress()
▼ 排序 Sort()
▼ 倒序 Invert()
▼ 搜索 Find(value),FindFirst(value)
▼ 和并重复项 Unique()

数组循环

▼ 赋值循环Do value
do !Name values !BestCar
$p Array element is $!Name
enddo
▼ 索引循环Do indices
do !n indices !BestCar
!Car = !BestCar[!n]
$p Array element $!n is $!Car
enddo

20
20
特殊方法生成数组(Collections)

▼ 指定类型
Var !PipeComps Collect all Branch members For CE
生成的!PipeComps是数组,保存的是元素的参考号
▼ 类型用法示例
ALL 所有元素
ALL Pipe 所有的Pipe
BRANCH MEMBERS 所有管件,不包括Tube
ALL BRANCH MEMBERS 所有管件,包括Tube
ITEMS OF EQUI /D1201 设备中的所有基本体

继续…

▼ 限制条件
Var !Elbows Coll All Elbow With (Abor gt 100) for CE
With后面是一个表达式
▼ 限制区域
Var !Elbows Coll All Elbow Within W0N0U0 to
W2000N2000U2000

Var !Elbows Coll All Elbow Exclusive Within Volume


/D1201 1500
▼ 追加
Var !Elbows Append Coll all Bend for CE

21
21
求值(Evaluate)

▼ 管道排序
Var !Pipes Coll all Pipe for ce
Var !Names Eval name for all from !Pipes
!Name.sort().invert()
Do !n indices !Names
reorder $!names[$!n] before $!n
EndDo

文件处理(Handling Files)
▼ 读写文件需要使用FILE对象
!Input = object FILE(‘%pdmsexe%abc.txt')
!Lines = !Input.ReadFile() $* ReadFile将文件内容写到字符串数组

!ResultArray = ARRAY() $* 声明新数组
do !Line VALUES !Lines
!Column1 = !Line.Part(1)
!ResultArray.Append( !Column1)
Enddo
!Output = object FILE('%pdmsexe%def.txt')
!Output.WriteFile(‘WRITE’, !ResultArray) $* WriteFile将数组写到文

▼ ReadFile()方法可以自动打开(Open)和关闭(Close)文件
▼ 写文件还有覆盖模式‘OVERWRITE’和追加模式‘APPEND’

22
22
练习-文件处理

▼ 将一个文本文件的内容显示在命令行中

!!CE Object

▼ 一个特殊的PML GLOBAL variable(全程变


量 )!!CE 常常是指向当前的PDMS元件及它的属性:

!BranchHeadBore = !!CE.Hbore
!HeadPosition = !!CE.Hposition
!Easting = !HeadPosition.East
▼ 相对于其它元件的位置:
!PosWRTValve = !HeadPosition.WRT(!Valve)

23
23
Alert Objects

▼ 有三种类型的无返回值的 alert :
!!Alert.Error( ’You cannot do this!’ )
!!Alert.Message( ‘Saving your data now' )
!!Alert.Warning( ‘Do not press this button again!' )
▼ 缺省情况,警告窗口出现在光标附近,可用X,Y
值指定其在屏幕上的位置
!!Alert.Error( ’You cannot do this!’ , 0.25, 0.1)

Alert Objects

24
24
Alert Objects

▼ 有三种类型带返回值的Alert:
confirm, question 和 input
▼ Confirm Alerts
!Answer = !!Alert.Confirm( ‘Are you sure!’ )
Confirm alerts 返回 ‘YES’ or ‘NO’
▼ Question Alerts
!Answer = !!Alert.Question( ‘OK to delete Site?’ )
Question alerts 返回 ‘YES’ or ‘NO’ or ‘CANCEL’

Alert Objects
▼ Input Alerts
!Answer = !!Alert.Input( ‘Enter Width of Floor’,’10’ )
第一个值是输入提示,第二个值是缺省值。
Input alerts 返回一个字符串值

25
25
Forms

▼ Forms 是由全局变量表示的一种对象类型
▼ 查询Forms:
q var !!formname
将列出form的所有属性及其所有gadget成员
▼ 查询 gadget :
q var !!formname.gadgetname
q var !!formname.gadgetname.val

FROM定义

setup form !!myform


Title ‘My Form Title’
Icontitle ‘Myform’
!!myform.initcall = ‘!this.init()’
..…
exit

define method .init()


.....
endmethod

26
26
显示和隐藏 Forms

▼ 新的搜索机制,不需预先加载
▼ 显示FORM:
show !!formname
有时,只LOAD FORM,而不用显示很有用
▼ 加载FORM,而不显示
loadform !!formname

Forms的内置METHOD

▼ 显示 form:
!!Myform.Show()
▼ 隐藏 form:
!!Myform.Hide()
▼ 查询FORM是否隐藏
if ( !!Myform.Shown() ) then
:
endif

27
27
Form Gadgets

▼ 在后面会见到许多种form gadgets
▼ 在form中定义gadgets, 通常有两个目的.
– 定义gadgets 在form中的区域
– 如果gadgets被选择,定义它的调用执行
– 每个gadgets 的大小和位置决定 决定其占据的区域
▼ Gadget 的 CALLBACK 来启动gadgets 的调用执行

Gadgets 的内置Method

▼ Gadgets 是有许多Members的 Object,可使用许多有用的


内置Method :
▼ 变灰一个 gadget:
!!Myform.GadgetName.Active = FALSE
▼ 使键盘键入收敛在某个 gadget:
!!Myform.GadgetName.SetFocus()

28
28
Callbacks 调用

▼ 任何一个可选择的gadget 在它创建时都有一个
callback
▼ 这个 callback 可执行以下三种功能
– 显示一个 form
– 直接执行一条命令
– 调用一个函数function或方法method
button .opt |Options…| call |show !!optionsform|
button .del |Delete| call |delete equipment|
button .apply |Apply| call |!!Myfunction()
button .apply |Apply| call |!this.MyMethod()|

Form Callbacks (Initcall初始化)

▼ Form的 initialisation callback 允许Form的


gadgets被初始化
▼ 可以用Form的 initcall member: INITCALL
‘Callbackstring’ 来设置Callback
▼ 或直接用 !!MyForm.initcall = ‘Callbackstring’
– 注意: 这个 callback 绝不能用来显示另一个Form.

29
29
Form Callbacks (OK)

▼ OKCALL callback 允许操作接受当前gadget 设置


▼ 可用命令OKCALL ‘Callbackstring’ 建立 Form的
OKCALL member
▼ 任何时候可修改Ok callback
!this.Okcall = ‘Callbackstring’

Form Callbacks (Cancel)

▼ CANCELCALL callback 允许操作不处理


▼ 可用命令CANCELCALL ‘Callbackstring’ 建立
Form的CANCELCALL member
▼ 任何时候可修改Cancel callback !this.Cancelcall
= ‘Callbackstring’

30
30
一个简单的 Form...

setup form !!hello


Title ‘My Form Title’
Icontitle ‘Myform’ ……SG specific
paragraph .Message text ‘Hello world’
button .bye ‘Goodbye’ OK
exit

Gadget 定位

▼ Gadgets are positioned on a form from top left


Gadgets原点在FORM的左上角

Form Origin

Gadget Origin

31
31
Gadget 定位

▼ 每个Gadget 有四个定位点
– XMIN, XMAX YMIN YMAX YMIN
▼ 可用以下语法定位Gadgets YMAX

XMIN

XMAX
At Xmin .apply Ymax - 0.5
at ymin
at xmax .frame1 + 4
▼ 定位Gadgets 在FORM的右下角
at xmax form - size

Gadgets 的相对布置
▼ 相对上一个 Gadget

Toggle .OnOff at XMIN YMAX+1

32
32
Gadgets 的相对布置

▼ 相对一个指定的 Gadget

Toggle .OnOff at XMIN .Gadget1-size YMAX .Gadget1 +1

Gadget 布置

▼ Path 命令可用来定位下一个Gadget的逻辑位置
– PATH DOWN 表示下一个Gadget在当前Gadget的下方
– PATH RIGHT表示下一个Gadget在当前Gadget右方
▼ gadgets 之间的垂直和水平间距由 VDIST 和
HDIST控制
▼ 可用 HALIGN 和 VALIGN 来水平方向和垂直方向
对齐
– 选项LEFT,RIGHT,TOP 和BOTTOM控制上、下、左、
右对齐
– 例如: HALIGN LEFT 水平左对齐

33
33
Gadget 布置

Paragraph Gadgets

▼ Paragraph 是一个简单的命名的gadgets,它用来
在FORM上显示文本或图片.
Para .cwd at 0 0 Text 'Current Directory'

This is a paragraph gadget

34
34
Buttons按钮

Button .Button ‘Pop Form’ FORM !!PopForm


Button .Calculate ‘Calculate’ Callback ‘!!MyFunctionName()’
Button .Apply ‘Apply’ Callback ‘!!MyFunction()’
Button .ok ‘OK’ Callback ‘!!MyFunction()’ OK
Button .cancel ‘Cancel’ Callback ‘!!MyFunction()’ CANCEL
Button .reset ‘Reset’ Callback ‘!!MyFunction()’ RESET
Button .help ‘Help’ Callback ‘!!MyFunction()’ HELP
Button .dismiss ‘Dismiss’ ok

Frame

▼ Frame 类似一个镜框,包含一些相似的gadgets.
▼ FRAME的语法:
FRAME .MYFRAME AT 0 3 ‘My Frame’
BUTTON .B1 ‘Press Here
BUTTON .B2 ‘Or Press Here’
EXIT

35
35
文本输入的Gadgets

▼ Text input gadget 提供用户输入值的位置


Text .DirName callback '!This.TopDir()' AT X 0 Width 50
is String

This is a text entry gadget

List Gadgets

▼ List gadget 允许用户作单项选择或多项选择


List .SubDirs 'Sub Dirs’ CallBack '!This.SDirs()’ Width 60
Hei 4
List .Files |Teams| Width 60 Hei 9

This is a list gadget

36
36
Textpane Gadgets

▼ TEXTPANE 提供一个可编辑多行文本的区域,可
以从区域内剪切、粘贴、删除文本
Textpane .textp ‘MyTextpane’ at x3y6 width 50 hei 6

This is a textpane

Buttons

▼ 改变 button的背景颜色:

!!Workbench.Apply.Background = 2
▼ 为 button增加一个图片:

Button .Apply pixmap /c:/pml/aveva.bmp

37
37
PML练习 4

▼ 把一个建立梯子(Ladder)的
宏,转换成一个函数
▼ 定义函数!!Ladder,用3个变
量:
– !name, !height !width
– 注意每个变量的数据类型
– 调用函数:
!!Ladder(‘myladder’,3000,350)
– 注意:调用函数时,确保在ZONE

PML练习 5

▼ 建立窗体FORM
▼ 建立Method : convertctof()
▼ 进行摄氏温度和华氏温度的
转换,并返回结果值
▼ 转换公式:
degf = degc *1.8 + 32
degc = (degf – 32) / 1.8
▼ 建立Method : temrange()
▼ 把批量转换结果以数组形式
显示到温度转换表中
▼ 建立Method :inputs()
▼ 以空格为分隔,反向字符串
排列

38
38

You might also like