Thursday, 15 June 2017

How to publish your GUI-based SAP List Viewer (ALV) report in ABAP Web Dynpro

In this blog I will explain how any GUI-based ALV report can be displayed quite easily in ABAP Web Dynpro (WDA). The development is based on two out-of-the-box ABAP-tools: Class CL_SALV_BS_RUNTIME_INFO and the List Viewer for Webdynpro. More information about this class can be found here and some excellent documentation for the List Viewer for Webdynpro can be found here.

Data supply by submitting FBL5N


We start by creating the data provider for the WDA-List Viewer. We need the information from transaction FBL5N, which under the hood is program RFITEMAR. I’ll wrap this in a function module.

FUNCTION z2_alv_output_fbl5n.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(I_R_BUKRS) TYPE  Z2TT_BUKRS OPTIONAL
*"     VALUE(I_KUNNR) TYPE  KUNNR
*"  EXPORTING
*"     VALUE(ET_POS) TYPE  /SAPPCE/RFPOSXEXT
*"  EXCEPTIONS
*"      CUSTOMER_NOT_FOUND
*"      DATA_RETRIEVE_FAILED
*"----------------------------------------------------------------------

* Check if customer exists
  PERFORM check_customer      USING i_kunnr.

* Prepare catching ALV
  cl_salv_bs_runtime_info=>clear_all( ).

* Set No Display/No Metadata and get ALV DATA
  cl_salv_bs_runtime_info=>set( EXPORTING display  = abap_false
                                          metadata = abap_false
                                          data     = abap_true ).

* Init table items
  CLEAR et_pos[].

* Submit report RFITEMAR ie transaction FBL5N
  SUBMIT rfitemar AND RETURN
    WITH dd_bukrs IN i_r_bukrs          " Company
    WITH dd_kunnr EQ i_kunnr            " Customer
    WITH x_opsel  EQ abap_false         " Only open items
    WITH x_aisel  EQ abap_true          " All items
    WITH x_clsel  EQ abap_false         " Cleared items
    WITH pa_vari  EQ  '/AR'.            " Layout

  TRY.
*    Get the output and store in local table
      cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = lr_report ).
      ASSIGN lr_report->* TO <lt_rfitem>.

*    Errors detected ?
    CATCH cx_root.
      RAISE data_retrieve_failed.
  ENDTRY.

* Clear ALV
  cl_salv_bs_runtime_info=>clear_all( ).

* Output (items) available ?
  CHECK <lt_rfitem> IS ASSIGNED.

* Export selected items
  et_pos[] = <lt_rfitem>.

ENDFUNCTION.

In this function module we prepare the class CL_SALV_BS_RUNTIME_INFO, so that the next ALV call is not displayed on screen, but the data is stored in memory. After this preparation, the program for FBL5N is submitted (with the necessary selection-screen parameters) and finally the data generated by the ALV report is retrieved and returned to the caller.

Creation of Webdynpro


Now we have the function module ready that can deliver us the necessary data, we can build a Webdynpro to show the data to the user.

1. In SE80, create a Webdynpro. Only one view in one window is necessary.

SAP ALV, SAP ABAP Web Dynpro

2. Assign the Webdynpro ALV-usage.

SAP ALV, SAP ABAP Web Dynpro

3. Add the component usage group to the attributes of the view.

SAP ALV, SAP ABAP Web Dynpro

4. For both the selection and the ALV-data a node in the context for the view is made. For the ALV a supply function is added.


SAP ALV, SAP ABAP Web Dynpro

5. The supply function is coded. In this supply function we call the function module we created earlier, to retrieve the data, and we set the data from FBL5N to the context.

METHOD supply_fbl5n .

** data declaration
  DATA lt_alv TYPE wd_this->elements_alv.
  DATA lo_el_selection TYPE REF TO if_wd_context_element.
  DATA lv_kunnr TYPE wd_this->element_selection-kunnr.

* Get the value for the customer from the selection on the screen. 
  lo_el_selection = wd_context->get_child_node( name = wd_this->wdctx_selection )->get_element( ).
  lo_el_selection->get_attribute( EXPORTING name =  `KUNNR`
                                  IMPORTING value = lv_kunnr ).

* Check if we have a value for the customer.
  IF lv_kunnr IS INITIAL.
    APPEND INITIAL LINE TO lt_alv.
    EXIT.
  ENDIF.

* Call the functionmodule that will retrieve the ALV info from FBL5N .
  CALL FUNCTION 'Z2_GRAP_ALV_OUTPUT_FBL5N'
    EXPORTING
      i_kunnr              = lv_kunnr
    IMPORTING
      et_pos               = lt_alv
    EXCEPTIONS
      customer_not_found   = 1
      data_retrieve_failed = 2
      OTHERS               = 3.

  IF sy-subrc <> 0.
* Implement suitable error handling here " TODO; generate nice error messages on screen.
    APPEND INITIAL LINE TO lt_alv.
  ENDIF.

* bind all the elements to the context
  node->bind_table(
    new_items            =  lt_alv
    set_initial_elements = abap_true ).

ENDMETHOD.

6. In the view a selection for the customer is added, and a container for the ALV display.

SAP ALV, SAP ABAP Web Dynpro

7. Create an action for the OnEnter event of the customer inputfield, and trigger the retrieval of the data.

METHOD onactionselect_kunnr .

* All we want to do is the start the supply function for the chosen customer.
  wd_context->get_child_node( wd_this->wdctx_alv )->invalidate( ).

ENDMETHOD.

8. And now the fun part: the declaration & assignment of the Webdynpro ALV in methods WWDDOINIT and cleanup in WDDOEXIT.

METHOD wddoinit .

  DATA:
    l_cmp_usage       TYPE REF TO if_wd_component_usage,
    l_intf_controller TYPE REF TO iwci_salv_wd_table.


  IF wd_this->cmp_usage_group IS INITIAL.
    wd_this->cmp_usage_group = wd_comp_controller->wd_get_api( )->create_cmp_usage_group(
        name           = 'ALV_USAGE_GROUP'
        used_component = 'SALV_WD_TABLE' ).

    l_cmp_usage = wd_this->cmp_usage_group->add_component_usage(
         name           = 'ALV_USAGE'
         used_component = 'SALV_WD_TABLE').

    l_cmp_usage->create_component( ).

    wd_this->wd_get_api( )->do_dynamic_navigation(
        source_window_name          = 'W_MAIN'
        source_vusage_name          = 'V_MAIN_USAGE_0'
        source_plug_name            = 'TO_ALV'
        target_component_name       = 'SALV_WD_TABLE'
        target_component_usage      = 'ALV_USAGE'
        target_view_name            = 'TABLE'
        target_plug_name            = 'DEFAULT'
        target_embedding_position   = 'V_MAIN/CNT_ALV_CONTAINER' ).

    l_intf_controller ?= l_cmp_usage->get_interface_controller( ).
    l_intf_controller->set_data( wd_context->get_child_node( 'ALV' ) ).

  ENDIF.

* Optional: add some nice features for the end-user.
    l_intf_controller->get_model( )->if_salv_wd_std_functions~set_hierarchy_allowed( ).
    l_intf_controller->get_model( )->if_salv_wd_std_functions~set_aggregation_allowed( abap_true ).
    l_intf_controller->get_model( )->if_salv_wd_std_functions~set_hierarchy_allowed( abap_true ).
    l_intf_controller->get_model( )->if_salv_wd_std_functions~set_count_records_allowed( abap_true ).
    l_intf_controller->get_model( )->if_salv_wd_std_functions~set_group_aggregation_allowed( abap_true ).

ENDMETHOD.

METHOD wddoexit .

* And a nice clean-up after we're finished.
  wd_this->wd_get_api( )->remove_dynamic_meta_data(
        source_window_name          = 'W_MAIN'
        source_vusage_name          = 'V_MAIN_USAGE_0'
        source_plug_name            = 'TO_ALV'
        target_component_name       = 'SALV_WD_TABLE'
        target_component_usage      = 'ALV_USAGE'
        target_view_name            = 'TABLE'
        target_plug_name            = 'DEFAULT'
        target_embedding_position   = 'V_MAIN/CNT_ALV_CONTAINER' ).

  IF wd_this->cmp_usage_group IS BOUND.
    wd_this->cmp_usage_group->remove_all_cmp_usages( ).
    CLEAR wd_this->cmp_usage_group.
  ENDIF.

  wd_comp_controller->wd_get_api( )->remove_cmp_usage_group( 'ALV_USAGE_GROUP' ).

ENDMETHOD.

9. Finally, create a Webdynpro application and test it.

Results:

FBL5N in SAPGUI:

SAP ALV, SAP ABAP Web Dynpro

And in Webdynpro:

SAP ALV, SAP ABAP Web Dynpro

Please note that I did create a view for the Webdynpro Listviewer, in which I did hide quite a lot of columns to show the similarities between the GUI ALV and the Webdynpro Listviewer.

No comments:

Post a Comment