Proress学习.docx
《Proress学习.docx》由会员分享,可在线阅读,更多相关《Proress学习.docx(27页珍藏版)》请在冰点文库上搜索。
Proress学习
PROGRESS编程其实很简单
(一)
一、变量定义。
变量必须在第一次被使用之前定义,可以定义在程序的任何地方!
但是通常为了增加程序的可读性,变量定义都放在程序的开始处!
以下是变量定义的几个实例:
definevariablestr01ascharlabel"DemoString"initial"hello".
defvarstr02likestr01.
defvardt01asdateextent5.
defvarinte01asinteformat">>>9".
说明,第一行:
str01是变量名,变量名不要与系统关键字重复,字符或者下划线开头,比如strModel,_Model;
string表示变量类型,本例指字符型变量,其它类似的比如integer,date,logical等;
label就是后续程序中对变量的描述,比如需要用户输入这个变量值时,系统提示“DemoString";
initial给变量赋初始值
第二行:
def和var都是简写,def是define的简写,var是variable的简写;PROGRESS支持语法简写,但是初学者最好先写全,后面有经验了再简写。
like和as的不同点是:
as后面直接说明变量类型,而like后面跟另外一个变量或者字段。
第三行:
extent5,表示该变量是数组变量。
第四行:
format">>>9" 指定变量格式
指定变量格式一个最大的好处就是预留宽度,这个对变量的输入或报表的输出都很有用的。
比如年份的宽度一定是4位的,那么你就可以指定格式format"9999"。
PROGRESS程序每行结束必须有个“.”号!
!
!
二、注释。
注释就是用/* ... */,可以嵌套,比如
/*---注释1
/*注释2*/
---*/
三、记录的显示。
如果进入PROGRESS编程模式以后连接了数据库,那么直接显示记录的值即可,比如:
foreachTABLE_NAME:
displayTABLE_NAME.
end.
/*显示TABLE_NAME所有字段所有记录*/
或者:
findfirstTABLE_NAME.
displayTABLE_NAME.
/*显示TABLE_NAME第一条记录所有字段的值*/
通常显示记录值都是采用这2种方式!
当然,可以按要求显示特殊的字段,比如:
FOREACHpt_mstrWHEREpt_modelBEGINS"E"NO-LOCKBREAKBYpt_price:
DISPpt_modelpt_price.
END.
这个程序看起来真的很容易明白,简单说明:
1、where后面带条件,比如= <> <=>=等等,这种关系符,对数字、日期或者字符串,都适用;
关于条件的几种组合举例:
条件1and条件2
(条件1 or条件2)and(条件3or条件4)
not条件1
2、no-lock,这是关键字,你只要记住:
如果接下来的程序要对记录进行修改,那么不能加no-lock,如果不要,请加上no-lock;
3、breakby,就是按某个字段排列,默认是按这个字段的升序,如果降序则后面加上desc,比如:
breakbypt_pricedesc。
如果需要多次排列,那么多by几次就可以,比如:
breakbypt_pricebypt_date
另外一个常用的显示或者更新记录的语句是find!
比如:
findpt_mstrwherept_model="mainboard"no-lockno-error.
findfirstpt_mstrwherept_price<=10no-error.
findlastpt_mstrwherept_price<=10no-error.
说明:
1、where后面的条件跟foreach语句类似;
2、no-lock的作用跟foreach的no-lock也是一样的;
3、no-error,通常是find就加上,否则如果找不到满足条件的记录,系统会出错误提示;而实际上,通常需要在程序自己判断结果;
4、findfirst就是定位第一条满足条件的记录;findlast定位最后一条满足条件的记录;
4、还有一种叫findnext,就是定位当前记录的下一条;
5、find和findfirst/findlast不同的是,find后面带的条件,通常是满足TABLE的某个唯一索引。
关于foreach和find,这章你只要了解到这里就OK了!
四、判断。
判断最简单了,就是一个if条件then...else...,比如:
DEFINEVARstr1ASCHARINITIAL"CPU".
IF str1="CPU"THENDISP"cpu".
ELSEDISP"NOTcpu".
当然,这个”条件“可能有很复杂的组合。
如果,涉及到的动作比较多,那么做法是用do:
...end.,比如
DEFINEVARstr1ASCHARINITIAL"CPU".
IF str1="CPU"
THEN
DO:
str1="MyCPU".
DISP
"cpu".
END.
ELSE DO:
str1="Mymemory".
DISP"NOTcpu".
END.
DISPstr1.
if支持嵌套,怎么嵌套?
你自己会了!
不是吗?
五、循环。
PROGRESS的循环功能实在令人不敢恭维,没有when没有while,没有loop、for什么的,只有一个repeat!
不过,用好了这个repeat,一样实现任何功能。
通常实现循环的模式:
repeat:
/*处理事务*/
if条件thenleave./*退出循环*/
end.
现在,你试试用find和repeat实现foreach的功能!
REPEAT:
FINDNEXTpt_mstr.
DISPpt_mstrWITH2COLUMNS.
END.
或
DEFVARiASINTEGER.
FOREACH pt_mstrWHEREpt_price>10NO-LOCK.
i=i+1.
DISPpt_partpt_priceWITHDOWNFRAMEa.
IFi>200THENLEAVE.
END.
六、赋值和计算。
+-* /,就是加减乘除了!
比如:
ttl_amoount=ttl_ammount+dtl_amount.
x_a=x_b/x_c.
str_ttl="I'm"+"sure!
".
dt01=today-1.
dt01=3/22/2005./*日期*/
当然,日期和字符串不能做乘法或者除法!
七、其它零星的语法。
显示:
display简写disp
退出编程模式:
quit
执行UNIX命令:
unixCOMMAND
好了,这章你学会了,如果熟悉数据库表和字段的结构,你也大概能看任何东西了,甚至做一些常规的统计也肯定没问题!
PROGRESS编程其实很简单
(二)
PROGRESS程序架构。
PROGRESS启动应用程序,通常都是先启动一个主程序,比如mf.p,这个mf.p做一些全局变量设置,并初始化应用程序菜单。
当用户执行菜单功能时,实际上是运行菜单所指定的程序!
在这种模式下,PROGRESS的程序一般都不大,结构明了可读性很强,每个程序目的非常明确,但是也要遵循一定的准则,方便以后的阅读和修改。
一、程序扩展名的设定。
.p主程序(可直接运行,或者编译以后挂主菜单被调用)
.i子程序(经常使用的执行某一特定功能,或者为了使主程序易于阅读脱离出来)
.v验证程序
.wWindows的程序(Windows版的Progress支持可视化的组件编程,组件拉一拉放一放,就自动生成.w的文件了)
.r编译后的程序(菜单调用时,实际上是执行.r的程序)
二、程序的命名规则。
主程序格式:
aa+bb+cc+dd.p
其中:
aa---系统模块ID
bb---系统功能
cc---程序类型(mt-维护、iq-查询或者rp-报表等)
dd---序列号
子程序格式:
通常是主程序a.i 主程序b.i 这样子
//关于程序的命名,个人觉得也没必要一定要遵循特定格式,一家公司有自己固定的命名方式,容易区分即可;如果是咨询公司或者系统集成公司,则要先了解客户的命名习惯和规则;同理,下面的“程序头”。
三、程序头。
以注释的形式,标明尽可能多的程序相关的信息,比如:
程序名(路径,不过路径一般都是企业自己规定好了)、作者、菜单号、功能(菜单标题)、创建日期、修改日志等。
至于格式,也就是POSE,爱怎么摆怎么摆,清楚明了即可。
但是,在同一家公司,风格应该统一。
另外,关于修改日志,个人觉得最好在程序头和程序体,都明显说明一下修改的日期和原因,要点。
(注释不记入程序长度,所以不要担心程序太长,:
p)
四、维护类程序模板。
注意:
为方便说明,注释暂时用“//”,但是在PORGRESS程序里是错误的哈!
definevariables.
{mfdtitle.i}//程序头,全局变量定义等,是标准QAD的菜单程序就请加上这个,不要问为什么
formwithframea.
//定义格局(包含输入输出)
Mainloop:
repeat:
prompt-for… editing:
//通常这里输入主要字段(如果比如订单号,料件名称等)
{mfnp.i}
//前后记录显示功能,常用
end.
/*ADD/MODI/DELETE*/
assignglobal…
find…
ifnotavailable…
//新记录
{mfmsg.i11}“加入新记录”
//类似mfmsg的子程序,都是信息提示类
create…建立新记录
assign…给新纪录的关键索引字段赋值
end.
Status=stline{2}.
updatego-on(F5orCtrl-D) //继续维护剩余字段
ifF5orCTRL-Dthendo:
//判断是否按了删除键,一般定义是F5或者Ctrl+D
del-yn=yes.
{mfmsg01.i111del-yn}
end.
End.
Statusinput.
五、报表类程序的模板。
{mfdtitle.i}
formdefinition[selectioncriteria]
partcolon15part1colon40label{t001.i}
effdatecolon15effdate1colon40label{t001.i}
withframeaside-labelswidth80.
//以上4行定义用户输入“限制报表输出”的条件,比如生效日期啊什么的
repeat:
if
part1=hi_charthenpart1=“”.
//如果用户不输任何东西,则默认最大字符或者最小字符,以下类似
ifeffdate=low_datetheneffdate=?
.
ifeffdate1=hi_datetheneffdate1=?
.
datastatements[selectioncriteria] bcdparm="".
{mfquoter.i part}//BATCH专用,至今没用过,体会不到好处,哪位帮忙解释一下?
{mfquoter.i part1}
{mfquoter.i effdate}
{mfquoter.i effdate1}
{mfselbpr.i “printer”132}
//选择打印机的子程序
ifpart1=“”thenpart1=hi_char.
ifeffdate=?
Theneffdate=low_date.
ifeffdate1=?
Theneffdate1=hi_date.
{mfphead.iormfphead2.i}
//报表头
foreach…
display
{mfrpchk.i}or{mfrpexit..i}//报表结束
end.
{mfrtrail.i}or{mftr0801.i}or{mfreset.i}//报表结束、打印结束等
end.
六、查询类程序模板。
这个比报表来得要简单些了:
{mfdtitle.i}
formdefinition[selectioncriteria]withframeaside-labelswidth80.
repeat:
datastatement[selectioncriteria] withframea.
{mfselprt.i“terminal”80}
foreach[selectioncriteria]
display…
{mfrpchk.i}(maxpage)
end.
{mfreset.i}(scrolloutput)
{mfmsg.i81}//列表完毕
end.
通过这章的学习,你对QAD的PROGRESS程序已经有大致的了解。
但是你可能还是感觉到,如果叫你做一些切实的东西,还摸不着门(什么?
你摸得着了,那么恭喜你,你可以请我吃饭了),没关系,才2小时呢,25%的课程而已,不急不急!
PROGRESS编程其实很简单(三)
这章,重点解释PROGRESS报表的精髓first-of()&last-of()。
首先给出本章教程用到的示例信息---demo表的结构和数据。
因为测试环境只连接了一个数据库,所以本文所有对字段的引用都直接写出来而没有特别指明表名,如果是多数据库环境,则需要带表名。
(比如数据库名是dtbl,表名是demo,那么对字段的引用应该是:
dtbl.demo.mdlno)
【结构】
【数据】
1、first-of()&last-of()的语法;
先看示例:
foreachdemobreakbydemo.vend:
iffirst-of(demo.vend)thendispdemo.vend.
end.
/*结果是显示hp和ibm两条记录*/
很明显可以看出来的就是,每个first-of或者last-of对应的字段,必须有foreach...breakby来对应它,否则语法错误(即使first-of的字段是索引也会出错)。
比如以下语句会出错:
foreachdemono-lock:
iffirst-of(demo.vend)thendispdemo.vend.
end.
2、函数的功能;
first-of()函数的功能,就是通过breakby对该字段进行排序,然后对该字段相同的记录进行“预览”,当第一次出现时发生!
比如,示例中,breakby首先对demo.vend进行排序,这样会出现很多vend是“hp”和“ibm”的记录,当第一次出现“hp”记录和第一次出现“ibm”记录时,各显示一下该vend名称。
last-of()一样,不同的是“最后一次出现时发生”!
请看示例:
foreachdemobreakbydemo.mdlno:
iflast-of(demo.mdlno)thendispdemo.
end.
这段程序的结果如下:
通过收货日期和数量等,可以看到,每条记录,都是相同“mdlno”的最后一条
3、应用;
通过以上分析,不知道大家有没有懂的真正的意思呢?
现在如果要实现这样的报表,那又该怎么写程序呢?
对每个mdlno收货进行合计,然后在mdlno的下一行显示合计数,类似这样的结果:
不看答案自己想想看。
参考答案(为方便阅读暂不用accum()函数):
DEFVARttlASDECI.
OUTPUTTOc:
\demoout.txt.
FOREACHdemoBREAKBYdemo.mdlno:
ttl=ttl+demo.qty.
PUTdemo.mdlnodemo.rcvdtdemo.qtySKIP.
IFLAST-OF(demo.mdlno)THENdo:
PUT" 合计"ttlSKIP.
ttl=0.
END.
END.
OUTPUTCLOSE.
说明:
first-of 和 last-of可以对应多个breakby的字段,比如可以先按mdlno汇总,再按vendor汇总!
progress中的数据库访问1
progress中的数据库是关系型的,具备关系型数据库的基本特征,当然没有像oracle那样复杂了,甚至说比sqlserver或者mysql都要简单。
最简单的还是progress语言访问自己的数据库。
这里假定你已经有了自己的数据库(关于数据库的创建和维护,以后再讲),这里主要说怎么开发。
1.数据库的连接
连接数据库,有两种方式,一个是动态连接,一种是静态连接。
所谓的静态连接就是在程序启动的时候数据库作为一个参数直接连接,这个是由prowin32命令实现的,对应的在unix下是_progress命令。
prowin32的使用格式如下:
prowin32-pmain.p-paramparamString-dbdbname-Tc:
emp-Hdbserver-S5000-pfc:
myappdb.pf-ininamec:
myappmyapp.ini
-P参数,就是指定你的主程序,当然也可以是.w文件
-param就是你要输入的参数。
我们知道,一般的程序或者命令需要参数,这个就是。
在c/c++或者java里访问参数是在main函数中,那么 progress怎么获取这个参数呢?
这就要说到一个系统句柄session,它有一个parameter属性,可以用这个来访问它。
比如iparameter=session:
parameter.整个参数是一个双引号引起来的字符串,如果你又多个参数需要输入,你可以把这下参数合并为一个以某字符分割的字符串列。
-db就是你要连接的数据库名字
-T表示你要使用的临时目录
-H是数据库所在的服务器名字或者IP
-S端口
-pf就是parameterfile,也就是说你可以把一些参数写在一个文件里.比如我想连接两个数据库db1,db2;可以写两个文本文件,内容分别是:
-dbdb1-Hdbserver-S5000和-dbdb2-Hdbserver-S5001然后分别存为db1.pf,db2.pf.你就可以prowin32-pmain.p-dfdb1.pf-dfdb2.pf同时连接两个数据库了.设置你还可以在.pf文件里面再次使用-pf参数
-ininame你要使用的ini文件,里面定义了你要使用的字体,颜色等等多对应的索引值.
那么动态连接,指的就是在程序文件里在进行连接,比如在main.p里边,可以使用connect语句:
connectdb-name|value(db-name).
比如connect-dbmydb1-Hdbserver-S5000.或者connectvalue("-dbmydb1-Hdbserver-S5000").后边的用法通常是可以把你的数据库连接参数化。
如有两个定义一样的数据库但是在不同的服务器上.或者在同一服务器上但是数据库名字不一样,你可以使用-ld选项,ld就是逻辑名.比如connect-dbmydb1-ldmydb2-Hdbserver-S5001.那么你就要使用mydb2前缀来引用mydb1数据库,相当于起了个别名。
注意一点的是,接下来访问数据库的语句不能和connect在同一个.p文件中,你必须把访问代码写在另外的.p文件中然后再调用之.
相应的
connected(db-name)
是一个用来判别数据库是否已经成功连接的函数.
disconnect则是用来断开数据库连接的,比如:
disconnectdb-name|value(db-name).
2.访问数据库中的表和字段
假设有这样的一个数据库,名字叫mydb,其中有一张表order:
field-name fieldtype
order-num char
cust-num char
goods char
quantity decimal
order-related char
这里假定你的开发环境已经连接了数据库(在开发环境中连接数据库是一个简单的事情,你只要按照几个参数-db-H-S填充就行了),那么引用数据库是这样:
var1=mydb.order.order-num.如果只有一个数据库的话,mydb.可以省略。
当你访问数据库的时候,需要用到以下语句:
foreach...和find...
foreachtable-namewherefield1=value1andfield1=value2...no-lock:
yourstatement.
end.
foreach语句的常用方法很简单,就是一个循环。
你的表名其实就是一个buffer--缓冲区。
progress会把数据库中的纪录取回到当前的缓冲区中。
当你访问数据库的时候,有三种锁可以使用,no-lock,share-lock和ex