09界面编程,实践A2-设计界面管理订单

2018-03-09  本文已影响0人  真言真语SAP
图9-A2_1 程序执行初始界面 图9-A2_2 订单维护界面

需求分析:

1、具体需求

本《设计界面管理订单》有如下需求:

  1. 程序执行后,显示初始界面,在界面中可以输入订单号后,点击按钮进行新建、修改、查看和删除的操作;
  2. 在点击“新建订单”时,如果输入的订单编号在订单表中已存在,则发出错误提示且停止创建操作;否则在订单维护界面中维护订单的具体信息,包括订单相关的员工、雇员、物料等信息;
  3. 在点击“修改订单”时,如果输入的订单编号在订单表中不存在,或输入的订单编号在10000~60000范围,则发出错误提示且停止修改操作;否则打开订单维护界面以进行更改;
  4. 在点击“查看订单”时,如果输入的订单编号在订单表中不存在,则发出错误提示且停止查看操作;否则打开显示订单的详细;
  5. 在点击“删除订单”时,如果输入的订单编号在订单表中不存在,或输入的订单编号在10000~60000范围,则发出错误提示且停止删除操作;否则将删除此订单编号的记录及返回提示;
  6. 在“新建订单”和“修改订单”操作的订单维护界面中,如果输入了数据后,还没点击“保存”前点击了“返回”,则弹出窗口给用户进行确认是否保存。

2、开发分析

要达成本实践目标,将需要使用ABAP的数据处理和界面设计技术,程序流程分析如下。

图9- 34 程序流程

实践步骤:

本实践可以在ABAP工作台(SE80)完成所有工作,也可以通过不同的工具完成不同部分。

No 部分 说明 事务代码
1 建立程序 建立本实践的程序,设置程序基本信息。 SE38
2 GUI状态标题设计 设计GUI状态,增加相应的功能以接受用户的指令;设计GUI标题,以在程序运行时显示在界面的标题上。 SE41
3 屏幕设计 根据实践需求设计屏幕,并将相关元素添加到屏幕上。 SE51
4 代码编写 编写代码以进行变量定义、数据获取、输出数据到界面等。 SE38
4.1 对象定义 定义要使用的变量,以在程序执行过程中计算和存储临时值。
4.2 程序初始事件 通过START-OF-SELECTION执行程序初始事件。
4.3 屏幕100事件 对于屏幕100,数据输出到屏幕前的处理(PBO事件);以及在用户点击按钮后触发相应操作(PAI事件)。
4.4 屏幕150事件 对于屏幕150,数据输出到屏幕前的处理(PBO事件);以及在用户点击按钮后触发相应操作(PAI事件)。
4.5 子程序 根据程序执行的过程将部分代码封装为主程序,以实现代码重用、提高效率和提高代码可读性。

1、建立程序

与一般程序的建立过程一样,在程序编辑器初始界面输入程序名称后点击创建,设置类型和状态后,将进入程序编辑器界面,默认代码如下,不改动内容,保存后退出。

REPORT zu0902_order_trans.

2、GUI状态标题设计

使用菜单设计器(SE41),完成GUI状态和GUI标题的设计。

2.1、建立状态

在本实践中,在程序执行初始界面和订单维护的界面都会有相应的工具栏,因此需要建立2个相应的GUI状态,本步骤可参考实践9A1完成。

1)GUI状态STAT1

GUI状态STAT1的模拟结果如图9-35所示,编辑维护的界面如图9-36。

图9- 35 STAT1模拟结果 图9- 36 STAT1维护

各功能按钮的定义可参考下表完成。


2)GUI状态STAT2

GUI状态STAT1的模拟结果如图9-37所示,编辑维护的界面如图9-38。

图9- 37 STAT2模拟结果 图9- 38 STAT2维护界面

各功能按钮的定义可参考下表完成。

2.2、建立标题

重新执行“菜单设计器”,在初始界面中选择“标题列表”后点击创建,参考图9-39所示建立2个标题。

图9- 39 GUI标题列表

3、屏幕设计

在本实践中,有程序执行初始界面,还有订单维护的界面,因此需要建立2个屏幕,本步骤可参考实践9A1,使用屏幕设计器(SE51),完成各个屏幕的设计。

3.1、初始屏幕100
1)屏幕属性
图9- 40 屏幕100的属性
2)屏幕格式设计

点击工具栏的“格式”后,在显示“屏幕绘制器”界面中添加屏幕元素,结果如图9-41。

图9- 41屏幕100的格式
3)屏幕元素清单

点击工具栏的“元素列表”按钮,将返回到屏幕定义的“元素清单”中,此处将列出界面中所包含的元素,以及各元素的具体属性,如图9-42。

图9- 42 屏幕100包含的元素
4)屏幕逻辑流

点击“逻辑流”页签,逻辑流的代码如下。

PROCESS BEFORE OUTPUT.
  MODULE status_0100.
*
PROCESS AFTER INPUT.
*  MODULE user_command_0100.
  MODULE over_and_out_0100 AT EXIT-COMMAND.
  CHAIN.
    FIELD:ztorders_h-orderid
    MODULE validate_input_0100.
  ENDCHAIN.
  MODULE main_pai_0100.

在如上屏幕100的“逻辑流”PBO事件中,包含一个MODULE:status_0100,此MODULE在屏幕输出前执行,包括设置GUI、标题栏、变量初始值等,具体代码将在后续屏幕100的PBO事件代码中实现。

PAI事件中,则包含了3个MODULE:
over_and_out_0100,此MODULE是在屏幕100中点击“退出”时的响应,并加上AT EXIT-COMMAND关键字,以在自动字段检查之前调用模块(对应按钮需将类型设置为E);如果PAI中没有此MODULE,则会点击“退出”按钮时还会执行后面的语句,如检查输入的订单编号,而这是多余的。
validate_input,此MODULE是继续响应点击按钮,以对输入的订单编号进行检查;如点击“新建”时,输入的订单编号在数据表中已存在,则返回相应提示。
main_pai_0100,此MODULE是继续对点击不同的按钮进行响应,如点击新建或修改、显示,则进入屏幕150,如点击删除,则对指定的订单进行删除。
CHAIN……ENDCHAIN,通过CHAIN语句,当输入的编号发生变化时,则调用MODULE:validate_input进行检查。

3.2、订单明细屏幕150
1)屏幕属性
图9- 43 屏幕150的属性
2)屏幕格式设计

通过“屏幕绘制器”对屏幕150添加的屏幕元素结果,如图9-44所示。

图9- 44屏幕150的格式
3)屏幕元素清单

点击工具栏的“元素列表”按钮,将返回到屏幕定义的“元素清单”中,此处将列出界面中所包含的元素,以及各元素的具体属性,如图9-45。

图9- 45 屏幕150包含的元素
4)屏幕逻辑流

点击“逻辑流”页签,逻辑流的代码如下。

PROCESS BEFORE OUTPUT.
  MODULE status_0150.
  LOOP AT ordersi_tab INTO ztorders_i  WITH  CONTROL items.
    MODULE items_0150_change_field_attr.
  ENDLOOP.
*
PROCESS AFTER INPUT.
  CHAIN.
    FIELD:ztorders_h-orderid, ztorders_h-customerid,
       ztorders_h-employeeid,ztorders_h-orderdate, ztorders_h-shipdate.
    MODULE set_change_0150 ON CHAIN-REQUEST.
  ENDCHAIN.

  LOOP AT ordersi_tab.
    MODULE items_0150_modify.
  ENDLOOP.
  MODULE user_command_0150.

在如上屏幕150的“逻辑流”PBO事件中,包含2个MODULE:
status_0150,此MODULE在屏幕150输出前执行,包括设置GUI、标题栏、元素显示属性等,具体代码将在后续屏幕150的PBO事件代码中实现。
items_0150_change_field_attr,此MODULE是设置字段的显示,通过LOOP AT语句读取和填充数据到屏幕150的界面元素后,根据不同的操作(新建、修改、显示)设置元素显示状态(可更改、只显示)

PAI事件中,则包含了3个MODULE:
CHAIN……ENDCHAIN,通过CHAIN语句,当订单编号、客户编号、雇员编号、订单日期、交货日期值发生变化时,则调用MODULE:set_change_0150设置界面元素的显示状态。
set_change_0150,此MODULE是通过对变量“data_chg_150”的赋值,设置界面元素的显示状态(X则为可更改)。
items_0150_modify,此MODULE结合LOOP AT语句,调用子程序在维护订单明细数据后,更新内表数据。
user_command_0150,此MODULE是对点击不同的按钮进行响应。

4、代码编写

完成如上步骤后,接下来通过程序编辑器(SE38)对代码的各部分进行编写。

4.1、对象定义

根据程序功能需求,定义的变量、内表、控件等对象如代码所列。

*****对象定义*****
CONTROLS: items TYPE TABLEVIEW USING SCREEN 0150."子屏幕150中的列表元素
TABLES:ztorders_h, ztorders_i.                   "根据表格定义的内表
DATA:ordersi_tab     TYPE STANDARD TABLE OF ztorders_i
                          WITH HEADER LINE,      "含工作区内表,存储读取的订单明细数据
     ok_code         TYPE sy-ucomm,              "用户指令
     save_ok_code    TYPE sy-ucomm,              "保存用户指令,用以设置界面元素状态
     strng           TYPE string,                "在不同操作时显示的界面标题不同
     data_chg_150(1) TYPE c,                     "记录子屏幕150是否为修改状态
     answer(1)       TYPE c,                     "记录数据更改退出时用户的确认
     prv_orderid     TYPE ztorders_h-orderid.    "用以记录已操作过的订单

4.2、程序初始事件

在程序执行后,通过START-OF-SELECTION语句,调用屏幕100以进行后续处理。

*&----------------------------------------------------------------------*
*& START-OF-SELECTION
*&----------------------------------------------------------------------*
START-OF-SELECTION.
  CALL SCREEN 0100.                                "调用主屏幕100

4.3、屏幕100事件
1)PBO事件的MODULE

当屏幕100被调用的时候,首先触发屏幕的PBO事件,此事件包含的MODULE status_0100的代码如下。

*&---------------------------------------------------------------------*
*&      Module  STATUS_0100  OUTPUT
*&---------------------------------------------------------------------*
*       主屏幕100的初始GUI状态标题栏及变量设置
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
  SET PF-STATUS 'STAT1'.                           "设置屏幕GUI状态为STAT1
  SET TITLEBAR 'TITLE01'.                          "设置屏幕GUI标题栏为TITLE01
  prv_orderid = ztorders_h-orderid.                "清空内表前将操作过的订单号记录起来
  FREE: ztorders_h,                                "清空变量数据以对新的订单进行操作
        ordersi_tab.
  ok_code = ' '.
  data_chg_150 = ' '.
  items-lines = 0.
  ztorders_h-orderid = prv_orderid.                "设置屏幕中的订单编号为之前操作的
ENDMODULE.

此代码首先设置GUI状态为STAT1,标题为TITLE01;然后使用prv_orderid变量,记录上一次操作的订单编号;随后对存储订单抬头信息和订单明细数据的内表、包括点击的操作、字段状态、行数量进行重置;最后将前面保存的prv_orderid值赋值给字段ztorders_h-orderid。这样在操作完成一个订单后返回初始屏幕时,各个变量被重置,同时上一次订单编号显示在输入框。

2)PAI事件的MODULE

当点击GUI状态对应图标时,将触发屏幕的PAI事件。

over_and_out_0100是PAI后的第一个MODULE,此MODULE是对按钮“退出”点击后的响应:退出程序。

*&---------------------------------------------------------------------*
*&      Module  OVER_AND_OUT_0100  INPUT
*&---------------------------------------------------------------------*
*       订单编号输入及订单操作前如果点击退出按钮,则退出程序
*----------------------------------------------------------------------*
MODULE over_and_out_0100 INPUT.
  IF ok_code = 'EXIT'.
    LEAVE PROGRAM.
  ENDIF.
ENDMODULE.

validate_input_0100通过CHAIN语句,在输入的订单编号更改时触发。此MODULE首先根据输入的订单编号从订单表ztorders_h中读取记录;然后根据点击的按钮和读取记录的结果,给出不同的处理:如果点击的按钮为“新建”且读取到记录(sy-subrc为0)则输出错误提示,如果点击的按钮不是“新建”且没有读取到记录也一样输出错误提示。

*&---------------------------------------------------------------------*
*&      Module  VALIDATE_INPUT_0100  INPUT
*&---------------------------------------------------------------------*
*       输入订单编号后,
*           如果此编号已存在且点击了新建,则发出错误提示
*           如果此编号不存在而点击的不是新建,同样发出错误提示
*----------------------------------------------------------------------*
MODULE validate_input_0100 INPUT.
  SELECT SINGLE * FROM ztorders_h INTO ztorders_h WHERE
      orderid = ztorders_h-orderid.               "根据输入的订单编号从表中读取记录
  "点击新建且记录存在则输出错误提示
  IF ok_code = 'NEW' AND sy-subrc = 0.
    MESSAGE  e091(zu03_mclass01) WITH ztorders_h-orderid.
    "点击的不是新建且记录不存在则输出错误提示
  ELSEIF ok_code <> 'NEW' AND sy-subrc <> 0.
    MESSAGE e092(zu03_mclass01) WITH ztorders_h-orderid.
  ENDIF.
ENDMODULE.

main_pai_0100则根据点击的按钮进行不同的处理。

*&---------------------------------------------------------------------*
*&      Module  MAIN_PAI_0100  INPUT
*&---------------------------------------------------------------------*
*       主屏幕100的不同按钮点击后触发事件
*----------------------------------------------------------------------*
MODULE main_pai_0100 INPUT.
  save_ok_code = ok_code.
  CASE ok_code.
    WHEN 'NEW'.
      strng = '新建'.
      LEAVE TO SCREEN 150.
    WHEN 'MODIFY'.
      IF ztorders_h-orderid NOT BETWEEN 10000 AND 60000.
        PERFORM read_table.
        strng = '修改'.
        LEAVE TO SCREEN 150.
      ELSE.                       "不能修改编号范围在10000~60000的订单
        MESSAGE s096(zu03_mclass01) WITH ztorders_h-orderid
                DISPLAY LIKE 'E'.
      ENDIF.
    WHEN 'DISPLAY'.
      PERFORM read_table.
      strng = '显示'.
      LEAVE TO SCREEN 150.
    WHEN 'DELETE'.
      IF ztorders_h-orderid NOT BETWEEN 10000 AND 60000.
        PERFORM delete_sr USING answer ztorders_h.
        IF answer = 1.
          DELETE ztorders_h.
          DELETE FROM ztorders_i WHERE orderid = ztorders_h-orderid.
          MESSAGE s094(zu03_mclass01) WITH ztorders_h-orderid
                  DISPLAY LIKE 'W'.
        ELSE.
          MESSAGE s095(zu03_mclass01).
        ENDIF.
      ELSE.                       "不能删除编号范围在10000~60000的订单
        MESSAGE s096(zu03_mclass01) WITH ztorders_h-orderid
                DISPLAY LIKE 'E'.
      ENDIF.
    WHEN 'EXIT'.
      LEAVE PROGRAM.
  ENDCASE.
ENDMODULE.

4.4、屏幕150事件
1)PBO事件的MODULE

当屏幕150被调用的时候,首先触发屏幕的PBO事件。

MODULE status_0150中,首先设置GUI状态为STAT2,标题为TITLE02;然后调用子程序change_scr_150_prop设置屏幕元素的显示属性。

*&---------------------------------------------------------------------*
*&      Module  STATUS_0150  OUTPUT
*&---------------------------------------------------------------------*
*       子屏幕150的初始GUI状态标题栏及界面元素属性设置
*----------------------------------------------------------------------*
MODULE status_0150 OUTPUT.
  SET PF-STATUS 'STAT2'.  SET TITLEBAR 'TITLE02' WITH ztorders_h-orderid strng.
  PERFORM change_scr_150_prop.
ENDMODULE.

MODULE items_0150_change_field_attr是结合PAI中的LOOP AT语句,逐行对表格控件的各个单元格设置显示属性。

*&---------------------------------------------------------------------*
*&      Module  items_0150_change_field_attr  OUTPUT
*&---------------------------------------------------------------------*
*       子屏幕150设置界面表格控件的显示。
*----------------------------------------------------------------------*
MODULE items_0150_change_field_attr OUTPUT.
  PERFORM change_scr_150_prop.
ENDMODULE.

2)PAI事件的MODULE

当点击GUI状态对应图标时,将触发屏幕的PAI事件。

set_change_0150模块,将变量data_chg_150赋值为“X”,由此表示为界面元素为可更改状态。

*&---------------------------------------------------------------------*
*&      Module  SET_CHANGE_0150  INPUT
*&---------------------------------------------------------------------*
*       子屏幕150设置界面元素为修改状态
*----------------------------------------------------------------------*
MODULE set_change_0150 INPUT.
  data_chg_150 = 'X'.
ENDMODULE.

Items_0150_modify模块,则通过调用子程序,在表格控件中的数据更改后,更新内表的数据。

*&---------------------------------------------------------------------*
*&      Module  ITEMS_0150_MODIFY  INPUT
*&---------------------------------------------------------------------*
*       子屏幕150将修改后的表格数据填充到表格控件对应内表
*----------------------------------------------------------------------*
MODULE items_0150_modify INPUT.
  PERFORM modify_ordersitem.
ENDMODULE.

user_command_0150模块则是响应不同按钮点击后的处理。

*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0150  INPUT
*&---------------------------------------------------------------------*
*       子屏幕150的不同按钮点击后触发的事件
*----------------------------------------------------------------------*
MODULE user_command_0150 INPUT.
  CASE ok_code.
    WHEN 'BACK'.
      IF data_chg_150 = 'X'.
        PERFORM abort_sr USING answer ztorders_h.
        IF answer = 1.
          LEAVE TO SCREEN 0100.
        ENDIF.
      ELSE.
        LEAVE TO SCREEN 0100.
      ENDIF.
    WHEN 'SAVE'.
      data_chg_150 = ' '.
      MODIFY ztorders_h.
      MODIFY ztorders_i FROM TABLE ordersi_tab.
      IF sy-subrc <> 0.
      ENDIF.
      MESSAGE s093(zu03_mclass01) WITH ztorders_h-orderid.
  ENDCASE.
ENDMODULE.

4.5、子程序

在屏幕事件(包括PBO和PAI)中,多处用到了不同的子程序。

其中子程序read_table,是用以根据屏幕100中输入的订单编号,获得订单抬头和订单行项目的数据并分别存储到内表ztorders_h和ordersi_tab中,同时设置表格控件的行数量(items-lines)。

*&---------------------------------------------------------------------*
*&      FORM   read_table
*&---------------------------------------------------------------------*
*       从订单和订单明细表中获得数据填充内表以备输出
*----------------------------------------------------------------------*
FORM read_table.
  SELECT SINGLE * FROM ztorders_h INTO ztorders_h WHERE
    orderid = ztorders_h-orderid.
  ztorders_h-oamount = 0.
  SELECT * FROM ztorders_i INTO ordersi_tab WHERE
    orderid = ztorders_h-orderid.
    ztorders_h-oamount = ztorders_h-oamount + ordersi_tab-oquantity *
                         ordersi_tab-nprice * ( 1 - ordersi_tab-discount ).
    APPEND ordersi_tab TO ordersi_tab.
  ENDSELECT.
  items-lines = sy-dbcnt.
ENDFORM.

子程序delete_sr,是在点击“删除”按钮后的响应,此子程序通过CALL FUNCTION调用功能函数“POPUP_TO_CONFIRM”以弹出对话框,以让用户确认。

*&---------------------------------------------------------------------*
*&      Form  DELETE_SR
*&---------------------------------------------------------------------*
*       确定是否对订单进行删除
*----------------------------------------------------------------------*
*      -->P_ANSWER  返回是否删除,1则删除
*      -->P_ZTORDERS_H  订单结构体,根据订单编号进行判断
*----------------------------------------------------------------------*
FORM delete_sr  USING    p_answer
                         p_ztorders_h TYPE ztorders_h.
  DATA: txt TYPE string.
  CONCATENATE '是否对编号为' p_ztorders_h-orderid '的订单进行删除?'
       INTO txt.

  CALL FUNCTION 'POPUP_TO_CONFIRM'
    EXPORTING
      titlebar      = '确定是否删除订单'
*     DIAGNOSE_OBJECT             = ' '
      text_question = txt
      text_button_1 = '删除'(001)
*     ICON_BUTTON_1 = ' '
      text_button_2 = '不删除'(002)
*     ICON_BUTTON_2 = ' '
*     DEFAULT_BUTTON              = '1'
*     DISPLAY_CANCEL_BUTTON       = 'X'
*     USERDEFINED_F1_HELP         = ' '
*     START_COLUMN  = 25
*     START_ROW     = 6
*     POPUP_TYPE    =
*     IV_QUICKINFO_BUTTON_1       = ' '
*     IV_QUICKINFO_BUTTON_2       = ' '
    IMPORTING
      answer        = p_answer
*   TABLES
*     PARAMETER     =
*   EXCEPTIONS
*     TEXT_NOT_FOUND              = 1
*     OTHERS        = 2
    .
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.
ENDFORM.

子程序change_scr_150_prop,则是根据不同的按钮操作,设置屏幕元素的显示属性。

*&---------------------------------------------------------------------*
*&      Form  CHANGE_SCR_150_PROP
*&---------------------------------------------------------------------*
*       子屏幕150设置界面元素的属性
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM change_scr_150_prop .
  LOOP AT SCREEN.
    CASE save_ok_code.
      WHEN 'DISPLAY'.
        screen-input = 0.
      WHEN 'MODIFY'.
        screen-input = 1.
      WHEN 'NEW'.
        screen-input = 1.
    ENDCASE.
    CASE screen-name.
      WHEN 'ZTORDERS_H-ORDERID'.
        screen-input = 0.
    ENDCASE.

    MODIFY SCREEN.
  ENDLOOP.
ENDFORM.

子程序modify_ordersitem,则是将表格控件的数据更新到内表ordersi_tab中。

*&---------------------------------------------------------------------*
*&      Form  MODIFY_ORDESITEM
*&---------------------------------------------------------------------*
*       将表格控件包含的数据更改后更新到内表
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM modify_ordersitem .
  ztorders_i-orderid = ztorders_h-orderid.
  IF items-current_line <= lines( ordersi_tab ).
    MODIFY ordersi_tab FROM ztorders_i INDEX items-current_line.
  ELSE.
    APPEND ztorders_i TO ordersi_tab.
  ENDIF.
ENDFORM.

子程序abort_sr,跟子程序delete_sr类似,在点击退出时进行确认。

*&---------------------------------------------------------------------*
*&      Form  ABORT_SR
*&---------------------------------------------------------------------*
*       确定是否退出订单修改
*----------------------------------------------------------------------*
*      -->answr  返回是否退出更改,1则退出
*      -->stru  订单结构体,根据订单编号进行判断
*----------------------------------------------------------------------*
FORM abort_sr  USING answr stru TYPE ztorders_h.
  DATA txt TYPE string .
  CONCATENATE '退出订单' ztorders_h-orderid '的修改?' INTO txt.

  CALL FUNCTION 'POPUP_TO_CONFIRM'
    EXPORTING
      titlebar              = '退出修改'
*     DIAGNOSE_OBJECT       = ' '
      text_question         = txt
      text_button_1         = '退出'(001)
*     ICON_BUTTON_1         = ' '
      text_button_2         = '不退出'(002)
*     ICON_BUTTON_2         = ' '
      default_button        = '2'
      display_cancel_button = ' '
*     USERDEFINED_F1_HELP   = ' '
      start_column          = 40
      start_row             = 2
*     POPUP_TYPE            =
*     IV_QUICKINFO_BUTTON_1 = ' '
*     IV_QUICKINFO_BUTTON_2 = ' '
    IMPORTING
      answer                = answr
* TABLES
*     PARAMETER             =
* EXCEPTIONS
*     TEXT_NOT_FOUND        = 1
*     OTHERS                = 2
    .
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.
ENDFORM.

将如上各部分代码合并,则组成了整个实践的程序,完成后对所有内容进行激活。

上一篇下一篇

猜你喜欢

热点阅读