Creating an ALV Grid Using OOP

SAP provides many ways to accomplish a task, creating an ALV Grid is no different. Though there are simple Function Modules available to create an ALV grid, Object Oriented methodology is more preferred due to its own advantages which are always debated in the ABAP world. As far as OO is concerned, my advice to ABAP developers is "Sometimes, you have to take a leap of faith first. The trust part comes later" (from the film Man of Steel) . Debates apart, we are going to try our hands creating an ALV grid display using the class CL_GUI_ALV_GRID.

How we are going to do

We are going to create a screen with a custom container placed in it. When the report is run, a new ALV grid instance will be created and it will placed into the custom container of the screen. It is as simple as that!

Create the Screen

Before creating a screen, you need a program to be created so that a screen corresponding to the program can be created later. So go to SE38 and create a program named ZFAR_CL_GUI_ALV_GRID (you are free to choose your own program names).

Now we are going to create a screen. Go to SE51 and create a screen with screen number 0100.

Create a new screen using SE51

Press the Layout button in the tool bar to open the screen designer.

Add custom control to screen using screen painter

The Screen Painter will appear and you have to draw a Custom Container in the screen. Double click the container the you just drew now and set the name of the container as CUSTCONT in the properties window that appears as shown below.

Give name to custom control in the Screen Painter attributes

Now the screen is ready, but you have to specify what code should be executed during the PBO and PAI events of the screen. So close the Screen Painter and select the Flow Logic tab in the previous section where you will see the PBO and PAI Events. Below those events there are commented lines, which you have to uncomment now. After uncommenting, double click it to create the modules in the program. Make sure you have created both the modules into the main program we created at the beginning.

Now your code should look like this

report  zfar_cl_gui_alv_grid.

*&---------------------------------------------------------------------*
*&      Module  STATUS_0100  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
module status_0100 output.
*  SET PF-STATUS 'xxxxxxxx'.
*  SET TITLEBAR 'xxx'.

endmodule.                 " STATUS_0100  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0100  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
module user_command_0100 input.

endmodule.                 " USER_COMMAND_0100  INPUT

Time to code

Now we are going to create an object for the class CL_GUI_ALV_GRID and make the grid appear on the custom container that we created in the screen with some data from the table KNA1. So we are going to have the following variables & references in the program.

data:
      "Reference to the instance of ALV Grid
      g_alv type ref to cl_gui_alv_grid,
      "Reference to the custom container that
      "we placed in the screen
      g_cust type ref to cl_gui_custom_container,
      "Internal table for data to be displayed
      gt_kna1 type standard table of kna1,
      "Internal table for field catalog
      gt_fcat type lvc_t_fcat,
      "Work area for field catalog
      gs_fcat type lvc_s_fcat. 

As soon as we start the program we need the screen we created to appear. And hence...

start-of-selection.

  set screen 0100.

So when the screen is going to appear

  • We need to load the data needed
  • Create object for Custom Container & ALV Grid
  • Prepare the field catalogue for ALV Grid
  • Display the ALV Grid

Load the data

form load_data.

  select * from kna1
    into corresponding fields of table gt_kna1
    up to 10 rows.

endform.

Yes you got it! That’s it!

Prepare Field Catalogue

form prepare_fcat.

  define add_fcat.
    clear gs_fcat.
    gs_fcat-col_pos = &1.
    gs_fcat-fieldname = &2.
    gs_fcat-coltext = &3.
    gs_fcat-outputlen = &4.
    append gs_fcat to gt_fcat.
  end-of-definition.

  add_fcat:
     1 'KUNNR' 'Customer No.' 15,
     2 'LAND1' 'Country'      5,
     3 'NAME1' 'Name'         30,
     4 'ORT01' 'City'         20.

endform.

Personally I prefer macros to do this kind of repeated work, so that its easy to code and the code looks very neat and understandable. If you don’t understand macros, please give a try learning, it will be worth it. To say roughly what I'm doing in this code, I have added four records to gt_fcat with very simple Field Catalogue configuration, to show four columns in the ALV grid.

Putting it together

We have written two FORM*s so that we can call them when needed. Now all this process has to happen before the screen appears in the output. And so we have to place the code in *PBO. But PBO runs again and again whenever an action takes place in the screen, whereas we want to load and display the table only the first time the scree loads. The solution is simple, we will do all this process only when g_alv is initial, and after the first run g_alv is not going to be initial so the code will run only once.

module status_0100 output.

  set pf-status 'STAT1'.

  if g_cust is initial.

    create object g_cust
      exporting
        container_name              = 'CUSTCONT'
      exceptions
        cntl_error                  = 1
        cntl_system_error           = 2
        create_error                = 3
        lifetime_error              = 4
        lifetime_dynpro_dynpro_link = 5
        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.

    create object g_alv
      exporting
        i_parent          = g_cust
      exceptions
        error_cntl_create = 1
        error_cntl_init   = 2
        error_cntl_link   = 3
        error_dp_create   = 4
        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.

    perform load_data.
    perform prepare_fcat.


    call method g_alv->set_table_for_first_display
      changing
        it_outtab                     = gt_kna1
        it_fieldcatalog               = gt_fcat
      exceptions
        invalid_parameter_combination = 1
        program_error                 = 2
        too_many_lines                = 3
        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.



  endif.

endmodule.

Create a Status

Now you have to create a Status for our screen, so that you are able to press the back button and come out of the output screen.

Go to SE41 and create a new Status with the name STAT1.

Create menu using SE41

And in the Function Keys section add BACK and EXIT as shown below.

Create BACK and EXIT in the status

BACK and EXIT has to be handled in the PAI event as follows.

module user_command_0100 input.

  case sy-ucomm.
    when 'BACK'.
      leave to screen 0.
    when 'EXIT'.
      leave program.
  endcase.

endmodule.

That’s the end of it. Now you will be able to get the output we wanted.

ALV Table created using OOP

Here is the entire program...

report  zfar_cl_gui_alv_grid.

data:
      g_alv type ref to cl_gui_alv_grid,
      g_cust type ref to cl_gui_custom_container,
      gt_kna1 type standard table of kna1,
      gt_fcat type lvc_t_fcat,
      gs_fcat type lvc_s_fcat.

start-of-selection.

  set screen 0100.


*&---------------------------------------------------------------------*
*&      Module  STATUS_0100  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
module status_0100 output.

  set pf-status 'STAT1'.

  if g_cust is initial.

    create object g_cust
      exporting
        container_name              = 'CUSTCONT'
      exceptions
        cntl_error                  = 1
        cntl_system_error           = 2
        create_error                = 3
        lifetime_error              = 4
        lifetime_dynpro_dynpro_link = 5
        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.

    create object g_alv
      exporting
        i_parent          = g_cust
      exceptions
        error_cntl_create = 1
        error_cntl_init   = 2
        error_cntl_link   = 3
        error_dp_create   = 4
        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.

    perform load_data.
    perform prepare_fcat.


    call method g_alv->set_table_for_first_display
      changing
        it_outtab                     = gt_kna1
        it_fieldcatalog               = gt_fcat
      exceptions
        invalid_parameter_combination = 1
        program_error                 = 2
        too_many_lines                = 3
        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.



  endif.

endmodule.                 " STATUS_0100  OUTPUT

*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0100  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
module user_command_0100 input.

  case sy-ucomm.
    when 'BACK'.
      leave to screen 0.
    when 'EXIT'.
      leave program.
  endcase.

endmodule.                 " USER_COMMAND_0100  INPUT

*&---------------------------------------------------------------------*
*&      Form  load_data
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
form load_data.

  select * from kna1
    into corresponding fields of table gt_kna1
    up to 10 rows.

endform.                    "load_data

*&---------------------------------------------------------------------*
*&      Form  prepare_fcat
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
form prepare_fcat.

  define add_fcat.
    clear gs_fcat.
    gs_fcat-col_pos = &1.
    gs_fcat-fieldname = &2.
    gs_fcat-coltext = &3.
    gs_fcat-outputlen = &4.
    append gs_fcat to gt_fcat.
  end-of-definition.

  add_fcat:
     1 'KUNNR' 'Customer No.' 15,
     2 'LAND1' 'Country'      5,
     3 'NAME1' 'Name'         30,
     4 'ORT01' 'City'         20.

endform.                    "prepare_fcat

Fareez Ahamed

SAP Developer, Full Stack Web Developer, Laravel & Vue.js fanatic