Step 1. 관련된 변수 선언
* 필요한 변수만 모았습니다.
TYPE-POOLS slis.
CONSTANTS : gc_data_changed TYPE slis_formname VALUE 'ALV_DATA_CHANGED'.
DATA : gs_selfield TYPE slis_selfield.
DATA : gt_fieldcat TYPE slis_t_fieldcat_alv,
gt_events TYPE slis_t_event,
gs_gridset TYPE lvc_s_glay.
* 예를 들어서 상품코드가 바뀔때 상품명이 바뀌고 특정 플래그가 'X'가 되는
경우 입니다.
* 전체를 입력모드로 하는 것이 아니고 MATNR 필드만 입력가능하게 합니다.
* 필드의 속성을 수정이 가능하도록 합니다.
FORM set_fieldcat .
CLEAR gt_fieldcat[].
PERFORM make_fieldcat USING :
........
기타 등등
........
'S' 'FIELDNAME' 'MATNR',
' ' 'OUTPUTLEN' '18',
' ' 'EDIT' 'X', < -----
'E' 'SELTEXT_L' '상품코드',
'S' 'FIELDNAME' 'TEXT',
' ' 'OUTPUTLEN' '30',
'E' 'SELTEXT_L' '상품DESC',
........
기타 등등
........
ENDFORM.
* 이부분은 거의 표준(?) 이죠...
FORM make_fieldcat USING p_gub p_fname p_con.
IF p_gub = 'S'.
CLEAR gs_fieldcat.
ENDIF.
DATA l_col(40).
FIELD-SYMBOLS <fs>.
CONCATENATE 'GS_FIELDCAT-' p_fname INTO l_col.
ASSIGN (l_col) TO <fs>.
MOVE p_con TO <fs>.
IF p_gub = 'E'.
APPEND gs_fieldcat TO gt_fieldcat.
ENDIF.
ENDFORM. " MAKE_FIELDCAT
* 이제 이벤트 처리를 합니다.
FORM set_events.
PERFORM get_alv_event_list.
PERFORM set_event_form USING : slis_ev_user_command gc_user_command,
slis_ev_top_of_page gc_top_of_page,
.....
기타등등 쓰시는 이벤트... 등록
.....
여기에 DATA_CHANGED 이벤트를 등록해줍니다.
slis_ev_data_changed gc_data_changed.
ENDFORM. " set_events
* FUNCTION을 쓸경우 사용가능한 이벤트의 리스트를 가져옵니다.
* 주의하실점은 gt_events 테이블에 'DATA_CHANGED'는 없습니다.
* 그런데, 개발클래스 SLIS를 보면 분명히 위의 이벤트가 있습니다.
* 여기서 의문점을 가지고.....
FORM get_alv_event_list.
CALL FUNCTION 'REUSE_ALV_EVENTS_GET'
EXPORTING
i_list_type = 0
IMPORTING
et_events = gt_events.
ENDFORM. " get_alv_event_list
* 강제로 DATA_CHANGED 이벤트를 등록합니다.
FORM set_event_form USING p_event
p_form.
CLEAR gs_events.
READ TABLE gt_events WITH KEY name = p_event
INTO gs_events.
IF sy-subrc = 0.
gs_events-form = p_form.
MODIFY gt_events FROM gs_events INDEX sy-tabix.
ELSE. < -- 당연히 없죠.. 없을 경우 등록...
gs_events-name = p_event.
gs_events-form = p_form.
APPEND gs_events TO gt_events.
ENDIF.
ENDFORM. " set_event_form
* 여기부터가 진짜죠..
* 어디서 많이 본 SOURCE인데.. 하시는 분들은 CLASS로 프로그램을 작성한
* 기억이 나신 경우입니다.
*&--------------------------------------------------------------------*
*& Form alv_data_changed
*&--------------------------------------------------------------------*
* text
*---------------------------------------------------------------------*
FORM alv_data_changed USING rr_data_changed TYPE REF TO
cl_alv_changed_data_protocol.
DATA : ls_mod_cells TYPE lvc_s_modi,
ls_cells TYPE lvc_s_modi,
l_matnr LIKE mara-matnr.
LOOP AT rr_data_changed->mt_good_cells INTO ls_mod_cells.
CASE ls_mod_cells-fieldname.
WHEN 'MATNR'.
PERFORM mark_changed USING rr_data_changed ls_mod_cells.
ENDCASE.
ENDLOOP.
ENDFORM. "alv_data_changed
* 클래스로 프로그램을 코딩할때와 똑 같죠 ^^
FORM mark_changed USING
rr_data_changed TYPE REF TO cl_alv_changed_data_protocol
rs_mod_cells TYPE lvc_s_modi.
DATA: LV_MAKTX LIKE MAKT-MAKTX.
READ TABLE gt_display INDEX rs_mod_cells-tabix.
* 화면을 갱신할 필요가 있는 경우.....
* METHOD를 바로 CALL해도 문제가 없습니다.
SELECT single maktx INTO lv_maktx
FROM MAKT
WHERE MATNR = GT_DISPLAY-MATNR
AND SPRAS = SY-LANGU.
CALL METHOD rr_data_changed->modify_cell
EXPORTING i_row_id = rs_mod_cells-row_id
i_fieldname = 'MAKTX'
i_value = LV_MAKTX.
* 화면에 보여줄 필요가 없는 경우. 가령 데이터가 바뀌었다는 것만 CHECK.
gt_display-changed = 'X'.
MODIFY TABLE GT_DISPLAY INDEX rs_mod_cells-row_id
TRANSPORTING changed.
ENDFORM. " mark_changed
* 마지막으로 중요한 부분이 남아있습니다.
* Class에서도 edit 이벤트를 등록을 해준 기억이 나실겁니다.
* 가령.. 데이터가 바뀔때..
IF sy-batch IS INITIAL.
CALL METHOD g_grid->register_edit_event EXPORTING
i_event_id =
cl_gui_alv_grid=>mc_evt_modified.
ENDIF.
* 엔터키를 눌렀을때..
IF sy-batch IS INITIAL.
CALL METHOD g_grid->register_edit_event EXPORTING
i_event_id =
cl_gui_alv_grid=>MC_EVT_ENTER.
ENDIF.
와 같이 어떤 경우에 Data_Changed 이벤트가 발생하라고 알려주죠..
이부분에서 역으로 찾았습니다.
gs_gridset-edt_cll_cb = 'X'.
이렇게 해주면 되더군요.. 엔터키를 누르는 경우나 데이터가 바뀌는 경우..
둘다 반응하더군요...
FORM display_alv_function .
gs_gridset-edt_cll_cb = 'X'.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
.......
.......
it_events = gt_events[]
i_grid_settings = gs_gridset
.......
.......
TABLES
t_outtab = gt_display
*** 여기까지 입니다.
주의하실점은 reuse_alv_grid_display함수를 쓰는 경우의 예입니다.
*** 조금 응용을 하시면 데이터가 바뀔때 인터널테이블의 특정 필드에 'X' 표시를 하고
LOOP AT GT_DISPLAY WHERE CHANGED = 'X'.
PERFORM EXEC_BDC. "또는
PERFORM SAVE_CBO_TABLE.
ENDLOOP.
등과 같은 로직을 추가 하시면 됩니다.
* 필요한 변수만 모았습니다.
TYPE-POOLS slis.
CONSTANTS : gc_data_changed TYPE slis_formname VALUE 'ALV_DATA_CHANGED'.
DATA : gs_selfield TYPE slis_selfield.
DATA : gt_fieldcat TYPE slis_t_fieldcat_alv,
gt_events TYPE slis_t_event,
gs_gridset TYPE lvc_s_glay.
* 예를 들어서 상품코드가 바뀔때 상품명이 바뀌고 특정 플래그가 'X'가 되는
경우 입니다.
* 전체를 입력모드로 하는 것이 아니고 MATNR 필드만 입력가능하게 합니다.
* 필드의 속성을 수정이 가능하도록 합니다.
FORM set_fieldcat .
CLEAR gt_fieldcat[].
PERFORM make_fieldcat USING :
........
기타 등등
........
'S' 'FIELDNAME' 'MATNR',
' ' 'OUTPUTLEN' '18',
' ' 'EDIT' 'X', < -----
'E' 'SELTEXT_L' '상품코드',
'S' 'FIELDNAME' 'TEXT',
' ' 'OUTPUTLEN' '30',
'E' 'SELTEXT_L' '상품DESC',
........
기타 등등
........
ENDFORM.
* 이부분은 거의 표준(?) 이죠...
FORM make_fieldcat USING p_gub p_fname p_con.
IF p_gub = 'S'.
CLEAR gs_fieldcat.
ENDIF.
DATA l_col(40).
FIELD-SYMBOLS <fs>.
CONCATENATE 'GS_FIELDCAT-' p_fname INTO l_col.
ASSIGN (l_col) TO <fs>.
MOVE p_con TO <fs>.
IF p_gub = 'E'.
APPEND gs_fieldcat TO gt_fieldcat.
ENDIF.
ENDFORM. " MAKE_FIELDCAT
* 이제 이벤트 처리를 합니다.
FORM set_events.
PERFORM get_alv_event_list.
PERFORM set_event_form USING : slis_ev_user_command gc_user_command,
slis_ev_top_of_page gc_top_of_page,
.....
기타등등 쓰시는 이벤트... 등록
.....
여기에 DATA_CHANGED 이벤트를 등록해줍니다.
slis_ev_data_changed gc_data_changed.
ENDFORM. " set_events
* FUNCTION을 쓸경우 사용가능한 이벤트의 리스트를 가져옵니다.
* 주의하실점은 gt_events 테이블에 'DATA_CHANGED'는 없습니다.
* 그런데, 개발클래스 SLIS를 보면 분명히 위의 이벤트가 있습니다.
* 여기서 의문점을 가지고.....
FORM get_alv_event_list.
CALL FUNCTION 'REUSE_ALV_EVENTS_GET'
EXPORTING
i_list_type = 0
IMPORTING
et_events = gt_events.
ENDFORM. " get_alv_event_list
* 강제로 DATA_CHANGED 이벤트를 등록합니다.
FORM set_event_form USING p_event
p_form.
CLEAR gs_events.
READ TABLE gt_events WITH KEY name = p_event
INTO gs_events.
IF sy-subrc = 0.
gs_events-form = p_form.
MODIFY gt_events FROM gs_events INDEX sy-tabix.
ELSE. < -- 당연히 없죠.. 없을 경우 등록...
gs_events-name = p_event.
gs_events-form = p_form.
APPEND gs_events TO gt_events.
ENDIF.
ENDFORM. " set_event_form
* 여기부터가 진짜죠..
* 어디서 많이 본 SOURCE인데.. 하시는 분들은 CLASS로 프로그램을 작성한
* 기억이 나신 경우입니다.
*&--------------------------------------------------------------------*
*& Form alv_data_changed
*&--------------------------------------------------------------------*
* text
*---------------------------------------------------------------------*
FORM alv_data_changed USING rr_data_changed TYPE REF TO
cl_alv_changed_data_protocol.
DATA : ls_mod_cells TYPE lvc_s_modi,
ls_cells TYPE lvc_s_modi,
l_matnr LIKE mara-matnr.
LOOP AT rr_data_changed->mt_good_cells INTO ls_mod_cells.
CASE ls_mod_cells-fieldname.
WHEN 'MATNR'.
PERFORM mark_changed USING rr_data_changed ls_mod_cells.
ENDCASE.
ENDLOOP.
ENDFORM. "alv_data_changed
* 클래스로 프로그램을 코딩할때와 똑 같죠 ^^
FORM mark_changed USING
rr_data_changed TYPE REF TO cl_alv_changed_data_protocol
rs_mod_cells TYPE lvc_s_modi.
DATA: LV_MAKTX LIKE MAKT-MAKTX.
READ TABLE gt_display INDEX rs_mod_cells-tabix.
* 화면을 갱신할 필요가 있는 경우.....
* METHOD를 바로 CALL해도 문제가 없습니다.
SELECT single maktx INTO lv_maktx
FROM MAKT
WHERE MATNR = GT_DISPLAY-MATNR
AND SPRAS = SY-LANGU.
CALL METHOD rr_data_changed->modify_cell
EXPORTING i_row_id = rs_mod_cells-row_id
i_fieldname = 'MAKTX'
i_value = LV_MAKTX.
* 화면에 보여줄 필요가 없는 경우. 가령 데이터가 바뀌었다는 것만 CHECK.
gt_display-changed = 'X'.
MODIFY TABLE GT_DISPLAY INDEX rs_mod_cells-row_id
TRANSPORTING changed.
ENDFORM. " mark_changed
* 마지막으로 중요한 부분이 남아있습니다.
* Class에서도 edit 이벤트를 등록을 해준 기억이 나실겁니다.
* 가령.. 데이터가 바뀔때..
IF sy-batch IS INITIAL.
CALL METHOD g_grid->register_edit_event EXPORTING
i_event_id =
cl_gui_alv_grid=>mc_evt_modified.
ENDIF.
* 엔터키를 눌렀을때..
IF sy-batch IS INITIAL.
CALL METHOD g_grid->register_edit_event EXPORTING
i_event_id =
cl_gui_alv_grid=>MC_EVT_ENTER.
ENDIF.
와 같이 어떤 경우에 Data_Changed 이벤트가 발생하라고 알려주죠..
이부분에서 역으로 찾았습니다.
gs_gridset-edt_cll_cb = 'X'.
이렇게 해주면 되더군요.. 엔터키를 누르는 경우나 데이터가 바뀌는 경우..
둘다 반응하더군요...
FORM display_alv_function .
gs_gridset-edt_cll_cb = 'X'.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
.......
.......
it_events = gt_events[]
i_grid_settings = gs_gridset
.......
.......
TABLES
t_outtab = gt_display
*** 여기까지 입니다.
주의하실점은 reuse_alv_grid_display함수를 쓰는 경우의 예입니다.
*** 조금 응용을 하시면 데이터가 바뀔때 인터널테이블의 특정 필드에 'X' 표시를 하고
LOOP AT GT_DISPLAY WHERE CHANGED = 'X'.
PERFORM EXEC_BDC. "또는
PERFORM SAVE_CBO_TABLE.
ENDLOOP.
등과 같은 로직을 추가 하시면 됩니다.
댓글 8
-
e-abap
2007.02.09 05:21
잘봤습니다. 감사합니다~ -
체인지
2007.11.20 20:45
좋은 자료 감사합니다^^ -
삐러
2008.01.08 18:18
유용한 정보 감사합니다. -
st
2008.01.09 19:46
감사합니다
-
Goldenbell
2008.03.04 01:52
유용한 자료 감사합니다. -
카이사르
2008.06.09 20:55
감사합니당... -
천군
2008.07.11 23:20
감사합니다... -
indianhead
2009.12.23 22:29
감사합니다.