Don’t get too excited about the editable SALV solution out of the box, but I think we have a solution.
Recently paul.hardy2 published a blog International Editable SALV day as the 8th anniversary of the first SALV Editable question and so far no out of the box solution. To those who hasn’t read the previous so many discussion, out of box solution means a single method to make it editable. As of ABAP 740 SP05, there isn’t any new method in SALV OM which does the same thing or at least sounds like SET_EDITABLE.
I developed an work around in November 2008 and got lot of criticism for that. You can see the solution and read the comments - Power of ABAP Objects: Overcome the Restrictions of SALV Model
Based on the comments, customers should never use these type of workarounds. Obviously, SAP must not use the work around as they say Editable is not intended purpose of SALV OM. But, look what I found >> Standard SAP (yes, standard SAP) has used the almost similar approach to make SALV editable which I used in my solution.
Standard SAP Application
I was replying to some query on CL_SALV_TREE and I did a where used on the adapter object and stumbled upon this function group FOT_RFD_MONI. Usually the adapter is used by only CL_SALV* Classes and my test program. But, suddenly I see a new program popping up in the where used list and that kept me thinking what is this program doing here?
This standard SAP application is developed using this approach – almost same as the approach used in my solution. (Note, that I’m not calling it a workaround anymore :wink: 😞
- Inherit the class from the Model class
- Create a method in the inherited class to gain access to the Adapter object – E.g. Grid, Fullscreen, Tree
- Gain access of the underlying object – Grid or Tree
Class definition
Class Implementation
Use of method to make Grid editable / non-editable
Redefined Solution
So, based on this design, I simplified my version of the approach. Created a custom class where I have couple of helper methods to gain access to the adapter and then the underlying object – either Grid or Tree.
- GET_GRID would be used to get the CL_GUI_ALV_GRID object
- GET_TREE would be used to get the CL_GUI_ALV_TREE object
Utility Class
*----------------------------------------------------------------------*
* CLASS ZCL_TEST_NP_SALV_MODEL DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS zcl_test_np_salv_model DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
CLASS-METHODS get_grid
IMPORTING
!io_salv_model TYPE REF TO cl_salv_model
RETURNING
value(eo_grid) TYPE REF TO cl_gui_alv_grid
RAISING
cx_salv_error .
CLASS-METHODS get_tree
IMPORTING
!io_salv_model TYPE REF TO cl_salv_model
RETURNING
value(ro_tree) TYPE REF TO cl_gui_alv_tree
RAISING
cx_salv_error .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ZCL_TEST_NP_SALV_MODEL IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_TEST_NP_SALV_MODEL=>GET_GRID
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_SALV_MODEL TYPE REF TO CL_SALV_MODEL
* | [<-()] EO_GRID TYPE REF TO CL_GUI_ALV_GRID
* | [!CX!] CX_SALV_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_grid.
DATA: lo_error TYPE REF TO cx_salv_msg.
IF io_salv_model->model NE if_salv_c_model=>table.
RAISE EXCEPTION TYPE cx_salv_msg
EXPORTING
msgid = '00'
msgno = '001'
msgty = 'E'
msgv1 = 'Incorrect SALV Type'.
ENDIF.
eo_grid = lcl_salv_model_list=>get_grid( io_salv_model ).
ENDMETHOD. "get_grid
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_TEST_NP_SALV_MODEL=>GET_TREE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_SALV_MODEL TYPE REF TO CL_SALV_MODEL
* | [<-()] RO_TREE TYPE REF TO CL_GUI_ALV_TREE
* | [!CX!] CX_SALV_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_tree.
DATA: lo_error TYPE REF TO cx_salv_msg.
IF io_salv_model->model NE if_salv_c_model=>tree.
RAISE EXCEPTION TYPE cx_salv_msg
EXPORTING
msgid = '00'
msgno = '001'
msgty = 'E'
msgv1 = 'Incorrect SALV Type'.
ENDIF.
ro_tree = lcl_salv_model_list=>get_tree( io_salv_model ).
ENDMETHOD. "GET_TREE
ENDCLASS.
To get the CL_GUI_ALV_GRID:
DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
DATA: lo_msg TYPE REF TO cx_salv_msg.
TRY .
lo_grid = zcl_test_np_salv_model=>get_grid( o_salv ).
CATCH cx_salv_msg INTO lo_msg.
"appropriate handling
ENDTRY.
Local class LCL_SALV_MODEL_LIST which is inherited from CL_SALV_MODEL_BASE. Previously, I used the CL_SALV_MODEL_LIST to inherit my helper class, which wouldn't provide me the instance for the TREE. Thus, moved higher in the class hierarchy.
*"* use this source file for the definition and implementation of
*"* local helper classes, interface definitions and type
*"* declarations
*
CLASS lcl_salv_model_list DEFINITION INHERITING FROM cl_salv_model_base.
PUBLIC SECTION.
CLASS-METHODS:
get_grid
IMPORTING
io_salv_model TYPE REF TO cl_salv_model
RETURNING
value(ro_gui_alv_grid) TYPE REF TO cl_gui_alv_grid
RAISING
cx_salv_msg,
get_tree
IMPORTING
io_salv_model TYPE REF TO cl_salv_model
RETURNING
value(ro_tree) TYPE REF TO cl_gui_alv_tree
RAISING
cx_salv_msg.
ENDCLASS. "lcl_salv_model_list DEFINITION
*
CLASS lcl_salv_model_list IMPLEMENTATION.
METHOD get_grid.
DATA:
lo_grid_adap TYPE REF TO cl_salv_grid_adapter,
lo_fs_adap TYPE REF TO cl_salv_fullscreen_adapter,
lo_root TYPE REF TO cx_root.
TRY .
lo_grid_adap ?= io_salv_model->r_controller->r_adapter.
CATCH cx_root INTO lo_root.
"could be fullscreen adaptper
TRY .
lo_fs_adap ?= io_salv_model->r_controller->r_adapter.
CATCH cx_root INTO lo_root.
RAISE EXCEPTION TYPE cx_salv_msg
EXPORTING
previous = lo_root
msgid = '00'
msgno = '001'
msgty = 'E'
msgv1 = 'Check PREVIOUS exception'.
ENDTRY.
ENDTRY.
IF lo_grid_adap IS NOT INITIAL.
ro_gui_alv_grid = lo_grid_adap->get_grid( ).
ELSEIF lo_fs_adap IS NOT INITIAL.
ro_gui_alv_grid = lo_fs_adap->get_grid( ).
ELSE.
RAISE EXCEPTION TYPE cx_salv_msg
EXPORTING
msgid = '00'
msgno = '001'
msgty = 'W'
msgv1 = 'Adapter is not bound yet'.
ENDIF.
ENDMETHOD. "get_grid
METHOD get_tree.
DATA:
lo_tree_adap TYPE REF TO cl_salv_tree_adapter,
lo_root TYPE REF TO cx_root.
TRY .
lo_tree_adap ?= io_salv_model->r_controller->r_adapter.
CATCH cx_root INTO lo_root.
RAISE EXCEPTION TYPE cx_salv_msg
EXPORTING
previous = lo_root
msgid = '00'
msgno = '001'
msgty = 'E'
msgv1 = 'Check PREVIOUS exception'.
ENDTRY.
IF lo_tree_adap IS NOT BOUND.
RAISE EXCEPTION TYPE cx_salv_msg
EXPORTING
msgid = '00'
msgno = '001'
msgty = 'W'
msgv1 = 'Adapter is not bound yet'.
ENDIF.
ro_tree = lo_tree_adap->r_tree.
ENDMETHOD. "get_tree
ENDCLASS. "lcl_salv_model_list IMPLEMENTATION
To get the CL_GUI_ALV_TREE:
DATA: lo_tree TYPE REF TO cl_gui_alv_tree.
TRY .
lo_tree = zcl_test_np_salv_model=>get_tree( gr_tree ).
CATCH cx_salv_msg.
ENDTRY.
Updated version of the ON_USER_COMMAND method in the original solution Power of ABAP Objects: Overcome the Restrictions of SALV Model
METHOD on_user_command.
DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
DATA: ls_layout TYPE lvc_s_layo.
CASE e_salv_function.
* Make ALV as Editable ALV
WHEN 'MYFUNCTION'.
*>>
TRY .
lo_grid = zcl_test_np_salv_model=>get_grid( lo_report->o_salv ).
CATCH cx_salv_msg.
ENDTRY.
*<<
IF lo_grid IS BOUND.
* Editable ALV
ls_layout-edit = 'X'.
* Set the front layout of ALV
CALL METHOD lo_grid->set_frontend_layout
EXPORTING
is_layout = ls_layout.
* refresh the table
CALL METHOD lo_grid->refresh_table_display.
ENDIF.
ENDCASE.
ENDMETHOD. "on_user_command
Questions are ...
These also raises to these questions:
- Is SAP not planning to have SET_EDITABLE method in OM as they have started using this approach?
- Would SAP now provide support if customer uses the same approach and run into issues?
- If no, than how come SAP approved this design to exist it in customer’s system?
- If yes, As you can see, the application was created in somewhere 2011 by SAP. So, the developer must be aware of the existence of my solution. Shouldn't I get at least a some credit? Not that I want, but would be good to have, :wink:
Please share your thoughts...
updated on 23-Jun-15 at 8:30 AM CST to add the missing local class