Обнаружилось с какого-то момента, что АЛВ при редактировании на режиме изменения ( cl_gui_alv_grid=>mc_evt_modified ) не всегда нормально отрабатывает пара зарегистрированных событий:
data_changed и data_changed_finished.
Кстати, для события cl_gui_alv_grid=>mc_evt_enter - это нормально работает
А именно, если изначально АЛВ был пустым, то при изменении ячейки попадает только в …._finished.
На основе демо примера: BCALV_GRID_EDIT, я сделал тестовый пример, вставки я пометил комментариями: *МОИ ИЗМЕНЕНИЯ: начало* и *МОИ ИЗМЕНЕНИЯ: конец . Добавив пустое событие data_changed_finished и поставив в обеих событиях точки прерывания(логику F4 я закомментил).
Если задать:
p_num = 0
То при добавлении новых строк
Вы только единожды попадете в отладчик попарно в data_changed и data_changed_finished.
Потом, поменяв любую ячейку, будете попадать лишь в data_changed_finished.
А если изначально задать ненулевое кол-во записей в алв
p_num = 5 , например
Потом добавлять/редактировать ячейки вы точками прерываний будете ВСЕГДА попадать попарно на data_changed и data_changed_finished
ПРИЧЕМ, если удалить все записи из алв, а потом добавлять то все равно ВСЕГДА события отрабатывают верно.
В чем соль? Вот весь код
Code:
program test.
*МОИ ИЗМЕНЕНИЯ: начало*
PARAMETERS: p_num(2) TYPE N. "Кол-во строк в АЛВ по умолчанию
parameters p_cell as checkbox default 'X'.
parameters p_loce NO-DISPLAY default ' ' .
parameters p_cedit NO-DISPLAY default ' '.
parameters p_f4 NO-DISPLAY default ' '.
parameters p_bforf4 NO-DISPLAY default ' '.
parameters p_aftrf4 AS CHECKBOX default ' '.
parameters p_style NO-DISPLAY default ' '.
*МОИ ИЗМЕНЕНИЯ: конец*
class cl_gui_object definition load.
class lcl_event_receiver definition deferred.
include <cl_alv_control>.
data: ok_code like sy-ucomm.
data: blubber2(30) type c.
data: blubber6(1) type c value 'X'.
data: blubber7(1) type c value ' '.
data: ls_cell type lvc_s_styl.
data: blubber9(1) type c value ' '.
data: gs_variant type disvariant.
data: gt_fieldcat type lvc_t_fcat.
data: gt_sort type lvc_t_sort.
data: gs_sort type lvc_s_sort.
data: gs_layout type lvc_s_layo.
data: gt_f4 type lvc_t_f4.
data: gs_f4 type lvc_s_f4.
data: gs_fieldcat type lvc_s_fcat.
data: begin of gt_sflight occurs 0.
include structure sflight.
data: carrname like scarr-carrname,
cell type lvc_t_styl,
end of gt_sflight.
data: begin of gt_sflight1 occurs 0.
include structure sflight.
data: carrname like scarr-carrname,
end of gt_sflight1,
g_container type scrfname value 'BCALV_GRID_DEMO_0100_CONT1',
g_container2 type scrfname value 'BCALV_GRID_DEMO_0100_CONT2',
grid1 type ref to cl_gui_alv_grid,
g_custom_container type ref to cl_gui_custom_container.
data g_custom_container2 type ref to cl_gui_custom_container.
data: event_receiver type ref to lcl_event_receiver.
initialization.
if cl_gui_object=>www_active = 'X'.
p_loce = 'X'.
endif.
blubber2 = text-002.
*---------------------------------------------------------------------*
* CLASS LCL_EVENT_RECEIVER DEFINITION
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
class lcl_event_receiver definition.
public section.
methods handle_data_changed
for event data_changed of cl_gui_alv_grid
importing er_data_changed.
*МОИ ИЗМЕНЕНИЯ: начало - определил событие
METHODS handle_data_changed_finish
FOR EVENT DATA_CHANGED_FINISHED OF cl_gui_alv_grid
IMPORTING E_MODIFIED
ET_GOOD_CELLS .
*МОИ ИЗМЕНЕНИЯ: конец
methods handle_f4
for event onf4 of cl_gui_alv_grid
importing e_fieldname
es_row_no
er_event_data
et_bad_cells.
endclass.
*---------------------------------------------------------------------*
* CLASS lcl_event_receiver IMPLEMENTATION
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
class lcl_event_receiver implementation.
method handle_data_changed.
perform data_changed using er_data_changed.
endmethod.
method handle_f4.
perform f4 using e_fieldname
es_row_no
er_event_data
et_bad_cells.
endmethod.
METHOD handle_data_changed_finish.
PERFORM DATA_CHANGED_FINISHED USING E_MODIFIED
ET_GOOD_CELLS.
ENDMETHOD.
endclass.
*---------------------------------------------------------------------*
* MAIN *
*---------------------------------------------------------------------*
start-of-selection.
if ( p_loce = ' ' and cl_gui_object=>www_active = 'X' ).
message i000(0K) with text-003.
p_loce = 'X'.
endif.
if ( cl_gui_control=>www_active = ' ' ).
select * into corresponding fields of table gt_sflight1 from
( sflight left join scarr
on sflight~carrid = scarr~carrid ) up to 50 rows.
else.
select * into corresponding fields of table gt_sflight1 from
( sflight left join scarr
on sflight~carrid = scarr~carrid ) up to 60 rows.
endif.
loop at gt_sflight1.
clear gt_sflight.
clear ls_cell.
move-corresponding gt_sflight1 to gt_sflight.
if p_cedit = 'X'.
if sy-tabix = 7.
ls_cell-style = cl_gui_alv_grid=>mc_style_disabled.
append ls_cell to gt_sflight-cell.
endif.
if sy-tabix = 9.
ls_cell-style = cl_gui_alv_grid=>mc_style_enabled.
ls_cell-maxlen = 4.
ls_cell-fieldname = 'PLANETYPE'.
append ls_cell to gt_sflight-cell.
endif.
if sy-tabix = 11.
ls_cell-style = cl_gui_alv_grid=>mc_style_enabled.
ls_cell-maxlen = 4.
ls_cell-fieldname = 'CARRNAME'.
append ls_cell to gt_sflight-cell.
endif.
endif.
append gt_sflight.
endloop.
clear gs_fieldcat.
gs_fieldcat-fieldname = 'CARRID'.
gs_fieldcat-ref_table = 'SFLIGHT'.
gs_fieldcat-outputlen = '5'.
gs_fieldcat-key = 'X'.
gs_fieldcat-edit = 'X'.
gs_fieldcat-auto_value = 'X'.
append gs_fieldcat to gt_fieldcat.
clear gs_fieldcat.
gs_fieldcat-fieldname = 'CARRNAME'.
gs_fieldcat-ref_table = 'SCARR'.
gs_fieldcat-outputlen = '12'.
gs_fieldcat-key = 'X'.
gs_fieldcat-auto_value = 'X'.
append gs_fieldcat to gt_fieldcat.
clear gs_fieldcat.
gs_fieldcat-fieldname = 'CONNID'.
gs_fieldcat-ref_table = 'SFLIGHT'.
gs_fieldcat-key = 'X'.
gs_fieldcat-edit = 'X'.
gs_fieldcat-auto_value = 'X'.
append gs_fieldcat to gt_fieldcat.
clear gs_fieldcat.
gs_fieldcat-fieldname = 'FLDATE'.
gs_fieldcat-ref_table = 'SFLIGHT'.
gs_fieldcat-edit = 'X'.
gs_fieldcat-key = 'X'.
append gs_fieldcat to gt_fieldcat.
clear gs_fieldcat.
gs_fieldcat-fieldname = 'PLANETYPE'.
gs_fieldcat-ref_table = 'SFLIGHT'.
gs_fieldcat-edit = 'X'.
append gs_fieldcat to gt_fieldcat.
clear gs_fieldcat.
gs_fieldcat-fieldname = 'SEATSMAX'.
gs_fieldcat-ref_table = 'SFLIGHT'.
append gs_fieldcat to gt_fieldcat.
clear gs_fieldcat.
gs_fieldcat-fieldname = 'SEATSOCC'.
gs_fieldcat-ref_table = 'SFLIGHT'.
gs_fieldcat-edit = 'X'.
append gs_fieldcat to gt_fieldcat.
clear gs_fieldcat.
gs_fieldcat-fieldname = 'PAYMENTSUM'.
gs_fieldcat-datatype = 'CURR'.
gs_fieldcat-coltext = text-004.
gs_fieldcat-cfieldname = 'CURRENCY'.
gs_fieldcat-edit = 'X'.
append gs_fieldcat to gt_fieldcat.
clear gs_fieldcat.
gs_fieldcat-fieldname = 'PRICE'.
gs_fieldcat-ref_table = 'SFLIGHT'.
gs_fieldcat-cfieldname = 'CURRENCY'.
gs_fieldcat-edit = 'X'.
append gs_fieldcat to gt_fieldcat.
clear gs_fieldcat.
gs_fieldcat-fieldname = 'CURRENCY'.
gs_fieldcat-ref_table = 'SFLIGHT'.
gs_fieldcat-edit = 'X'.
gs_fieldcat-checktable = '!'.
gs_fieldcat-auto_value = 'X'.
append gs_fieldcat to gt_fieldcat.
gs_variant-report = sy-repid.
gs_sort-fieldname = 'CARRID'.
append gs_sort to gt_sort.
gs_f4-fieldname = 'PLANETYPE'.
if p_f4 = 'X'.
gs_f4-register = 'X'.
endif.
if p_bforf4 = 'X'.
gs_f4-getbefore = 'X'.
endif.
if p_aftrf4 = 'X'.
gs_f4-chngeafter = 'X'.
endif.
insert gs_f4 into table gt_f4.
gs_f4-fieldname = 'CONNID'.
if p_f4 = 'X'.
gs_f4-register = 'X '.
endif.
if p_bforf4 = 'X'.
gs_f4-getbefore = 'X'.
endif.
if p_aftrf4 = 'X'.
gs_f4-chngeafter = 'X'.
endif.
if ( p_loce = 'X' ).
call screen 200.
else.
call screen 100.
endif.
*---------------------------------------------------------------------*
* MODULE PBO OUTPUT *
*---------------------------------------------------------------------*
module pbo output.
perform pbo_output.
endmodule.
*---------------------------------------------------------------------*
* MODULE PAI INPUT *
*---------------------------------------------------------------------*
module pai input.
perform pai_input.
endmodule.
*&---------------------------------------------------------------------*
*& Form data_changed
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
form data_changed using rr_data_changed type ref to
cl_alv_changed_data_protocol.
*МОИ ИЗМЕНЕНИЯ: начало - добавил точку прерывания
break-POINT.
*МОИ ИЗМЕНЕНИЯ: конец
*МОИ ИЗМЕНЕНИЯ: начало - все закомментировал, но можно раскомментить :)*
* data: ls_mod_cells type lvc_s_modi.
* data: ls_cells type lvc_s_modi.
* data: l_carrid type sflight-carrid.
* data: l_seats type sflight-seatsocc.
* data: l_curr type sflight-currency.
* data: l_seatsmax type sflight-seatsmax.
* data: ls_sflight like gt_sflight1.
* data: ls_tcurc like tcurc. "#EC NEEDED
*
* loop at rr_data_changed->mt_good_cells into ls_mod_cells.
*
* case ls_mod_cells-fieldname.
* when 'CARRID'.
* call method rr_data_changed->get_cell_value
* exporting i_row_id = ls_mod_cells-row_id
* i_fieldname = ls_mod_cells-fieldname
* importing e_value = l_carrid.
* select single * into corresponding fields
* of ls_sflight from
* ( sflight left join scarr
* on sflight~carrid = scarr~carrid )
* where sflight~carrid = l_carrid.
* if sy-subrc ne 0.
* else.
* call method rr_data_changed->modify_cell
* exporting i_row_id = ls_mod_cells-row_id
* i_fieldname = 'CARRNAME'
* i_value = ls_sflight-carrname.
* endif.
* when 'CONNID'.
* if p_style = 'X'.
* call method rr_data_changed->modify_style
* exporting i_fieldname = 'CURRENCY'
* i_row_id = ls_mod_cells-row_id
* i_style = cl_gui_alv_grid=>mc_style_disabled.
* endif.
*
* when 'PLANETYPE'.
** perform change_planetype using rr_data_changed
** ls_mod_cells.
* when 'SEATSOCC'.
* call method rr_data_changed->add_protocol_entry
* exporting i_msgid = '0K'
* i_msgno = '000'
* i_msgty = 'I'
* i_msgv1 = text-007
* i_msgv2 = text-008
* i_fieldname = ls_mod_cells-fieldname
* i_row_id = ls_mod_cells-row_id.
* read table rr_data_changed->mt_good_cells into ls_cells
* with key row_id = ls_mod_cells-row_id
* fieldname = 'PLANETYPE'.
* if sy-subrc = 0.
* perform change_planetype using rr_data_changed
* ls_cells.
* endif.
* call method rr_data_changed->get_cell_value
* exporting i_row_id = ls_mod_cells-row_id
* i_fieldname = ls_mod_cells-fieldname
* importing e_value = l_seats.
*
* call method rr_data_changed->get_cell_value
* exporting i_row_id = ls_mod_cells-row_id
* i_fieldname = 'SEATSMAX'
* importing e_value = l_seatsmax.
*
* if l_seatsmax < l_seats.
* call method rr_data_changed->add_protocol_entry
* exporting i_msgid = '0K'
* i_msgno = '000'
* i_msgty = 'E'
* i_msgv1 = text-007
* i_msgv2 = text-008
* i_fieldname = ls_mod_cells-fieldname
* i_row_id = ls_mod_cells-row_id.
* call method rr_data_changed->add_protocol_entry
* exporting i_msgid = '0K'
* i_msgno = '000'
* i_msgty = 'I'
* i_msgv1 = text-007
* i_msgv2 = text-008
* i_fieldname = ls_mod_cells-fieldname
* i_row_id = ls_mod_cells-row_id.
* endif.
* when 'CURRENCY'.
* call method rr_data_changed->get_cell_value
* exporting i_row_id = ls_mod_cells-row_id
* i_fieldname = ls_mod_cells-fieldname
* importing e_value = l_curr.
*
* select single * from tcurc into ls_tcurc where waers = l_curr.
* if sy-subrc ne 0.
* call method rr_data_changed->add_protocol_entry
* exporting i_msgid = '0K'
* i_msgno = '000'
* i_msgty = 'E'
* i_msgv1 = text-001
* i_msgv2 = l_curr
* i_msgv3 = text-006
* i_fieldname = ls_mod_cells-fieldname
* i_row_id = ls_mod_cells-row_id.
* endif.
* endcase.
* endloop.
*МОИ ИЗМЕНЕНИЯ: конец*
endform. " data_changed
*&---------------------------------------------------------------------*
*& Form change_planetype
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
form change_planetype using rr_data_changed type ref to
cl_alv_changed_data_protocol
rs_mod_cells type lvc_s_modi.
data: l_planetype type sflight-planetype.
data: ls_saplane type saplane .
call method rr_data_changed->get_cell_value
exporting i_row_id = rs_mod_cells-row_id
i_fieldname = rs_mod_cells-fieldname
importing e_value = l_planetype.
select single * from saplane into ls_saplane where
planetype = l_planetype.
if sy-subrc ne 0.
call method rr_data_changed->add_protocol_entry
exporting i_msgid = '0K'
i_msgno = '000'
i_msgty = 'E'
i_msgv1 = text-005
i_msgv2 = l_planetype
i_msgv3 = text-006
i_fieldname = rs_mod_cells-fieldname
i_row_id = rs_mod_cells-row_id.
else.
call method rr_data_changed->modify_cell
exporting i_row_id = rs_mod_cells-row_id
i_fieldname = 'SEATSMAX'
i_value = ls_saplane-seatsmax.
call method rr_data_changed->modify_cell
exporting i_row_id = rs_mod_cells-row_id
i_fieldname = 'PAYMENTSUM'
i_value = '1000'.
call method rr_data_changed->modify_style
exporting i_fieldname = 'PAYMENTSUM'
i_row_id = rs_mod_cells-row_id
i_style = cl_gui_alv_grid=>mc_style_disabled.
endif.
endform. " change_planetype
*&---------------------------------------------------------------------*
*& Form F4
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
form f4 using r_fieldname type lvc_fname
rs_row_no type lvc_s_roid
rr_event_data type ref to cl_alv_event_data
rt_bad_cells type lvc_t_modi. "#EC *
field-symbols: <lt_f4> type lvc_t_modi.
data: ls_f4 type lvc_s_modi.
assign rr_event_data->m_data->* to <lt_f4>.
ls_f4-fieldname = r_fieldname.
ls_f4-row_id = rs_row_no-row_id.
ls_f4-value = 'BLUBBER'.
append ls_f4 to <lt_f4>.
rr_event_data->m_event_handled = 'X'.
endform. " F4
*&---------------------------------------------------------------------*
*& Form pbo_output
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM pbo_output.
set pf-status 'MAIN100'.
if g_custom_container is initial.
if sy-batch is initial.
create object g_custom_container
exporting container_name = g_container.
if ( p_loce = 'X' ).
create object g_custom_container2
exporting container_name = g_container2.
endif.
endif.
create object grid1
exporting i_parent = g_custom_container
i_applogparent = g_custom_container2.
create object event_receiver.
set handler event_receiver->handle_data_changed for grid1.
*МОИ ИЗМЕНЕНИЯ: начало - зарегистрировал событие
set handler event_receiver->handle_data_changed_finish for grid1.
*МОИ ИЗМЕНЕНИЯ: конец
if p_f4 = 'X'.
set handler event_receiver->handle_f4 for grid1.
endif.
* call method grid1->register_f4_for_fields exporting it_f4 = gt_f4.
if sy-batch is initial.
if p_cell = 'X'.
call method grid1->register_edit_event exporting
i_event_id =
cl_gui_alv_grid=>mc_evt_modified.
else.
call method grid1->register_edit_event exporting
i_event_id =
cl_gui_alv_grid=>mc_evt_enter.
endif.
endif.
gs_layout-stylefname = 'CELL'.
*МОИ ИЗМЕНЕНИЯ: начало - ограничиваю чилос строк параметром селекционного экрана p_num
DATA: gt_sflight1 LIKE gt_sflight OCCURS 0 WITH HEADER LINE.
DO p_num TIMES.
READ TABLE gt_sflight INTO gt_sflight1 INDEX sy-index.
APPEND gt_sflight1.
ENDDO.
gt_sflight[] = gt_sflight1[].
*МОИ ИЗМЕНЕНИЯ: конец
call method grid1->set_table_for_first_display
exporting " i_buffer_active = 'X'
i_save = 'A'
is_variant = gs_variant
is_layout = gs_layout
changing it_fieldcatalog = gt_fieldcat
it_sort = gt_sort
it_outtab = gt_sflight[].
endif.
ENDFORM. " pbo_output
*&---------------------------------------------------------------------*
*& Form pai_input
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM pai_input.
data: l_valid(1) type c.
case ok_code.
when 'SAVE'.
call method grid1->check_changed_data importing e_valid = l_valid.
if l_valid = 'X'.
message i000(0k) with text-009.
else.
message i000(0k) with text-010.
endif.
when 'CHANGE'.
if grid1->is_ready_for_input( ) = 0.
call method grid1->set_ready_for_input exporting
i_ready_for_input = 1.
else.
call method grid1->check_changed_data
importing e_valid = l_valid.
if l_valid = 'X'.
call method grid1->set_ready_for_input exporting
i_ready_for_input = 0.
endif.
endif.
when 'EXIT'.
set screen 0.
leave screen.
endcase.
clear ok_code.
ENDFORM. " pai_input
*МОИ ИЗМЕНЕНИЯ: начало - добавил событие с точкой прерывания
form DATA_CHANGED_FINISHED using E_MODIFIED Type CHAR01
ET_GOOD_CELLS Type LVC_T_MODI.
break-POINT.
endform.
*МОИ ИЗМЕНЕНИЯ: конец