PROGRESS编程其实很简单(二)
这章,重点解释PROGRESS报表的精髓 first-of() & last-of() 。
首先给出本章教程用到的示例信息---demo表的结构和数据。
因为测试环境只连接了一个数据库,所以本文所有对字段的引用都直接写出来而没有特别指明表名,如果是多数据库环境,则需要带表名。
(比如数据库名是dtbl,表名是demo,那么对字段的引用应该是:dtbl.demo.mdlno)
【结构】
【数据】
1、first-of() & last-of()的语法;
先看示例:
for each demo break by demo.vend:
???? if first-of(demo.vend) then disp demo.vend.
end.
/*结果是显示hp和ibm两条记录*/
很明显可以看出来的就是,每个first-of或者last-of对应的字段,必须有for each ... break by来对应它,否则语法错误(即使first-of的字段是索引也会出错)。
比如以下语句会出错:
for each demo no-lock:
???? if first-of(demo.vend) then disp demo.vend.
end.
2、函数的功能;
first-of()函数的功能,就是通过break by 对该字段进行排序,然后对该字段相同的记录进行“预览”,当第一次出现时发生!比如,示例中,break by首先对demo.vend进行排序,这样会出现很多vend是“hp”和“ibm”的记录,当第一次出现“hp”记录和第一次出现“ibm”记录时,各显示一下该vend名称。
last-of()一样,不同的是“最后一次出现时发生”!
请看示例:
for each demo break by demo.mdln
???? if last-of(demo.mdlno) then disp demo.
end.
这段程序的结果如下:
通过收货日期和数量等,可以看到,每条记录,都是相同“mdlno”的最后一条
3、应用;
通过以上分析,不知道大家有没有懂的真正的意思呢?
现在如果要实现这样的报表,那又该怎么写程序呢?
对每个mdlno收货进行合计,然后在mdlno的下一行显示合计数,类似这样的结果:
不看答案自己想想看。
参考答案(为方便阅读暂不用accum()函数):
DEF VAR ttl AS DECI.
OUTPUT TO c:\demoout.txt.
FOR EACH demo BREAK BY demo.mdln
????ttl = ttl + demo.qty.
????PUT demo.mdlno demo.rcvdt demo.qty SKIP .
????IF LAST-OF(demo.mdlno) THEN d
?????? PUT "???????????????????? 合计" ttl SKIP.
?????? ttl = 0.
????END.
END.
OUTPUT CLOSE.
说明:first-of?? 和??last-of 可以对应多个 break by的字段,比如可以先按mdlno汇总,再按 vendor汇总!
?
I 1 2 3 4
?
?
?
|
PROGRESS语言是一种非可视化的编程语言,符合4GL规范,具有高级语言的优点,可以进行条件选择(IF、WHERE)、嵌套循环(FOR)、计算(如求和、求平均)等操作,还可以直接进行打印、显示(PUT、DISPLAY),并且不区分大小写。 |
?
|
PROGRESS源程序一般由4部分组成:全局变量定义、图形变量定义(一般是用户指定的查询选择条件)、输出数据的格式和主程序(如何利用数据库中的字段生成用户需要的正确数据)。 |
?
?
|
全局变量用define variable 关键字定义。格式如下: |
?
|
define variable w1 like(数据格式integer,character……) |
?
|
define varialbe w2 as variable2 |
?
|
使用as可以直接引用已经定义好的数据格式。比如我们要把某个变量定义成和表中的字段类型一致时,可直接定义如下: |
?
|
define varialbe1 as 表中定义的字段 |
?
|
这样我们就不用再到后台数据库中去查询该字段的数据格式,提高了编程速度。如果这个变量在调用过程中也要用到,则分别定义如下: |
?
?
|
define shared variable w1 like (数据格式integer,character……) |
?
?
|
define new shared variable w1 like (数据格式integer,character……) |
?
?
|
数据类型 |
缺省格式 |
示例 |
|
字符型(character) |
x(8) |
dongnan |
|
日期型(data) |
99/99/99 |
03/02/99 |
|
布尔型(logical) |
yes/no |
yes |
|
浮点型(decimal) |
->>,>>9.99 |
12.00 |
|
整型(integer) |
->,>>>,>>.9 |
12 |
|
?
?
|
图型变量的定义主要是把已经定义好的变量在界面上显示出来。 |
?
?
?
?
|
rect-frame at row 1 column 1.25 |
?
|
rect-frame-label at row 1 column 3 no-label view-as text size-pixels 1 by 1 |
?
?
?
|
entity colon 25 label ‘会计单位’ entity1 colon 50 label “至” |
?
?
|
acc colon 25 label ‘账户’acc1 colon 50 label “至” |
?
|
sub colon 25 label ‘分账户’ sub1 colon 50 label “至” |
?
|
ctr colon 25 label ‘成本中心’ ctr1 colon 50 label “至” |
?
|
begdt colon 25 label ‘生效日期’ enddt colon 50 label “至” |
?
|
subflag colon 25 label ‘汇总分账户’ |
?
|
ccflag colon 25 label ‘汇总成本中心’ |
?
|
rpt_curr colon 25 label ‘货币’ |
?
|
with frame a side-labels attr-space width 80 |
?
?
|
cname colon 25 label ‘摘要’ |
?
?
?
?
?
|
报表格式的定义非常简单,只要用at和to标出相对位置即可: |
?
?
?
?
?
?
?
?
?
|
“account description” at 1 |
?
?
?
?
?
?
|
with stream-io /*gui*/ frame phead1 page-top width 186. |
?
|
at和to 表示数据在frame phead1 上的相对位置。不同之处在于,at后边的数据表示从该点开始,而to后边的数据表示到该点结束。特别要注意的是,在progress中,只能画横线,不能画竖线。 |
?
?
|
对于数据的处理,本文主要介绍如何读取数据,以及在编程时需要注意的地方。 |
?
|
我们以账户余额查询报表为例。当在数据库的表中查找数据时,使用下述语句: |
?
?
?
?
?
?
|
find first or last (表) where (条件)。 |
?
?
?
?
|
在progress中,有两对语句first 和first-of、last和last-of,这两个判断语句非常重要,常用于判断循环的开始还是结束以及循环中的分类是开始还是已经结束。 |
?
|
first(break-group ):当前的循环是循环体的第一次循环则返回true,如果不是则返回false; |
?
|
first-of(break-group ):当前的循环是循环中的分类的第一次循环则返回true,如果不是则返回false; |
?
|
last(break-group ):当前的循环是循环体的最后循环则返回true,如果不是则返回false; |
?
|
last-of(break-group ):当前的循环是循环中的分类的最后一次循环则返回true,如果不是则返回false。 |
?
|
如果程序需要处理大量的数据,可以使用调用过程。调用过程可以采用*.p或者*.i文件。它们的区别在于*.i文件是包含文件,在编译时不生成相应的*.r文件;而*.p文件生成相应的*.r文件。 |
?
|
注意:如果在过程中多次使用到同一个表,必须定义一个buffer格式: |
?
|
define buffer ww like (表名) |
?
|
ww为表的别名。如果不定义buffer,编译时将出现“table 无法辨别!”的警告。 |