건양대학교 기업소프트웨어학부
ABAP Report 12주차 과제 본문
[12주차 과제]
ALV에서 여러 라인을 선택하고 ‘학점조회’ 버튼을 누르면 학생 이름과 학점이 팝업 형태의 ALV 로 조회되도록 구현합니다.
1. Toolbar 이벤트
ALV의 Standard Toolbar에 버튼을 추가할 때 Toolbar 이벤트를 사용합니다. Toolbar 이벤트에서는 버튼을 추가하기 위한 로직만 적어줍니다.
버튼을 클릭했을 때 동작은 user_command 이벤트에서 수행하므로 클릭했을 때 동작하는 로직은 user_command 이벤트에 적어줍니다.
[Toolbar 이벤트의 파라미터]
-e_object : cl_alv_event_toolbar_set 클래스를 참조하는 참조 변수. mt_toolbar를 포함.
-mt_toolbar : Toolbar의 Button Element(stb_button) Type의 행을 가진 인터널 테이블.
CLASS-METHODS: on_toolbar FOR EVENT toolbar OF cl_gui_alv_grid IMPORTING e_object.
Toolbar 이벤트를 처리하기 위해서 클래스에 핸들러 메소드 on_toolbar를 선언해줍니다.
METHOD on_toolbar.
DATA ls_button TYPE stb_button. "stb_button을 타입으로 하는 데이터 선언
ls_button-butn_type = 3. "Toolbar에 구분선 추가
INSERT ls_button INTO TABLE e_object->mt_toolbar.
CLEAR : ls_button.
ls_button-function = 'GRADE'. "user_command에 호출될 펑션코드
ls_button-text = '학점조회'. "버튼에 표시되는 Text
INSERT ls_button INTO TABLE e_object->mt_toolbar.
ENDMETHOD.
핸들러 메소드 구현 부분에서는 새로운 버튼을 추가하기 위한 로직을 적어줍니다.
버튼을 추가하기 위해 stb_button이라는 스트럭쳐의 필드에 값을 채우고 mt_toolbar에 insert 합니다.
버튼을 구현하기 위해 Data를 선언합니다. ls_button-butn_type = 3은 버튼 사이에 구분선을 넣어주는 것입니다.
버튼의 펑션 코드는 GRADE, 버튼의 텍스트는 학점조회라고 적힌 버튼을 만들어줍니다.
2. user_command 이벤트
버튼을 클릭했을 때 동작은 user_command 이벤트에서 수행하므로 클릭했을 때 동작하는 로직을 구현해줍니다.
CLASS-METHODS: on_user_command FOR EVENT user_command OF cl_gui_alv_grid IMPORTING e_ucomm.
클래스에 핸들러 메소드인 on_user_command를 선언해줍니다. 해당 이벤트는 e_ucomm을 파라미터로 전달하는데, 이 파라미터에는 Toolbar에서 선택한 버튼의 펑션코드가 들어있습니다.
TYPES: BEGIN OF t_data2,
name TYPE zstudent_31-name,
grade TYPE zstdclass_31-grade,
END OF t_data2.
DATA: gt_data2 TYPE TABLE OF t_data2,
gs_data2 TYPE t_data2.
SALV에 학점과 이름을 띄울 것이기 때문에 Types로 구조체 선언해줍니다.
그리고 구조체와 인터널 테이블 선언했습니다.
METHOD on_user_command.
DATA: lt_row_no TYPE lvc_t_roid,
ls_row_no TYPE lvc_s_roid.
DATA gr_table TYPE REF TO cl_salv_table.
CASE e_ucomm.
WHEN 'GRADE'.
go_alv->get_selected_rows( IMPORTING et_row_no = lt_row_no ).
LOOP AT lt_row_no INTO ls_row_no.
READ TABLE gt_data INTO gs_data INDEX ls_row_no-row_id.
gs_data2-name = gs_data-name.
gs_data2-grade = gs_data-grade.
APPEND gs_data2 TO gt_data2.
CLEAR gs_data2.
ENDLOOP.
cl_salv_table=>factory( IMPORTING r_salv_table = gr_table
CHANGING t_table = gt_data2 ).
gr_table->set_screen_popup(
start_column = 1
end_column = 100
start_line = 1
end_line = 20 ).
gr_table->display( ).
CLEAR gt_data2.
ENDCASE.
ENDMETHOD.
메소드 구현 부분에서는 Toolbar 이벤트에서 추가한 학점조회 버튼을 클릭했을 때의 로직을 구현해줍니다.
파라미터 e_ucomm에 들어온 펑션 코드가 'GRADE' 일 때의 로직을 적어줍니다.
여러 라인을 선택하고 값을 화면에 띄우기 위해 get_selected_rows 메소드를 호출해 사용합니다.
라인을 선택하고 메소드를 호출하면 선택된 라인의 번호를 받아 테이블 gt_data에서 읽어오고 gs_data에 넣어줍니다. 그리고 이름과 학점을 gs_data2라는 구조체에 값을 넣어주고 gt_data2에 값을 어펜드 해줍니다.
gr_table은 SALV의 메인 클래스인 cl_salv_table의 참조 변수로 선언합니다. gr_table은 SALV를 화면에 출력하는 용도로 사용됩니다.
SALV를 화면에 출력하기 위해 factory 메소드를 사용해서 SALV 인스턴스를 생성합니다.
SALV를 화면에 출력하려면 Factory, Display 2개 메소드를 사용해줍니다.
-factory : 화면에 출력할 데이터를 정의하게 된다. ALV 리스트 형태를 정의하게 된다.
-Display : 메소드를 호출하면 스크린에 ALV가 조회된다.
SALV를 팝업창에서 조회하기 위해서 Set_screen_popup 메소드를 호출해 사용합니다. 그리고 Display 메소드를 호출해 스크린에 ALV가 조회되도록 합니다.
3. Set handler 구문을 통한 핸들러 메소드 등록
SET HANDLER lcl_handler=>on_toolbar FOR go_alv.
SET HANDLER lcl_handler=>on_user_command FOR go_alv.
Set handler 구문을 통해 2개의 이벤트를 등록해줍니다.
[프로그램 실행]
[전체코드]
REPORT zclass_31_04.
TABLES: zstudent_31, zstdclass_31_2, zsubject_31, zstutor_31.
TYPES: BEGIN OF t_data,
id TYPE zstudent_31-id,
name TYPE zstudent_31-name,
phone TYPE zstudent_31-phone,
grade TYPE zstdclass_31-grade,
class TYPE zstdclass_31-class,
cname TYPE zsubject_31-cname,
sid TYPE zsubject_31-class,
tutor TYPE zsubject_31-tutor,
tname TYPE zstutor_31-tname,
tid TYPE zstutor_31-tname,
light TYPE c LENGTH 1,
color TYPE c LENGTH 4,
it_col TYPE lvc_t_scol,
END OF t_data.
TYPES: BEGIN OF t_data2,
name TYPE zstudent_31-name,
grade TYPE zstdclass_31-grade,
END OF t_data2.
SELECTION-SCREEN BEGIN OF BLOCK block WITH FRAME TITLE TEXT-001.
SELECT-OPTIONS s_id FOR zstudent_31-id.
SELECT-OPTIONS s_name FOR zstudent_31-name.
SELECTION-SCREEN END OF BLOCK block.
DATA: ok_code TYPE sy-ucomm,
gv_gender TYPE zstudent_31-gender.
DATA: gt_data TYPE TABLE OF t_data,
gs_data TYPE t_data.
DATA: gt_tutor TYPE TABLE OF zstutor_31,
gs_tutor TYPE zstutor_31.
DATA: gt_data2 TYPE TABLE OF t_data2,
gs_data2 TYPE t_data2.
DATA: go_container TYPE REF TO cl_gui_custom_container,
go_alv TYPE REF TO cl_gui_alv_grid.
DATA: gs_layout TYPE lvc_s_layo,
gt_sorting_criteria TYPE lvc_t_sort,
gs_sorting_criterion TYPE lvc_s_sort,
gs_colfield LIKE LINE OF gs_data-it_col,
gt_field_cat TYPE lvc_t_fcat,
gs_field_cat TYPE lvc_s_fcat.
CLASS lcl_handler DEFINITION.
PUBLIC SECTION.
CLASS-METHODS on_double FOR EVENT double_click OF cl_gui_alv_grid IMPORTING es_row_no.
CLASS-METHODS: top_print FOR EVENT print_top_of_page OF cl_gui_alv_grid,
on_toolbar FOR EVENT toolbar OF cl_gui_alv_grid IMPORTING e_object,
on_user_command FOR EVENT user_command OF cl_gui_alv_grid IMPORTING e_ucomm.
ENDCLASS.
CLASS lcl_handler IMPLEMENTATION.
METHOD on_double.
READ TABLE gt_data INTO gs_data INDEX es_row_no-row_id.
DATA: lv_text TYPE c LENGTH 100.
DATA: lv_text2 TYPE c LENGTH 100.
DATA: lv_text3 TYPE c LENGTH 100.
lv_text = gs_data-tname.
lv_text2 = gs_data-cname.
lv_text3 = gs_data-class.
MESSAGE lv_text3 && lv_text2 && lv_text TYPE 'I'.
ENDMETHOD.
METHOD top_print.
DATA lv_pos TYPE i.
WRITE: '건양대학교' ,gs_data-name, '학점은' ,gs_data-grade.
WRITE: / sy-datum.
lv_pos = sy-linsz / 2 - 3. " length of pagno: 6 chars
WRITE AT lv_pos sy-pagno.
lv_pos = sy-linsz - 11. " length of username: 12 chars
WRITE: AT lv_pos sy-uname.
ULINE.
ENDMETHOD.
METHOD on_toolbar.
DATA ls_button TYPE stb_button.
ls_button-butn_type = 3.
INSERT ls_button INTO TABLE e_object->mt_toolbar.
CLEAR : ls_button.
ls_button-function = 'GRADE'.
ls_button-text = '학점조회'.
INSERT ls_button INTO TABLE e_object->mt_toolbar.
ENDMETHOD.
METHOD on_user_command.
* DATA: lv_row TYPE i, lv_col TYPE i.
* DATA: lv_text TYPE c LENGTH 100.
DATA: lt_row_no TYPE lvc_t_roid,
ls_row_no TYPE lvc_s_roid.
* DATA: lv_lines TYPE i.
DATA gr_table TYPE REF TO cl_salv_table.
CASE e_ucomm.
WHEN 'GRADE'.
go_alv->get_selected_rows( IMPORTING et_row_no = lt_row_no ).
LOOP AT lt_row_no INTO ls_row_no.
READ TABLE gt_data INTO gs_data INDEX ls_row_no-row_id.
gs_data2-name = gs_data-name.
gs_data2-grade = gs_data-grade.
APPEND gs_data2 TO gt_data2.
CLEAR gs_data2.
ENDLOOP.
* 팝업
cl_salv_table=>factory( IMPORTING r_salv_table = gr_table
CHANGING t_table = gt_data2 ).
gr_table->set_screen_popup(
start_column = 1
end_column = 50
start_line = 1
end_line = 10 ).
gr_table->display( ).
CLEAR gt_data2.
ENDCASE.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
SELECT
a~id a~name b~class c~cname b~grade a~phone c~tutor
FROM zstudent_31 AS a INNER JOIN zstdclass_31_2 AS b
ON a~id = b~id
INNER JOIN zsubject_31 AS c
ON b~class = c~class
INTO CORRESPONDING FIELDS OF TABLE gt_data
WHERE a~id IN s_id
AND a~name IN s_name.
SELECT *
INTO CORRESPONDING FIELDS OF TABLE gt_tutor
FROM zstutor_31
FOR ALL ENTRIES IN gt_data
WHERE tid = gt_data-tutor.
LOOP AT gt_data INTO gs_data.
READ TABLE gt_tutor WITH KEY tid = gs_data-tutor INTO gs_tutor.
gs_data-tname = gs_tutor-tname.
gs_data-tutor = gs_tutor-tid.
MODIFY gt_data FROM gs_data.
ENDLOOP.
LOOP AT gt_data INTO gs_data.
CASE gs_data-grade.
WHEN 'A+' OR 'A'.
gs_data-light = '3'.
WHEN 'B+' OR 'B'.
gs_data-light = '0'.
WHEN 'C+' OR 'C'.
gs_data-light = '2'.
WHEN OTHERS.
gs_data-light = '1'.
ENDCASE.
*신호등 설정
MODIFY gt_data FROM gs_data.
IF gs_data-grade = 'A+'.
gs_data-color = 'C' && col_positive && '10'.
ENDIF.
IF gs_data-grade = 'F'.
gs_data-color = 'C' && col_negative && '10'.
ENDIF.
*row 컬러 설정
gs_sorting_criterion-fieldname = 'ID'.
APPEND gs_sorting_criterion TO gt_sorting_criteria.
CLEAR gs_sorting_criterion.
gs_sorting_criterion-fieldname = 'TNAME'.
APPEND gs_sorting_criterion TO gt_sorting_criteria.
*필드 ID와 TNAME 기준으로 sort
MODIFY gt_data FROM gs_data.
IF gs_data-tname ='김성준'.
gs_colfield-fname = 'TNAME'.
gs_colfield-color-col = col_heading.
gs_colfield-color-int = '1'.
gs_colfield-color-inv = '0'.
APPEND gs_colfield TO gs_data-it_col.
ENDIF.
*cell 컬러 설정
MODIFY gt_data FROM gs_data TRANSPORTING light color it_col.
ENDLOOP.
END-OF-SELECTION.
CALL SCREEN 100.
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
SET PF-STATUS 'G100'.
SET TITLEBAR 'T100'.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.
CASE ok_code.
WHEN 'BACK'.
PERFORM free_control.
LEAVE TO SCREEN 0.
WHEN 'EXIT'.
PERFORM free_control.
LEAVE PROGRAM.
ENDCASE.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Module CLEAR_CODE OUTPUT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
MODULE clear_code OUTPUT.
CLEAR ok_code.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Module INIT_ALV OUTPUT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
MODULE init_alv OUTPUT.
IF go_container IS INITIAL.
CREATE OBJECT go_container
EXPORTING
container_name = 'CONTROL_AREA'
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE 'error' TYPE 'e'.
ENDIF.
CREATE OBJECT go_alv
EXPORTING
i_parent = go_container.
IF sy-subrc <> 0.
MESSAGE 'control error' TYPE 'e'.
ENDIF.
PERFORM set_fcat.
gs_layout-cwidth_opt = 'X'.
gs_layout-excp_fname = 'LIGHT'.
gs_layout-info_fname = 'COLOR'.
gs_layout-ctab_fname = 'IT_COL'.
gs_layout-sel_mode = 'D'.
SET HANDLER lcl_handler=>on_double FOR go_alv.
SET HANDLER lcl_handler=>top_print FOR go_alv.
SET HANDLER lcl_handler=>on_toolbar FOR go_alv.
SET HANDLER lcl_handler=>on_user_command FOR go_alv.
CALL METHOD go_alv->set_table_for_first_display
EXPORTING
i_structure_name = 'ZSCLASS_31'
is_layout = gs_layout
CHANGING
it_outtab = gt_data
it_fieldcatalog = gt_field_cat
it_sort = gt_sorting_criteria
EXCEPTIONS
invalid_parameter_combination = 1
program_error = 2
too_many_lines = 3
OTHERS = 4.
IF sy-subrc <> 0.
ENDIF.
ENDIF.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Form FREE_CONTROL
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM free_control .
CALL METHOD go_container->free
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
OTHERS = 3.
IF sy-subrc <> 0.
ENDIF.
CALL METHOD go_alv->free
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
OTHERS = 3.
IF sy-subrc <> 0.
ENDIF.
FREE: go_alv, go_container.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form SET_FCAT
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM set_fcat .
gs_field_cat-fieldname = 'NAME'.
gs_field_cat-coltext = '학생이름'.
gs_field_cat-col_pos = 2.
APPEND gs_field_cat TO gt_field_cat.
gs_field_cat-fieldname = 'TNAME'.
gs_field_cat-coltext = '교수이름'.
gs_field_cat-col_pos = 7.
APPEND gs_field_cat TO gt_field_cat.
ENDFORM.
[ALV 메소드]
1) get_current_cell
ALV Grid에서 현재 마우스 커서가 있는 Cell의 좌표와 값을 반환합니다. 선택된 Cell이 존재하지 않으면 라인의 Row값은 0을 반환합니다.
[get_current_cell의 파라미터]
-e_row : ALV 현재 라인 인덱스
-e_value : ALV 현재 셀 값
-e_col : ALV 현재 칼럼 이름
-es_row_id : 아웃풋 테이블의 현재 라인 타입과 인덱스에 대한 정보 구조
-es_col_id : 아웃풋 테이블의 현재 칼럼과 필드면에 대한 정보 구조
2) get_selected_cells
선택된 복수의 Cell의 좌표와 값을 lvc_t_cell 타입의 테이블로 반환합니다. 현재 선택된 셀들의 필드명, 인덱스 들의 정보를 가져옵니다.
3) get_selected_columns
선택된 Column의 정보를 lvc_t_col 타입의 테이블로 반환합니다.
4) get_selected_rows
선택된 여러 Line의 번호를 lvc_t_row 타입의 테이블로 반환합니다.