需求分析:
1、具体需求
本《使用宏技术输出系统图标列表》有如下需求:
- 将系统中自带的图标输出为列表;
- 分页输出,并在每页的上方输出页码和列表抬头;
-
内容含四周(上下左右)框线输出。
其中列表输出效果如图5-1。
2、开发分析
要达成本实践目标,在不考虑使用模块化编程技术的情况下,其方式可有2种,如图5-2所示。
如上两种方式,都可以完成本实践,且实现的代码也并不复杂。如果使用方式1,一条记录一次输出,从效率上比较高,但代码的复用性比较弱,如有其他的需求,或同一个报表仅仅是增加一列,或需要指定另一个长度,或输出颜色要单独设置,那么输出数据、输出上/下横线的代码则都需要修改;使用方式2时,每个单元格的输出步骤都是类似的,可以充分使用ABAP的模块化编程技术,将输出一个单元格内容的完整步骤封装为一个模块,如此在相同的程序或不同的程序中都可以重复调用,如此代码的可读性、可维护性都将提高,当然,因为需要每个单元格都需独立完成一遍输出,效率会低点。
如果不考虑代码的可读性、可维护性、可重用性,不对方式2的代码进行模块化编程,每个单元格独立一次输出,此时使用方式2是完全没优势的,如此肯定是优先选择方式1;而在项目实践应用中,代码的可读性、可维护性、可重用性会更为重要,如此本实践使用模块化编程技术之一——宏予以实现。
实践步骤:
本实践通过程序编辑器(SE38)即可完成,编写的代码将有如下几部分组成,按开发人员风格不同,其组成部分并非强制一致。
No | 部分 | 说明 |
---|---|---|
1 | 程序声明 | 声明本程序执行后是否包含标准标题,数据输出宽度和每页的行数量为多少。 |
2 | 对象定义 | 通过定义类型池以在程序中使用相应的图标,定义要使用的变量等,以在程序执行过程中计算和存储临时值 |
3 | 宏定义 | 通过宏定义单元格内容,以及列表数据表头的输出 |
4 | 获取和输出数据 | 从表中获得要输出的数据,并调用宏将数据按要求输出 |
1、程序声明
程序声明部分的代码如下:
REPORT zu0501_icon_list_macro NO STANDARD PAGE HEADING
LINE-SIZE 100.
通过如上代码定义,程序输出时,页面宽度为100(能容纳100个数字或英文字符),不控制输出行数,而是在代码中定义。
2、对象定义
对象定义部分的代码如下:
****对象定义
TABLES icon. " 定义了一个与表icon同名的工作区
DATA: col TYPE sy-colno, " 用于记录输出位置的列
lin TYPE sy-linno, " 用于记录输出位置的行
length TYPE i, " 用于确定输出横线的长度
cnt(6) TYPE c, " 用于记录输出的序号
cntr TYPE i, " 用于记录输出的行数
pg TYPE sy-pagno. " 页码
如上代码,使用类型MAT_AG_TYPE定义了一个含工作区的标准内表,如此,在输出时,可以将内表数据遍历后放到内表自己的工作区中,而不需要另外一个结构存储。在实际开发中,偏向于使用不含工作区的内表,如此增加代码的可读性。
3、宏定义
本实践定义了2个分别用于输出单元格数据和输出列表数据抬头的宏,代码如下。
3.1、单元格数据输出宏
此部分代码如下:
*&---------------------------------------------------------------------*
*& DEFINE WRITE_GRID
*&---------------------------------------------------------------------*
* 定义宏输出单元格内容数据
* &1: 输出内容
* &2: 输出内容占位长度
* &3: 颜色设置,on,文字颜色,off 背景色
* &4: 背景颜色浓淡设置,on浓, off淡,如&3为on不起作用
* &5: 颜色代码color_XXXX
*----------------------------------------------------------------------*
DEFINE write_grid.
lin = sy-linno. col = sy-colno. "将当前输出所在行列赋值给变量
FORMAT INVERSE &3 INTENSIFIED &4 COLOR &5. "输出颜色设置
WRITE: sy-vline NO-GAP, (&2) &1 NO-GAP, sy-vline NO-GAP. "绘制左右竖线和内容
length = sy-colno - col. "确定横线输出长度
lin = lin - 1.
SKIP TO LINE lin. "移动到上一行
ULINE AT col(length). "绘制顶部横线
lin = lin + 2.
SKIP TO LINE lin. "移动到下一行
ULINE AT col(length). "绘制底部横线
lin = lin - 1. col = sy-colno - 2.
SKIP TO LINE lin. POSITION col. "移动到右侧竖线前一位置,以备下一输出
END-OF-DEFINITION.
通过DEFINE……END-OF-DEFINITION定义一个宏,可以在调用宏时传入变量值,并可在代码中按顺序使用&1……&5在宏定义的代码中使用。
3.2、列表数据抬头输出宏
此部分代码如下:
*&---------------------------------------------------------------------*
*& DEFINE WRITE_PHEAD
*&---------------------------------------------------------------------*
* 定义宏输出每页的列表数据抬头
*----------------------------------------------------------------------*
DEFINE write_phead.
NEW-PAGE NO-HEADING. "无页眉新页
pg = pg + 1.
WRITE:/65 '页码:', (3) pg.
SKIP 2.
POSITION 5.
write_grid 'NO' 6 on off col_key. "调用宏输出
write_grid '图标名称' 35 on off col_key.
write_grid '图示' 8 on off col_group.
write_grid '代码' 4 on off col_total.
cntr = 5. "包含列表头已输出5行
"每页输出行数重置
SKIP 2. "空2行以输出下一行数据
POSITION 5. "空5个字符作为起始位置
END-OF-DEFINITION.
本部分代码定义的宏,也调用了“单元格数据输出宏”,以输出列表数据抬头,同时此宏其输出内容都是在代码中定义的,无需在调用时传入变量值。
4、获取和输出数据
获取和输出数据部分的代码如下:
*&----------------------------------------------------------------------*
*& START-OF-SELECTION
*&----------------------------------------------------------------------*
START-OF-SELECTION.
*****获得ICON数据
SELECT * FROM icon.
IF cntr => 59 OR cnt IS INITIAL. "输出超过59行或在初始时输出表头
"每页输出(59-5)/2=27条记录
write_phead. "调用宏输出数据列表抬头
ENDIF.
cnt = sy-dbcnt.
write_grid cnt 6 on off col_key. "调用宏输出数据
write_grid icon-name 35 on off col_key.
write_grid icon-id 8 on off col_group.
write_grid icon+1(2) 4 on off col_total.
cntr = cntr + 2. "包括下横线增加了2行输出
SKIP 2. "空2行以输出下一行数据
POSITION 5. "空5个字符作为起始位置
ENDSELECT.
本部分通过SELECT语句从icon中获得数据后存储到icon表同名的工作区中,然后按需求输出列表抬头和逐条输出系统图标内容。
如上4部分代码合在一起则实现了本实践的需求。
本实践小结:
宏(Macros)是一段独立的代码,与子程序类似,能实现数据的运算与输出,主要应用于同一程序中需要的重复运算与输出,以简化代码;而与子程序不同,宏不需要定义接收参数的类型及格式,其通过&N(N为索引)接收传入的参数;宏只能被本程序中定义于宏后面的语名所调用,因此一般定义于程序最开始。
可以在表TRMAC中查看到系统所包含的宏。
(实践5A1 End)