I know my problem has been asked hundred times.
But I still cannot find any suitable solution for me
I have a dropdown, every time I change data in dropdown it will load new data based on dropdown data
From step one, I refresh editable ALV
Any change in editable ALV willbe saved (another action for saving)
My problem if, After I save, I can't refresh my ALV.
But it's not problem if I haven't pressed save button
NOTE :
in SAP forum, they told me to move refresh function to PBO, I tried this but still failed.
Attached Code is Step 1 is "when SET_P" in this code
PBO
MODULE pbo_1000 OUTPUT.
IF flag = 0.
SET PF-STATUS '1000'.
SET TITLEBAR '1000'.
PERFORM create_toolbar.
PERFORM create_catalog.
PERFORM select_data.
CREATE OBJECT ob_custom
EXPORTING
container_name = 'CCTRL'.
CREATE OBJECT ob_grid
EXPORTING
i_parent = ob_custom
i_appl_events = 'X'.
PERFORM create_dropbox.
CALL METHOD ob_grid->set_table_for_first_display
EXPORTING
i_structure_name = 'TYPE'
it_toolbar_excluding = lt_toolbar
is_layout = lyt
CHANGING
it_fieldcatalog = fld[]
it_outtab = itab[].
CALL METHOD ob_grid->set_ready_for_input
EXPORTING
i_ready_for_input = 1.
CALL METHOD ob_grid->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_enter.
ENDIF.
ENDMODULE.
PAI
MODULE user_command_1000 INPUT .
DATA: v_perio(6) TYPE c.
CASE sy-ucomm.
WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
LEAVE TO SCREEN 0.
WHEN 'SAVE'.
PERFORM save_data.
PERFORM send_email.
WHEN 'SET_S'.
flag = 1.
PERFORM set_status.
CALL METHOD ob_grid->refresh_table_display
EXPORTING
is_stable = stbl.
WHEN 'SET_P'.
flag = 1.
PERFORM select_data.
CALL METHOD ob_grid->refresh_table_display
EXPORTING
is_stable = stbl.
ENDCASE.
ENDMODULE.
I guess you will need the CHECK_CHANGED_DATA method called as first thing in the PAI, which would fire up the events DATA_CHANGED and DATA_CHANGED_FINISHED.
But most important thing is, that it will synchronize the OLE object with the instance backend and then when you are calling the REFRESH_TABLE_DISPLAY it would refresh your ALV properly. I don't have any example at the moment, but I can maybe try next week when I have access to system.
By the way in PBO you don't need to have the variable flag you can use check if the ALV object has been already initialized or not and according to this you can create/refresh alv. Something like this:
if alvGridRef is NOT bound .
data(container) = new cl_gui_custom_container( ) .
data(alvGridRef) = new cl_gui_alv_grid( ) .
else .
alvGridRef->refresh_table_display( ) .
endif .
I've done something similar in an application that needed to be refreshed when saved because some calculations had to change in the screen. I set part of the following code in the command form for the 'REUSE_ALV_GRID_DISPLAY' function module.
form user_command using r_ucomm like sy-ucomm
rs_selfield type slis_selfield.
data: ref_grid type ref to cl_gui_alv_grid, l_valid type c.
if ref_grid is initial.
call function 'GET_GLOBALS_FROM_SLVC_FULLSCR'
importing
e_grid = ref_grid.
endif.
if not ref_grid is initial.
call method ref_grid->check_changed_data
importing
e_valid = l_valid.
endif.
rs_selfield-refresh = 'X'.
...
if not ref_grid is initial.
call method ref_grid->refresh_table_display( ) .
endif.
endform.
Hope it helps
You might achieve this by manually triggering PBO. You stated that the Editing is saved, so you can just display the ALV in PBO again:
CALL FUNCTION 'SAPGUI_SET_FUNCTIONCODE'
EXPORTING
functioncode = 'REFRESH'
EXCEPTIONS
function_not_supported = 1
OTHERS = 2.
After this action, sy-ucomm in PBO has the value REFRESH.
Related
I'm having trouble making the Toolbar(see image) of my SAP Report working despite having tried multiple solutions.
My report's code:
CLASS cl_orders_alv DEFINITION.
PUBLIC SECTION.
METHODS:
on_init, on_display.
PRIVATE SECTION.
METHODS:
on_data_fetch.
DATA: ct_orders TYPE TABLE OF zordhead_str, " header itab
ct_orders_pos TYPE TABLE OF zordpos_str, " pos itab
co_orders_alvgrid TYPE REF TO cl_gui_alv_grid, " ALV Table
co_ordpos_alvgrid TYPE REF TO cl_gui_alv_grid, " ALV Table
co_orders_alvccntr TYPE REF TO cl_gui_custom_container, " Orders Head
co_ordpos_alvccntr TYPE REF TO cl_gui_custom_container, " Orders Position
cs_orders TYPE zordhead_str, " header structure
cs_orders_pos TYPE zordpos_str,
cs_orders_fieldcat TYPE slis_fieldcat_alv, " ALV Structure
ct_orders_fieldcat TYPE lvc_t_fcat, " ALV Table
cs_ordpos_fieldcat TYPE slis_fieldcat_alv,
ct_ordpos_fieldcat TYPE lvc_t_fcat.
ENDCLASS. "cl_orders_alv
CLASS cl_orders_alv IMPLEMENTATION.
METHOD on_init.
CLEAR ct_orders.
CLEAR ct_orders_pos.
CLEAR cs_orders.
CLEAR cs_orders_pos.
CREATE OBJECT co_orders_alvccntr
EXPORTING
container_name = 'ALV_CCONTAINER0'.
CREATE OBJECT co_ordpos_alvccntr
EXPORTING
container_name = 'ALV_CCONTAINER1'.
CREATE OBJECT co_orders_alvgrid
EXPORTING
i_parent = co_orders_alvccntr.
CREATE OBJECT co_ordpos_alvgrid
EXPORTING
i_parent = co_ordpos_alvccntr.
on_data_fetch( ).
ENDMETHOD. "on_init
METHOD on_display.
CALL METHOD co_orders_alvgrid->set_table_for_first_display
EXPORTING
i_structure_name = 'ZORDHEAD_STR'
CHANGING
it_outtab = ct_orders.
CALL METHOD co_ordpos_alvgrid->set_table_for_first_display
EXPORTING
i_structure_name = 'ZORDPOS_STR'
CHANGING
it_outtab = ct_orders_pos.
CALL SCREEN '0100'.
ENDMETHOD. "on_display
METHOD on_data_fetch.
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = 'ZORDHEAD_STR'
CHANGING
ct_fieldcat = ct_orders_fieldcat
EXCEPTIONS
inconsistent_interface = 1
program_error = 2
OTHERS = 3.
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = 'ZORDPOS_STR'
CHANGING
ct_fieldcat = ct_ordpos_fieldcat
EXCEPTIONS
inconsistent_interface = 1
program_error = 2
OTHERS = 3.
ENDMETHOD. "on_data_fetch
ENDCLASS. "CL_ORDERS_ALV IMPLEMENTATION
START-OF-SELECTION.
SET PF-STATUS 'STANDARD_FULLSCREEN'.
DATA: go_alv_gui TYPE REF TO cl_orders_alv.
CREATE OBJECT go_alv_gui.
go_alv_gui->on_init( ).
go_alv_gui->on_display( ).
This is what I have tried so far:
Copied an existing Status into my Program/Report:
Go to Transaction SE41
User Interface => Copy => Status...
From: Program= SAPLSLVC_FULLSCREEN ; Status=STANDARD_FULLSCREEN
To: Program = ZESXDV ; Status = STANDARD_FULLSCREEN
Hit Ok.
Go to Transaction SE80 and open up your Report/Program
The GUI Status folder is created, inside of which there's the new copied status.
Added the following instruction in the report's code(after START-OF-SELECTION):
SET PF-STATUS 'STANDARD_FULLSCREEN'.
Note: I noticed that the Toolbar doesn't work only when working with ALV tables and custom ALV Containers(which both needs a Screen Object[which is called by the CALL SCREEN 'XXXX' instruction.])
Am I missing something?
Thanks in advance for your help.
P.S.: If some info are missing let me know and I'll add them as soon as possible.
You must use screen code as below
PROCESS BEFORE OUTPUT.
MODULE PBO_100.
*
PROCESS AFTER INPUT.
MODULE PAI_100.
creating perform module and put your into pf-status
MODULE pbo_100 OUTPUT.
SET PF-STATUS 'MAIN100'.
set titlebar 'MAIN100'.
ENDMODULE. " PBO_100 OUTPUT
Note: check activeted gui status "MAIN100"
Thanks to #Mustafa Hamit. I'll post what I've done baesd on #Mustafa Hamit's comment.
Go to the Screen object(Double click on CALL SCREEN 100).
Navigate to tab Flow Logic.
Insert MODULE PBO_100. right after PROCESS BEFORE OUTPUT..
Insert MODULE PAI_100. right after PROCESS AFTER INPUT..
Double click on PBO_100 -> Create Object
On the PBO_100 screen write SET PF-STATUS '{NAME OF THE STATUS}' between MODULE pbo_100 OUTPUT. and ENDMODULE.
Go back and create the PAI_100 object(double click on it).
Activate everything.
Two INCLUDE statements should appear on your report's code at the end of the program.
The Toolbar should now be enabled and functional.
I found this issue in some scenario, and that is how I've resolve.
Scenario. Call a Popup window from the component-controller not from a the view.
METHOD wddoinit.
DATA: lo_popup_window TYPE REF TO if_wd_window,
lo_window_manager TYPE REF TO if_wd_window_manager,
lo_cmp_api TYPE REF TO if_wd_component,
lt_text TYPE string_table,
ls_text TYPE string.
lo_cmp_api = wd_this->wd_get_api( ).
lo_window_manager = lo_cmp_api->get_window_manager( ).
ls_text = 'Do you want to continue?'.
INSERT ls_text INTO TABLE lt_text.
CALL METHOD lo_window_manager->create_popup_to_confirm
EXPORTING
text = lt_text
button_kind = if_wd_window=>co_buttons_yesno
default_button = if_wd_window=>co_button_no
window_title = 'Information'
close_button = abap_false
RECEIVING
result = lo_popup_window.
CALL METHOD lo_popup_window->popup_to_confirm->subscribe_to_button_event
EXPORTING
controller = lo_cmp_api
button = if_wd_window=>co_button_no
handler_name = 'ACTION_BTN_NO'.
CALL METHOD lo_popup_window->popup_to_confirm->subscribe_to_button_event
EXPORTING
controller = lo_cmp_api
button = if_wd_window=>co_button_yes
handler_name = 'ACTION_BTN_YES'.
lo_popup_window->open( ).
ENDMETHOD.
-----------------------------------------------------------------------------------
In the methods set the event handlers as follow.
-----------------------------------------------------------------------------------
When I run the program
Following steps will assist you.
Create method popup_window inside component controller having method paramter
ir_vc type ref to if_wd_view_controller
Write above code in the question inside method popup_window.
add below code inside view where you want to call popup.
Code in view:
DATA lo_componentcontroller TYPE REF TO ig_componentcontroller .
lo_componentcontroller = wd_this->get_componentcontroller_ctr( ).
lo_componentcontroller->call_popup( ir_vc = lo_api_main ).
regards,
Umar Abdullah
I want to develop the following logic:
The box "DISPLAY ALV" corresponds to the function module REUSE_ALV_GRID_DISPLAY.
With LEAVE TO SCREEN 0 I can't pass directly to DISPLAY ALV. Is it possible?
Thank you.
No, you cannot return to FM, as you intend to do, 'cause FM is a special callable unit and LEAVE TO SCREEN statement works only for screens. However, you can return to screen 100 which shows that ALV.
Consider following coding, for which you should have screens 100 and 300 with custom containers 100_CONT and 300_CONT on them.
Screen 100 PBO
MODULE pbo_100 OUTPUT.
SET PF-STATUS 'YOUR_PF_STATUS'.
IF custom_container1 IS INITIAL.
SELECT *
FROM mara AS m
INTO TABLE gt_mara
WHERE EXISTS ( SELECT * FROM vbrp WHERE matnr = m~matnr ).
CREATE OBJECT custom_container1
EXPORTING
container_name = cont_on_main.
CREATE OBJECT grid1
EXPORTING
i_parent = custom_container1.
CALL METHOD grid1->set_table_for_first_display
EXPORTING
i_structure_name = 'mara'
is_layout = gs_layout
CHANGING
it_outtab = gt_mara.
CREATE OBJECT event_receiver.
SET HANDLER event_receiver->handle_double_click FOR grid1.
ENDIF.
ENDMODULE. " PBO_100 OUTPUT
Screen 300 PBO
MODULE pbo_0300 OUTPUT.
IF custom_container2 IS INITIAL.
CREATE OBJECT custom_container2
EXPORTING
container_name = cont_on_dialog.
CREATE OBJECT grid2
EXPORTING
i_parent = custom_container2.
gs_layout-grid_title = 'Orders'.
CALL METHOD grid2->set_table_for_first_display
EXPORTING
i_structure_name = 'VBRP'
is_layout = gs_layout
CHANGING
it_outtab = gt_vbrp.
ELSE.
CALL METHOD grid2->refresh_table_display.
ENDIF.
ENDMODULE. " PBO_0300 OUTPUT
Screen 300 PAI
MODULE pai_0300 INPUT.
CASE ok_code.
WHEN 'RETURN'.
DATA: ans.
CALL FUNCTION 'POPUP_TO_CONFIRM'
EXPORTING
titlebar = 'SO sample'
text_question = 'Select next action'
text_button_1 = 'Yes'
icon_button_1 = 'ICON_CHECKED'
text_button_2 = 'No'
icon_button_2 = 'ICON_CANCEL'
display_cancel_button = ' '
IMPORTING
answer = ans.
CASE ans.
WHEN 1.
LEAVE TO SCREEN 0.
WHEN 2.
LEAVE PROGRAM.
WHEN OTHERS.
ENDCASE.
ENDCASE.
CLEAR ok_code.
ENDMODULE.
Main program
CLASS lcl_event_receiver DEFINITION DEFERRED.
DATA: ok_code LIKE sy-ucomm,
gt_mara TYPE TABLE OF mara,
gt_vbrp TYPE TABLE OF vbrp,
grid1 TYPE REF TO cl_gui_alv_grid,
grid2 TYPE REF TO cl_gui_alv_grid,
cont_on_main TYPE scrfname VALUE '100_CONT',
cont_on_dialog TYPE scrfname VALUE '300_CONT',
custom_container1 TYPE REF TO cl_gui_custom_container,
custom_container2 TYPE REF TO cl_gui_custom_container,
event_receiver TYPE REF TO lcl_event_receiver.
START-OF-SELECTION.
CALL SCREEN 100.
CLASS lcl_event_receiver DEFINITION.
PUBLIC SECTION.
METHODS: handle_double_click FOR EVENT double_click OF cl_gui_alv_grid
IMPORTING e_row e_column.
ENDCLASS.
CLASS lcl_event_receiver IMPLEMENTATION.
METHOD handle_double_click.
READ TABLE gt_mara INDEX e_row-index ASSIGNING FIELD-SYMBOL(<fs_mara>).
SELECT *
INTO TABLE gt_vbrp
FROM vbrp
WHERE matnr = <fs_mara>-matnr.
CALL SCREEN 300 STARTING AT 10 5.
ENDMETHOD.
ENDCLASS.
Here at program start we fetch material list with sales orders in the system, and then on double click on screen 100 these orders are showed in screen 300.
By special button with function code RETURN (you should place it on screen 300) we call popup window for interaction with user. By pressing Yes it returns to the initial screen 100, by pressing No the program is interrupted completely.
Here you should pay attention to statement LEAVE TO SCREEN 0 which terminates current dynpro sequence (i.e. 300) and thus returns to 100.
I can't say for sure if this will work but you should try 'set screen 0'. I recently had to do this after programming a 'refresh' button into my ALV report, because after refreshing and re-displaying data, it took multiple 'green arrow' clicks to get out of the report.
I am making a report by using cl_salv_table, and I want to make a button on toolbar of the ALV grid which will show a predefined popup.
I was able to make a button on the toolbar and set the "Functional code" as details, and I saw in the debug mode that on clicking the button the "sy-ucomm" is set to details but it is not going the case loop.
Any help or suggestion would be appreciated.
Please look at the program SALV_DEMO_TABLE_SELECTIONS how to implement event handlers correctly, basically method on_user_command in the class lcl_handle_events is what your looking for.
First of all you should have SALV grid on a screen with container:
try.
cl_salv_table=>factory(
exporting
r_container = gr_container
container_name = 'CONTAINER'
importing
r_salv_table = gr_table
changing
t_table = gt_outtab ).
catch cx_salv_msg. "#EC NO_HANDLER
endtry.
Then all functions should be enabled:
lr_functions = gr_table->get_functions( ).
lr_functions->set_all( gc_true ).
Finally you add own function like this:
include <icon>.
try.
lr_functions->add_function(
name = 'MYFUNCTION'
icon = CONV string( icon_complete )
text = `My function`
tooltip = `My custom function`
position = if_salv_c_function_position=>right_of_salv_functions ).
catch cx_salv_existing cx_salv_wrong_call.
endtry.
The next significant step is to create on_user_command event handler either in the same class or in separate handler class:
data: gr_events type ref to lcl_handle_events.
set handler gr_events->on_user_command for lr_events.
The final thing is the handler method implementation which will do actual function work
class lcl_handle_events implementation.
method on_user_command.
message |Function { e_salv_function } is fired| TYPE 'I'.
endmethod.
endclass.
I experience a problem when I use ALV Tree without item selection enabled. In this case I am not able to receive an event for node context menu request.
When I turn item selection on, everything works fine.
I get the events for the context menu request for nodes as well as items, but i don't need item selection enabled for my application.
Here is some code I can share:
DATA: g_tree TYPE REF TO cl_gui_alv_tree.
* create container for alv-tree
DATA: l_tree_container_name(30) TYPE c,
l_custom_container TYPE REF TO cl_gui_custom_container.
l_tree_container_name = 'TREE'.
CREATE OBJECT l_custom_container
EXPORTING
container_name = l_tree_container_name.
* create tree control
CREATE OBJECT g_tree
EXPORTING
parent = l_custom_container
node_selection_mode = cl_gui_column_tree=>node_sel_mode_single
item_selection = abap_true "WOULD LIKE TO HAVE THIS SET TO FALSE
no_html_header = abap_true
no_toolbar = ''.
And here I register the events:
DATA: lt_events TYPE cntl_simple_events,
l_event TYPE cntl_simple_event.
l_event-eventid = cl_gui_column_tree=>eventid_node_context_menu_req.
APPEND l_event TO lt_events.
l_event-eventid = cl_gui_column_tree=>eventid_item_context_menu_req.
APPEND l_event TO lt_events.
CALL METHOD g_tree->set_registered_events
EXPORTING
events = lt_events
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
illegal_event_combination = 3.
DATA: l_event_receiver TYPE REF TO tree_event_receiver.
CREATE OBJECT l_event_receiver.
SET HANDLER l_event_receiver->handle_node_ctmenu_request FOR g_tree.
SET HANDLER l_event_receiver->handle_node_ctmenu_selected FOR g_tree.
SET HANDLER l_event_receiver->handle_item_ctmenu_request FOR g_tree.
SET HANDLER l_event_receiver->handle_item_ctmenu_selected FOR g_tree.
And here are my handlers:
METHOD handle_node_ctmenu_request.
CALL METHOD menu->add_function
EXPORTING
fcode = 'DELETE_ITEM'
text = 'delete'.
ENDMETHOD.
METHOD handle_item_ctmenu_request.
CALL METHOD menu->add_function
EXPORTING
fcode = 'DELETE_ITEM'
text = 'delete'.
ENDMETHOD.
So both methods are working when item_selection is set to true. Neither of them is working, when item_selection is set to false. However, I would have expected the handle_node_ctmenu_request would be fired in this case.
The trick is in the interconnection of different types of events in ALV Tree Model.
Official SAP Control Framework documentation states that:
If you set the parameter item_selection = 'X' when you created the
instance, you can also react to the following events:
...
ITEM_CONTEXT_MENU_REQUEST
ITEM_CONTEXT_MENU_SELECT
...
But, unfortunately, it doesn't state (it is implied, like many else in SAP world) that Control Framework treats item and node events in pool.
So, if you register item-related events with disabled item_selection parameter, the node-related events will not work as well.
In other words, do not register item-related events, if you want to achieve reaction to your node-related events, or set this parameter to "Enabled".