Hi all
In using and fiddling a lot with CL_GUI_ALV_GRID and related classes for ALV applications.
Whilst having got pretty standardized code for different applications a big draw back is that each program or application needs it's own IDENTICAL screen (say 100) and the same piece of code for the PBO/PAI.
For example.
MODULE status_0100 OUTPUT.
invoker = sy-repid.
IF z_object IS INITIAL.
CREATE object Z_OBJECT
exporting Z_OBJECT = Z_OBJECT.
CALL METHOD z_object->build_dynamic_structures
EXPORTING
my_line = my_line
calling_program = invoker
IMPORTING
dy_table = dy_table
CHANGING
it_fldcat = it_fldcat.
name columns and set grid title in main program in this form
perform name_columns.
fill dynmic table and display
PERFORM populate_dynamic_itab.
CALL METHOD z_object->display_grid
EXPORTING
g_outtab = <dyn_table>
g_fldcat = it_fldcat
i_gridtitle = i_gridtitle
i_edit = i_edit
i_zebra = i_zebra
CHANGING
it_fldcat = it_fldcat
gt_outtab = <dyn_table>.
SET PF-STATUS '001'.
SET TITLEBAR '000'.
ENDIF.
ENDMODULE.
*
----
MODULE user_command_0100 INPUT.
CASE sy-ucomm.
WHEN 'BACK'.
LEAVE PROGRAM.
WHEN 'EXIT'.
LEAVE PROGRAM.
WHEN 'RETURN'.
LEAVE PROGRAM.
WHEN OTHERS.
ENDCASE.
ENDMODULE.
Since the screens are IDENTICAL -- have same elements - a single custom container and logic there ought to be a way of calling up a SHARED SCREEN.
Now two questions
1) Could I create PAI / PBO events entirely in OO.
2) could I create a CALL SCREEN class whereby the SAME SCREEN is called by any users of the class. This would avoid having to define a separate screen for each ALV program I am creating.
if I still must have the PBO / PAI can I get this in the Screen class.
The whole object here is to be able to create ALV programs without needing the screen definition in ech of them.
I need still to use class cl_gui_alv_grid rather than the new salv class set as I need editable grids etc. The SALV class set only allows fairly simple display mde i.e no data edit etc. and is not available in releases earlier than ECC 6.
Cheers (Max points will be awarded for useful answer)
Jimbo
Hello James
I think there is a simple solution available for your problem. The sample report <b>ZUS_SDN_ALVGRID_SHARED_SCREEN</b> tries to demonstrate this approach. The crucial points are:
<b>
(1) The screen for displaying the ALV list is defined within a function group.</b>
The screen is displayed by calling a function module which gets the following input:
- container instance (holding the ALV grid), screen number, and (if required) container name
The function module returns the ok-code to the caller.
<b>(2) The PBO/PAI logic of the screen is rather simple:</b>
*&---------------------------------------------------------------------* *& Module STATUS_0100 OUTPUT *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* MODULE status_0100 OUTPUT. SET PF-STATUS 'STATUS_0100'. * SET TITLEBAR 'xxx'. ENDMODULE. " STATUS_0100 OUTPUT *&---------------------------------------------------------------------* *& Module USER_COMMAND_0100 INPUT *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* MODULE user_command_0100 INPUT. SET SCREEN 0. LEAVE SCREEN. " no processing of ok-code here !!! ENDMODULE. " USER_COMMAND_0100 INPUT
<b>
(3) The ok-code handling occurs outside the screen, e.g.:</b>
DO. * ok-code field = GD_OKCODE CALL SCREEN ud_dynnr. CASE gd_okcode. WHEN 'BACK' OR 'EXIT' OR 'CANC'. RETURN. WHEN OTHERS. " do something... Refresh, Modify, etc. ENDCASE. ENDDO.
For the sake of simplicity I included the coding of the function module and the screen within the report. Simple replace the routine <b>CALL_SHARED_SCREEN</b> by a
CALL FUNCTION 'CALL_SHARED_SCREEN'.
Place this CALL FUNCTION 'CALL_SHARED_SCREEN' in any of your ALV reports and do the individual ok-code handling within your report.
<b>Result</b>: single screen for all ALV lists.
What happens if you need a variety of different screens (with or without container) for your different ALV lists? Simple create the appropriate screen within your function group and call the function module with the required screen number.
Obviously this architecture will break under very specific requirements yet it should work for many (if not most) ALV reports.
Well, and here is the entire coding:
*&---------------------------------------------------------------------* *& Report ZUS_SDN_ALVGRID_SHARED_SCREEN *& *& Description: concept of single shared screen *&---------------------------------------------------------------------* *& Dynpro flow logic: no screen elements, ok_code = GD_OKCODE ** PROCESS BEFORE OUTPUT. ** MODULE STATUS_0100. *** ** PROCESS AFTER INPUT. ** MODULE USER_COMMAND_0100. ** *& *&---------------------------------------------------------------------* REPORT zus_sdn_alvgrid_shared_screen. DATA: gd_repid TYPE syst-repid, gd_okcode TYPE ui_func, * gt_fcat TYPE lvc_t_fcat, go_obj TYPE REF TO object, go_docking TYPE REF TO cl_gui_docking_container, go_grid TYPE REF TO cl_gui_alv_grid. DATA: gt_outtab TYPE STANDARD TABLE OF knb1. *---------------------------------------------------------------------* * CLASS lcl_eventhandler DEFINITION *---------------------------------------------------------------------* * *---------------------------------------------------------------------* CLASS lcl_eventhandler DEFINITION. PUBLIC SECTION. CLASS-METHODS: handle_data_changed FOR EVENT data_changed OF cl_gui_alv_grid IMPORTING er_data_changed e_onf4 e_onf4_before e_onf4_after e_ucomm sender. ENDCLASS. "lcl_eventhandler DEFINITION *---------------------------------------------------------------------* * CLASS lcl_eventhandler IMPLEMENTATION *---------------------------------------------------------------------* * *---------------------------------------------------------------------* CLASS lcl_eventhandler IMPLEMENTATION. METHOD handle_data_changed. * define local data ** cl_gui_cfw=>set_new_ok_code( 'NEXT_ROW' ). " not possible on 4.6c CALL METHOD cl_gui_cfw=>set_new_ok_code EXPORTING new_code = 'NEXT_ROW' * IMPORTING * RC = . " Triggers PAI of dynpro with ok_code = 'NEXT_ROW' ENDMETHOD. "handle_data_changed ENDCLASS. "lcl_eventhandler IMPLEMENTATION START-OF-SELECTION. SELECT * FROM knb1 INTO TABLE gt_outtab WHERE bukrs = '1000'. PERFORM init_controls. * Build fieldcatalog and set hotspot for field KUNNR PERFORM build_fieldcatalog_knb1. * Display data CALL METHOD go_grid->set_table_for_first_display CHANGING it_outtab = gt_outtab it_fieldcatalog = gt_fcat EXCEPTIONS OTHERS = 4. IF sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. ENDIF. go_obj = go_docking. " NOTE: Think of this routine as function module where the screen(s) " is (are) defined PERFORM call_shared_screen USING go_obj '0100' space CHANGING gd_okcode. " ok-code from screen in fm END-OF-SELECTION. *&---------------------------------------------------------------------* *& Module STATUS_0100 OUTPUT *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* MODULE status_0100 OUTPUT. SET PF-STATUS 'STATUS_0100'. * SET TITLEBAR 'xxx'. ENDMODULE. " STATUS_0100 OUTPUT *&---------------------------------------------------------------------* *& Module USER_COMMAND_0100 INPUT *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* MODULE user_command_0100 INPUT. SET SCREEN 0. LEAVE SCREEN. " no processing of ok-code here !!! ENDMODULE. " USER_COMMAND_0100 INPUT *&---------------------------------------------------------------------* *& Form BUILD_FIELDCATALOG_KNB1 *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM build_fieldcatalog_knb1 . * define local data DATA: ls_fcat TYPE lvc_s_fcat. CALL FUNCTION 'LVC_FIELDCATALOG_MERGE' EXPORTING * I_BUFFER_ACTIVE = i_structure_name = 'KNB1' * I_CLIENT_NEVER_DISPLAY = 'X' * I_BYPASSING_BUFFER = * I_INTERNAL_TABNAME = CHANGING ct_fieldcat = gt_fcat EXCEPTIONS inconsistent_interface = 1 program_error = 2 OTHERS = 3. IF sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. ENDIF. LOOP AT gt_fcat INTO ls_fcat WHERE ( fieldname = 'ZUAWA' ). ls_fcat-edit = abap_true. ls_fcat-col_opt = abap_true. MODIFY gt_fcat FROM ls_fcat. ENDLOOP. ENDFORM. " BUILD_FIELDCATALOG_KNB1 *&---------------------------------------------------------------------* *& Form INIT_CONTROLS *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM init_controls . * Create docking container CREATE OBJECT go_docking EXPORTING parent = cl_gui_container=>screen0 ratio = 90 EXCEPTIONS OTHERS = 6. IF sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. ENDIF. CALL METHOD go_docking->set_extension EXPORTING extension = 99999 EXCEPTIONS cntl_error = 1 OTHERS = 2. IF sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. ENDIF. * Create ALV grid CREATE OBJECT go_grid EXPORTING i_parent = go_docking EXCEPTIONS OTHERS = 5. IF sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. ENDIF. ENDFORM. " INIT_CONTROLS *&---------------------------------------------------------------------* *& Form CALL_SHARED_SCREEN *&---------------------------------------------------------------------* " Think of this routine as function module *----------------------------------------------------------------------* * -->P_GO_DOCKING text * -->P_0131 text * -->P_SPACE text *----------------------------------------------------------------------* FORM call_shared_screen USING uo_container TYPE REF TO object ud_dynnr TYPE syst-dynnr ud_container TYPE c CHANGING cd_okcode TYPE ui_func. * define local data DATA: lo_container TYPE REF TO cl_gui_container. lo_container ?= uo_container. CLEAR: cd_okcode. * Link the docking container to the target dynpro " NOTE: in the function group it may be necessary to place this " piece of coding (the linking) into the PBO module gd_repid = syst-repid. CALL METHOD lo_container->link EXPORTING repid = gd_repid dynnr = ud_dynnr container = ud_container EXCEPTIONS OTHERS = 4. IF sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. ENDIF. DO. * ok-code field = GD_OKCODE CALL SCREEN ud_dynnr. CASE cd_okcode. WHEN 'BACK' OR 'EXIT' OR 'CANC'. RETURN. WHEN OTHERS. " do something... Refresh, Modify, etc. ENDCASE. ENDDO. ENDFORM. " CALL_SHARED_SCREEN
Regards,
Uwe
That's right, when using the CL_GUI_ALV_GRID, you do need the screen, PBO, and PAI. It is simply a clean approach to the use of the gui control framework. Basically, you could create a template program which has the screen, PAI, and PBO already in it, and when you need to create a new ALV grid report, simply copy that program and modify it.
Another way to use CL_GUI_ALV_GRID without a screen is to do something like this, with a subscreen definition. Not pretty, and not recommended.
report zrich_0001. * Used to limit user commands on selection-screen include rsdbc1xx. data: begin of i_alv occurs 0, matnr type mara-matnr, maktx type makt-maktx, end of i_alv. data: alv_grid type ref to cl_gui_alv_grid. data: fieldcat type lvc_t_fcat. selection-screen begin of block b1 with frame title text-001 . select-options: s_matnr for i_alv-matnr. selection-screen end of block b1. selection-screen begin of screen 1010. selection-screen end of screen 1010. * Events at selection-screen output. if sy-dynnr = '1010'. current_scr-mode = 'S'. append 'SPOS' to current_scr-excl. append 'SCRH' to current_scr-excl. append 'ONLI' to current_scr-excl. endif. start-of-selection. perform get_data. create object alv_grid exporting i_parent = cl_gui_container=>screen0. * Populate Field Catalog perform get_fieldcatalog. call method alv_grid->set_table_for_first_display changing it_outtab = i_alv[] it_fieldcatalog = fieldcat[]. call selection-screen 1010. ************************************************************************ * FORM GET_DATA ************************************************************************ form get_data. select * into corresponding fields of table i_alv from mara inner join makt on mara~matnr = makt~matnr where mara~matnr in s_matnr and makt~spras = sy-langu. sort i_alv ascending by matnr. endform. ************************************************************************ * Form Get_Fieldcatalog - Set Up Columns/Headers ************************************************************************ form get_fieldcatalog. data: ls_fcat type lvc_s_fcat. refresh: fieldcat. clear: ls_fcat. ls_fcat-reptext = 'Material Number'. ls_fcat-coltext = 'Material Number'. ls_fcat-fieldname = 'MATNR'. ls_fcat-ref_table = 'I_ALV'. ls_fcat-outputlen = '18'. ls_fcat-col_pos = 1. append ls_fcat to fieldcat. clear: ls_fcat. ls_fcat-reptext = 'Material Description'. ls_fcat-coltext = 'Material Description'. ls_fcat-fieldname = 'MAKTX'. ls_fcat-ref_table = 'I_ALV'. ls_fcat-outputlen = '40'. ls_fcat-col_pos = 2. append ls_fcat to fieldcat. endform.
Regards,
Rich Heilman
Hi Uwe and Rich
The answers are both good and work but I think I've found an even easier one.
I've got a program Z_DUMMY with the statements
Form call_screen
using
z_object (ref to my ALV handling class - already instaniated)
dyn_table
fld_cat
grid_title
edit_mode
zebra_mode.
call screen 100.
endform.
MODULE status_0100 OUTPUT.
name columns and set grid title in main program in this form
CALL METHOD z_object->display_grid
EXPORTING
g_outtab = dyn_table
g_fldcat = fld_cat
i_gridtitle = grid_title
i_edit = edit_mode
i_zebra = zebra_mode
CHANGING
it_fldcat = it_fldcat
gt_outtab = dyn_table.
SET PF-STATUS '001'.
SET TITLEBAR '000'.
ENDMODULE.
MODULE user_command_0100 INPUT.
CASE sy-ucomm.
WHEN 'BACK'.
LEAVE PROGRAM.
WHEN 'EXIT'.
LEAVE PROGRAM.
WHEN 'RETURN'.
LEAVE PROGRAM.
WHEN OTHERS.
ENDCASE.
Now in the application program I just do the following at the point where I need to call a screen
perform call_screen in program z_dummy
using
z_object
<dyn_table>
it_fldcat
i_gridtitle
i_edit
i_zebra.
In the application program the value of sy_ucomm is still the value set by the called program - or it can be saved in memory and retrieved so I don't need any PAI in the calling program.
I'm not certain that this will work but should in theory. As soon as I have a SAP system back up and available I'll test it but this to mee seems by far the easiest and gives the maximum flexibility as you only need the screen at the point you want to display the grid. All the other processing has already been done.
Cheers
Jimbo
Add a comment