需求分析:
1、具体需求
本《ALV输出销售单据》有如下需求:
2、开发分析
要达成本实践目标,将需要使用ABAP的数据处理和界面设计技术,程序流程分析如下。
实践步骤:
本实践可以在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 | 子程序 | 根据程序执行的过程将部分代码封装为主程序,以实现代码重用、提高效率和提高代码可读性。 |
1、建立程序
与一般程序的建立过程一样,在程序编辑器初始界面输入程序名称后点击创建,设置类型和状态后,将进入程序编辑器界面,默认代码如下,不改动内容,保存后退出。
REPORT zu1002_order_output.
2、GUI状态标题设计
2.1、系统交付程序
使用程序编辑器(SE38),查看系统交付程序SAPLKKBL。
标准程序交付的ALV工具栏
复制状态栏到程序
2.2、建立状态
将标准GUI状态复制过来后,可以据此新建2个GUI状态栏。
1)GUI状态ALV_PF_STATUS
GUI状态编辑维护的界面如图。
各功能按钮的定义可参考下表完成,其他&开头的为标准GUI中所包含,直接输入即可。
2)GUI状态STAT2
GUI状态STAT2编辑维护的界面如图所示。
各功能按钮的定义可参考下表完成。
2.2、建立标题
重新执行“菜单设计器”,在初始界面中选择“标题列表”后点击创建,参考图9-39所示建立2个标题。
3、屏幕设计
在本实践中,有程序执行初始界面,还有点击“查看订单”后显示的订单明细界面,其中初始界面在程序中定义后自动生成,订单明细界面则需要设计,使用屏幕设计器(SE51),完成屏幕的设计。
1)屏幕属性
2)屏幕格式设计
点击工具栏的“格式”后,在显示“屏幕绘制器”界面中添加屏幕元素,结果如图。
3)屏幕元素清单
点击工具栏的“元素列表”按钮,将返回到屏幕定义的“元素清单”中,此处将列出界面中所包含的元素,以及各元素的具体属性,如图。
4)屏幕逻辑流
点击“逻辑流”页签,逻辑流的代码如下。
PROCESS BEFORE OUTPUT.
MODULE status_0100.
LOOP AT orderdetail_tab INTO orderdetail_tab WITH CONTROL order_items.
ENDLOOP.
PROCESS AFTER INPUT.
MODULE USER_COMMAND_0100.
LOOP AT orderdetail_tab.
ENDLOOP.
在如上屏幕100的“逻辑流”PBO事件中,包含一个MODULE:status_0100,此MODULE在屏幕输出前执行,包括设置GUI、标题栏、变量初始值等,具体代码将在后续屏幕100的PBO事件代码中实现。
PAI事件中,也包含了1个MODULE:user_command_0100此MODULE是在屏幕100中点击按钮时的响应。
4、代码编写
完成如上步骤后,接下来通过程序编辑器(SE38)对代码的各部分进行编写。
4.1、对象定义
根据程序功能需求,定义的变量、内表、控件等对象如代码所列。
*****对象定义
TABLES:ztorders_h.
CONTROLS: order_items TYPE TABLEVIEW USING SCREEN 100.
DATA: ordersh_stru TYPE zu1002_ordersh_stru,
ordersh_tab TYPE zu1002_ordersh_tab WITH HEADER LINE,
gt_print_out TYPE zu1002_ordersh_tab WITH HEADER LINE,
orderdetail_tab TYPE zu1002_orderdetail_tab WITH HEADER LINE,
report_id TYPE sy-repid,
ok_code TYPE sy-ucomm.
TYPE-POOLS:slis.
DATA: it_fieldcat TYPE slis_t_fieldcat_alv WITH HEADER LINE,
i_layout TYPE slis_layout_alv.
*****选择屏幕
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-t01.
SELECT-OPTIONS: s_oid FOR ztorders_h-orderid,
s_odate FOR ztorders_h-orderdate,
s_custid FOR ztorders_h-customerid,
s_empid FOR ztorders_h-employeeid.
SELECTION-SCREEN END OF BLOCK b1.
4.2、程序初始事件
在程序执行后,通过START-OF-SELECTION语句,进行数据的读取和ALV列表的显示。
*&----------------------------------------------------------------------*
*& START-OF-SELECTION
*&----------------------------------------------------------------------*
START-OF-SELECTION.
report_id = sy-repid.
PERFORM read_order.
PERFORM show_alv.
4.3、屏幕100事件
1)PBO事件的MODULE
当屏幕100被调用的时候,首先触发屏幕的PBO事件,此事件包含的MODULE status_0100的代码如下。
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
* 屏幕初始化
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
SET PF-STATUS 'STAT2'.
SET TITLEBAR 'TITLE02'.
ENDMODULE.
此代码首先设置GUI状态为STAT2,标题为TITLE02。
2)PAI事件的MODULE
当点击GUI状态对应图标时,将触发屏幕的PAI事件。user_command_0100是PAI中的MODULE,此MODULE是对按钮点击后的响应,代码如下。
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT
*&---------------------------------------------------------------------*
* 用户点击按钮后的响应
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.
CASE ok_code.
WHEN 'EXIT'.
LEAVE TO SCREEN 0 .
ENDCASE.
ENDMODULE.
4.4、子程序
在程序中,多处用到了不同的子程序。
1)子程序read_order
是用以根据初始界面中输入的选择条件号,获得数据到内表。
*&---------------------------------------------------------------------*
*& Form READ_ORDER
*&---------------------------------------------------------------------*
* 读取订单数据
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM read_order .
SELECT oh~orderid oh~customerid ct~customername ct~city oh~employeeid
et~employeename oh~orderdate oh~shipdate oh~oamount
INTO CORRESPONDING FIELDS OF TABLE ordersh_tab
FROM ztorders_h AS oh
LEFT OUTER JOIN ztcustomer AS ct
ON ct~customerid = oh~customerid
LEFT OUTER JOIN ztemployee AS et
ON et~employeeid = oh~employeeid
WHERE oh~orderid IN s_oid
AND oh~orderdate IN s_odate
AND oh~customerid IN s_custid
AND oh~employeeid IN s_empid.
SORT ordersh_tab BY orderid.
ENDFORM.
2)子程序show_alv
是将获得的数据输出到ALV。
*&---------------------------------------------------------------------*
*& Form ALV_SHOW
*&---------------------------------------------------------------------*
* 显示ALV列表
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM show_alv .
PERFORM prepare_alv_field.
PERFORM layout_init.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_callback_program = report_id
i_background_id = 'ALV_BACKGROUND'
i_callback_pf_status_set = 'SET_PF_STATUS'
i_callback_user_command = 'ALV_USER_COMMAND'
is_layout = i_layout
i_save = 'A'
it_fieldcat = it_fieldcat[]
TABLES
t_outtab = ordersh_tab
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ENDFORM.
3)子程序prepare_alv_field
则是确定ALV中输出的列。
*&---------------------------------------------------------------------*
*& Form PREPARE_ALV_FIELD
*&---------------------------------------------------------------------*
* 设置ALV字段格式
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM prepare_alv_field .
"定义宏m_fieldcat
DEFINE m_fieldcat.
it_fieldcat-fieldname = &1.
it_fieldcat-reptext_ddic = &2.
it_fieldcat-col_pos = &3.
it_fieldcat-checkbox = &4.
it_fieldcat-edit = &5.
APPEND it_fieldcat.
END-OF-DEFINITION.
"调用宏定义ALV字段
m_fieldcat 'SEL' '选择' '010' 'X' 'X'.
m_fieldcat 'ORDERID' '订单编号' '110' ' ' ' '.
m_fieldcat 'CUSTOMERID' '客户ID' '210' ' ' ' '.
m_fieldcat 'CUSTOMERNAME' '客户名称' '310' ' ' ' '.
m_fieldcat 'CITY' '城市' '410' ' ' ' '.
m_fieldcat 'EMPLOYEEID' '雇员ID' '510' ' ' ' '.
m_fieldcat 'EMPLOYEENAME' '雇员名称' '610' ' ' ' '.
m_fieldcat 'ORDERDATE' '订单日期' '710' ' ' ' '.
m_fieldcat 'SHIPDATE' '交货日期' '810' ' ' ' '.
* m_fieldcat 'OAMOUNT' '金额' '910' ' ' ' '.
ENDFORM.
4)子程序layout_init
则是将布局进行初始化,以自动根据列宽进行调整。
*&---------------------------------------------------------------------*
*& Form LAYOUT_INIT
*&---------------------------------------------------------------------*
* ALV布局初始化
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM layout_init .
CLEAR i_layout.
i_layout-colwidth_optimize = 'X'.
ENDFORM.
5)子程序set_pf_status
用于设置ALV列表的GUI状态和标题。
*&---------------------------------------------------------------------*
*& Form SET_PF_STATUS
*&---------------------------------------------------------------------*
* 设置GUI状态标题
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM set_pf_status USING rt_extab TYPE slis_t_extab.
SET PF-STATUS 'ALV_PF_STATUS'.
SET TITLEBAR 'TITLE01'.
ENDFORM.
6)子程序alv_user_command
用于响应用户对ALV列表的操作。
*&---------------------------------------------------------------------*
*& Form ALV_USER_COMMAND
*&---------------------------------------------------------------------*
* ALV列表指令
*----------------------------------------------------------------------*
* --> R_UCOMM text
* <-- RS_SELFIELD text
*----------------------------------------------------------------------*
FORM alv_user_command USING r_ucomm LIKE sy-ucomm
rs_selfield TYPE slis_selfield.
DATA: lr_grid TYPE REF TO cl_gui_alv_grid.
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
* EXPORTING
* IR_SALV_FULLSCREEN_ADAPTER =
IMPORTING
* ET_EXCLUDING =
* E_REPID =
* E_CALLBACK_PROGRAM =
* E_CALLBACK_ROUTINE =
e_grid = lr_grid
* ET_FIELDCAT_LVC =
* ER_TRACE =
* E_FLG_NO_HTML =
* ES_LAYOUT_KKBLO =
* ES_SEL_HIDE =
* ET_EVENT_EXIT =
* ER_FORM_TOL =
* ER_FORM_EOL =
.
CALL METHOD lr_grid->check_changed_data.
rs_selfield-refresh = 'X'.
rs_selfield-col_stable = 'X'.
rs_selfield-row_stable = 'X'.
CASE r_ucomm.
WHEN '&IC1'. "双击时
CHECK rs_selfield-tabindex > 0.
READ TABLE ordersh_tab INTO ordersh_stru INDEX rs_selfield-tabindex.
SUBMIT zu0902_order_trans.
* SET PARAMETER ID 'ORDERID' FIELD ordersh_tab-orderid.
* CALL TRANSACTION 'xxx'.
WHEN 'DISPLAY'. "ALV显示订单详细
CHECK rs_selfield-tabindex > 0.
READ TABLE ordersh_tab INTO ordersh_stru INDEX rs_selfield-tabindex.
PERFORM get_detail_data.
PERFORM display_detail.
WHEN 'PRINTSF'. "打印SMARTFORM
* READ TABLE ordersh_tab INDEX rs_selfield-tabindex.
CHECK rs_selfield-tabindex > 0.
PERFORM get_sf_data.
PERFORM call_smartform.
ENDCASE.
ENDFORM. "ALV_USER_COMMAND
7)子程序get_detail_data
用于响应点击ALV工具栏的“显示订单”的操作,获得订单详细数据。
*&---------------------------------------------------------------------*
*& Form GET_DETAIL_DATA
*&---------------------------------------------------------------------*
* 获得订单明细数据
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM get_detail_data .
SELECT
oi~orderid
oi~materialid
mt~materialname
oi~oquantity
oi~ounit
oi~nprice
oi~pcurrency
oi~discount
INTO TABLE orderdetail_tab
FROM ztorders_i AS oi
INNER JOIN ztmaterial AS mt
ON mt~materialid = oi~materialid
WHERE oi~orderid = ordersh_stru-orderid.
ENDFORM.
8)子程序display_detail
用于响应点击ALV工具栏的“显示订单”的操作,调用屏幕100显示订单详细。
*&---------------------------------------------------------------------*
*& Form DISPLAY_DETAIL
*&---------------------------------------------------------------------*
* 显示订单明细数据
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM display_detail .
CALL SCREEN 100 STARTING AT 20 10.
ENDFORM.
9)子程序get_sf_data
用于响应点击ALV工具栏的“打印-SF”的操作,获得勾选的订单编号。
*&---------------------------------------------------------------------*
*& Form GET_SF_DATA
*&---------------------------------------------------------------------*
* 获得数据准备SmartForms打印输出
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM get_sf_data .
CLEAR gt_print_out.
CLEAR gt_print_out[].
LOOP AT ordersh_tab.
IF ordersh_tab-sel = 'X'.
gt_print_out = ordersh_tab.
APPEND gt_print_out.
ENDIF.
ENDLOOP.
ENDFORM.
10)子程序call_smartform
用于响应点击ALV工具栏的“打印-SF”的操作,调用SmartForms输出单据。
*&---------------------------------------------------------------------*
*& Form CALL_SMARTFORM
*&---------------------------------------------------------------------*
* 调用SmartForms打印单据
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM call_smartform .
DATA: lf_fmnam TYPE rs38l_fnam,
lv_sfnam TYPE tdsfname,
ctrl_param TYPE ssfctrlop,
out_option TYPE ssfcompop.
ctrl_param-preview = 'X'. " 打印预览
ctrl_param-no_dialog = 'X'.
* ctrl_param-device = 'CNSAPWIN'.
out_option-tddest = 'LP02'. " 打印设备
out_option-tdimmed = 'X'. " 直接打印
out_option-tddelete = 'X'. " 打印后删除
lv_sfnam = 'ZU1002_ORDER_SF'.
CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
EXPORTING
formname = lv_sfnam
* VARIANT = ' '
* DIRECT_CALL = ' '
IMPORTING
fm_name = lf_fmnam
* EXCEPTIONS
* NO_FORM = 1
* NO_FUNCTION_MODULE = 2
* OTHERS = 3
.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
LOOP AT gt_print_out.
CALL FUNCTION lf_fmnam
EXPORTING
* ARCHIVE_INDEX =
* ARCHIVE_INDEX_TAB =
* ARCHIVE_PARAMETERS =
control_parameters = ctrl_param
* MAIL_APPL_OBJ =
* MAIL_RECIPIENT =
* MAIL_SENDER =
output_options = out_option
user_settings = space
* IMPORTING
* DOCUMENT_OUTPUT_INFO =
* JOB_OUTPUT_INFO =
* JOB_OUTPUT_OPTIONS =
TABLES
it_order = gt_print_out
EXCEPTIONS
formatting_error = 1
internal_error = 2
send_error = 3
user_canceled = 4
OTHERS = 5.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ENDLOOP.
ENDFORM.
将如上各部分代码合并,则组成了整个实践的程序,完成后对所有内容进行激活。