需求分析:
1、具体需求
本《设计界面输出客户基本信息及相关的订单》有如下需求:
- 程序执行后,从客户表、订单表中读取记录,并自定义界面,每次输出一个客户相关记录;
- 客户的基本信息和销售订单信息分开在不同页签显示;
- 可通过设计的工具栏按钮,切换显示不同客户的相关记录;
界面布局设计规划如图9-1、图9-2。
2、开发分析
要达成本实践目标,将需要使用ABAP的数据处理和界面设计技术,分析如下。
2.1、数据处理流程
- 根据需求,是要输出每一个客户的基本信息和此客户对应的订单的信息,这2部分信息分别存储于客户表ztcustomer和订单表ztorder_h中;因为程序执行后需要能输出从第一个到最后一个客户的记录,因此可以将客户表的所有记录先读取到内表中;
- 在用户执行操作时根据指令,从内表中获得一个客户的相应记录并存储到工作区和内表中以备输出;
- 将数据输出到界面中。
数据处理流程如图9-3。
2.2、界面设计分析
- 通过屏幕可以设计界面中所需要显示的元素和数据,因为基本信息、客户订单页签显示的内容都在同一位置,且输出的界面元素不同,因此需定义2个子屏幕对应页签的输出;
- 工具栏按钮可以通过SAP的GUI状态进行设计;
- 通过屏幕的PBO事件,调用GUI状态显示对应的工具栏,同时获得和输出数据;
- 通过屏幕的PAI事件,响应用户的操作,以实现切换不同客户记录、切换页签、退出程序等。
程序运行界面事件如图9-4。
实践步骤:
本实践可以在ABAP工作台(SE80)完成所有工作,也可以通过不同的工具完成不同部分。
No | 部分 | 说明 | 事务代码 |
---|---|---|---|
1 | 建立程序 | 建立本实践的程序,设置程序基本信息。 | SE38 |
2 | GUI状态标题设计 | 设计GUI状态,增加相应的功能以接受用户的指令;设计GUI标题,以在程序运行时显示在界面的标题上。 | SE41 |
3 | 屏幕设计 | 根据实践需求设计屏幕,并将相关元素添加到屏幕上。 | SE51 |
4 | 代码编写 | 编写代码以进行变量定义、数据获取、输出数据到界面等。 | SE38 |
4.1 | 对象定义 | 定义要使用的变量,以在程序执行过程中计算和存储临时值。 | |
4.2 | 获得客户表数据 | 从客户表中获得数据存储到内表。 | |
4.3 | 屏幕事件 | 将数据传输到界面上(PBO事件);以及在用户点击按钮后触发相应操作(PAI事件)。 | |
4.4 | 子程序 | 将获取一个客户的基本信息和订单到内表以备输出的代码,封装为一个主程序,以实现代码重用、提高效率和提高代码可读性。 |
1、建立程序
与一般程序的建立过程一样,在程序编辑器初始界面输入程序名称后点击创建,设置类型和状态后,将进入程序编辑器界面,默认代码如下,不改动内容,保存后退出。
REPORT zu0901_cust_detail_screen
2、GUI状态标题设计
使用菜单设计器(SE41),完成GUI状态和GUI标题的设计。
2.1、建立状态
通过GUI状态,可定义界面工具栏以及菜单中有哪些功能,这些功能可以是自定义的,也可以是系统标准交付的;如果是自定义的功能,在GUI状态中并不指明功能(如点击“退出”)的具体实现,而是在PAI屏幕事件中予以实现。
1)状态的建立
执行菜单设计器后,初始界面如图9-5所示,在“程序”输入框中输入步骤1所建立的程序,然后在“子对象”中选择“状态”后点击界面下方的“创建”按钮,表示为此实践的程序建立一个状态。
随后,将弹出如图9-6所示的“创建状态”的窗口,在此窗口中输入状态的名称和短文本,保持状态类型为默认(正常屏幕),然后点击对勾,在出现的界面中完成后续操作。
2)建立工具栏
状态维护的界面如图9-7所示,展开“应用程序工具栏”,将列出所包含的各个项目,初始内容为空。
在项目列表的第一个单元格处,输入功能代码“FIRST”后回车,将弹出图9-8所示的窗口,保留默认文本类型(静态文本)后点击对勾,将显示图9-9所示窗口,参考图示输入“功能文本”和“图标名称”后点击对勾;随后将显示“分配功能键”的窗口如图9-10所示,从界面中选择“Ctrl+F1”,表示键盘输入“Ctrl+F1”时,与点击此按钮“第一个”的效果一样;至此,则完成了功能按钮“第一个”的定义。
参考如上步骤,按下表完成所有功能按钮的定义(其中“FIRST”已定义完成)。
所有需要的功能完成后,结果如图9-11所示。
展开界面下方的“功能键”,也可看到不同项目对应的快捷方式,如图9-12。
3)建立菜单栏
展开界面中的“菜单栏”,在输入框中输入“客户数据”,然后双击此“客户数据”,将展开所包含的代码列表,如图9-12,参考图示输入各个功能代码(文本会自动带出)。
完成如上工作后,点击激活,至此完成了GUI状态的建立。
2.2、建立标题
重新执行“菜单设计器”,在初始界面中选择“标题列表”后点击创建,将显示如图9-14所示界面,参考图示输入后点击对勾,则完成了GUI标题的建立。同时可以在此窗口中点击“所有标题”列出此程序包括的标题,并可以进行维护和激活等的操作。
3、屏幕设计
使用屏幕设计器(SE51),完成各个屏幕的设计。
3.1、主屏幕100
1)建立屏幕
在屏幕设计器执行后,在如图9-15所示的初始界面中输入本实践程序名和屏幕编号 “0100”后,点击“创建”按钮。
在显示的如图9-16所示的界面中,输入屏幕的描述,保持其他属性不变(屏幕类型为通常)。
2)屏幕格式设计
点击工具条的“格式”按钮[图片上传失败...(image-657a80-1520584567903)] ,将显示如图9-17所示的界面,界面工作区左边为各功能工具条,图中列出各功能的用途。
在格式界面的应用工具栏的右上方,找到“字典/程序元素”按钮,点击后将显示如图9-18所示窗口,在窗口的“表/字段名称”中输入客户表名称(ZTCUSTOMER)后,点击右边按钮“从字典获取”,随后将在界面的表格列表区域显示出客户表所包含的各个字段以及描述、类型等属性,从中选择客户编号(CUSTOMERID)和客户名称(CUSTOMERNAME)行,点击对勾。
随后选择合适位置后点击,则自动生成了客户编号和客户名称对应的文本框和输入框,结果如图9-19所示。此步骤也可通过点击工具栏上的按钮完成,不过这样的话则需要指定每一个元素的名称、文本、属性等。
随后,点击“多页签控件”按钮,在工作区中拖动鼠标,大小合适后松开,则添加了页签控件,然后在名称处输入此控件名称“CUST-INFO”,结果如图9-20所示。
双击选中页签控件中的“表1”,将显示此选择页签的属性如图9-21所示,在属性窗口中参考图示输入名称、文本、图标、工具提示、功能码等信息。
参考如下列表,以同样的方式设置页签“订单信息”的属性,完成后如图9-22所示。
接下来,先按住Ctrl键,选中2个已经建立好的页签名称,然后点击子屏幕控件,并在页签输出信息区域拖动,并输入名称为“SAREA”,完成后显示如图9-23,同时页签控件的参考字段也将被填充。
3)屏幕元素清单
点击工具栏的“元素列表”按钮,将返回到屏幕定义的“元素清单”中,此处将列出界面中所包含的元素,以及各元素的具体属性。
4)屏幕逻辑流
点击“逻辑流”页签,此处已包含默认的PBO(PROCESS BEFORE OUTPUT,输出前处理)事件以及PAI(PROCESS AFTER INPUT,输入后处理)事件,并包含了默认的MODULE status_0100和MODULE user_command_0100共2个模块, Module前面的*去掉解除注释以启用这2个Module,这两个Module的处理将在“屏幕事件”代码中实现;同时添加CALL SUBSCREEN ……语句,以在调用屏幕100的输出前,调用子屏幕后统一输出,结果如图9-25所示。
逻辑流的代码如下。
PROCESS BEFORE OUTPUT.
MODULE status_0100.
CALL SUBSCREEN sarea INCLUDING prog scrn.
*
PROCESS AFTER INPUT.
MODULE user_command_0100.
3.2、子屏幕210
子屏幕是用以输出客户的基本信息,包括客户城市、地址、联系人姓名、电话等的。
1)屏幕基本属性
参考主屏幕110,在屏幕设计器初始界面输入程序名和屏幕编号后点击创建,将显示如图9-26所示的属性界面,将屏幕类型更改为“子屏幕”,其他内容不变。
2)屏幕格式设计
通过“字典/程序数据元素”按钮,将客户表ZTCUSTOMER的城市、地址、联系人姓名、电话号码字段(如图9-27)添加到屏幕上,并调整元素的位置,完成后如图9-28所示。
3)屏幕元素清单
屏幕格式设计完成后,返回可看到数据元素清单如图9-29所示。
4)屏幕逻辑流
查看屏幕逻辑流,此处包含了默认的PBO和PAI事件,因为数据的获取和工具栏的操作已通过屏幕100的逻辑流实现,此子屏幕210不需要再进行定义,因此默认即可,2个MODULE保持为注释状态。
3.3、子屏幕220
参考子屏幕210建立的过程建立子屏幕220,屏幕描述为“客户订单”,类型同样为子屏幕。
1)屏幕格式设计
点击表格控件,然后在工作区中拖动以指定表格区域,并将表格控件命名为“ORDER_ITEMS”,再通过“字典程序元素”,从订单表ZTORDERS_H中获得需要输出的字段(如图9-30)并放置到表格控件区域,得到结果如图9-31所示。
2)屏幕元素清单
完成子屏幕220的格式设计后,其元素清单如图9-32所示。
3)屏幕逻辑流
子屏幕220的逻辑流代码如下,其中PBO的LOOP AT语句,是在客户的订单明细数据界面输出前,将读取到内表order_tab中的一个客户的相关订单的记录,传输到表格控件order_items所包含的ztorders_h结构中,如此才能显示对应的数据;可以通过PAI事件,对内表order_tab的数据进行处理。
根据屏幕设计技术规范,如果在屏幕中使用到表格控件,那么必须在PBO和PAI中包含LOOP AT语句,即使不用实现功能(如本实践中PAI的LOOP AT)。
PROCESS BEFORE OUTPUT.
* MODULE status_0220.
LOOP AT order_tab INTO ztorders_h WITH CONTROL order_items.
ENDLOOP.
*
PROCESS AFTER INPUT.
* MODULE user_command_0220.
LOOP AT order_tab.
ENDLOOP.
4、代码编写
完成如上步骤后,接下来通过程序编辑器(SE38)对代码的各部分进行编写。
4.1、对象定义
根据程序功能需求,定义的变量、内表、控件等对象如代码所列。
******对象定义*****
CONTROLS: cust_info TYPE TABSTRIP, "屏幕输出-表标签控制器
order_items TYPE TABLEVIEW USING SCREEN 220. "屏幕输出-表控制器
TABLES:ztorders_h, ztcustomer. "根据透明表定义的内表
DATA: ok_code TYPE sy-ucomm, "用户的命令
main_tab TYPE SORTED TABLE OF ztcustomer "存储客户数据的内表
WITH UNIQUE KEY customerid,
order_tab TYPE STANDARD TABLE OF ztorders_h, "存储销售订单数据的内表
once(1) TYPE c, "记录第一次打开状态
current_rw TYPE sy-tabix, "当前内表记录序号
no_of_rows TYPE sy-tabix, "总共客户记录数量
prog TYPE sy-repid "本程序名称
VALUE 'ZU0901_CUST_DETAIL_SCREEN',
scrn TYPE sy-dynnr. "屏幕编号
4.2、获得客户表数据
在程序执行后,通过START-OF-SELECTION语句,从客户表ztcustomer中获得所有记录存到内表main_tab,并将获得的记录数量sy-dbcnt赋值给no_of_rows,如此可根据此值显示最后一条记录。
获得数据后,调用屏幕100以进行后续处理。
*&----------------------------------------------------------------------*
*& START-OF-SELECTION
*&----------------------------------------------------------------------*
START-OF-SELECTION.
SELECT * FROM ztcustomer INTO TABLE main_tab. "获得所有客户的数据并存到内表
no_of_rows = sy-dbcnt.
CALL SCREEN 100. "调用屏幕100
4.3、屏幕事件
1)PBO事件的MODULE
当屏幕100被调用的时候,首先触发屏幕的PBO事件,此事件包含的MODULE status_0100的代码如下。此代码首先设置GUI状态为STAT1,标题为TITLE01;然后初始调用时,once值为空,由此通过IF语句,可以显示第一个客户的记录;在代码中,读取记录并输出到界面的语句通过子程序read_table予以实现,此子程序在程序最后部分添加。
*&---------------------------------------------------------------------*
*& Module status_0100 OUTPUT
*&---------------------------------------------------------------------*
*对界面进行初始化
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
SET PF-STATUS 'STAT1'. "设置GUI状态为STAT1
SET TITLEBAR 'TITLE01'. "设置GUI标题为TITLE01
IF once = ' '. "刚开始执行时,once为空,为空则输出第一条记录
current_rw = 1. "设置当前行为第1条
PERFORM read_table. "读取记录
cust_info-activetab = 'CONTACT'. "激活标签CONTACT
scrn = '0210'. "设置子屏幕为0210
once = 'X'. "读取了1条记录后,设置为非初始
ENDIF.
ENDMODULE.
2)PAI事件的MODULE
当点击GUI状态对应图标或切换页签时,将触发屏幕的PAI事件,同时根据操作传输功能代码值到ok_code,如下则通过MODULE user_command 0100实现对不同操作的处理。
*&---------------------------------------------------------------------*
*& Module status_0100 OUTPUT
*&---------------------------------------------------------------------*
*接收不同用户命令并进行输出
*----------------------------------------------------------------------*
MODULE user_command_0100.
CASE ok_code. "对界面上不同按钮执行后的处理
WHEN 'EXIT'. "退出
LEAVE PROGRAM. "退出程序
WHEN 'FIRST'. "第一个
current_rw = 1. "当前记录号为1
PERFORM read_table. "读取记录
WHEN 'PREVIOUS'. "前一个
IF current_rw > 1.
current_rw = current_rw - 1.
PERFORM read_table.
ENDIF.
WHEN 'NEXT'. "后一个
IF current_rw < no_of_rows.
current_rw = current_rw + 1.
PERFORM read_table.
ENDIF.
WHEN 'LAST'. "最后一个
current_rw = no_of_rows.
PERFORM read_table.
WHEN 'CONTACT'. "联系人
cust_info-activetab = 'CONTACT'. "激活标签CONTACT
scrn = '0210'. "设置子屏幕为0210
WHEN 'ORDER'. "客户订单
cust_info-activetab = 'ORDER'. "激活标签ORDER
scrn = '0220'. "设置子屏幕为0220
ENDCASE.
ENDMODULE.
4.4、子程序
在屏幕事件(包括PBO和PAI)中,多处用到子程序read_table以获得一个客户的记录并进行输出,此部分则是定义此子程序的实现,其中根据指定序号current_rw的值,从内表main_tab中读取记录到工作区zt_customer;然后根据读取记录的客户编号,从透明表ztorders_h中获得客户编号相同的订单记录并添加到内表order_tab,同时设定了子屏幕220的控件order_items的行数,这样在显示页签“客户订单”时,调用子屏幕220并通过PBO事件中的代码将order_tab的数据输出到屏幕中。
*&---------------------------------------------------------------------*
*& FORM READ_TABLE
*&---------------------------------------------------------------------*
* 获得要输出到屏幕的客户信息
*----------------------------------------------------------------------*
FORM read_table.
READ TABLE main_tab INTO ztcustomer INDEX current_rw. "按指定序号读取一条客户记录到内表
SELECT * FROM ztorders_h INTO TABLE order_tab "读取客户相关订单的记录到内表
WHERE customerid = ztcustomer-customerid
ORDER BY orderid.
order_items-lines = sy-dbcnt.
ENDFORM.
将如上各部分代码合并,则组成了整个实践的程序,完成后对所有内容进行激活。