Skip to Content

This has been a SALV Editable week. Earlier this week, I published a blog on standard application using SALV for editable(SALV Editable? Yes, as per this Standard SAP Application)

 

The solution works great if there is an extra button. This extra button – say Edit – would make the SALV editable. This button is required to gain the access of the underlying Grid object (CL_GUI_ALV_GRID). The Grid object than used to set up the editable functionality. Paul Hardy had asked if we can remove that extra button and make the SALV editable directly, in his comment section of my previous blog SALV Editable? Yes, as per this Standard SAP Application

 

 

No more button

The idea was to find an event which gets triggered but before the output is displayed to the user. I did some research, infect lot of research to find an event that would work in both Grid and FullScreen ALV. I played with different events like TOP_OF_PAGE, TOP_OF_LIST, PRINT_TOP_OF_PAGE etc.

 

Fullscreen ALV triggers TOP_OF_PAGE but not the Grid ALV, as for Grid there is no direct TOP_OF_PAGE. FullScreen ALV triggers it when the top of page is created using the method O_SALV->SET_TOP_OF_LIST( ). Also this would bring up a header in the ALV. For the Grid, You would need to create an object for CL_DD_DOCUMENT, pass it to the Grid object and raise the event TOP_OF_PAGE. Without having the Grid to begin with, can’t assign the header, and thus can’t get the TOP_OF_PAGE event to work.

 

Event AFTER_REFRESH is the trick, I was looking for 😎

SALV_Editable_0.png

 

Event AFTER_REFRESH

Event AFTER_REFRESH gets triggered after system finished rendering ALV – Field catalog parsed, Data sent to the DP (data provider) aka Frontend, Layout applied, Toolbar created, and all other ALV related stuff. Now, how to capture this event when there is no Grid object. So, declared an event handler to handle the event AFTER_REFRESH of class CL_GUI_ALV_GRID. The trick is the registration of the event using the addition FOR ALL INSTANCES of SET EVENT HANDLER.

 

  “To gain an access to the underlying object and
”  do the magic
SET HANDLER lo_event_h->on_after_refresh
FOR ALL INSTANCES
ACTIVATION ‘X’.

 

FOR ALL INSTANCES is quite powerful. It can register the event for any object for that event belongs, even if the object is instantiated after the handler is registered. That’s very useful in this scenario as the Grid object is not yet instantiated.

 

 

Avoid Endless Loop Trap

To make the grid editable, either you can pass the LAYOUT-EDIT = ‘X’ with following REFRESH_TABLE_DISPLAY( ) call or method SET_READY_FOR_INPUT call . The thing is, both of these methods would call the method SOFT_REFRESH_TABLE_DISPLAY and would raise the event AFTER_REFRESH. This would again be caught in our event handler. The event handler would make the grid editable again with refresh – so going in the loop.

 

To avoid this, we would switch off – more technically deregister the event handler. Using the addition ACTIVATION space in the SET HANDLER would do this for us.

 

    “deregister the event handler
SET HANDLER me->on_after_refresh
FOR ALL INSTANCES
ACTIVATION space.

 

 

 

Toolbar

Next is the toolbar. The edit buttons in the toolbar are displayed without any additional work, but for grid there is some special logic which prevents it from creating the edit buttons in the toolbar. This all happens in the method CL_SALV_CONTROLLER_EVENTS=> RAISE_BUILD_UIFUNCTION where only few of the buttons are displayed.

 

So we will trick the toolbar to add the same missing buttons. To do this, we would need to register the event TOOLBAR for the CL_GUI_ALV_GRID. This would be done same – with using the FOR ALL INSTANCE.

 

  “only for GRID, would need to add the toolbar buttons
IF io_salv->get_display_object( ) = 3.
SET HANDLER lo_event_h->on_toolbar
FOR ALL INSTANCES
ACTIVATION ‘X’.
ENDIF.

 

 

Single Method to Make it Editable

Not out of the box single method :), but I enclosed all these logic in one single method.  Call this method by passing the ALV object before the DISPLAY method, and all done.

 

The method would register the event AFTER_REFRESH and TOOLBAR (for grid). The class also host the event handler methods in the local class. The event handler would make the grid editable and add the buttons in the toolbar as well. All the complexity for making it editable is hidden and wrapped in this method.

 

Also this method would control the logic for multiple SALV objects. Optional parameter SENDER for the event handler with the object pool design pattern is used.

 

” Make grid editable
” call before display
zcl_test_np_salv_model=>set_editable( gr_table ).
 

 

In Action

Fullscreen ALV generated by SALV in Editable mode

SALV_Editable_2.png

 

ALV Grid generated by SALV in Editable mode

SALV_Editable_2_0.png

 

Multiple Grid, only one is editable

SALV_Editable_1.png

 

Full Method Code

Here is the method ZCL_TEST_NP_SALV_MODEL=>SET_EDITABLE

class ZCL_TEST_NP_SALV_MODEL definition
public
final
create public .
public section.
class-methods SET_EDITABLE
importing
!IO_SALV type ref to CL_SALV_TABLE .
PROTECTED SECTION.
PRIVATE SECTION.
class-data o_event_h type ref to OBJECT.
ENDCLASS.

CLASS ZCL_TEST_NP_SALV_MODEL IMPLEMENTATION.
* <SIGNATURE>—————————————————————————————+
* | Static Public Method ZCL_TEST_NP_SALV_MODEL=>SET_EDITABLE
* +————————————————————————————————-+
* | [—>] IO_SALV                        TYPE REF TO CL_SALV_TABLE
* +————————————————————————————–</SIGNATURE>
METHOD set_editable.

DATA: lo_event_h TYPE REF TO lcl_event_handler.

“Event handler
IF zcl_test_np_salv_model=>o_event_h IS NOT BOUND.
CREATE OBJECT zcl_test_np_salv_model=>o_event_h
TYPE lcl_event_handler.
ENDIF.

lo_event_h ?= zcl_test_np_salv_model=>o_event_h.
APPEND io_salv TO lo_event_h->t_salv.

“To gain an access to the underlying object and
”  do the magic
SET HANDLER lo_event_h->on_after_refresh
FOR ALL INSTANCES
ACTIVATION ‘X’.

“only for GRID, would need to add the toolbar buttons
IF io_salv->get_display_object( ) = 3.
SET HANDLER lo_event_h->on_toolbar
FOR ALL INSTANCES
ACTIVATION ‘X’.
ENDIF.

ENDMETHOD.
ENDCLASS.

 

 

And the event handler LCL_EVENT_HANDLER

*———————————————————————-*
* Event handler ALV events
*———————————————————————-*
CLASS lcl_event_handler DEFINITION.
PUBLIC SECTION.
METHODS:
on_after_refresh FOR EVENT after_refresh OF cl_gui_alv_grid
IMPORTING
sender,
on_toolbar      FOR EVENT toolbar      OF cl_gui_alv_grid
IMPORTING
e_object
e_interactive
sender.
DATA: t_salv TYPE STANDARD TABLE OF REF TO cl_salv_table.
ENDCLASS.                    “lcl_event_handler DEFINITION
*
CLASS lcl_event_handler IMPLEMENTATION.
METHOD on_after_refresh.
DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
DATA: ls_layout TYPE lvc_s_layo.
DATA: lo_salv TYPE REF TO cl_salv_table.
TRY .
LOOP AT t_salv INTO lo_salv.
lo_grid = zcl_test_np_salv_model=>get_grid( lo_salv ).
CHECK lo_grid EQ sender.

“deregister the event handler
SET HANDLER me->on_after_refresh
FOR ALL INSTANCES
ACTIVATION space.

“Set editable
ls_layoutedit = ‘X’.
lo_grid->set_frontend_layout( ls_layout ).
lo_grid->set_ready_for_input( 1 ).
ENDLOOP.
CATCH cx_salv_error.
ENDTRY.
ENDMETHOD.                    “on_AFTER_REFRESH
*
METHOD on_toolbar.

DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
DATA: ls_layout TYPE lvc_s_layo.
DATA: mt_toolbar TYPE ttb_button.
DATA: ls_toolbar LIKE LINE OF mt_toolbar.
DATA: lo_salv TYPE REF TO cl_salv_table.

TRY .
LOOP AT t_salv INTO lo_salv.
lo_grid = zcl_test_np_salv_model=>get_grid( lo_salv ).
IF lo_grid EQ sender.
EXIT.
ELSE.
CLEAR lo_grid.
ENDIF.
ENDLOOP.
CATCH cx_salv_msg.
EXIT.
ENDTRY.

CHECK lo_grid IS BOUND.
CHECK lo_grid->is_ready_for_input( ) = 1.

*… Toolbar Button CHECK
CLEAR ls_toolbar.
ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_check.
ls_toolbarquickinfo  = text053“Eingaben prfen
ls_toolbaricon        = icon_check.
ls_toolbardisabled    = space.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Seperator
CLEAR ls_toolbar.
ls_toolbarfunction    = ‘&&SEP01’.
ls_toolbarbutn_type  = 3.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Button CUT
CLEAR ls_toolbar.
ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_cut.
ls_toolbarquickinfo  = text046“Ausschneiden
ls_toolbaricon        = icon_system_cut.
ls_toolbardisabled    = space.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Button COPY
CLEAR ls_toolbar.
ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_copy.
ls_toolbarquickinfo  = text045.                        ” Kopieren
ls_toolbaricon        = icon_system_copy.
ls_toolbardisabled    = space.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Button PASTE OVER ROW
CLEAR ls_toolbar.
ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_paste.
ls_toolbarquickinfo  = text047.
ls_toolbaricon        = icon_system_paste.
ls_toolbardisabled    = space.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Button PASTE NEW ROW
CLEAR ls_toolbar.
ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_paste_new_row.
ls_toolbarquickinfo  = text063.
ls_toolbaricon        = icon_system_paste.
ls_toolbardisabled    = space.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Button UNDO
CLEAR ls_toolbar.
ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_undo.
ls_toolbarquickinfo  = text052“Rckgngig
ls_toolbaricon        = icon_system_undo.
ls_toolbardisabled    = space.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Separator
CLEAR ls_toolbar.
ls_toolbarfunction    = ‘&&SEP02’.
ls_toolbarbutn_type  = 3.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Button APPEND ROW
CLEAR ls_toolbar.
ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_append_row.
ls_toolbarquickinfo  = text054“Zeile anhngen
ls_toolbaricon        = icon_create.
ls_toolbardisabled    = space.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Button INSERT ROW
CLEAR ls_toolbar.
ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_insert_row.
ls_toolbarquickinfo  = text048“Zeile einfgen
ls_toolbaricon        = icon_insert_row.
ls_toolbardisabled    = space.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Button DELETE ROW
CLEAR ls_toolbar.
ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_delete_row.
ls_toolbarquickinfo  = text049“Zeile lschen
ls_toolbaricon        = icon_delete_row.
ls_toolbardisabled    = space.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Button COPY ROW
CLEAR ls_toolbar.
ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_copy_row.
ls_toolbarquickinfo  = text051“Duplizieren
ls_toolbaricon        = icon_copy_object.
ls_toolbardisabled    = space.
APPEND ls_toolbar TO mt_toolbar.

*… Toolbar Separator
CLEAR ls_toolbar.
ls_toolbarfunction    = ‘&&SEP03’.
ls_toolbarbutn_type  = 3.
APPEND ls_toolbar TO mt_toolbar.

APPEND LINES OF mt_toolbar TO e_object->mt_toolbar.

ENDMETHOD.                    “on_toolbar
ENDCLASS.                    “lcl_event_handler IMPLEMENTATION

 

To report this post you need to login first.

41 Comments

You must be Logged on to comment or reply to a post.

  1. Jānis B

    Just a heads up…Now that you have done the hard work of compiling the list of necessary functions, icons and such, I quickly tried if the toolbar could potentially be “reassembled” over CL_SALV_FUNCTIONS_LIST->ADD_FUNCTION( ) calls – prior to display( ) call, and it looks to be doable – at least for the grid in the container! 🙂

    I can’t seem to be able to add separators yet… but ALV somehow knew to insert one between Check and Cut anyway… And subsequent CL_SALV_FUNCTIONS_LIST->SET_ALL( ) call doesn’t disturb the added/custom functions! I already like the solution a little bit more 🙂

    Partially assembled toolbar:

    SALV Toolbar.png

    cheers

    Janis

    (0) 
    1. Naimesh Patel Post author

      Hello Jānis,

      Sure method CL_SALV_FUNCTIONS_LIST->ADD_FUNCTION( )  would be able to add the additional buttons on the toolbar.

      You have correctly noted that they isn’t any possibility to add separator via ADD_FUNCTION, I noted that earlier SALV OM Undocumented Limitations – Separator in the Toolbar – ABAP Help Blog

      The idea of having them in the one common place was for:

      • Reusability – Don’t want to have the same code again in all different programs
      • Set the buttons based on the Grid’s edit state (IS_READY_FOR_INPUT)
      • Wanted to have same toolbar with almost all the fields
      • Work for both grid and fullscreen

      So using the Toolbar event made more intimidating, instead of using the ADD_FUNCTION.

      Adding toolbar button wasn’t the biggest effort – the buttons are copied from the method CL_GUI_ALV_GRID->BUILD_COMPLETE_TOOLBAR( ) .. lines 61 onwards for about 100 lines 🙂

      Regards,
      Naimesh Patel

      (0) 
      1. Jānis B

        My idea is: since SALV may be able (and in the case of grid in a container is able) to accept and cleverly “buffer” adding of functions within its own state, prior to the adapter and the grid even being instantiated (prior to SALV display( ) call), maybe the direct grid’s on_toolbar handler can be dropped from the solution and the initial enabling of toolbar, programmed using functionality exposed by SALV object model itself, can be put into private ZCL_TEST_NP_SALV_MODEL method, which would then be called from set_editable( ) instead of subscribing for on_toolbar event.

        If that works, since the SALV state will then be fully aware of the added functions, the benefit would be disabling/re-enabling the editing functions from application via proper SALV Function object method calls…

        Also, the less the solution has to meddle with state of underlying grid directly, the less possibility for something to go awry, I hope…

        What does still worry me a bit is: whether or not the added functions would introduce some incompatibility with functioning of CL_SALV_FUNCTIONS_LIST method calls. They should not, i feel, but one only knows after enough testing…

        I’ll try it out some day and let you know.

        cheers

        Jānis

        (0) 
        1. Naimesh Patel Post author

          Agree that we should do it using the methods from CL_SALV_FUNCTIONS_LIST and move away from using underlying grid object as less as possible ..

          Let me know how it goes.. 🙂

          Thanks,
          Naimesh Patel

          (0) 
          1. Jānis B

            It does indeed seem to work for container (I’ve not been able to find any side effects thus far); haven’t gotten to fullscreen yet. 🙂

            A tiny bug: lcl_event_handler->on_after_refresh( ) must get the current frontend field catalog before it modifies it – so as not to reset layout attributes set by application via SALV.

            I’m also a bit uneasy about deregistration of potential grid’s on_after_refresh handlers, however… It is working as the SALV is built currently. Morover, it’s very likely working for whole of SALV. But CL_SALV_GRID_ADAPTER->IF_SALV_ADAPTER~SET_METADATA( ) does already set up a range of own handlers for other grid events. What will happen if the need will arrise for standard SALV to handle this event as well…

            Furthermore, application programmers must also know not to attempt to handle the event if they too prise the grid out of SALV and try to do something with it directy…

            Furthermore, application programmers likely will need access to grid (field catalog specifically), in order to cover scenarios where only a subset of columns needs to be editable.

            Edit in: actually, no – the following is just a foolish idea that can’t possibly work. One would also need at least an own controller, grid adapter and god knows what else…

            In order to properly encapsulate access to field catalog, one would need to inherit and extended CL_SALV_COLUMN_LIST, which isn’t final…  (CL_SALV_COLUMN_TABLE used by CL_SALV_TABLE inherits but does not extend in any way CL_SALV_COLUMN_LIST).


            The use of such extended column object could — I foolishly feel after looking around for a few hours 🙂 — very well be possible in ZCL_SALV_EDITABLE_TABLE, which would mimic/extend CL_SALV_TABLE functionality…, while reusing everything but CL_SALV_COLUMN_TABLE, including reusing the standard SALV controller.


            It would of course mean a LOT more work and custom/copied code, which would need to be maintained, or even break beyond repair, if there are incompatible changes in SALV, even though CL_SALV_TABLE itself is not a terribly large or complex class.


            And, ZCL_SALV_EDITABLE_TABLE would allow to get rid of the need to enable editing via grid event handler – using controller~display( ) followed by doing a bit of “funky stuff” on the grid, followed by “SALV”~refresh( ), for example.

            Something to keep me busy in free time, in other words…

            cheers

            Janis

            (0) 
            1. Naimesh Patel Post author

              Hello Janis,

              I hear your concern about deregistartion of the AFTER_REFRESH event.. If SALV model starts using it, it may not fail as the custom event handler should be called after the standard event handler. Generally SAP – even though SAP asks not to rely on that – uses alphabetical sorting for event handlers.

              If this stops working, we would fallback to the “button” approach 🙂

              I’m bit uncomfortable for adding enhancements. The same applies that solution as well – that it works as how SALV is built right now and you may need to have at least couple of overwrite or implicit enhancements to achieve it.

              Regards,
              Naimesh Patel

              (0) 
      2. Mario Andreschak

        Hello Naimesh,

         

        out of curiosity, because I just stumbled across this – why didn’t you just call the CL_GUI_ALV_GRID->BUILD_COMPLETE_TOOLBAR( ) method?

        all it takes is implementing IF_ALV_RM_GRID_FRIEND in your helper class…

         

        Cheers

        Mario

        (0) 
  2. Paul Hardy

    I am very impressed.

    This removes the last reason to use CL_GUI_ALV_GRID directly.

    Many thanks for working this out, this is going to be a very big help for everyone, and me in particular! I always felt bad about having to force the users to press a button to go into edit mode when they had been used to opening up applications directly in edit mode.

    Every extra button press for an end user (or developer for that matter) is a Bad Thing.

    Thanks once again.

    Cheersy Cheers

    Paul

    (1) 
    1. Paul Hardy

      This afternoon I update by custom classes and gave an option to open a SALV grid in editable mode, using your approach above.

      Everything worked wonderfully.

      Because I am never content, I am now going to create some sort of generic way of saying what columns I want editable and what ones I don’t. Most of the time it is just the key fields you don’t want editable, but sometimes the business requirement is all over the place as in “just that one field editable, except on a Tuesday”.

      I’ll keep you posted.

      (0) 
    2. Paul Hardy

      In addition, I notice in the code you cut and pasted from CL_GUI_ALV_GRID you were passing in a function such as ‘&&SEP01’ / button type 3, to get the separator.

      I had been experimenting with adding user commands (icons at the top of the screen) programmatically using the SALV, it only works when you have a container and I could never get a separator, as has been mentioned above.

      Just for kicks, five minutes ago I tried to insert a &&SEP01 / button type 3, between two of my user defined commands and I did get a separator (sort of).

      I say sort of, as it does not look like the SAP separators, it looks more like a sausage.

      Then I realised it was a really thin button. I passed in BOING instead of &&SEP01 and the sausage was still there.

      Still it does the job of breaking up groups of icons. It has been said a human brain cannot process more than three things at a time, which is why you need some sort of separator between groups of three icons, if you have a lot of them.

      If this can only be achieved by thin buttons that look like sausages then so be it.

      (0) 
      1. Naimesh Patel Post author

        Glad that you like the new solution..

        If toolbar buttons can be achieved using SALV native methods, than no need to create the object pool within the method SET_EDITABLE method. The object pool was mainly to handle the TOOLBAR event.

        The AFTER_REFRESH would work ok without the object pool. For the first grid, the event wold be registered and within the event handler in for All events, it would be deregistered, when DISPLAY method is called. The second grid, the event would be registered again and deregistered in DISPLAY, so and so forth.. So, no need for object to keep track of sender and compare it against the object.

        Regards,
        Naimesh Patel

        (0) 
      2. Jānis B

        This sausage nonsense

        /wp-content/uploads/2015/06/salv_separator1_734466.png

        is easily taken care of (for container, at least) by doing short post method enhancement on CL_SALV_GRID_ADAPTER->IF_SALV_TOOLBAR_ADAPTER~BUILD_UIFUNCTION( )


        CLASS lcl_z_salv_toolbar_adapter DEFINITION.

          PUBLIC SECTION.

            CLASS-DATA obj TYPE REF TO lcl_z_salv_toolbar_adapter.  “#EC NEEDED

            DATA core_object TYPE REF TO cl_salv_grid_adapter .     “#EC NEEDED

        INTERFACES  IPO_Z_SALV_TOOLBAR_ADAPTER.

            METHODS:

             constructor IMPORTING core_object

               TYPE REF TO cl_salv_grid_adapter OPTIONAL.

        ENDCLASS.

        CLASS lcl_z_salv_toolbar_adapter IMPLEMENTATION.

          METHOD constructor.

            me->core_object = core_object.

          ENDMETHOD.

          METHOD ipo_z_salv_toolbar_adapter~build_uifunction.

        *”————————————————————————*

        *” Declaration of POST-method, do not insert any comments here please!

        *”

        *”methods BUILD_UIFUNCTION

        *”  changing

        *”    !T_TOOLBAR_EXCLUDING type UI_FUNCTIONS

        *”    !T_TOOLBAR type TTB_BUTTON .

        *”————————————————————————*

           FIELD-SYMBOLS: <cs_toolbar_item> like line of t_toolbar .

           loop at t_toolbar ASSIGNING <cs_toolbar_item>

             where

               function cs cl_gui_alv_grid=>mc_fc_separator .

             <cs_toolbar_item>-butn_type = ‘3’ .  “Grr… no constant anywhere in ALV?

           endloop.

          ENDMETHOD.

        ENDCLASS.

        /wp-content/uploads/2015/06/salv_separator2_734469.png

        Somewhat amusing is: what looked to me like successful enabling of edit functions via CL_SALV_FUNCTIONS_LIST->ADD_FUNCTION( ) on closer inspection actually “abuses” what looks like a bug. Or at least “unintended behavior”.

        The method happily takes any INT4 garbage (like 0) as input for POSITION and sets up a SALV function. While CL_SALV_GRID_ADAPTER->BUILD_UIFUNCTION( ) passes on to grid toolbar only the functions having valid IF_SALV_C_FUNCTION_POSITION=>LEFT_OF_SALV_FUNCTIONS or RIGHT_OF_SALV_FUNCTIONS positioning… 😛 Were that not so or were I to pass correct POSITION, the buttons would be in toolbar twice except for the Paste functions…

        /wp-content/uploads/2015/06/salv_separator3_734495.png

        because intent was probably to pass on “simple” custom functions only, and not the ones grouped under fancy dropdown…

        Once the functions are set up in SALV, they can indeed be disabled and re-enabled using SALV.

        Contemplating another likely foolish idea – to enable editing by doing only SALV object enhancements…

        cheers

        Janis

        (0) 
        1. Paul Hardy

          Cheers for that – my sausage problem is no more!

          After a mere eight years we have collectively managed to get CL_SALV_TABLE almost on a par with CL_GUI_SALV_GRID, which of course SAP should have done straight off when the thing was created in the first place.

          Next February on international editable SALV day when I write a blog moaning about how SAP refuses to make the SALV editable there will be lots of news to report!

          Cheersy Cheers

          Paul

          PS When I was young the UK TV program “That’s Life” made much of  a talking dog they had found called “Prince”. It wasn’t much of a talker though – it could only say one word and that was “sausages”.

          (0) 
  3. ASHISH AHIRE

    Excellent Naimesh , I tried your solution and it’s working perfectly. I would say finally EDITABLE SALV is possible. Thanks for finding this 🙂

    Regards

    Ashish

    (0) 
    1. Jānis B

      1) Remove these two lines in event handler on_after_refresh method

                “Set editable

                ls_layoutedit = ‘X’.

                lo_grid->set_frontend_layout( ls_layout ).


      2) get the grid in your application and set the edit flag per field directly in the grid frontend field catalog.

      To do it via SALV OM methods would require multiple enhancements to several SALV objects; I plan to try that out as  well.

      Edit in: my plan at the moment is as follows:

      1) enhance CL_SALV_COLUMN:

      – add instance attribute EDITABLE;

      – add instance method SET_EDITABLE( ); analog to SET_VISIBLE, in order to follow “SAP style”, although I’d have preferred SET_EDITABLE_ON( ), SET_EDITABLE_OFF( );

      – add instance method IS_EDITABLE( )

      2) enhance CL_SALV_COLUMNS_LIST

      – add instance method SET_EDITABLE_COLUMNs( ), analog to SET_COLOR_COLUMN( ); this is just for convenience and completeness and could be omitted since application has access to individual column instances;

      3) do a post method enhancements on:

      – CL_SALV_CONTROLLER_METADATA=>GET_LVC_FIELDCATALOG( ) to transfer column’s EDITABLE attribute to frontend T_FIELDCATALOG-EDIT

      – CL_SALV_CONTROLLER_METADATA=>SET_LVC_FIELDCATALOG( ) to transfer

      frontend T_FIELDCATALOG-EDIT to column’s EDITABLE attribute


      That may be it, I believe at the moment, but the tests will show…


      And, at some time one also needs proper ADD_SEPARATOR( ) in CL_SALV_FUNCTIONS_LIST…


      Following that, CL_SALV_TABLE needs to be enhanced by adding SET_EDITABLE( ) method… The biggest challenge would probably be exposing grid editing related events – in part because I have actually not done a single editable grid application yet… 😳


      How I wish I knew, whether SAP developers had found some insurmountable technical challenges when they decided not to make CL_SALV_TABLE editable 🙂 There may still be some out there…

      (0) 
      1. Ilmir Nuriev


        2) get the grid in your application and set the edit flag per field directly in the grid frontend field catalog.

        Something I did not get.

        I tried to get the field catalog and substitute jackdaws that editing is not.

        data: lt_fcat TYPE lvc_t_fcat.

          lt_fcat = cl_salv_controller_metadata => get_lvc_fieldcatalog (

               r_columns = gc_columns

               r_aggregations = lo_aggregations).

          FIELD-SYMBOLS: <fs_fcat> like LINE OF lt_fcat.

          LOOP AT lt_fcat ASSIGNING <fs_fcat>.

            IF sy-tabix mod 2 = 0.

               <fs_fcat> -edit = ‘X’.

               else.

               clear <fs_fcat> -edit.

            ENDIF.

        * BREAK-POINT.

        ** WRITE 1.

            ENDLOOP.

            cl_salv_controller_metadata => set_lvc_fieldcatalog (

           EXPORTING

             t_fieldcatalog = lt_fcat

             r_columns = gc_columns

             r_aggregations = lo_aggregations

        ).

        But I did not work 🙁

        Looked method, there seems no opportunity to change the edit.

        What am i doing wrong?

        (0) 
        1. Jānis B

          No, no – you can’t do it via SALV… And those methods are actually mappers used by SALV OM: convert from SALV column list object to frontend field catalog internal table and vice versa. They don’t write to the actual grid object… Since SALV doesn’t handle EDIT field catalog attribute, it will not help. My idea is to extend those methods, and SALV Column object, so they do take EDIT attribute and pass it through to grid…

          What I meant is: absent enhanced SALV, get the underlying grid instance using the approach Naimesh outlined previously and set the catalog directly, bypassing SALV:

          DATA: lo_grid TYPE REF TO cl_gui_alv_grid.            

                                                                

          lo_grid = zcl_test_np_salv_model=>get_grid( lo_salv ).

          lo_grid->get_frontend_fieldcatalog(                  

             IMPORTING                                         

                et_fieldcatalog = lt_fieldcat ).               

                                                                

          “do field catalog modifications                       

                                                                

          lo_grid->set_frontend_fieldcatalog( lt_fieldcat ).   


          Edit in: added the get which of course should come before modification 😉

          The implementation of zcl_test_np_salv_model=>get_grid( ) method, which involves another local class, is in his previous blog post SALV Editable? Yes, as per this Standard SAP Application

          (0) 
      2. Jānis B

        Yup, SALV Column objects and “Controller Metadata” mapping methods of course can be enhanced to handle EDIT attribute, but it’s a bit jarring experience to see some SALV things recompiling while enhancing SALV objects in WB/Enhancement tools 🙂

        A word of warning: all I’m doing thus far successfully is for SALV Table in a containerFullscreen SALV Table looks like different animal… CL_SALV_FUNCTIONS_LIST->ENABLE_FUNCTION( ) and by extension CL_SALV_FUNCTIONS_LIST->ADD_FUNCTION( ) are not supported there, for example.

        So no edit toolbar, if frontend layout edit attribute is not set… lo_grid->set_ready_for_input( 1 ) alone is not enough.

        Two more CL_SALV_CONTROLLER_METADATA field catalog mappers might need post enhancements in order to pass through column EDIT attributes for fullscreen…


        Does anyone know if SAPLink enhancement plugin support class enhancement objects? They should of course be deliverable using conventional transport request, isn’t it..?

        Jānis

        (0) 
        1. Naimesh Patel Post author

          Does anyone know if SAPLink enhancement plugin support class enhancement objects? They should of course be deliverable using conventional transport request, isn’t it..?

          If you decided to deliver not via transport, I think it would be better to deliver via step by step instructions. It would be cumbersome for developer to adapt, but they would know what they are getting. And no more surprises when they see these enhancements in SPAU_ENH at a time of support pack. They should be in a possible and knowledgeable that the logic in the enhancement is required or not.

          Regards,
          Naimesh Patel

          (0) 
          1. Jānis B

            Hi,

            The more I think about it, the less I like the enhancments way. For Fullscreen it will already require overwriting (copying and adjusting) at least one complete method – CL_SALV_FUNCTIONS_LIST->ENABLE_FUNCTION( ) . That I don’t want to do and there are likely more such methods.

            I also have no experience with Class Enhancements. The following scenario scares me: one of my enhancements (to CL_SALV_COLUMN for example) gets deactivated during upgrade due to SAP changes. CL_SALV_CONTROLLER_METADATA enhancement relies on the methods from deactivated enhancement… what will happen – syntax error in CL_SALV_CONTROLLER_METADATA? That would render the whole SALV inoperable. Or would SAP be clever enough to deactivate only CL_SALV_CONTROLLER_METADATA enhancement and compile standard class without it..?


            I’ll try to play with this kind of scenarios (don’t have sandbox at the moment) and do it only for grid in container (put checks in my enhancements similar to the one in CL_SALV_FUNCTIONS_LIST->ENABLE_FUNCTION( ) ), but I’m just too scared to render important parts of system unusable during upgrade at the moment.

            cheers

            Jānis

            (0) 
            1. Naimesh Patel Post author

              Hello Janis,

              I also don’t like the implicit enhancement solution as it involves quite a few places to change.

              one of my enhancements (toCL_SALV_COLUMN for example) gets deactivated during upgrade due to SAP changes.CL_SALV_CONTROLLER_METADATA enhancement relies on the methods from deactivated enhancement… what will happen – syntax error in CL_SALV_CONTROLLER_METADATA?

              At time of upgrade, The method of the class CL_SALV_CONTROLLER_METADATA would be shown in the SAPU_ENH. It would clearly mention the type of conflict. E.g. If SAP has declared a new variable which you had declared in your Post-method or Implicit, it would be listed as the error. The “latest source” of that method would be “Inactive”. During the upgrade, you would have an opportunity to fix these errors.

              If you don’t fix these errors, there would a change that you would run into errors as some of the classes in the class hierarchy would be expecting something from this class but that source is still inactive.

              This is the exact reason, I mentioned that developer should know what they are getting.

              Regards,
              Naimesh Patel

              (0) 
      3. Naimesh Patel Post author

        Janis – I think your approach should work. Only thing is it involves lot of implicit enhancements.

        How I wish I knew, whether SAP developers had found some insurmountable technical challenges when they decided not to make CL_SALV_TABLE editable 🙂 There may still be some out there…

        I think it is just a bad design. They might had been way past the deadline and preventing the SALV to make editable would had been much faster solution than making it available.

        Regards,
        Naimesh Patel

        (0) 
    2. Paul Hardy

      Mr.Ilmar,

      I am working on a solution to this as well – it may be different than the one Janis proposes but I will get there.

      When I do, I will post my solution here.

      In the interim whey don’t you try and come up with one as well – this is what is could about the SCN, lots of people working on the same problem and then you end up with several possible solutions in no time.

      That is much better than some forums where people just sit back and wait for a solution to their problem to drop out of the sky!

      Cheersy Cheers

      Paul

      (0) 
      1. Naimesh Patel Post author

        That is much better than some forums where people just sit back and wait for a solution to their problem to drop out of the sky!

        Cloudy with a definite chance of Editable SALV solutions 😛

        (0) 
      2. Paul Hardy

        Thus far I have split the requirements into two, for only having some fields editable.

        Firstly as we know the data table to be displayed in the ALV  itself has to have a field which I will call CELLTAB typed as LVC_T_STYL.

        You can change the values of this cell in each row of the data table directly in the model to say what fields should be editable. I agonised over whether the model should really be doing this, as it is a UI type thing, but in the end I satisfied myself that all the model is doing is saying what fields should be editable.

        Then when (just after) the SALV is rendered that “after refresh” method should somehow tell the LAYOUT that the STYLEFNAME is “CELLTAB” and then somehow know which columns are editable, and then loop through the FCAT switching the EDIT flag on for each.

        So, I have just started on this, but I often find that most of the battle is working out what needs to be done!

        I will keep you all posted.

        Cheersy Cheers

        Paul

        (0) 
        1. Paul Hardy

          I’ve got it working!

          A generic way for the model to say what fields it wants to be editable – it is the models choice what fields it wants to expose, how to technically make these editable is the responsibility of the view.

          Then I modified the above solution to alter both the data table and the underlying CL_GUI_ALV_GRID field catalogue for the fields in question as well as the layout, and Bob is your uncle, the grid opens up with just the fields I want editable.

          editable monsters.PNG

          I am going to post a detailed blog on how I got this to work in the very near future, I just want to polish up the code a bit first – as all the programming gurus say “first make it work, then make it good”.

          My idea was always to have a generic report template where I could pass in what user interface technology (view) I wanted to use i.e. CL_GUI_ALV_GRID or CL_SALV_TABLE and by the magic of polymorphism the effect would be exactly the same. In any actual report using this framework the only difference would be in the CREATE OBJECT TYPE xyz statement in regard to the view object, and that would most likely be controlled by configuration in order to adhere to the open-closed principle.,

          That is crazy I hear you say, why bother to go to all the trouble of making CL_SALV_TABLE do everything CL_GUI_ALV_GRID can do, if then you define a framework where it does not matter which one you use.

          Firstly, it is for the same reason I climb Mount Everest – SAP did not want us customer types to raise CL_SALV_TABLE to the status of a first class citizen, so it pretty much had to be done.

          Secondly, the idea is that when a new ALV technology comes along e.g. the version of the SALV in 7.40 for massive data tables, you just have to create a new Z view class implementing the generic view interface, change the customising table and the report programs can remain utterly unchanged.

          Anyway, when I am finished cleaning up my code, I will post a detailed blog, and attach a SAPLINK file with all the objects.

          Cheersy Cheers

          Paul

          (0) 
          1. Naimesh Patel Post author

            Great and waiting for your blog with details ..

            Would you also write about the generic report template design? Its sounds interesting and promising 🙂

            Thanks.

            (0) 
  4. Alejandro Bindi

    Congratulations to you all (mainly Naimesh) for the research you are doing and for documenting it, this solution seems far more acceptable to me than others proposed in the past involving inheritance from “internal use” classes. Will have to try it as soon as I have some spare time…

    I don’t know if I would develop a report known to need editability from start using this method (since it doesn’t have SAP’s blessing). But it may at least come in handy as a quick solution to enable editability in an already developed one.

    Regards!

    (0) 
  5. Salil Vaidya

    Very good post. Is it possible to use the Sorting button in a custom way and not the standard way. Based on one of my requirement where, I need to display one cell as Left Justified and another cell of next row as Right justified. for this i am displaying the contents in 2 different columns. Now when i sort it, the whole layout goes for a toss. Basically, i need something as per the following screen shot.

    Here I am displaying Contracts and the related orders in same column and I need the orders to be intended so its easier to view for end user and makes it logical.

    Untitled.jpg

    (0) 
  6. Evgeniy Astafev

    Got weird table while using this method for editable salv (both grid and fullscreen modes). On any user command alv get refreshed and go to edit mode. Any hints?.. I’m on EHP7SP08.

    Also when use both set_ready_for_input and refresh_table_display methods I have ASSERTION_FAILED dump.

    editable-salv-question.PNG

    (0) 
  7. Yury Horinovich

    Is there any chance to open SALV Table in the editable mode for a particular cell? At the moment it is possible to open it in the editable mode for a particular column with “fieldcat-edit = ‘X'”, but “layout-stylefname = ‘CELLTAB'” is not working for me (with a proper population of an output table).

    Also, I have managed to open SALV with a container (grid) in the edit mode, but a fullscreen version of CL_SALV_TABLE does the same thing only after additional action (a double click on a cell or a toolbar button click) and it is not possible to call an additional refresh after the call of DISPLAY( ).

    It looks like CL_GUI_ALV_GRID is still needed for the scenario where individual cells have to be edited.

    Sandbox system is 7.40 SP4.

    (0) 
    1. Paul Hardy

      http://scn.sap.com/community/abap/blog/2016/01/10/falv–fast-alv-grid-object

      I’ve come to the horrible conclusion that editing a single cell in the SALV just cannot be done. As you say, you pass in the table which would work perfectly for a CL_GUI_ALV_GRID and make a single cell editable, and nothing happens.

      Also, yes, it has to be in container mode. I set my workaround up so a container is always created, even if I want a full screen..

      I have been playing with SALV, making it editable just because “it cannot be done” but SAP fight every step of the way, and with each release change the code to close off avenues we have been taking to make SALV editable. They don’t want it to be editable, and will not stop until they defeat us.

      In the end I have to conclude that the best approach is to wrap up CL_GUI_ALV_GRID in helper methods, that way you get all the proper functionality plus the ease of CL_SALV_TABLE.

      Have a look at this blog I put the link to at the top of this reply. Actually I wanted to put the link at the END of this reply, but the “insert link” function seems to always add the link at the start.

      Cheersy Cheers

      Paul

      (1) 
      1. Yury Horinovich

        Paul, thanks for the quick and informative response.

        I’ll look at the blog you’ve mentioned and most likely I will end up with a wrapper for CL_GUI_ALV_GRID (FALV or my own).

        Update: FALV is a very promising, except it cannot be executed in a background. SALV can handle this (at any selection screen you can send a report to a background job with a standard menu).

        The source of an issue with individual cells in SALV is a parameter IR_SALV_ADAPTER which is passed during the call of R_GRID->SET_TABLE_FOR_FIRST_DISPLAY in the method CL_SALV_GRID_ADAPTER->IF_SALV_ADAPTER~SET_METADATA. In case it is not initialized I’ve got individual editable cell. I’ve just skip this line in a debugger:

        *ALV Customer Wrapper

        me->r_salv_adapter = ir_salv_adapter.

        (0) 
        1. Łukasz Pęgiel

          Yury Horinovich wrote:

          Update: FALV is a very promising, except it cannot be executed in a background. SALV can handle this (at any selection screen you can send a report to a background job with a standard menu).

          I was working in previous version of 7.40 and still working with 7.31 version. I must have screw it up when adding top_of_page handling….

          Will try to fix it soon.

          (0) 
  8. Paul Hardy

    Mr. Naimesh,

     

    Have you tried this in a 7.50 system? I have a horrible suspicion that the powers that be at SAP monitor these blogs, and find a way to shut down our workarounds in the next release!

     

    Cheersy Cheers

     

    Paul

    (0) 
  9. Rafael Freitas

    simplified example for a fullscreen with just one alv :

    report  ztest_oo_alv_main.
    *----------------------------------------------------------------------*
    *       CLASS lcl_salv_model_list DEFINITION
    *----------------------------------------------------------------------*
    class lcl_salv_event definition." inheriting from cl_salv_model_base.
      public section.
        CLASS-methods:
          on_after_refresh for event after_refresh of cl_gui_alv_grid
            importing
              sender.
    endclass.                    "lcl_salv_model_list DEFINITION
    *----------------------------------------------------------------------*
    *       CLASS lcl_salv_model_list IMPLEMENTATION
    *----------------------------------------------------------------------*
    class lcl_salv_event implementation.
      method on_after_refresh.
        data: ls_layout          type lvc_s_layo,
              lt_fcat            type lvc_t_fcat.
        field-symbols: <ls_fcat> like line of lt_fcat.
        try .
    
            set handler on_after_refresh
              for all instances
              activation space.
    
            sender->get_frontend_fieldcatalog( importing et_fieldcatalog = lt_fcat ).
            loop at lt_fcat assigning <ls_fcat>.
              if <ls_fcat>-fieldname eq 'MATNR'.
    
                <ls_fcat>-edit = abap_true.
              endif.
            endloop.
            sender->set_frontend_fieldcatalog( lt_fcat ).
    *        ls_layout-edit = abap_true. "Edit ALL
            sender->set_frontend_layout( ls_layout ).
            sender->set_ready_for_input( 1 ).
          catch cx_salv_error.
        endtry.
      endmethod.                    "on_AFTER_REFRESH
    endclass.                    "lcl_salv_model_list IMPLEMENTATION
    
    
    start-of-selection.
    data: t_mara type standard table of mara.
    data: o_alv type ref to cl_salv_table.
      select *
             into  table t_mara
        from mara
             up to 20 rows.
    
      try.
          cl_salv_table=>factory(
            importing
              r_salv_table = o_alv
            changing
              t_table      = t_mara ).
        catch cx_salv_msg .
      endtry.
    
    *  "Event handler
      set handler lcl_salv_event=>on_after_refresh
        for all instances
        activation 'X'.
    
      o_alv->display( ).
    (0) 

Leave a Reply