The concept of ALV grid uisng OO looks fine on the surface but an underlying drawback is that each program needs to have a screen and GUI status. ( I'm not discussing the new SALV type as this does not have any editable facility yet).
By building the Screen handling and Class calls within a Function module we can define a reasonably Generic method of creating and displaying Grids via simple Function Module call.
This way for displaying simple grids programs will no longer need a separate screen. The Dynamic table concept can also be used to build almost any type of display you want.
Note this process is designed for essentially "Normal" type table displays -- I haven't tried the approachjfor "Deep Structures".
Using the methodology shown here you should be able to put together any simple ALV display very quickly and in about 15 mins.
Here is a simple program that displays a few sales orders. When the sales order is double clicked in the grid the sales order is displayed via VA03.
All you need to do is pass the structure you want to display to the function module together with some other parameters as shown below. For an editable grid just make i_edit = 'X'.
PROGRAM zzjimbozzz.
TABLES : vapma.
TYPES: BEGIN OF s_elements,
vbeln TYPE vapma-vbeln,
posnr TYPE vapma-posnr,
matnr TYPE vapma-matnr,
kunnr TYPE vapma-kunnr,
werks TYPE vapma-werks,
vkorg TYPE vapma-vkorg,
vkbur TYPE vapma-vkbur,
status TYPE c,
END OF s_elements.
INCLUDE zz_jimbo_incl.
DATA: ord_nr TYPE vapma-vbeln.
START-OF-SELECTION.
CREATE DATA dref TYPE s_elements.
ASSIGN dref->* TO <fs>.
i_routine = 'POPULATE_DYNAMIC_ITAB'.
i_names = 'NAME_COLUMNS'.
i_gridtitle = 'Sales Order Display'.
invoker = sy-repid.
i_zebra = ' '.
i_edit = ' '.
CALL FUNCTION 'ZZ_DISPLAY_SINGLE_ALV_GRID'
EXPORTING
invoker = invoker
my_line = <fs>
i_gridtitle = i_gridtitle
i_edit = i_edit
i_zebra = i_zebra
i_names = i_names
i_routine = i_routine
IMPORTING
z_object = z_object
dy_table = dy_table.
FORM populate_dynamic_itab CHANGING dy_table.
ASSIGN dy_table->* TO <dyn_table>.
CREATE DATA dy_line LIKE LINE OF <dyn_table>.
ASSIGN dy_line->* TO <dyn_wa>.
SELECT vbeln posnr matnr kunnr werks vkorg vkbur
UP TO 200 ROWS
FROM vapma
INTO CORRESPONDING FIELDS OF TABLE <dyn_table>.
ENDFORM.
FORM verwerk.
ENDFORM.
FORM refresh.
CALL METHOD z_object->refresh_grid.
ENDFORM.
FORM dubbelklik USING
e_row TYPE lvc_s_row
e_column TYPE lvc_s_col
es_row_no TYPE lvc_s_roid.
READ TABLE <dyn_table> INDEX e_row INTO wa_elements.
ord_nr = wa_elements-vbeln.
SET PARAMETER ID 'AUN' FIELD ord_nr.
CALL TRANSACTION 'VA03' AND SKIP FIRST SCREEN.
wa_elements-status = 'V'.
MODIFY <dyn_table> FROM wa_elements INDEX e_row.
PERFORM refresh.
row_number-row_id = e_row.
CALL METHOD z_object->set_cell
EXPORTING
e_column = e_column
es_row_no = row_number.
ENDFORM.
FORM name_columns CHANGING it_fldcat TYPE lvc_t_fcat.
* Here before displaying you can change the field catalog to
* adjust your own names
* Method call just uses the names in the table structure.
col_name 1 'Order Nr' 12.
col_name 2 'Item' 4.
col_name 3 'Material' 16.
col_name 4 'Customer' 12.
col_name 5 'Plant' 4.
col_name 6 'Sales Org' 4.
col_name 7 'Sales Office' 4.
col_name 8 'Status' 2.
ENDFORM.
FORM data_changed
USING
changed_tab
inserted_tab
deleted_tab
modified_cells_tab.
ASSIGN changed_tab->* TO <fs1>.
* code anything here to be done when data in the grid is changed.
ENDFORM.
FORM data_changed_finished.
IF <fs1> IS ASSIGNED.
* code for any processing needed at end of data change
* updated data is in <dyn_table>.
* if <fs1> not assigned then no data has been changed.
UNASSIGN <fs1>.
ENDIF.
ENDFORM.
The INCLUDE
***INCLUDE ZZ_JIMBO_INCL .
* Generic editable ALV prog with dynamic structure and FCAT.
* Jimbo 2007.
DEFINE col_name.
read table it_fldcat into wa_it_fldcat index &1.
wa_it_fldcat-coltext = &2.
wa_it_fldcat-outputlen = &3.
modify it_fldcat from wa_it_fldcat index &1.
END-OF-DEFINITION.
DATA: dref TYPE REF TO data,
z_object TYPE REF TO zcl_alv_test, "My ALV class
invoker TYPE sy-repid,
dy_line TYPE REF TO data,
dy_table TYPE REF TO data,
it_fldcat TYPE lvc_t_fcat,
wa_it_fldcat TYPE lvc_s_fcat,
i_gridtitle TYPE lvc_title,
i_zebra TYPE lvc_edit,
i_edit TYPE lvc_edit,
wa_elements TYPE s_elements,
row_number TYPE lvc_s_roid,
i_routine(30) TYPE c,
i_names(30) TYPE c,
lt_dropdown TYPE lvc_t_drop,
ls_dropdown TYPE lvc_s_drop.
FIELD-SYMBOLS: <fs> TYPE ANY,
<fs1> TYPE ANY,
<dyn_table> TYPE STANDARD TABLE,
<dyn_wa>.
The Function module
function zz_display_single_alv_grid .
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" REFERENCE(INVOKER) TYPE SYREPID
*" REFERENCE(MY_LINE) TYPE ANY
*" REFERENCE(I_GRIDTITLE) TYPE LVC_TITLE
*" REFERENCE(I_EDIT) TYPE LVC_EDIT
*" REFERENCE(I_ZEBRA) TYPE LVC_EDIT
*" REFERENCE(I_ROUTINE) TYPE CHAR30
*" REFERENCE(I_NAMES) TYPE CHAR30 OPTIONAL
*" EXPORTING
*" REFERENCE(DY_TABLE) TYPE REF TO DATA
*" REFERENCE(Z_OBJECT) TYPE REF TO ZCL_ALV_TEST
*"----------------------------------------------------------------------
*
* This function module instantiates a generic
* ALV handling class
* Builds a dynamic fcat from the structure passed in my_line
* Creates a dynmic table using the FCAT created in the class
* calls the alv display
* Using this approach means that the calling programs
* now no longer need a separate screen.
* The dynamic table is now filled in the
* form whose name is passed via parameter i_routine
* which MUST exist in the calling program.
* It is done this way as it is not praticable to have
* a completely generic method of filling the dynamic table
* as data selection depends on the application - could be via
* joins etc etc.
* Note that screen 100 and a standard interface (se41) are contained *in
* the main program of this function module.
* screen just has one element a custom container called *CCONTAINER1
* status (SE41) is just a standard status with BACK EXIT and CANCEL
* buttons.
* screen logic simply
* PROCESS BEFORE OUTPUT.
* MODULE STATUS_0100.
*
* PROCESS AFTER INPUT.
* MODULE USER_COMMAND_0100.
*
*module STATUS_0100 output.
*z_object = <zogzilla>.
* call method z_object->display_grid
* exporting
* g_outtab = <dyn_table>
* g_fldcat = it_fldcat
* i_gridtitle = w_gridtitle
* i_edit = w_edit
* i_zebra = w_zebra
* 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.
*ENDMODULE.
* Function module code
* Create instance of the ALV handling class ZCL_ALV_TEST
* Build an FCAT based on the structure passes in my_line
* create a dynmic table based on the FCAT created
* call back to the calling program (invoker) to fill
* the dynamic table
* call the screen to display tha ALV grid
*
* event handling etc all built into the class
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.
endif.
* variable z_object contains the instance of our class zcl_alv_test
* we need to keep the value as it needs to be passed to the PBO routine
* when screen 100 is called.
assign z_object to <zogzilla>.
*
perform (i_routine) in program (invoker)
changing dy_table.
* As detailed in the comments above this form MUST exist in the calling
* program
*
* change column headings etc if required - not mandatory
if not i_names is initial.
perform (i_names) in program (invoker) if found
changing it_fldcat.
endif.
* now display the grid
assign dy_table->* to <dyn_table>.
w_gridtitle = i_gridtitle.
w_edit = i_edit.
w_zebra = i_zebra.
call screen 100.
endfunction.
All you need to do is call your ALV handling class -- the methods etc are in a class ZCL_ALV_TEST
class zcl_alv_test definition
public
final
create public .
*"* public components of class ZCL_ALV_TEST
*"* do not include other source files here!!!
public section.
events before_user_command .
events toolbar .
methods set_cell
importing
!e_column type lvc_s_col
!es_row_no type lvc_s_roid .
methods build_dynamic_structures
importing
!my_line type any
!calling_program type sy-repid
exporting
!dy_table type ref to data
changing
!it_fldcat type lvc_t_fcat .
methods change_title
importing
!i_gridtitle type lvc_title .
methods constructor
importing
!z_object type ref to zcl_alv_test .
methods display_grid
importing
!g_outtab type standard table
!g_fldcat type lvc_t_fcat
!i_gridtitle type lvc_title
!i_edit type lvc_edit
!i_zebra type lvc_zebra
changing
!it_fldcat type lvc_t_fcat
!gt_outtab type standard table .
methods refresh_grid .
methods set_drop_down_table
importing
!it_drop_down type lvc_t_drop .
*"* private components of class ZCL_ALV_TEST
*"* do not include other source files here!!!
private section.
data lr_rtti_struc type ref to cl_abap_structdescr .
data:
zog like line of lr_rtti_struc->components .
data:
zogt like table of zog .
data wa_it_fldcat type lvc_s_fcat .
data it_fldcat type lvc_t_fcat .
data dy_table type ref to data .
data dy_line type ref to data .
data struct_grid_lset type lvc_s_layo .
data e_row type lvc_s_row .
data e_column type lvc_s_col .
data es_rowid type lvc_s_roid .
data grid_container1 type ref to cl_gui_custom_container .
data grid1 type ref to cl_gui_alv_grid .
data ls_layout type kkblo_layout .
data lt_fieldcat_wa type kkblo_fieldcat .
data gt_outtab type ref to data .
data l_mode type raw4 .
data celltab type lvc_t_styl .
data wa_celltab type lvc_s_styl .
data lt_fieldcat type kkblo_t_fieldcat .
data l_tabname type slis_tabname .
data ls_toolbar type stb_button .
data inserted_tab type lvc_t_moce .
data deleted_tab type lvc_t_moce .
data changed_tab type ref to data .
data caller type sy-repid .
data modified_cells_tab type lvc_t_modi .
data g_outtab1 type ref to data .
data g_fldcat1 type ref to data .
methods on_user_command
for event before_user_command of cl_gui_alv_grid
importing
!e_ucomm
!sender .
methods on_toolbar
for event toolbar of cl_gui_alv_grid
importing
!e_object
!e_interactive .
methods on_dubbelklik
for event double_click of cl_gui_alv_grid
importing
!e_row
!e_column
!es_row_no .
methods handle_data_changed
for event data_changed of cl_gui_alv_grid
importing
!er_data_changed .
methods handle_data_changed_finished
for event data_changed_finished of cl_gui_alv_grid
importing
!e_modified .
methods process .
methods dubbelklik
importing
!e_row type lvc_s_row
!e_column type lvc_s_col
!es_row_no type lvc_s_roid .
methods return_structure
importing
!my_line type any .
methods create_dynamic_fcat
exporting
!it_fldcat type lvc_t_fcat .
methods create_dynamic_table
importing
!it_fldcat type lvc_t_fcat
exporting
!dy_table type ref to data .
methods download_to_excel .
methods refresh .
methods switch .
method set_cell.
call method grid1->set_current_cell_via_id
exporting
is_column_id = e_column
is_row_no = es_row_no.
* ...
endmethod.
method build_dynamic_structures.
caller = calling_program.
call method me->return_structure
exporting
my_line = my_line.
call method me->create_dynamic_fcat
importing
it_fldcat = it_fldcat.
call method me->create_dynamic_table
exporting
it_fldcat = it_fldcat
importing
dy_table = dy_table.
* ...
endmethod.
method change_title.
call method grid1->set_gridtitle
exporting
i_gridtitle = i_gridtitle.
* ...
endmethod.
method constructor.
create object grid_container1
exporting
container_name = 'CCONTAINER1'.
create object grid1
exporting
i_parent = grid_container1.
set handler z_object->on_user_command for grid1.
set handler z_object->on_toolbar for grid1.
set handler z_object->handle_data_changed for grid1.
set handler z_object->handle_data_changed_finished for grid1.
set handler z_object->on_dubbelklik for grid1.
call method grid1->register_edit_event
exporting
i_event_id = cl_gui_alv_grid=>mc_evt_enter.
endmethod.
method display_grid.
get reference of g_outtab into g_outtab1.
get reference of g_fldcat into g_fldcat1.
struct_grid_lset-edit = i_edit. "To enable editing in ALV
struct_grid_lset-zebra = i_zebra.
struct_grid_lset-grid_title = i_gridtitle.
* struct_grid_lset-grid_title = 'TEST ALV USE generic class'.
struct_grid_lset-ctab_fname = 'T_CELLCOLORS'.
struct_grid_lset-stylefname = 'CELLTAB'.
call method grid1->set_ready_for_input
exporting
i_ready_for_input = '1'.
call method grid1->set_table_for_first_display
exporting
is_layout = struct_grid_lset
changing
it_outtab = gt_outtab
it_fieldcatalog = it_fldcat.
endmethod.
* ...
method refresh_grid .
call method cl_gui_cfw=>flush.
call method grid1->refresh_table_display.
* ...
endmethod.
method set_drop_down_table.
call method grid1->set_drop_down_table
exporting it_drop_down = it_drop_down.
* ...
endmethod.
method on_user_command.
* FOR EVENT before_user_command OF cl_gui_alv_grid
* IMPORTING
* e_ucomm
* sender.
case e_ucomm.
when 'EXIT'.
leave program.
when 'EXCEL'.
call method me->download_to_excel.
when 'SAVE'.
when 'PROC'.
call method me->process.
when 'REFR'.
call method me->refresh.
when 'SWITCH'.
call method me->switch.
endcase.
* ...
endmethod.
method on_toolbar.
type-pools icon.
clear ls_toolbar.
move 0 to ls_toolbar-butn_type.
move 'EXIT' to ls_toolbar-function.
move space to ls_toolbar-disabled.
move icon_system_end to ls_toolbar-icon.
move 'Click2Exit' to ls_toolbar-quickinfo.
append ls_toolbar to e_object->mt_toolbar.
clear ls_toolbar.
move 0 to ls_toolbar-butn_type.
move 'SAVE' to ls_toolbar-function.
move space to ls_toolbar-disabled.
move icon_system_save to ls_toolbar-icon.
move 'Save data' to ls_toolbar-quickinfo.
append ls_toolbar to e_object->mt_toolbar.
clear ls_toolbar.
move 0 to ls_toolbar-butn_type.
move 'SWITCH' to ls_toolbar-function.
move space to ls_toolbar-disabled.
move icon_toggle_display_change to ls_toolbar-icon.
move 'Switch processing mode' to ls_toolbar-quickinfo.
move 'SWITCH' to ls_toolbar-text.
append ls_toolbar to e_object->mt_toolbar.
clear ls_toolbar.
move 0 to ls_toolbar-butn_type.
move 'PROC' to ls_toolbar-function.
move space to ls_toolbar-disabled.
move icon_businav_process to ls_toolbar-icon.
move 'Process.' to ls_toolbar-quickinfo.
move 'PROC' to ls_toolbar-text.
append ls_toolbar to e_object->mt_toolbar.
clear ls_toolbar.
move 0 to ls_toolbar-butn_type.
move 'EXCEL' to ls_toolbar-function.
move space to ls_toolbar-disabled.
move icon_xxl to ls_toolbar-icon.
move 'Excel' to ls_toolbar-quickinfo.
move 'EXCEL' to ls_toolbar-text.
append ls_toolbar to e_object->mt_toolbar.
move 0 to ls_toolbar-butn_type.
move 'REFR' to ls_toolbar-function.
move space to ls_toolbar-disabled.
move icon_refresh to ls_toolbar-icon.
move 'Refresh' to ls_toolbar-quickinfo.
move 'REFR' to ls_toolbar-text.
append ls_toolbar to e_object->mt_toolbar.
* ...
endmethod.
method on_dubbelklik.
call method me->dubbelklik
exporting
e_row = e_row
e_column = e_column
es_row_no = es_row_no.
* ...
endmethod.
method handle_data_changed.
* Insert user code here if required
* this METHOD is entered if user ENTERS DATA.
changed_tab = er_data_changed->mp_mod_rows.
inserted_tab = er_data_changed->mt_inserted_rows.
deleted_tab = er_data_changed->mt_deleted_rows.
modified_cells_tab = er_data_changed->mt_mod_cells.
perform data_changed in program (caller) if found
using changed_tab
inserted_tab
deleted_tab
modified_cells_tab.
* ...
endmethod.
method handle_data_changed_finished.
* if field symbol is unassigned it means no data has been changed;
* Insert user code here if required
* METHOD entered here after data entry has finished.
perform data_changed_finished in program (caller) if found.
* ...
endmethod.
method process.
perform process in program (caller) if found.
* ...
endmethod.
method dubbelklik.
perform dubbelklik in program (caller) if found
using
e_row
e_column
es_row_no.
* ...
endmethod.
method return_structure.
lr_rtti_struc ?= cl_abap_structdescr=>describe_by_data( my_line ).
zogt[] = lr_rtti_struc->components.
* ...
endmethod.
method create_dynamic_fcat.
loop at zogt into zog.
clear wa_it_fldcat.
wa_it_fldcat-fieldname = zog-name .
wa_it_fldcat-datatype = zog-type_kind.
wa_it_fldcat-inttype = zog-type_kind.
wa_it_fldcat-intlen = zog-length.
wa_it_fldcat-decimals = zog-decimals.
wa_it_fldcat-coltext = zog-name.
wa_it_fldcat-lowercase = 'X'.
append wa_it_fldcat to it_fldcat .
endloop.
* ...
endmethod.
method create_dynamic_table.
call method cl_alv_table_create=>create_dynamic_table
exporting
it_fieldcatalog = it_fldcat
importing
ep_table = dy_table.
* ...
endmethod.
method download_to_excel.
field-symbols:
<fs0> type standard table,
<fs1> type standard table.
assign g_outtab1->* to <fs0>.
assign g_fldcat1->* to <fs1>.
call function 'LVC_TRANSFER_TO_KKBLO'
exporting
it_fieldcat_lvc = <fs1>
* is_layout_lvc = m_cl_variant->ms_layout
is_tech_complete = ' '
importing
es_layout_kkblo = ls_layout
et_fieldcat_kkblo = lt_fieldcat.
loop at lt_fieldcat into lt_fieldcat_wa.
clear lt_fieldcat_wa-tech_complete.
if lt_fieldcat_wa-tabname is initial.
lt_fieldcat_wa-tabname = '1'.
modify lt_fieldcat from lt_fieldcat_wa.
endif.
l_tabname = lt_fieldcat_wa-tabname.
endloop.
call function 'ALV_XXL_CALL'
exporting
i_tabname = l_tabname
is_layout = ls_layout
it_fieldcat = lt_fieldcat
i_title = sy-title
tables
it_outtab = <fs0>
exceptions
fatal_error = 1
no_display_possible = 2
others = 3.
if sy-subrc <> 0.
message id sy-msgid type 'S' number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.
* ...
endmethod.
method refresh.
perform refresh in program (caller) if found.
* ...
endmethod.
method switch.
if grid1->is_ready_for_input( ) eq 0.
call method grid1->set_ready_for_input
exporting i_ready_for_input = 1.
else.
call method grid1->set_ready_for_input
exporting i_ready_for_input = 0.
endif.
* ...
endmethod.
Have fun
Cheers
Jimbo