需求分析:
1、具体需求
本《按地区分组输出客户列表》有如下需求:
- 从客户表获取数据后,按地区进行分组;
- 客户列表按客户编号升序排序,同时输出序号以了解一个地区存在的客户数量;
- 每行客户记录前输出选择框,同时在不同数据前显示图标。
2、开发分析
要达成本实践目标,需要综合ABAP的数据输出实现方式:
- 如实践4-A1,可通过ABAP的Open SQL从表中获得要输出的数据存储到内表,因为要通过地区分组显示,同时在每一个地区组中记录按客户编号列升序排列,因此要对内表的记录用地区、客户编号列进行排序;实现的方式可以是使用标准内表然后用SORT语句,或者用键列为地区、客户编号的排序内表;
- 在显示时相同的地区名称只显示一次,可以用一个变量存储上一记录的地区名称,然后逐一执行输出时用IF语句判断本记录的地区名称是否与上一地区名称相同,不同则表示为新的地区分组;还有另一种方式是用AT NEW事件,不过使用此事件需要一定的条件,在使用时需特别注意;
-
在数据输出时可以输出选择框、图标、符号等,因此在代码中要先通过“TYPE-POOLS”定义要使用的库ICON、SYM,随后才能在代码中定义及输出图标、符号。
开发思路如图。
实践步骤:
本实践通过程序编辑器(SE38)即可完成,编写的代码将有如下几部分组成,按开发人员风格不同,其组成部分并非强制一致。
No | 部分 | 说明 |
---|---|---|
1 | 程序声明 | 声明本程序执行后是否包含标准标题,数据输出宽度和每页的行数量为多少,另需考虑页脚输出 |
2 | 对象定义 | 通过定义类型池以在程序中使用相应的图标,通过定义要使用的以变量或常量或要使用的表结构等,以在程序执行过程中计算和存储临时值 |
3 | 页眉页脚 | 通过代码设置输出页眉页脚 |
4 | 获取数据 | 从表中获得要输出的数据数据并存储到内表中以待后续输出 |
5 | 输出数据 | 将内表中的数据按要求输出,本代码可有2种方式实现:条件、AT NEW事件。 |
1、程序声明
程序声明部分的代码如下:
REPORT zu0402_cust_region NO STANDARD PAGE HEADING
LINE-SIZE 100 LINE-COUNT 62(2).
通过如上代码定义,程序输出时,页面宽度为100(能容纳100个数字或英文字符),每页输出区域为62行,其中页眉最下方2行为页脚,上方的60行则为页眉和数据区。
2、对象定义
对象定义部分的代码如下:
*****对象定义
TYPE-POOLS: icon, " 定义图标库以在程序中使用图标
sym. " 定义符号库以在程序中使用符号
TYPES: BEGIN OF cust_type, " CUST_TYPE-类型名称
region TYPE ztcustomer-region,
city TYPE ztcustomer-city,
customerid TYPE ztcustomer-customerid,
customername TYPE ztcustomer-customername,
address TYPE ztcustomer-address,
contact TYPE ztcustomer-contact,
cphone TYPE ztcustomer-cphone,
END OF cust_type.
DATA:cust_stru TYPE cust_type,
cust_itab TYPE SORTED TABLE OF cust_type
WITH UNIQUE KEY region customerid,
prv_reg TYPE ztcustomer-region, " 记录前一个地区
cnt TYPE i, " 客户序号
c_box(1) TYPE c, " 输出选择框
nxt_page(3) TYPE n. " 下一页页码
TYPE-POOLS,是ABAP数据字典中的类型组,在其中包含了对类型、变量常量等的定义,在程序中通过此语句指定类型组后,可以在代码中引用其对象,如如上代码中,icon、sym指定后,则可在代码中使用icon_address等以显示相应的图标。
另外注意本程序中类型cust_type的定义,在其中region是类型的第一个字段,如此定义的目的是为了满足AT NEW事件的需要,如果REGION在此案例中不是第一个,那么使用AT NEW时则不能得到预期的结果(按客户数据除非第1个字段为country,第2个字段是region)。
在类型cust_type定义后,也用此类型定义了一个结构cust_stru用于在数据循环输出时存储从内表读取的数据,而如果内表定义为含WorkArea(也称为HeadLine,则不需要定义结构,直接使用内表的WA)。
随后定义的cust_itab为按region、customerid排序的内表,如此定义后,则将数据select到内表时已经是按要求排序的,不需要再进行排序;如果没有定义为排序内表,则方式有2:
方式1-select:select XXX into table 内表 from 表 order by 排序字段;
方式2-sort table: select时无order by,然后sort 内表 by 排序字段。
3、页眉页脚
页眉页脚部分的代码如下:
*&----------------------------------------------------------------------*
*& 输出页眉
*&----------------------------------------------------------------------*
TOP-OF-PAGE. " 页眉事件
WRITE:/5 '客户列表',sy-datum, 80 '页码:', 86 sy-pagno.
WRITE:/5 sy-uline.
*&----------------------------------------------------------------------*
*& 页脚定义
*&----------------------------------------------------------------------*
END-OF-PAGE.
nxt_page = sy-pagno + 1.
SKIP 1.
WRITE:/60 '下一页',(3) nxt_page.
如上代码定义了页眉页脚的输出,其中sy-datum、sy-pagno为系统标准变量,表示当前日期和当前页码;另外从如上定义,页眉占2行,页脚也占2行。
4、获取数据
获取数据部分的代码如下:
*&----------------------------------------------------------------------*
*& START-OF-SELECTION
*&----------------------------------------------------------------------*
START-OF-SELECTION. " 数据处理事件
*****获得客户信息
SELECT "通过SELECT 语句从表ZTCUSTOMER中获得数据并赋值到内表
region city customerid customername address contact cphone
INTO TABLE cust_itab
FROM ztcustomer.
如上代码通过select语句获得数据并存储到内表,注意select后的字段及顺序必须与cust_type中相同,否则数据到了内表就不能对应到相应的列或者因为类型不能自动转换导致出错。
5、输出数据
输出数据部分的代码如下:
*****按地区分组输出客户列表
LOOP AT cust_itab INTO cust_stru.
*---通过判断语句确定新地区---*
IF cust_stru-region <> prv_reg. " 当前行的地区名称与上一行不一样时
cnt = 0. " 重置每一地区分组的客户记录序号
FORMAT INVERSE ON COLOR = 7. " 设置文字颜色为橙色
RESERVE 5 LINES. " 如果页面余留行不足5,则换页输出,
" 以保持地区名称与第一个客户记录再同一行
WRITE:/5(4) cust_stru-region, '地区',
/5(60) sy-uline.
ENDIF.
prv_reg = cust_stru-region. " 将当前行的地区名称赋值给变量,以待下一行记录处理
**---通过AT语句确定新地区---*
* AT NEW region. "获得新的地区值的记录时
* cnt = 0.
* FORMAT INVERSE ON COLOR = 7.
* RESERVE 5 LINES.
* WRITE:/5(4) cust_stru-region, '地区',
* /5(60) sy-uline.
* ENDAT.
FORMAT RESET.
cnt = cnt + 1.
RESERVE 3 LINES. "如果页面遗留的行不足3,则换页输出
WRITE:
/10 c_box AS CHECKBOX, (2) cnt, 15(6) cust_stru-customerid,
'/', cust_stru-customername,
/20 icon_address AS ICON, '详细地址:', (8) cust_stru-city,
'/', cust_stru-address,
/20 icon_usergroup AS ICON, '联系方式:', (8) cust_stru-contact,
'/', icon_phone AS ICON,
cust_stru-cphone HOTSPOT.
SKIP.
AT END OF region. "在相同地区的最后一条记录时执行
WRITE:/10(4) cust_stru-region, '地区共有',(2) cnt, '个客户'.
SKIP.
ENDAT.
ENDLOOP.
因为对地区名称分组,一个地区名称只出现一次,如上代码中通过2种方式予以实现,编辑代码时可以通过注释或取消注释启用一个方式。
同时,在WRITE语句中通过 as checkbox、as icon等进行选择框、图标等的输出。
在一个地区的客户记录都输出后,通过AT END OF指定要输出的内容,结果如图所示。
如上从上到下各部分代码则是组成实现本实践的全部代码,编写完成后激活,则可进行程序的测试发布。
本实践小结:
1、输出控制
1)输出为图标符号选择框热点
语法:WRITE 输出内容 AS 选项
选项 | 说明 |
---|---|
AS ICON | 输出内容为TYPE-POOLS(类型组)ICON中的固有常量,按此语法后输出为图标。 |
AS SYMBOL | 输出内容为TYPE-POOLS(类型组)SYM中的固有常量,按此语法后输出为符号。 |
AS CHECKBOX | 输出为选择框,如果输出内容的第一个内容不为空,则为选择状态,反之则为非选择状态。 |
HOPSPOT | 输出为热点,鼠标移动到内容后,将切换为可点击的样式。 |
2)输出在同一页
语法:RESERVE n LINES.
此语句用于实现输出在同一页面,后面一般是输出语句,如果检查到页面遗留的行不足指定的n,则输出语句的内容换页输出。
2、系统变量
系统变量 | 说明 | 系统变量 | 说明 |
---|---|---|---|
SY-LINCT | REPROT语句中设定的LINE-COUNT | SY-DATUM | 当前服务器日期 |
SY-LINSZ | REPROT语句中设定的LINE-SIZE | SY-UZEIT | 当前服务器时间 |
SY-SROWS | 当前窗口的列表行数 | SY-INDEX | 循环说执行的次数 |
SY-SCOLS | 当前窗口的列表栏目数 | SY-TABIX | 内表循环的次数 |
SY-PAGNO | 当前页的页码 | SY-MANDT | 当前登录的Client号 |
SY-LINNO | 当前选定行的行号 | SY-STEPL | 当前表格控件中操作记录的行号 |
SY-COLNO | 当前选定列的列号 | SY-LOOPC | 当前表格控件在屏幕中的总行数 |
SY-LSIND | 当前列表索引,第一级列表为1 | SY-UCOMM | PAI所出发的功能代码 |
SY-LILLI | 选择某行时光标行位置 | SY-DYNNR | 当前屏幕号 |
SY-CUROW | 选择某行时光标列位置 | SY-MSGID | 消息类 |
SY-ULINE | 水平线 | SY-MSGNR | 消息编号 |
SY-VLINE | 垂直线 | SY-MSGTY | 消息类型 |
SY-SUBRC | 语句执行后的返回值,0表示成功 | SY-MSGV1~4 | 消息变量 |
3、REPORT事件
在ABAP中通过不同的事件,确定不同的处理方式。
(实践A2 End)