How to disable the Editable ALV Grid in case of an incorrect entry? - abap

Whenever an invalid value is entered in an ALV Grid, how do I disable the other fields (grey out) in the grid and force the user to fix the incorrect field.
I have tried adding protocol in DATA_CHANGED event. But protocol list only shows the error in popup. Editing is still possible and no fields are disabled.
But how do I disable the other fields. Sample behavior as shown below:
Here, the other fields are greyed out and the invalid entry is highlighted. Until the user fixes this error, he/she cannot proceed further.

Having screen 100 with container CCONTAINER1 paste this snippet
CLASS zcl_alv_test DEFINITION.
PUBLIC SECTION.
METHODS: constructor, display_grid, populate_grid.
DATA: lr_rtti_struc TYPE REF TO cl_abap_structdescr,
it_fldcat TYPE lvc_t_fcat,
grid_container1 TYPE REF TO cl_gui_custom_container,
grid1 TYPE REF TO cl_gui_alv_grid.
DATA: BEGIN OF gs_outtab.
INCLUDE TYPE spfli.
DATA: celltab TYPE lvc_t_styl.
DATA: END OF gs_outtab.
DATA gt_outtab1 LIKE TABLE OF gs_outtab INITIAL SIZE 0.
METHODS:
handle_data_changed FOR EVENT data_changed OF cl_gui_alv_grid IMPORTING er_data_changed,
handle_data_changed_finished FOR EVENT data_changed_finished OF cl_gui_alv_grid IMPORTING e_modified et_good_cells,
create_dynamic_fcat.
PRIVATE SECTION.
TYPES: ty_tab LIKE LINE OF gt_outtab1.
METHODS: refresh_grid, fill_celltab IMPORTING p_fieldname TYPE lvc_fname
CHANGING pt_celltab TYPE lvc_t_styl.
ENDCLASS.
CLASS zcl_alv_test IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT grid_container1 EXPORTING container_name = 'CCONTAINER1'.
CREATE OBJECT grid1 EXPORTING i_parent = grid_container1.
SET HANDLER handle_data_changed FOR grid1.
SET HANDLER handle_data_changed_finished FOR grid1.
CALL METHOD grid1->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_enter.
ENDMETHOD. "constructor
METHOD fill_celltab.
LOOP AT pt_celltab ASSIGNING FIELD-SYMBOL(<fs_fcat>).
IF <fs_fcat>-fieldname = p_fieldname.
<fs_fcat>-style = cl_gui_alv_grid=>mc_style_enabled.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD handle_data_changed.
DATA: lt_celltab TYPE lvc_t_styl.
LOOP AT it_fldcat ASSIGNING FIELD-SYMBOL(<fs_fcat>).
INSERT VALUE lvc_s_styl( style = cl_gui_alv_grid=>mc_style_disabled fieldname = <fs_fcat>-fieldname ) INTO TABLE lt_celltab.
ENDLOOP.
MODIFY gt_outtab1 FROM VALUE ty_tab( celltab = lt_celltab ) TRANSPORTING celltab WHERE connid IS NOT INITIAL.
LOOP AT er_data_changed->mt_mod_cells ASSIGNING FIELD-SYMBOL(<mods>).
READ TABLE gt_outtab1 ASSIGNING FIELD-SYMBOL(<sym>) INDEX <mods>-row_id.
fill_celltab( EXPORTING p_fieldname = <mods>-fieldname
CHANGING pt_celltab = <sym>-celltab ).
MODIFY gt_outtab1 FROM <sym> INDEX <mods>-row_id.
ENDLOOP.
refresh_grid( ).
ENDMETHOD.
METHOD handle_data_changed_finished.
DATA: lt_celltab TYPE lvc_t_styl.
LOOP AT it_fldcat ASSIGNING FIELD-SYMBOL(<fs_fcat>).
IF sy-tabix MOD 2 = 0.
DATA(style) = cl_gui_alv_grid=>mc_style_disabled.
ELSE.
style = cl_gui_alv_grid=>mc_style_enabled.
ENDIF.
INSERT VALUE lvc_s_styl( style = style fieldname = <fs_fcat>-fieldname ) INTO TABLE lt_celltab.
ENDLOOP.
MODIFY gt_outtab1 FROM VALUE ty_tab( celltab = lt_celltab ) TRANSPORTING celltab WHERE connid IS NOT INITIAL.
refresh_grid( ).
ENDMETHOD.
METHOD create_dynamic_fcat.
lr_rtti_struc ?= cl_abap_structdescr=>describe_by_name( 'SPFLI' ).
DATA(comps) = lr_rtti_struc->components.
LOOP AT comps ASSIGNING FIELD-SYMBOL(<comps>).
IF sy-tabix MOD 2 = 0.
DATA(edit) = abap_false.
ELSE.
edit = abap_true.
ENDIF.
APPEND VALUE lvc_s_fcat( edit = edit fieldname = <comps>-name datatype = <comps>-type_kind inttype = <comps>-type_kind intlen = <comps>-length decimals = <comps>-decimals coltext = <comps>-name lowercase = 'X' ) TO it_fldcat .
ENDLOOP.
ENDMETHOD. "create_dynamic_fcat
METHOD populate_grid.
SELECT * UP TO 1000 ROWS
FROM spfli
INTO CORRESPONDING FIELDS OF TABLE gt_outtab1.
ENDMETHOD. "CHANGE_TITLE
METHOD display_grid.
create_dynamic_fcat( ).
grid1->set_table_for_first_display(
EXPORTING
is_layout = VALUE lvc_s_layo( zebra = abap_true stylefname = 'CELLTAB' )
CHANGING
it_outtab = gt_outtab1
it_fieldcatalog = it_fldcat ).
ENDMETHOD. "display_grid
METHOD refresh_grid.
cl_gui_cfw=>flush( ).
grid1->refresh_table_display( ).
ENDMETHOD.
ENDCLASS.
MODULE status_0100 OUTPUT.
SET PF-STATUS 'MAIN100'.
DATA: yalv TYPE REF TO zcl_alv_test.
CREATE OBJECT yalv.
yalv->populate_grid( ).
yalv->display_grid( ).
ENDMODULE.
MODULE user_command_0100 INPUT.
CASE sy-ucomm.
WHEN 'BACK' OR 'EXIT' OR 'RETURN'.
LEAVE PROGRAM.
WHEN OTHERS.
ENDCASE.
ENDMODULE.
START-OF-SELECTION.
CALL SCREEN 100.
It uses the concept of cell styles, where each row in table is assigned a table of styles for each of the column in this row. There you can apply conditional attributes on a cell level, including editability.
When throwing an error through builtin checktables/domains, the grid is made not editable except erroneous cell, and when correcting the error, editability returns.

Related

Total and subtotals problem in Export Excel from ALV tree

I have created a SALV tree, using the CL_SALV_TREE class, the output is shown in the following image:
Now for the export in Excel that works correctly for me, I have used the following code, but the problem is that it does not export the subtotals, so how could I add the subtotals or how could I solve it? since apparently the aggregation functions can't be visible in the ALV tree.
CLASS lcl_tree IMPLEMENTATION.
METHOD export_tree.
DATA: lr_data TYPE REF TO data,
lt_spfli TYPE STANDARD TABLE OF spfli,
levels TYPE TABLE OF rsplf_srv_p.
DATA: lr_zip TYPE REF TO cl_abap_zip,
lr_xlnode TYPE REF TO if_ixml_node,
lr_xldimension TYPE REF TO if_ixml_node,
lr_file TYPE REF TO cl_xml_document,
lr_xlrows TYPE REF TO if_ixml_node_list,
lr_xlrow TYPE REF TO if_ixml_element,
lr_xlformat TYPE REF TO if_ixml_element,
lr_xlworksheet TYPE REF TO if_ixml_element.
FIELD-SYMBOLS: <spfli> TYPE spfli.
DATA(lt_nodes) = go_alv_tree->get_nodes( )->get_all_nodes( ).
LOOP AT lt_nodes INTO DATA(ls_node).
DATA(lr_node) = ls_node-node.
DATA(lv_level) = 0.
DO.
TRY.
lr_node = lr_node->get_parent( ).
lv_level = lv_level + 1.
CATCH cx_salv_msg.
EXIT.
ENDTRY.
ENDDO.
APPEND VALUE rsplf_srv_p( indx = sy-tabix value = lv_level ) TO levels.
lr_data = ls_node-node->get_data_row( ).
ASSIGN lr_data->* TO <spfli>.
APPEND <spfli> TO lt_spfli.
ENDLOOP.
cl_salv_table=>factory(
IMPORTING
r_salv_table = DATA(lr_table)
CHANGING
t_table = lt_spfli ).
DATA(lv_xlsx) = lr_table->to_xml( if_salv_bs_xml=>c_type_xlsx ).
CREATE OBJECT lr_zip.
lr_zip->load( lv_xlsx ).
lr_zip->get( EXPORTING name = 'xl/worksheets/sheet1.xml' IMPORTING
content = DATA(lv_file) ).
CREATE OBJECT lr_file.
lr_file->parse_xstring( lv_file ).
* Row elements are under SheetData
lr_xlnode = lr_file->find_node( 'sheetData' ).
lr_xlrows = lr_xlnode->get_children( ).
DO lr_xlrows->get_length( ) TIMES.
lr_xlrow ?= lr_xlrows->get_item( sy-index - 1 ).
READ TABLE lt_nodes INTO ls_node INDEX sy-index - 1. "find this row
in tree
IF sy-subrc = 0.
READ TABLE levels ASSIGNING FIELD-SYMBOL(<line_level>) INDEX sy-index.
* Find the level of the node
CHECK <line_level>-value - 1 NE 0.
* Assign the level to row
lr_xlrow->set_attribute( name = 'outlineLevel' value = condense( CONV string( <line_level>-value - 1 ) ) ).
lr_xlrow->set_attribute( name = 'hidden' value = 'true' ).
ENDIF.
ENDDO.
* Create new element in the XML file
lr_xlworksheet ?= lr_file->find_node( 'worksheet' ).
DATA(lr_xlsheetpr) = cl_ixml=>create( )->create_document( )->create_element( name = 'sheetPr' ).
DATA(lr_xloutlinepr) = cl_ixml=>create( )->create_document( )->create_element( name = 'outlinePr' ).
lr_xlsheetpr->if_ixml_node~append_child( lr_xloutlinepr ).
lr_xloutlinepr->set_attribute( name = 'summaryBelow' value = 'false' ).
lr_xldimension ?= lr_file->find_node( 'dimension' ).
lr_xlworksheet->if_ixml_node~insert_child( new_child = lr_xlsheetpr ref_child = lr_xldimension ).
* Create xstring and move it to XLSX
lr_file->render_2_xstring( IMPORTING stream = lv_file ).
lr_zip->delete( EXPORTING name = 'xl/worksheets/sheet1.xml' ).
lr_zip->add( EXPORTING name = 'xl/worksheets/sheet1.xml' content = lv_file ).
lv_xlsx = lr_zip->save( ).
DATA lv_size TYPE i.
DATA lt_bintab TYPE solix_tab.
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = lv_xlsx
IMPORTING
output_length = lv_size
TABLES
binary_tab = lt_bintab.
CHECK lt_bintab IS NOT INITIAL.
DATA(p_file) = cl_openxml_helper=>browse_local_file_open( iv_title = 'Save to XLSX File' iv_filename = '' iv_extpattern = 'All files(*.*)|*.*' ).
cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_size
filename = p_file && `.xlsx`
filetype = 'BIN'
CHANGING data_tab = lt_bintab ).
ENDMETHOD.
ENDCLASS.
I tried to replicate the code from this link: https://blogs.sap.com/2015/07/24/salv-tree-to-excel-xlsx/comment-page-1/#comment-658453
There, what it does is add this add-corresponding statement before adding it to the ALV, but that doesn't work on classes which I'm using in my program:
"ADD-CORRESPONDING" is not supported in the OO context
If your question is simplified to what is the code equivalent to add-corresponding in the "OO context", this is one possible answer, I propose the method add_corresponding below, and a test code to demonstrate how it works - this code compiles in 7.40 SP08:
CLASS lcx_add_corresp_not_all_struct DEFINITION INHERITING FROM cx_static_check.
ENDCLASS.
CLASS lcl_app DEFINITION.
PUBLIC SECTION.
CLASS-METHODS add_corresponding IMPORTING from_struct TYPE any
CHANGING to_struct TYPE any
RAISING lcx_add_corresp_not_all_struct
cx_sy_conversion_overflow.
ENDCLASS.
CLASS lcl_app IMPLEMENTATION.
METHOD add_corresponding.
TYPES: ty_names TYPE HASHED TABLE OF abap_compname WITH UNIQUE KEY table_line,
ty_names_in_structs TYPE STANDARD TABLE OF ty_names WITH EMPTY KEY,
ty_table_rtti TYPE STANDARD TABLE OF REF TO cl_abap_typedescr WITH EMPTY KEY.
DATA(rtti_from_struct) = cl_abap_typedescr=>describe_by_data( from_struct ).
DATA(rtti_to_struct) = cl_abap_typedescr=>describe_by_data( to_struct ).
IF rtti_from_struct->kind <> rtti_from_struct->kind_struct
OR rtti_to_struct->kind <> rtti_to_struct->kind_struct.
RAISE EXCEPTION NEW lcx_add_corresp_not_all_struct( ).
ENDIF.
DATA(names_in_structs) = VALUE ty_names_in_structs(
FOR rtti IN VALUE ty_table_rtti( ( rtti_from_struct ) ( rtti_to_struct ) )
( VALUE #( FOR <comp> IN CAST cl_abap_structdescr( rtti )->components
WHERE ( type_kind CA '8abeFIPs' ) " all numeric types
( <comp>-name ) ) ) ).
DATA(same_names) = FILTER ty_names( names_in_structs[ 1 ] IN names_in_structs[ 2 ] WHERE table_line = table_line ).
LOOP AT same_names REFERENCE INTO DATA(same_name).
ASSIGN COMPONENT same_name->* OF STRUCTURE from_struct TO FIELD-SYMBOL(<from_number>).
ASSERT sy-subrc = 0.
ASSIGN COMPONENT same_name->* OF STRUCTURE to_struct TO FIELD-SYMBOL(<to_number>).
ASSERT sy-subrc = 0.
<to_number> = <to_number> + <from_number>.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
CLASS ltc_app DEFINITION
FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS test FOR TESTING RAISING cx_static_check.
METHODS overflow FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltc_app IMPLEMENTATION.
METHOD test.
TYPES: ty_output LIKE ls_output.
ls_output = VALUE #( clabs = 100 ceinm = 500 ).
DATA(ls_output2) = ls_output.
lcl_app=>add_corresponding( EXPORTING from_struct = ls_output2 CHANGING to_struct = ls_output ).
cl_abap_unit_assert=>assert_equals( act = ls_output exp = VALUE ty_output( clabs = 200 ceinm = 1000 ) ).
ENDMETHOD.
METHOD overflow.
TYPES: BEGIN OF ty_struct,
int1 TYPE int1,
END OF ty_struct.
DATA(from_struct) = VALUE ty_struct( int1 = 200 ).
DATA(to_struct) = from_struct.
TRY.
lcl_app=>add_corresponding( EXPORTING from_struct = from_struct CHANGING to_struct = to_struct ).
CATCH cx_sy_conversion_overflow INTO DATA(arithmetic_overflow).
ENDTRY.
cl_abap_unit_assert=>assert_bound( act = arithmetic_overflow msg = |Actual: { to_struct-int1 } ; expected: arithmetic overflow| ).
ENDMETHOD.
ENDCLASS.
NB: instead of ADD-CORRESPONDING, you may simply use ls_output-clabs = ls_output-clabs + ls_mchb-clabs and repeat for all numeric components.
NB: ADD-CORRESPONDING and other arithmetic "corresponding" statements were made obsolete because they are considered error-prone:
"These statements are error-prone because, particularly in complex structures, it is not easy to check that identically named components have the data type and content necessary for a numeric operation."

How can I use dynamic SALV with 3 different raditobutton in OO ABAP

I have to do Batch program for 3 different info types (0014,0015,2010).
First step, I have a parameter that is reading the .xls file in a selection screen and 3 different radio buttons for each info type. I want to display a different ALV as when I execute the program with selected radio button. For example, I want to see 0014 if I selected 0014's radio button. The same situation for others.
I can do what I want with one way. That's way is using Perform which have parameters tables and using.
But I cannot do it with OO ABAP. It means using SALV and CLASS/Method style.
Anyone can guide me?
*------------DEFINITION--------
class lcl_report definition.
public section.
types: begin of ty_list_14,
pernr(8) type c,
begda(10) type c,
endda(10) type c,
lgart(5) type c,
betrg(9) type c,
anzhl type i,
message(200) type c,
durum(5) type c,
end of ty_list_14.
data: gt_list_14 type standard table of ty_list_14,
gs_list_14 like line of gt_list_14.
methods:
check_filename,
file_operations,
display_alv.
private section.
data: mo_alv type ref to cl_salv_table.
data: gt_rows type salv_t_row,
gs_rows type i.
data: it_raw type truxs_t_text_data.
data: v_strln type i,
offset type i,
extension type string.
data: i_0014 type table of p0014 initial size 1,
w_0014 type p0014,
l_bapireturn type bapireturn1.
data: filename type string.
methods:
create_alv,
selection_rows,
alv_properties,
upload_file,
create_record_i0014.
methods :
on_user_command for event added_function of cl_salv_events
importing e_salv_function.
endclass.
*------------IMPLEMENTATION--------
class lcl_report implementation.
method display_alv.
me->create_alv( ).
me->selection_rows( ).
me->alv_properties( ).
endmethod.
method file_operations.
me->upload_file( ).
endmethod.
method create_alv.
data: lo_events type ref to cl_salv_events_table.
try.
cl_salv_table=>factory(
importing
r_salv_table = mo_alv
changing
t_table = gt_list_14[]
).
catch cx_salv_msg.
endtry.
lo_events = mo_alv->get_event( ).
set handler go_report->on_user_command for lo_events.
mo_alv->display( ).
endmethod.
method selection_rows .
data: lo_selection type ref to cl_salv_selections.
try.
"Soldan seçim kutularını ekrana getirir.
lo_selection = mo_alv->get_selections( ).
lo_selection->set_selection_mode( if_salv_c_selection_mode=>row_column ).
catch cx_salv_not_found.
endtry.
endmethod.
method check_filename.
v_strln = strlen( p_file ).
if v_strln le 4.
message text-003 type 'E'.
else.
offset = v_strln - 1.
do v_strln times.
if p_file+offset(1) eq '.'.
extension = p_file+offset.
shift extension left deleting leading '.'.
exit.
endif.
subtract 1 from offset.
enddo.
if extension ne 'xls' and
extension ne 'XLS' and
extension ne 'xlsx' and
extension ne 'XLSX' and
extension ne 'txt' and
extension ne 'TXT'.
message text-003 type 'E'.
endif.
endif.
endmethod.
method create_record_i0014.
data: lv_begda type begda,
lv_endda type endda.
loop at gt_rows into gs_rows.
read table gt_list_14 into gs_list_14 index gs_rows.
call function 'CONVERSION_EXIT_ALPHA_INPUT'
exporting
input = gs_list_14-pernr
importing
output = gs_list_14-pernr.
call function 'CONVERSION_EXIT_QNTY1_INPUT'
exporting
input = gs_list_14-betrg
importing
output = gs_list_14-betrg.
clear: lv_begda, lv_endda.
concatenate gs_list_14-begda+6(4)
gs_list_14-begda+3(2)
gs_list_14-begda(2)
into lv_begda.
concatenate gs_list_14-endda+6(4)
gs_list_14-endda+3(2)
gs_list_14-endda(2)
into lv_endda.
move-corresponding gs_list_14 to w_0014.
w_0014-infty = '0014'.
w_0014-begda = lv_begda.
w_0014-endda = lv_endda.
w_0014-lgart = gs_list_14-lgart.
w_0014-betrg = gs_list_14-betrg.
w_0014-anzhl = gs_list_14-anzhl.
append w_0014 to i_0014.
call function 'BAPI_EMPLOYEE_ENQUEUE'
exporting
number = w_0014-pernr
importing
return = l_bapireturn.
call function 'HR_INFOTYPE_OPERATION'
exporting
infty = '0014'
number = w_0014-pernr
record = w_0014
operation = 'INS'
importing
return = l_bapireturn.
gs_list_14-message = l_bapireturn-message.
if l_bapireturn-type eq 'E'.
gs_list_14-durum = '#5C#'.
elseif l_bapireturn-type eq 'W'.
gs_list_14-durum = '#5D#'.
elseif l_bapireturn-type eq 'S' or
l_bapireturn-type is initial.
gs_list_14-durum = '#5B#'.
gs_list_14-message = text-033.
endif.
call function 'BAPI_EMPLOYEE_DEQUEUE'
exporting
number = w_0014-pernr
importing
return = l_bapireturn.
modify gt_list_14 from gs_list_14 index gs_rows.
clear: gs_list_14, w_0014.
refresh i_0014.
endloop.
endmethod.
method on_user_command.
data: lo_selection type ref to cl_salv_selections.
lo_selection = mo_alv->get_selections( ).
gt_rows = lo_selection->get_selected_rows( ).
case e_salv_function.
when '&AKTAR'.
me->create_record_i0014( ).
endcase.
mo_alv->refresh( ).
endmethod.
endclass.
You need create a field-symbol like Excel table structure and set this field-symbol in the SALV.
See this post to know how to create the field-symbol.
Create a structure from a dynamically assigned <itab>
Best regards.
Sebastian

How to trigger code when the user clicks an ALV hotspot field?

I am struggling with the following issue:
I have two tables (header and items) that I want to connect them by using a hotspot and the class CL_SALV_TABLE. I managed to display the header table and set a hotspot on the column with the number of the order. I want that the second table opens as a popup window after I click once on the number field (which was my hotspot). However, I don't know how to define the event. I know how to get a popup window by using the display method of CL_SALV_TABLE, e.g., this code:
CALL METHOD cl_salv_table=>factory(
* EXPORTING
* list_display = IF_SALV_C_BOOL_SAP=>FALSE
* r_container =
* container_name =
IMPORTING
r_salv_table = o_alv
CHANGING
t_table = it_tab )
.
CATCH cx_salv_msg .
ENDTRY.
o_alv->set_screen_popup( start_column = 1
end_column = 150
start_line = 1
end_line = 30 ).
o_alv->display( ).
Any comment or help is highly appreciated. Thank you in advance!
Here is a minimal example to execute code when an ALV hotspot field is clicked (when any cell in the column "Book number" is clicked, a popup is displayed with a text, but you can do whatever you want of course).
What is important to remember:
METHODS on_hotspot_click FOR EVENT hotspot_click OF cl_gui_alv_grid ... : this is the method to define the code to run when the hotspot field is clicked
SET HANDLER on_hotspot_click ... : to tell the Control Framework to trigger the method when the event occurs
Code:
CLASS lcl_app DEFINITION.
PUBLIC SECTION.
METHODS constructor.
METHODS on_hotspot_click
FOR EVENT hotspot_click OF cl_gui_alv_grid
IMPORTING e_row_id e_column_id es_row_no.
DATA go_alv TYPE REF TO cl_gui_alv_grid.
DATA gt_sbook TYPE TABLE OF sbook.
ENDCLASS.
CLASS lcl_app IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT go_alv EXPORTING i_parent = cl_gui_container=>screen0.
SELECT * FROM sbook INTO TABLE gt_sbook.
DATA(fieldcatalog) = VALUE lvc_t_fcat(
( fieldname = 'BOOKID' ref_table = 'SBOOK' ref_field = 'BOOKID' hotspot = 'X' ) ).
SET HANDLER on_hotspot_click FOR go_alv.
go_alv->set_table_for_first_display(
EXPORTING i_structure_name = 'SBOOK'
CHANGING it_outtab = gt_sbook it_fieldcatalog = fieldcatalog ).
ENDMETHOD.
METHOD on_hotspot_click.
READ TABLE gt_sbook INDEX es_row_no-row_id INTO DATA(ls_sbook).
IF sy-subrc = 0.
MESSAGE |click { ls_sbook-bookid } col { e_column_id-fieldname } row { es_row_no-row_id }| TYPE 'I'.
ENDIF.
ENDMETHOD.
ENDCLASS.
DATA go_app TYPE REF TO lcl_app.
PARAMETERS dummy.
AT SELECTION-SCREEN OUTPUT.
IF go_app IS NOT BOUND.
go_app = NEW lcl_app( ).
ENDIF.

ALV Grid custom F4 help works but then shows No help found

I have a program that displays an editable ALV grid, with a custom F4 help for the field "No." handled via the event onf4. My custom F4 help is displayed and the selected value is returned correctly.
However every time after the custom F4 help closes, another window opens saying "No input help is available".
How to get rid of this supplementary popup?
Thanks.
Here's my code:
CLASS lcl_app DEFINITION.
PUBLIC SECTION.
METHODS constructor.
METHODS display.
METHODS on_onf4
FOR EVENT onf4 OF cl_gui_alv_grid
IMPORTING e_fieldname es_row_no e_fieldvalue.
DATA: grid TYPE REF TO cl_gui_alv_grid,
spflis TYPE TABLE OF spfli.
ENDCLASS.
CLASS lcl_app IMPLEMENTATION.
METHOD constructor.
SELECT * FROM spfli INTO TABLE spflis.
grid = NEW cl_gui_alv_grid(
i_parent = cl_gui_container=>screen0 ).
SET HANDLER on_onf4 FOR grid.
grid->register_f4_for_fields(
it_f4 = VALUE #( ( fieldname = 'CONNID' register = 'X' chngeafter = 'X' ) ) ).
ENDMETHOD.
METHOD display.
DATA(fcat) = VALUE lvc_t_fcat(
( fieldname = 'CARRID' ref_table = 'SPFLI' )
( fieldname = 'CONNID' ref_table = 'SPFLI' f4availabl = 'X' ) ).
grid->set_table_for_first_display(
EXPORTING is_layout = VALUE #( edit = 'X' )
CHANGING it_outtab = spflis
it_fieldcatalog = fcat
EXCEPTIONS OTHERS = 4 ).
ENDMETHOD.
METHOD on_onf4.
DATA return TYPE TABLE OF ddshretval.
IF e_fieldname = 'CONNID'.
SELECT DISTINCT connid FROM spfli INTO TABLE #DATA(connids).
CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
EXPORTING
retfield = 'CONNID'
value_org = 'S'
TABLES
value_tab = connids
return_tab = return
EXCEPTIONS
parameter_error = 1
no_values_found = 2
OTHERS = 3.
IF sy-subrc = 0 AND return IS NOT INITIAL.
FIELD-SYMBOLS <modis> TYPE lvc_t_modi.
ASSIGN er_event_data->m_data->* TO <modis>.
<modis> = VALUE #( BASE <modis> ( row_id = es_row_no-row_id
fieldname = e_fieldname
value = return[ 1 ]-fieldval ) ).
ENDIF.
ENDIF.
ENDMETHOD.
ENDCLASS.
PARAMETERS dummy.
AT SELECTION-SCREEN OUTPUT.
NEW lcl_app( )->display( ).
There's a flag er_event_data->m_event_handled which needs to be set to 'X' in the F4 method handler to say that the F4 was actually managed by the custom handling, otherwise the ALV grid attempts displaying the standard F4 (there was no standard F4 in my case hence the popup).
First add the ER_EVENT_DATA parameter in the method declaration :
METHODS on_onf4
FOR EVENT onf4 OF cl_gui_alv_grid
IMPORTING e_fieldname es_row_no e_fieldvalue
er_event_data.
Inside the method ON_ONF4, set the flag :
er_event_data->m_event_handled = 'X'.

ALV data_changed with deleted rows

I want to access cell value in my ALV OOPS instance for a deleted row.
LOOP AT er_data_changed->mt_deleted_rows INTO ls_del.
CALL METHOD er_data_changed->get_cell_value
EXPORTING
i_row_id = ls_del-row_id
i_fieldname = 'FIPEX'
IMPORTING
e_value = lv-fipex.
ENDLOOP.
but lv-fipex is always blank. Why get_cell_value doesn't work with deleted rows? What can I use for this?
This method seems to return data only if you modify a particular cell or cells of a row. In order to achieve what you want read directly from the internal table used as CHANGING parameter in the call of method SET_TABLE_FOR_FIRST_DISPLAY. The actual deletion occurs after the event DATA_CHANGED so you can do that as the data to be deleted are still in the internal table.
Look at this example (you have to create the screen and status 100 by yourself).
REPORT ZZZ.
CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS:
main,
on_data_changed FOR EVENT data_changed OF cl_gui_alv_grid
IMPORTING
er_data_changed,
on_double_click FOR EVENT double_click OF cl_gui_alv_grid
IMPORTING
es_row_no.
PRIVATE SECTION.
CLASS-DATA:
st_t000 TYPE STANDARD TABLE OF t000 WITH EMPTY KEY.
ENDCLASS.
MODULE status_0100 OUTPUT.
SET PF-STATUS '100'.
lcl_main=>main( ).
ENDMODULE.
MODULE user_command_0100 INPUT.
IF sy-ucomm = 'BACK'.
LEAVE TO SCREEN 0.
ENDIF.
ENDMODULE.
CLASS lcl_main IMPLEMENTATION.
METHOD on_double_click.
ASSERT 1 = 1.
ENDMETHOD.
METHOD on_data_changed.
DATA: l_value TYPE t000-ort01.
LOOP AT er_data_changed->mt_deleted_rows ASSIGNING FIELD-SYMBOL(<fs_deleted_row>).
* er_data_changed->get_cell_value(
* EXPORTING
* i_row_id = <fs_deleted_row>-row_id
* i_fieldname = 'ORT01'
* IMPORTING
* e_value = l_value
* ).
l_value = st_t000[ <fs_deleted_row>-row_id ]-ort01.
ENDLOOP.
ENDMETHOD.
METHOD main.
DATA(lo_gui_container) = NEW cl_gui_custom_container( container_name = 'CONTAINER' ).
DATA(lo_gui_alv_grid) = NEW cl_gui_alv_grid( i_parent = lo_gui_container ).
SELECT * FROM t000 INTO TABLE st_t000 UP TO 20 ROWS.
lo_gui_alv_grid->set_ready_for_input( 1 ).
SET HANDLER on_data_changed FOR lo_gui_alv_grid.
SET HANDLER on_double_click FOR lo_gui_alv_grid.
lo_gui_alv_grid->set_table_for_first_display(
EXPORTING
i_structure_name = 'T000'
CHANGING
it_outtab = st_t000
EXCEPTIONS
invalid_parameter_combination = 1
program_error = 2
too_many_lines = 3
OTHERS = 99
).
ASSERT sy-subrc = 0.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
CALL SCREEN 100.