Search This Blog

Thursday, November 11, 2010

ABAP Objects : ALV Grid Manipulations

The SAP List Viewer (ALV) is an integrated element of the ABAP Objects programming environment. It allows application developers to quickly implement the display of structured datasets .

With the ALV object model, you have the option of using almost unified programming techniques independent of the ALV tool in order to display various lists, tables or tree structures. The methods, parameters or classes only vary where tool-specific functions require a special procedure.

You are using the ALV object model with CL_SALV_TABLE class . you use the main ALV class to make all the settings that you need for the ALV output except one thing that you are not able to do which is "EDIT" your data inside the ALV grid.

If you about Modifying Subobjects of a Main Class CL_SALV_TABLE you'll see that the diagram looks like that :







































When you see this diagram, you must be thinking to yourself that this is the final and absolute settlement of hierarchical objects that represent the Class of ALV But if we will deepen our research we find that beyond the this traditional object diagram hierarchy that is before us there's a number of hidden objects that can help us make that we can bring the CL_SALV_TABLE object into a situation where we can edit the information that is displayed on the ALV grid and record the changes into our internal table .


The official statement about useing the CL_SALV_TABLE object is: "Tables displayed with ALV are not ready for input".

Reverse engineering process:


we will take a look in the opposite order from bottom to top and we will found that CL_SALV_MODEL_LIST is the super class of the CL_SALV_TABLE class .















 
 
 
 
 
 
 
 
 
 
Another step up will bring us to:

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Now we can see that we have a connection to CL_SALV_MODEL_BASE class .
Another step up will bring us to:

















Another step up will bring us to:














If we get the ALV object from the ALV model class than we can easily make the ALV model ALV to "Set Ready for input". I have started looking the ALV object inside the ALV model.

At the first entry in the list of nodes ALV model CL_SALV_MODEL, I found the method GET_GRID  in class CL_SALV_FULLSCREEN_ADAPTER which can provide me the relevant instance of CL_GUI_ALV_GRID class.

But Class CL_SALV_MODEL has a protected attribute R_CONTROLLER which has everything we need to get to GRID object. and because of that we have a problem to get a direct reference for the CL_SALV_MODEL. At this point it's a bit problem to get access to a protected attribute since all of the components declared in the protected section are accessible to all methods of the classand of classes that inherit from it. Protected components form a special interface between a class and its subclasses.

Proposed Solution:
All of the components declared in the protected section are accessible to all methods of the class and of classes that inherit from it. this means that in our solution should based on inherited class that could have an access to the protected attribute R_CONTROLLER  of the class CL_SALV_MODEL .
The core target of the solution is to get an access to the GRID object . once we will have an access to the grid object we could make it editable and could handle every data change and respond to it as we want.

We start to build the solution with an inherited class that we should build . 
Inherited a local program class LCL_SALV_MODEL from the CL_SALV_MODEL_LIST.

Our local class will contain 2 main compoments one is for CL_SALV_CONTROLLER_MODEL class , and the second is for CL_SALV_ADAPTER class , by maintaining these attributes we could get an access to the CL_GUI_ALV_GRID class and get it's fieldcatalog table .

After getting the fieldcatalog table of CL_GUI_ALV_GRID object we could set the fields that we want to be editable by turn on the appropriate value within the edit field in the fieldcatalog structure.

After getting and setting the fieldcatalog table we need to take care about edit events . for that there's an regsitration method which should be called when we want to react to one of the edit events like when pressing enter or when calling an search help field , we also can do more things that related to the frontend fieldcatalog like check tables , search help etc.

The data syncronization taken care by the CL_ALV_CHANGED_DATA_PROTOCOL class
and therefor we need to create an local event handler class and actually tell to the CL_GUI_ALV_GRID object that we are about deal with the changed data .

Solution Diagram:


Solution Implementation:

Well , in my personal case i got a task to update PO profit segment with an appropriate billing document , so my example will contain some BAPI calls and data from EKKO & EKPO tables .

&---------------------------------------------------------------------*

*& Report ZZGMM_POPROF_SEG_UPDATE
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
PROGRAM zzgmm_poprof_seg_update.
INCLUDE zzgmm_poprof_seg_update_top.
INCLUDE zzgmm_poprof_seg_update_sels.
INCLUDE zzgmm_poprof_seg_update_cls.

*----------------------------------------------------------------------*
* Start of selection
*----------------------------------------------------------------------*

START-OF-SELECTION.

CREATE OBJECT lo_report.
CHECK lo_report IS BOUND.
lo_report->get_data_from_db( ).

*&---------------------------------------------------------------------*

*& Include ZZGMM_POPROF_SEG_UPDATE_TOP
*&---------------------------------------------------------------------*

INCLUDE .
TABLES: ekpo, ekko.

TYPES: BEGIN OF ty_disp_action ,
             ebeln TYPE ekpo-ebeln,
             ebelp TYPE ekpo-ebelp,
             matnr TYPE ekpo-matnr,
             txz01 TYPE ekpo-txz01,
             menge TYPE ekpo-menge ,
            vbeln TYPE VBUK-VBELN,
TYPES: END OF ty_disp_action .

TYPES: tt_disp_action TYPE STANDARD TABLE OF zzgmm_poprof_seg_update.

CLASS lcl_report DEFINITION DEFERRED .
CLASS lcl_event_handler DEFINITION DEFERRED .

*----------------------------------------------------------------------*
* Global data
*----------------------------------------------------------------------*

DATA: lo_report TYPE REF TO lcl_report,
            go_event_h TYPE REF TO lcl_event_handler.

*&---------------------------------------------------------------------*

*& Include ZZGMM_POPROF_SEG_UPDATE_SELS
*&---------------------------------------------------------------------*

SELECTION-SCREEN BEGIN OF BLOCK block1 WITH FRAME TITLE text-001.
SELECT-OPTIONS: so_ebeln FOR ekpo-ebeln,
                                so_ebelp FOR ekpo-ebelp.
SELECTION-SCREEN END OF BLOCK block1 .


*&---------------------------------------------------------------------*

*& Include ZZGMM_POPROF_SEG_UPDATE_CLS
*&---------------------------------------------------------------------*

CLASS lcl_salv_model DEFINITION INHERITING FROM cl_salv_model_list.

PUBLIC SECTION.

DATA: o_control TYPE REF TO cl_salv_controller_model,
           o_adapter TYPE REF TO cl_salv_adapter.

METHODS: set_model IMPORTING io_model TYPE REF TO cl_salv_model,
                   set_controller,
                   set_adapter.

PRIVATE SECTION.

DATA: lo_model TYPE REF TO cl_salv_model.

ENDCLASS.
*----------------------------------------------------------------------*
* Event handler for the added buttons
*----------------------------------------------------------------------*

CLASS lcl_event_handler DEFINITION.

PUBLIC SECTION.
METHODS: on_user_command FOR EVENT added_function OF cl_salv_events
                     IMPORTING e_salv_function,
                   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.

PRIVATE SECTION.

DATA: lv_edit_mode TYPE abap_bool VALUE abap_false,
           o_salv TYPE REF TO cl_salv_table,
           t_log TYPE STANDARD TABLE OF bapiret2.


METHODS : execute_bapi,
                    display_log.
ENDCLASS.



*----------------------------------------------------------------------*

* Local Report class - Definition

*----------------------------------------------------------------------*

CLASS lcl_report DEFINITION.

PUBLIC SECTION.

DATA: t_data TYPE STANDARD TABLE OF zzgmm_poprof_seg_update,

o_salv TYPE REF TO cl_salv_table,

o_salv_model TYPE REF TO lcl_salv_model.



METHODS:

get_data_from_db,

generate_output.



ENDCLASS. "lcl_report DEFINITION



*----------------------------------------------------------------------*

* Local Report class - Implementation

*----------------------------------------------------------------------*

CLASS lcl_report IMPLEMENTATION.



METHOD get_data_from_db.



SELECT ebeln ebelp matnr txz01 menge FROM ekpo

INTO CORRESPONDING FIELDS OF TABLE me->t_data[]

WHERE ebeln IN so_ebeln

AND ebelp IN so_ebelp

AND knttp = 'Y'

AND loekz <> 'L'.



IF LINES( me->t_data[] ) > 0.

me->generate_output( ).

ELSE.

MESSAGE s131(m7) DISPLAY LIKE 'S'.

ENDIF.

ENDMETHOD. "get_data



METHOD generate_output.

DATA: lo_events TYPE REF TO cl_salv_events_table,

lo_msg TYPE REF TO cx_salv_msg,

lo_event_h TYPE REF TO lcl_event_handler,

lo_alv_mod TYPE REF TO cl_salv_model,

lv_msg TYPE string .





TRY.

cl_salv_table=>factory( EXPORTING list_display = abap_false

IMPORTING r_salv_table = me->o_salv

CHANGING t_table = t_data[] ).



CATCH cx_salv_msg.

lv_msg = lo_msg->get_text( ).

MESSAGE lv_msg TYPE 'I'.

CLEANUP.

ENDTRY.



o_salv->set_screen_status( pfstatus = 'ZALV_STANDARD'

report = 'ZZGMM_POPROF_SEG_UPDATE'

set_functions = o_salv->c_functions_all ).



lo_events = o_salv->get_event( ).



CREATE OBJECT lo_event_h.



SET HANDLER lo_event_h->on_user_command FOR lo_events.

lo_alv_mod ?= o_salv.



CREATE OBJECT o_salv_model.



IF o_salv_model IS BOUND .

o_salv_model->set_model( io_model = lo_alv_mod ).

ENDIF.

* o_salv->set_screen_popup( start_column = 1

* end_column = 100

* start_line = 1

* end_line = 20 ).

o_salv->display( ).



ENDMETHOD. "generate_output



ENDCLASS. "lcl_report IMPLEMENTATION



*----------------------------------------------------------------------*

* LCL_SALV_MODEL implementation

*----------------------------------------------------------------------*

CLASS lcl_salv_model IMPLEMENTATION.

* data encapsulation calss

METHOD set_model.

* save model

lo_model = io_model.

ENDMETHOD. "set_model

METHOD set_controller.

* save controller

o_control = lo_model->r_controller.

ENDMETHOD. "set_controller

METHOD set_adapter.

* save adapter from controller

o_adapter ?= lo_model->r_controller->r_adapter.

ENDMETHOD. "set_adapter

ENDCLASS. "LCL_SALV_MODEL IMPLEMENTATION



*----------------------------------------------------------------------*

* Event Handler for the ALV

*----------------------------------------------------------------------*

CLASS lcl_event_handler IMPLEMENTATION.



METHOD on_user_command.



DATA: lo_grid TYPE REF TO cl_gui_alv_grid,

lo_fullscreen_adapter TYPE REF TO cl_salv_fullscreen_adapter,

lt_fieldcatalog TYPE lvc_t_fcat,

ls_layout TYPE lvc_s_layo.



FIELD-SYMBOLS TYPE lvc_s_fcat .



CASE e_salv_function.



WHEN 'EDITMODE'.



lo_report->o_salv_model->set_controller( ).

lo_report->o_salv_model->set_adapter( ).

lo_fullscreen_adapter ?= lo_report->o_salv_model->o_adapter.

lo_grid = lo_fullscreen_adapter->get_grid( ).



IF lo_grid IS BOUND.

* lo_grid->get_frontend_layout( IMPORTING es_layout = ls_layout ).

* ls_layout-edit = 'X'.

* lo_grid->set_frontend_layout( is_layout = ls_layout ).

lo_grid->get_frontend_fieldcatalog( IMPORTING et_fieldcatalog = lt_fieldcatalog[] ).

READ TABLE lt_fieldcatalog[] ASSIGNING WITH KEY fieldname = 'VBELN'.



CHECK IS ASSIGNED .

-checktable = 'VBRK'.



IF -edit = 'X'.

me->lv_edit_mode = -edit = space .

ELSE.

me->lv_edit_mode = -edit = 'X'.

ENDIF.



lo_grid->set_frontend_fieldcatalog( EXPORTING it_fieldcatalog = lt_fieldcatalog[] ).

lo_grid->register_edit_event( EXPORTING i_event_id = cl_gui_alv_grid=>mc_evt_enter ).

lo_grid->register_edit_event( EXPORTING i_event_id = cl_gui_alv_grid=>mc_evt_modified ).

CREATE OBJECT go_event_h.

SET HANDLER go_event_h->data_changed FOR lo_grid.

lo_grid->refresh_table_display( ). "must after cahnge the fieldcatalog table

ENDIF.



WHEN 'EXEC'.

me->execute_bapi( ).

ENDCASE.

ENDMETHOD. "on_user_command

METHOD data_changed .

FIELD-SYMBOLS: TYPE lvc_s_modi.



READ TABLE er_data_changed->mt_mod_cells[] ASSIGNING INDEX 1.



CHECK IS ASSIGNED.



ENDMETHOD. "data_changed

METHOD execute_bapi.



CHECK me->lv_edit_mode = 'X'.



FIELD-SYMBOLS : TYPE zzgmm_poprof_seg_update.



DATA : lt_poaccount TYPE STANDARD TABLE OF bapimepoaccount,

lt_poaccountx TYPE STANDARD TABLE OF bapimepoaccountx,

lt_poaccountprofitsegment TYPE STANDARD TABLE OF bapimepoaccountprofitsegment,

ls_poaccount TYPE bapimepoaccount,

ls_poaccountx TYPE bapimepoaccountx,

ls_poaccountprofitsegment TYPE bapimepoaccountprofitsegment,

lt_return TYPE STANDARD TABLE OF bapiret2.



LOOP AT lo_report->t_data[] ASSIGNING WHERE vbeln IS NOT INITIAL.

ls_poaccountprofitsegment-po_item = ls_poaccountx-po_item = ls_poaccount-po_item =

-ebelp.



ls_poaccountprofitsegment-serial_no = ls_poaccountx-serial_no =

ls_poaccount-serial_no = '01'.

APPEND ls_poaccount TO lt_poaccount[].



ls_poaccountx-profit_ctr = 'X'.

APPEND ls_poaccountx TO lt_poaccountx[].



ls_poaccountprofitsegment-fieldname = 'WW004'.

ls_poaccountprofitsegment-value = -vbeln.



APPEND ls_poaccountprofitsegment TO lt_poaccountprofitsegment[].



CALL FUNCTION 'BAPI_PO_CHANGE'

EXPORTING

purchaseorder = -ebeln

TABLES

return = lt_return[]

poaccount = lt_poaccount[]

poaccountprofitsegment = lt_poaccountprofitsegment[]

poaccountx = lt_poaccountx[].



CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.

APPEND LINES OF lt_return[] TO me->t_log[].

ENDLOOP.



me->display_log( ) .

ENDMETHOD . "execute_bapi



METHOD display_log.

DATA: lexc_msg TYPE REF TO cx_salv_msg,

lv_msg_string TYPE string .



CHECK LINES( me->t_log[] ) > 0 .



TRY.

cl_salv_table=>factory( EXPORTING list_display = abap_true

IMPORTING r_salv_table = me->o_salv

CHANGING t_table = me->t_log[] ).

CATCH cx_salv_msg INTO lexc_msg.

lv_msg_string = lexc_msg->get_text( ).

MESSAGE lv_msg_string TYPE 'I'.

ENDTRY.

me->o_salv->display( ).

ENDMETHOD . "display_log

ENDCLASS. "lcl_event_handler IMPLEMENTATION



Result Screen:

As you can see we have an ALV grid with editable fields .
Enjoy ,
Harel Gilor .

16 comments:

  1. Sorry, my question is, Can I change the toolbar touching the CL_GUI_ALV_GRID object class?
    Because, I done this but, the toolbar in object CL_SALV_TABLE isn't modified...
    Do you think it can be done?

    Greetings!

    ReplyDelete
  2. Ecorptrainings.com provides ORACLE APPS TECH in hyderabad with best faculties on real time projects. We give the best online trainingamong the ORACLE APPS TECH in Hyderabad.
    Classroom Training in Hyderabad India

    ReplyDelete
  3. Well list found it very informative and wonderful keep it up.

    ReplyDelete
  4. This is very useful - it took a lot of hard work and time. Thank you very much for sharing.

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. It was so nice article.I was really satisfied by seeing this article and we are
    also giving tibco online training.ItTibco

    online training
    is one of the best
    online training center

    ReplyDelete
  7. Very good, many thanks!!!
    You saved my day...

    ReplyDelete

  8. this is very good nice article. this is very useful for SAP ABAP students.


    ==========================================================
    This is very nice article. This is very use ful for SAP ABAP Learners.
    http://www.bytesonlinetraining.com/sap-abap-online-training/
    ===========================================================

    hi sir. i want to do SAP ABAP training.
    SAP ABAP ONlINE TRAINING Thanks for providing

    valuable information.

    ReplyDelete
  9. After reading this post I got an idea about on this note.Really something grate in this article ,Thanks for sharing this. We are providing SAP courses training online. After reading this slightly am changed my way of introduction about my training to people. To know more Visit Us SAP PM Online Training Course

    ReplyDelete
  10. Your given most of the use full information,i read your post this post gives a very better idea on sap abab.

    ReplyDelete
  11. Great Work,After reading this post I got an idea about on this note.keep sharing us.

    ReplyDelete
  12. Great Work, after reading this post I felt comfortable with this post thank you very much..............................Please contact us to know more about Oracle Fusion Financials Training

    ReplyDelete
  13. Thanks for sharing the details! thanks for sharing information,nice article.
    i would like to more information from your side!
    please added more then tips!Am working in
    Excel Training In Hyderabad

    ReplyDelete