1、先看一下运行界面。
图1 Selection option查询界面(Block2支持动态显示)
图2 Classic output list查询输出
图3 ALV形式的查询输出
图4 Web Dynpro查询界面(实现部分要求)
图5 Web Dynpro结果界面
图6 SAP List View查询界面(实现部分要求)
图7 SAP List View结果界面
2、主要功能介绍:
主要使用Classic output list的形式完成了题目的所有基本要求,ALV和Web Dynpro功能只是用来练手,还有日后还要继续完善。下面将介绍一下程序实现的功能和用到的模块。
2.1 基本输入要求
如图1,使用select-options定义了Employee ID、Join Date和 Department等查询条件,使用Domain定义各输入,支持F1和F4帮助;其中,如下图,Employee ID定义了Search Help功能(自动填充部分选项);
图8 Search Help
2.2 三个Block
分三个Block供用户输入,Block1用于输入查询的基本信息;Block2用于选择计算工资总额的方式,如图9,支持动态显示;Blok3用于选择使用Classic output list或者ALV形式显示结果。
图9 Block2动态显示
2.3 Report输出
如图2,使用默认的Report形式输出查询结果(画表格部分参考了Y55系统里的example)。
2.4 Web Dynpro等
如图4-图7,同时使用Web Dynpro和SAP List View实现题中部分功能,待完善。
2.5 其他:
使用Text symbols、Selection Texts和多语言翻译;
尝试自定义了Message ID;
对表ZEMP_INFO_WARD和ZEMP_PAY定义了外键;
对以上两个表定义了Database View(内连接?),用于程序中查询
使用INCLUDE、Function Module和Class等,简单模块化程序;
如图,自定义了所需的Domain、Data Element、Tables、Range Types等。
3、源码部分
3.1 报表程序,主要实现图1-图3所示的功能。关键代码均有注释,不再详细介绍(动态显示参考链接在最后面)。
<ztest_demo_ward.abap>
*&---------------------------------------------------------------------*
*& Report ZTEST_DEMO_WARD
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT ztest_demo_wardreport
NO STANDARD PAGE HEADING
MESSAGE-ID zmessage_ward. "My message id
*&---------------------------------------------------------------------*
*& Definition of data
*&---------------------------------------------------------------------*
TABLES sscrfields.
DATA:
itab_employee LIKE STANDARD TABLE OF zdv_employee WITH HEADER LINE,
itab_emp_active LIKE STANDARD TABLE OF zdv_employee WITH HEADER LINE,
itab_emp_nonact LIKE STANDARD TABLE OF zdv_employee WITH HEADER LINE.
DATA:
wa_emp_info TYPE zemp_info_ward.
DATA: x TYPE i.
DATA: gv_total TYPE zdv_employee-payment_amount.
DATA: gt_empinfo_alv LIKE STANDARD TABLE OF zdv_employee.
INCLUDE zbc_demo_alv.
*Selection screen block 1: input the basic information
SELECTION-SCREEN BEGIN OF BLOCK blk1 WITH FRAME TITLE text-001."Please enter the basic infomation.
SELECT-OPTIONS:
so_empid FOR itab_employee-employee_id, "DEFAULT 'I327500' TO 'I327502',
so_join FOR itab_employee-join_date, "Join date
so_dep FOR itab_employee-department, "Department
so_act FOR itab_employee-active NO INTERVALS NO-EXTENSION ,"Active
so_payy FOR itab_employee-payment_year, "Payment year
so_paym FOR itab_employee-payment_month. "Payment month
SELECTION-SCREEN END OF BLOCK blk1.
*Selection screen block 2: the way of calculation of total amount
SELECTION-SCREEN BEGIN OF BLOCK blk2 WITH FRAME TITLE text-002.
"Please select a way of calculation of the total amount of salery.
PARAMETERS: " Radio button for count option
p1 TYPE c RADIOBUTTON GROUP g1 USER-COMMAND uc1 DEFAULT 'X',
p2 TYPE c RADIOBUTTON GROUP g1,
p3 TYPE c RADIOBUTTON GROUP g1.
PARAMETERS: " Sort options: by ID or by Department of by Date
pa_id_s TYPE zdv_employee-employee_id MODIF ID ty1 DEFAULT 'I327500', "by ID
pa_dep_s TYPE zdv_employee-department MODIF ID ty2 DEFAULT 'SDC',"Department
pa_ye_s TYPE zdv_employee-payment_year MODIF ID ty3 DEFAULT '2016', "by Year
pa_mo_s TYPE zdv_employee-payment_month MODIF ID ty3. "by Month
SELECTION-SCREEN END OF BLOCK blk2.
*Selection screen block 3: the way show data
SELECTION-SCREEN BEGIN OF BLOCK blk3 WITH FRAME TITLE text-006. "Please select a way to show data
PARAMETERS: " Radio button for count option
ra_rep TYPE c RADIOBUTTON GROUP g2 USER-COMMAND uc2 DEFAULT 'X',
ra_alv TYPE c RADIOBUTTON GROUP g2.
SELECTION-SCREEN END OF BLOCK blk3.
*&---------------------------------------------------------------------*
*& At selection-screen output
*& According to the user to select dynamic display screen
*&---------------------------------------------------------------------*
AT SELECTION-SCREEN OUTPUT.
LOOP AT SCREEN.
CASE screen-group1.
WHEN 'TY1'.
IF p1 IS INITIAL.
screen-active = '0'.
ELSE.
screen-active = '1'.
ENDIF.
WHEN 'TY2'.
IF p2 IS INITIAL.
screen-active = '0'.
ELSE.
screen-active = '1'.
ENDIF.
WHEN 'TY3'.
IF p3 IS INITIAL.
screen-active = '0'.
ELSE.
screen-active = '1'.
ENDIF.
ENDCASE.
MODIFY SCREEN.
ENDLOOP.
*&---------------------------------------------------------------------*
*& At selection-screen
*&---------------------------------------------------------------------*
AT SELECTION-SCREEN.
* MESSAGE i000(zmessage_ward) WITH text-001 sscrfields-ucomm ."For test
*&---------------------------------------------------------------------*
*& Start-of-selection
*&---------------------------------------------------------------------*
START-OF-SELECTION.
* If system date is greater than the preset quit date
* then update field active to 'N' and quit reason to ‘Contract End’.
SELECT *
FROM zemp_info_ward
INTO wa_emp_info
WHERE
quit_date < sy-datum
AND active = 'Y'.
wa_emp_info-active = 'N'.
wa_emp_info-quit_reason = text-003. "'Contract End'.
UPDATE zemp_info_ward FROM wa_emp_info.
ENDSELECT.
*Get all infomation of the select input
CALL METHOD zbctest_get_emp_info=>get_all_info
EXPORTING
it_empid = so_empid[]
it_joindate = so_join[]
it_department = so_dep[]
it_active = so_act[]
it_payyear = so_payy[]
it_paymonth
= so_paym[]
IMPORTING
ot_empinfo = itab_employee[]
EXCEPTIONS
no_data = 1
OTHERS = 2.
IF sy-subrc NE 0.
MESSAGE e001(zmessage_ward). "There is no data. Message with my own message id
ENDIF.
*&---------------------------------------------------------------------*
*& End-of-selection
*&---------------------------------------------------------------------*
END-OF-SELECTION.
"Quitted employees and current employeesin different blocks
LOOP AT itab_employee.
IF itab_employee-active = 'Y'.
APPEND itab_employee TO itab_emp_active[].
ELSE.
APPEND itab_employee TO itab_emp_nonact[].
ENDIF.
ENDLOOP.
IF ra_rep = 'X'.
"Display the information of current employee
CALL FUNCTION 'WRITEINFO'
EXPORTING
it_emp_info = itab_emp_active[].
"Display the infofmation of current employee
CALL FUNCTION 'WRITEINFO_QUITTED'
EXPORTING
it_emp_info = itab_emp_nonact[].
PERFORM disp_total_salery.
ELSEIF ra_alv = 'X'.
LOOP AT itab_employee.
APPEND itab_employee TO gt_empinfo_alv.
ENDLOOP.
PERFORM alv_grid.
ENDIF.
*&---------------------------------------------------------------------*
*& Form DISP_TOTAL_SALERY
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM disp_total_salery .
"Calculate and display the select total amount of salery
x = sy-linno + 4. SKIP TO LINE x."Set display position
x = sy-colno. POSITION x.
IF p1 = 'X'. "Calculte total anount by ID
CLEAR itab_employee.
gv_total = 0.
SELECT payment_amount
INTO CORRESPONDING FIELDS OF itab_employee
FROM zdv_employee
WHERE employee_id = pa_id_s.
gv_total = gv_total + itab_employee-payment_amount.
ENDSELECT.
WRITE: 'Total payment amount of ', pa_id_s,'is:', gv_total.
ELSEIF p2 = 'X'. "Calculte total anount by Department
CLEAR itab_employee.
gv_total = 0.
SELECT payment_amount
INTO CORRESPONDING FIELDS OF itab_employee
FROM zdv_employee
WHERE department = pa_dep_s.
gv_total = gv_total + itab_employee-payment_amount.
ENDSELECT.
WRITE:'Total payment amount of employee in',pa_dep_s,'is', gv_total.
ELSEIF p3 = 'X'. "Calculte total anount by Date
CLEAR itab_employee.
gv_total = 0.
IF pa_mo_s NE ''. "Calculate by Year and Month
SELECT payment_amount
INTO CORRESPONDING FIELDS OF itab_employee
FROM zdv_employee
WHERE payment_year = pa_ye_s AND payment_month = pa_mo_s.
gv_total = gv_total + itab_employee-payment_amount.
ENDSELECT.
ELSE. "Calculate by Year
SELECT payment_amount
INTO CORRESPONDING FIELDS OF itab_employee
FROM zdv_employee
WHERE payment_year = pa_ye_s.
gv_total = gv_total + itab_employee-payment_amount.
ENDSELECT.
ENDIF.
IF pa_mo_s NE ''.
WRITE:'Total payment amount during ',pa_ye_s, pa_mo_s,'is', gv_total.
ELSE.
WRITE:'Total payment amount during ',pa_ye_s,'is', gv_total.
ENDIF.
ENDIF.
ENDFORM. " DISP_TOTAL_SALERY
3.2 报表的其他程序
上段代码中的INCLUDE程序,用于ALV显示(参考链接在本文最后)。
<INCLUDE zbc_demo_alv & Method:get_emp_info-get_all_info.abap>
*&---------------------------------------------------------------------*
*& Include ZBC_DEMO_ALV
*&---------------------------------------------------------------------*
TYPE-POOLS: slis. "Class pool
DATA:
gt_fieldcat TYPE slis_t_fieldcat_alv,
gs_layout TYPE slis_layout_alv,
gt_sort TYPE slis_t_sortinfo_alv,
gt_list_top_of_page TYPE slis_t_listheader.
DATA:
ls_fieldcat TYPE slis_fieldcat_alv.
*data: gt_empinfo_alv LIKE STANDARD TABLE OF zdv_employee.
*--------------------alv标准的东西(2)------------------------------*
*--------------------------------------------------------------------*
*form alv_grid.
*--------------------------------------------------------------------*
FORM alv_grid.
IF gt_fieldcat[] IS INITIAL.
PERFORM fieldcat_init.
PERFORM layout_init.
ENDIF.
SORT gt_empinfo_alv ASCENDING BY active.
PERFORM grid_display.
ENDFORM. "ALV_GRID
*--------------------------------------------------------------------*
*form fieldcat_init
*--------------------------------------------------------------------*
FORM fieldcat_init.
*按照你需要显示的表头去修改参数
*每一列参数的名称可以查看下面的append_fc_alv函数
PERFORM append_fc_alv
USING:
'EMPLOYEE_ID' 'X' 'Employee' 12 '' 1,
'GENDER' '' 'Gender' 8 '' 2,
'AGE' '' 'Age' 4 '' 3,
'NAME' '' 'Name' 10 '' 4,
'JOIN_DATE' '' 'Join date' 12 '' 5,
'QUIT_DATE' '' 'Quit date' 12 '' 6,
'DEPARTMENT' '' 'Department' 12 '' 7,
'ACTIVE' '' 'Active' 6 '' 8,
'PAYMENT_YEAR' '' 'Pay year' 10 '' 9,
'PAYMENT_MONTH' '' 'Pay month' 10 '' 10,
'PAYMENT_AMOUNT' '' 'Amount' 8 '' 11,
'NO_PAYMENT_REASON' '' 'No payment reason' 20 '' 12 .
ENDFORM. "FIELDCAT_INIT
*--------------------------------------------------------------------*
*form append_fc_alv
*--------------------------------------------------------------------*
FORM append_fc_alv
USING fieldname TYPE slis_fieldcat_alv-fieldname
key TYPE slis_fieldcat_alv-key
reptext_ddic TYPE slis_fieldcat_alv-reptext_ddic
outputlen TYPE slis_fieldcat_alv-outputlen
inttype TYPE slis_fieldcat_alv-inttype
col_pos TYPE sy-cucol.
CLEAR ls_fieldcat.
ls_fieldcat-fieldname = fieldname. "对应内表的字段名称
ls_fieldcat-key = key. "是否是主键(用X标识)
ls_fieldcat-reptext_ddic = reptext_ddic. "前台显示的名称
ls_fieldcat-outputlen = outputlen. "输出的长度
ls_fieldcat-inttype = inttype. "输入类型(自己猜的,不过貌似空着就可以了)
ls_fieldcat-col_pos = col_pos. "输出在第几列
APPEND ls_fieldcat TO gt_fieldcat.
ENDFORM. " APPEND_FC_ALV
*--------------------------------------------------------------------*
*form layout_init *--------------------------------------------------------------------*
FORM layout_init.
gs_layout-zebra = 'X'.
gs_layout-cell_merge ='X'.
gs_layout-colwidth_optimize = 'X'.
gs_layout-no_vline = ''.
gs_layout-totals_before_items = ''.
ENDFORM. " LAYOUT_INIT
*--------------------------------------------------------------------*
*form grid_display
*--------------------------------------------------------------------*
FORM grid_display.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
is_layout = gs_layout
it_fieldcat = gt_fieldcat
i_callback_program = sy-repid
i_save = 'X'
TABLES
t_outtab = gt_empinfo_alv[]. "需要DISPLAY的内表
* CLEAR: gt_empinfo_alv. "用完内表及时清除内容是个好习惯:先清除HEADER line
* REFRESH: gt_empinfo_alv. "再清除内表数据存储空间
ENDFORM. " grid_display
*--------------------ALV标准的东西(2)------------------------------*
METHOD get_all_info.
DATA: wa_employee TYPE zdv_employee .
SELECT *
FROM zdv_employee
INTO wa_employee
WHERE employee_id IN it_empid
AND join_date IN it_joindate
AND department IN it_department
AND active IN it_active
AND payment_year IN it_payyear
AND payment_month IN it_paymonth.
APPEND wa_employee TO ot_empinfo.
ENDSELECT.
IF sy-subrc NE 0.
RAISE no_data.
ELSE.
SORT ot_empinfo ASCENDING BY payment_year payment_month employee_id.
ENDIF.
ENDMETHOD.
<CALL FUNCTION 'WRITEINFO'.abap>
FUNCTION writeinfo.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(IT_EMP_INFO) TYPE ZT_EMPINFO
*"----------------------------------------------------------------------
DATA: x TYPE i, y TYPE i, l TYPE i.
DATA: wa_emp_info TYPE zdv_employee.
DATA: lv_line TYPE i VALUE 0. "Lines of itab
DEFINE new_grid.
y = sy-linno. y = y + 2. skip to line y.
x = sy-colno. position x. write '|'.
END-OF-DEFINITION.
DEFINE write_grid.
x = sy-colno. y = sy-linno. position x.
write: &1, '|'.
l = sy-colno - x + 1.
x = x - 2. y = y + 1. skip to line y. position x.
uline at x(l).
y = y - 1. x = sy-colno. skip to line y. position x.
END-OF-DEFINITION.
*Display the infofmation of current employee
lv_line = LINES( it_emp_info ). "Get the lines of itab
IF lv_line NE 0. "Display date when itab is not empty.
WRITE text-004 "'The information of current employee'
COLOR COL_HEADING.
NEW-LINE.
ULINE AT (155).
y = sy-linno. y = y + 1. SKIP TO LINE y.
x = sy-colno. POSITION x. WRITE '|'.
write_grid:
'Employee ID ','G','Ag','Name ','Join Date ','Quit Date ','Department','A',
'Year','Mo','Payment Amout','No pay reason '.
LOOP AT it_emp_info INTO wa_emp_info.
new_grid.
write_grid:
wa_emp_info-employee_id,
wa_emp_info-gender,
wa_emp_info-age,
wa_emp_info-name,
wa_emp_info-join_date,
wa_emp_info-quit_date,
wa_emp_info-department,
wa_emp_info-active,
wa_emp_info-payment_year,
wa_emp_info-payment_month,
wa_emp_info-payment_amount,
wa_emp_info-no_payment_reason.
ENDLOOP.
ENDIF.
ENDFUNCTION.
<CALL FUNCTION 'WRITEINFO_QUITTED'.abap>
FUNCTION writeinfo_quitted.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(IT_EMP_INFO) TYPE ZT_EMPINFO
*"----------------------------------------------------------------------
DATA: x TYPE i, y TYPE i, l TYPE i.
DATA: wa_emp_info TYPE zdv_employee.
DATA: lv_line TYPE i VALUE 0.
DEFINE new_grid.
y = sy-linno. y = y + 2. skip to line y.
x = sy-colno. position x. write '|'.
END-OF-DEFINITION.
DEFINE write_grid.
x = sy-colno. y = sy-linno. position x.
write: &1, '|'.
l = sy-colno - x + 1.
x = x - 2. y = y + 1. skip to line y. position x.
uline at x(l).
y = y - 1. x = sy-colno. skip to line y. position x.
END-OF-DEFINITION.
lv_line = LINES( it_emp_info ). " Get the lines of internal table
IF lv_line NE 0. "If the itab is not empty , output data
*Display the infofmation of current employee
x = sy-linno + 4. SKIP TO LINE x."Set display position
x = sy-colno. POSITION x.
WRITE text-001 "'The information of quitted employee'
COLOR COL_HEADING.
*uline 1(183).
y = sy-linno. y = y + 1. SKIP TO LINE y.
ULINE AT 1(188).
y = sy-linno. y = y + 1. SKIP TO LINE y.
x = sy-colno. POSITION x. WRITE '|'.
write_grid:
'Employee ID ','G','Ag','Name ','Join Date ','Quit Date ','Department','A',
'Quit reason ','Year','Mo','Payment Amout','No pay reason '.
LOOP AT it_emp_info INTO wa_emp_info.
new_grid.
write_grid:
wa_emp_info-employee_id,
wa_emp_info-gender,
wa_emp_info-age,
wa_emp_info-name,
wa_emp_info-join_date,
wa_emp_info-quit_date,
wa_emp_info-department,
wa_emp_info-active,
wa_emp_info-quit_reason,
wa_emp_info-payment_year,
wa_emp_info-payment_month,
wa_emp_info-payment_amount,
wa_emp_info-no_payment_reason.
ENDLOOP.
*else.
* WRITE text-003 "'No data'
* COLOR COL_HEADING.
ENDIF.
ENDFUNCTION.
3.3 Web Dynpro程序(截图)
图10
图11
图12
3.4 SAP List View程序(合并)
<SAP ListView.abap>
*&---------------------------------------------------------------------*
*& Report ZBC_TEST_ALV
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zbc_test_alv.
DATA ok_code TYPE syucomm.
TABLES zdv_employee.
DATA gs_employee TYPE zdv_employee.
DATA:
go_container TYPE REF TO cl_gui_custom_container,
go_alv_grid TYPE REF TO cl_gui_alv_grid.
DATA gt_employee type zt_empinfo.
INCLUDE zbc_test_alv_user_command_0i01.
INCLUDE zbc_test_alv_user_command_pi01.
INCLUDE zbc_test_alv_init_control_po01.
*----------------------------------------------------------------------*
***INCLUDE ZBC_TEST_ALV_USER_COMMAND_0I01 .
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_pai_0100 INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE user_command_pai_0100 INPUT.
CASE ok_code.
WHEN 'GO'.
MOVE-CORRESPONDING zdv_employee TO gs_employee.
CALL METHOD zbc_get_info=>get_employee_range
EXPORTING
iv_emp_id = gs_employee-employee_id
IMPORTING
et_employee = gt_employee
EXCEPTIONS
no_data = 1
OTHERS = 2.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ELSE.
SET SCREEN 200.
ENDIF.
ENDCASE.
ENDMODULE. " USER_COMMAND_pai_0100 INPUT
*----------------------------------------------------------------------*
***INCLUDE ZBC_TEST_ALV_USER_COMMAND_PI01 .
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_PAI_0200 INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE USER_COMMAND_PAI_0200 INPUT.
CASE ok_code.
WHEN 'BACK'.
SET SCREEN 100.
WHEN 'EXIT'.
SET SCREEN 0.
ENDCASE.
ENDMODULE. " USER_COMMAND_PAI_0200 INPUT
*----------------------------------------------------------------------*
***INCLUDE ZBC_TEST_ALV_INIT_CONTROL_PO01 .
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Module INIT_CONTROL_PROCESSING_0200 OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE INIT_CONTROL_PROCESSING_0200 OUTPUT.
IF go_container IS INITIAL. " To instance the controls on a screen once!
CREATE OBJECT go_container
EXPORTING
container_name = 'CONTROL_AREA_EMPLOYEE'.
CREATE OBJECT go_alv_grid "constructor
EXPORTING
i_parent = go_container.
CALL METHOD go_alv_grid->set_table_for_first_display
EXPORTING
i_structure_name = 'zdv_employee' " a standard table
CHANGING
it_outtab = gt_employee.
ELSE."To be loaded to the grid control to update the display
CALL METHOD go_alv_grid->refresh_table_display.
ENDIF.
ENDMODULE. " INIT_CONTROL_PROCESSING_0200 OUTPUT
4、其他截图备份
图13数据字典-Database View
图14 DataElements Domains Srch Helps
图15类ZBCTEST_GET_EMP_INFO
图16 Web Dynpro中使用的方法
图17 SAP ListView中使用的方法
图18 Search Help
图19 TextElements
图20 Foreign Key
图21 Message ID
参考链接:
写在后面:
1、题目发布后的这两周,由于学校的导师的出勤要求,所以每周只有三个半下午能来公司,很多地方只是做了一个框架,没来得及完善细节,做了备份之后,日后可以继续完善Screen等功能。
2、可根据本周五Review时Mentor对提的意见,检查自己的代码,继续完善。
3、关于Web Drnpro功能,可继续阅读后续相关教材,继续完善代码(可以使用Web Dynpro功能重写“体育馆预约系统”)。
4、下周会开始BC402,BC405和BC414的课程,要制定重读400和430教材的计划,“常读常新”。