PROGRESS编程其实很简单


2023年12月16日发(作者:赶集网招聘最新招聘附近工作)

转帖]PROGRESS编程其实很简单(1-3)

PROGRESS编程其实很简单(1-3)

我可以很负责任的告诉你:Progress编程,其实很简单!

PROGRESS属于4GL数据库语言,没有指针没有类也不用搞什么高级接口等,入门起来简直比吃饭还容易,当然,我还告诉你,精通它其实也很容易!

《PROGRESS编程其实很简单》序列教程,只讨论编程的问题,一切数据库管理方面的知识,可以参见另一序列《精通PROGRESS数据库管理》!

其实,针对这2方面的Manual有好几本书,英文版挺厚的,但是个人觉得,实际上真正常用的也就那么几个,所以恭喜你,8小时以后,你就会成为专家了!当然,Manual毕竟是Manual,要留存,以防有些很偏僻的应用需要检索。

接下来的教程学习,需要有一个实际的Progress编程环境!本教程案例基于HP-UX的Progress 9.1D。

Now go ......

PROGRESS编程其实很简单(一)

一、变量定义。

变量必须在第一次被使用之前定义,可以定义在程序的任何地方!但是通常为了增加程序的可读性,变量定义都放在程序的开始处!以下是变量定义的几个实例:

define variable str01 as string label "DemoString" initial "hello".

def var str02 like str01.

def var dt01 as date extent 5.

def var inte01 as inte format ">>>9".

说明,第一行:

str01 是变量名, 变量名不要与系统关键字重复,字符或者下划线开头,比如strModel,_Model ;

string 表示变量类型,本例指字符型变量,其它类似的比如integer,date,logical等 ;

label 就是后续程序中对变量的描述,比如需要用户输入这个变量值时,系统提示“DemoString" ;

initial 变量的初始值

第二行:

def和var都是简写,def是define的简写,var是variable的简写;PROGRESS支持语法简写,但是初学者最好先写全,后面有经验了再简写。

like和as的不同点是:as后面直接说明变量类型,而like后面跟另外一个变量或者字段。

第三行:

extent 5 ,表示该变量是数组变量。

第四行:

format ">>>9" 变量格式

指定变量的格式一个最大的好处就是预留宽度,这个对变量的输入或者报表的输出都很有用的。

比如年份的宽度一定是4位的,那么你就可以指定格式 format "9999"。

PROGRESS程序每行结束必须有个“.”号!!!

二、注释。

注释就是用/* ... */ ,可以嵌套,比如

/*---注释1

/* 注释2 */

---*/

三、记录的显示。

如果进入PROGRESS编程模式以后连接了数据库,那么直接显示记录的值即可,比如:

for each TABLE_NAME:

display TABLE_NAME.

end.

/*显示TABLE_NAME所有字段所有记录*/

或者:

find first TABLE_NAME.

display TABLE_NAME.

/*显示TABLE_NAME第一条记录所有字段的值*/

通常显示记录值都是采用这2种方式!当然,可以按要求显示特殊的字段,比如:

for each pt_mstr where pt_model begins "E" no-lock break by pt_price:

disp pt_model pt_price.

end.

这个程序看起来真的很容易明白,简单说明:

1、where 后面带条件,比如 = <> <= >= 等等,这种关系符,对数字、日期或者字符串,都适用;

关于条件的几种组合举例:

条件1 and 条件2

( 条件1 or 条件2)and (条件3 or 条件4)

not 条件1

2、no-lock,这是关键字,你只要记住:

如果接下来的程序要对记录进行修改,那么不能加no-lock,如果不要,请加上no-lock;

3、break by ,就是按某个字段排列,默认是按这个字段的升序,如果降序则后面加上 desc,比如:

break by pt_price desc。

如果需要多次排列,那么by几次就可以,比如:

break by pt_price by pt_date

另外一个常用的显示或者更新记录的语句是find!比如:

find pt_mstr where pt_model = "mainboard" no-lock no-error.

find first pt_mstr where pt_price <= 10 no-error.

find last pt_mstr where pt_price <= 10 no-error.

说明:

1、where后面的条件跟for each语句类似;

2、no-lock的作用跟for each的no-lock也是一样的;

3、no-error,通常是find就加上,否则如果不到满足条件的记录,系统会出错误提示;而实际上,通常需要在程序自己判断结果;

4、find first 就是定位第一天满足条件的记录;find last 定位最后一条满足条件的记录;

4、还有一种叫find next,就是定位当前记录的下一条;

5、find 和 find first / find last 不同的是,find后面带的条件,通常是满足TABLE的某个唯一索引。

关于for each 和 find,这章你只要了解到这里就OK了!

四、判断。

判断最简单了,就是一个if 条件 then ... else ...,比如:

if str01 = "cpu" then disp "CPU"

else disp "Not CPU".

当然,这个”条件“可能有很复杂的组合。如果,涉及到的动作比较多,那么做法是用d ... end.,比如

if str01 = "cpu" then d

str01 = "my cpu".

disp "CPU".

end.

else d

str01 = "my memory".

disp "Not CPU".

end.

if 支持嵌套,怎么嵌套?你自己会了!不是吗?

五、循环。

PROGRESS的循环功能实在令人不敢恭维,没有when 没有while,没有loop、for什么的,只有一个repeat!

不过,用好了这个repeat,一样实现任何功能。

通常实现循环的模式:

repeat:

/*处理事务*/

if 条件 then leave. /* 退出循环 */

end.

现在,你试试用find 和 repeat 实现 for each的功能!

六、赋值和计算。

+ - * / ,就是 加 减 乘 除了!比如:

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命令: unix COMMAND

PROGRESS编程其实很简单(二)

PROGRESS程序架构。

PROGRESS启动应用程序,通常都是先启动一个主程序,比如mf.p,这个mf.p做一些全局变量设置,并初始化应用程序菜单。当用户执行菜单功能时,实际上是运行菜单所指定的程序!在这种模式下,PROGRESS的程序一般都不大,结构明了可读性很强,每个程序目的非常明确,但是也要遵循一定的准则,方便以后的阅读和修改。

一、程序扩展名的设定。

.p 主程序(可直接运行,或者编译以后挂主菜单被调用)

.i 子程序(经常使用的执行某一特定功能,或者为了使主程序易于阅读脱离出来)

.v 验证程序

.w Windows的程序(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程序里是错误的哈!

define variables.

{mfdtitle.i} //程序头,全局变量定义等,是标准QAD的菜单程序就请加上这个,不要问为什么

form with frame a. //定义格局(包含输入输出)

Mainloop:

repeat:

prompt-for … editing: //通常这里输入主要字段(如果比如订单号,料件名称等)

{mfnp.i} //前后记录显示功能,常用

end.

/* ADD/MODI/DELETE */

assign global…

find …

if not available … //新记录

{mfmsg.i 1 1} //类似mfmsg的子程序,都是信息提示类

create …

assign …

end.

Status = stline{2}.

update go-on (F5 or Ctrl-D) //继续维护剩余字段

if F5 or CTRL-D then d //判断是否按了删除键,一般定义是F5或者Ctrl + D

del-yn = yes.

{mfmsg01.i 11 1 del-yn}

end.

End.

Status input.

五、报表类程序的模板。

{mfdtitle.i}

form definition [selection criteria]

part colon 15 part1 colon 40 label {t001.i}

effdate colon 15 effdate1 colon 40 label {t001.i}

with frame a side-labels width 80.

//以上4行定义用户输入“限制报表输出”的条件,比如生效日期啊什么的

repeat:

if part1 = hi_char then part1 = “”. //如果用户不输任何东西,则默认最大字符或者最小字符,以下类似

if effdate = low_date then effdate = ?.

if effdate1 = hi_date then effdate1 = ?.

data statements [selection criteria]

bcdparm = "".

{mfquoter.i part } //BATCH专用,至今没用过,体会不到好处,哪位帮忙解释一下?

{mfquoter.i part1 }

{mfquoter.i effdate}

{mfquoter.i effdate1 }

{mfselbpr.i “printer” 132} //选择打印机的子程序

if part1 = “” then part1 = hi_char.

if effdate = ? Then effdate = low_date.

if effdate1 = ? Then effdate1 = hi_date.

{mfphead.i or mfphead2.i} //报表头

for each…

display

{mfrpchk.i} or {mfrpexit..i} //报表结束

end.

{mfrtrail.i} or {mftr0801.i} or {mfreset.i} //报表结束、打印结束等

end.

六、查询类程序模板。

这个比报表来得要简单些了:

{mfdtitle.i}

form definition [selection criteria]

with frame a side-labels width 80.

repeat:

data statement [selection criteria] with frame a.

{mfselprt.i “terminal” 80 }

for each [selection criteria]

display …

{mfrpchk.i} (max page)

end.

{mfreset.i} (scroll output)

{mfmsg.i 8 1}

end.

PROGRESS编程其实很简单(三)

这章,重点解释PROGRESS报表的精髓 first-of() & last-of() 。

首先给出本章教程用到的示例信息---demo表的结构和数据。

因为测试环境只连接了一个数据库,所以本文所有对字段的引用都直接写出来而没有特别指明表名,如果是多数据库环境,则需要带表名。

(比如数据库名是dtbl,表名是demo,那么对字段的引用应该是:)

【结构】

【数据】

1、first-of() & last-of()的语法;

先看示例:

for each demo break by :

if first-of() then disp .

end.

/*结果是显示hp和ibm两条记录*/

很明显可以看出来的就是,每个first-of或者last-of对应的字段,必须有for each ... break by来对应它,否则语法错误(即使first-of的字段是索引也会出错)。

比如以下语句会出错:

for each demo no-lock:

if first-of() then disp .

end.

2、函数的功能;

first-of()函数的功能,就是通过break by 对该字段进行排序,然后对该字段相同的记录进行“预览”,当第一次出现时发生!比如,示例中,break by首先对进行排序,这样会出现很多vend是“hp”和“ibm”的记录,当第一次出现“hp”记录和第一次出现“ibm”记录时,各显示一下该vend名称。

last-of()一样,不同的是“最后一次出现时发生”!

请看示例:

for each demo break by

if last-of() then disp demo.

end.

这段程序的结果如下:

通过收货日期和数量等,可以看到,每条记录,都是相同“mdlno”的最后一条

3、应用;

通过以上分析,不知道大家有没有懂的真正的意思呢?

现在如果要实现这样的报表,那又该怎么写程序呢?

对每个mdlno收货进行合计,然后在mdlno的下一行显示合计数,类似这样的结果:

不看答案自己想想看。

参考答案(为方便阅读暂不用accum()函数):

DEF VAR ttl AS DECI.

OUTPUT TO c:.

FOR EACH demo BREAK BY

ttl = ttl + .

PUT SKIP .

IF LAST-OF() THEN d

PUT " 合计" ttl SKIP.

ttl = 0.

END.

END.

OUTPUT CLOSE.

说明:first-of

汇总!

和 last-of 可以对应多个 break by的字段,比如可以先按mdlno汇总,再按 vendor


本文发布于:2024-09-23 12:28:10,感谢您对本站的认可!

本文链接:https://www.17tex.com/fanyi/4944.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:程序   比如   变量
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议