2

I display a hierarchical-sequential list via the class cl_salv_hierseq_table, all the lines are compressed by default, and the user can click the button + on any line to expand the lines of second level.

I'm trying to execute custom code when the user clicks on the button + to expand the row.

By default, there's no way to catch it, it's handled internally by SAP. If I setup a custom GUI status and define a custom function code for the F2 button, the event added_function is triggered but I can't determine which row is concerned.

I also tried to intercept the event link_click but it's not triggered anyway.

Here's my code:

report salv_hierseq.
tables: vbrp.
select-options:
werks for vbrp-werks default 'R001',
lgort for vbrp-lgort default 'NORS',
charg for vbrp-charg.

class lcl_report definition.
  public section.
    types:
      begin of ty_kp,
        exidv          type vekpvb-exidv,
        exida          type vekpvb-exida,
        ernam          type vekpvb-ernam,
        erdat          type vekpvb-erdat,
        aenam          type vekpvb-aenam,
        aedat          type vekpvb-aedat,
        vhilm          type vekpvb-vhilm,
        vhart          type vekpvb-vhart,
        vpobjkey       type vekpvb-vpobjkey,
        packvorschr_st type vekpvb-packvorschr_st,
        exidv2         type vekpvb-exidv2,
        venum          type vekpvb-venum,
        expand         type char01,
      end of ty_kp,
      begin of ty_po,
        matnr      type vepovb-matnr,
        velin      type vepovb-velin,
        vemng      type vepovb-vemng,
        vemeh      type vepovb-vemeh,
        werks      type vepovb-werks,
        lgort      type vepovb-lgort,
        sobkz      type vepovb-sobkz,
        qplos      type vepovb-qplos,
        /cwm/vemng type vepovb-/cwm/vemng,
        hu_lgort   type vepovb-hu_lgort,
        venum      type vepovb-venum,
        vepos      type vepovb-vepos,
      end of ty_po.

    data:
      w_vekp   type ty_kp,
      t_vekp   type standard table of ty_kp,
      w_vepo   type ty_po,
      t_vepo   type standard table of ty_po,
      o_hs_alv type ref to cl_salv_hierseq_table.
    methods:
      get_data,
      generate_output.
  private section.
    methods:
      set_pf_status      changing co_hs_alv type ref to cl_salv_hierseq_table,
      set_expand_option  changing co_hs_alv type ref to cl_salv_hierseq_table,
      set_event_handlers changing co_hs_alv type ref to cl_salv_hierseq_table,
      on_link_click      for event link_click        of cl_salv_events_hierseq importing row column level sender,
      on_added_function  for event added_function    of cl_salv_events_hierseq importing e_salv_function sender.
endclass.

start-of-selection.
  data: lo_report type ref to lcl_report.
  create object lo_report.
  lo_report->get_data( ).
  lo_report->generate_output( ).

class lcl_report implementation.
  method get_data.
    select * into corresponding fields of table @t_vepo from vepo where werks in @werks and lgort in @lgort and charg in @charg.
    select * into corresponding fields of table @t_vekp from vekp for all entries in @t_vepo where venum = @t_vepo-venum.
    if not t_vekp is initial.
      sort t_vekp by venum.
      select * from vepo into corresponding fields of table t_vepo for all entries in t_vekp where venum = t_vekp-venum.
      sort t_vepo by venum vepos.
      delete t_vepo where velin = '2' or velin = '3'.
    endif.
  endmethod.                    "get_data

  method generate_output.
    data: lt_bind type salv_t_hierseq_binding,
          la_bind like line of lt_bind.

    la_bind-master = 'VENUM'.
    la_bind-slave  = 'VENUM'.
    append la_bind to lt_bind.

    try.
        call method cl_salv_hierseq_table=>factory
          exporting
            t_binding_level1_level2 = lt_bind
          importing
            r_hierseq               = o_hs_alv
          changing
            t_table_level1          = t_vekp
            t_table_level2          = t_vepo.
      catch cx_root.
    endtry.

    me->set_event_handlers( changing co_hs_alv = o_hs_alv ).
    me->set_pf_status( changing co_hs_alv = o_hs_alv ).
    me->set_expand_option( changing co_hs_alv = o_hs_alv ).
    o_hs_alv->display( ).
  endmethod.                    "generate_output

  method set_event_handlers.
    data: lo_events type ref to cl_salv_events_hierseq.
    try .
        lo_events = co_hs_alv->get_event( ).
        set handler on_link_click for lo_events.
        set handler on_added_function for lo_events.
      catch cx_root.
    endtry.
  endmethod.

  method set_pf_status.
    data: lo_functions type ref to cl_salv_functions_list.
    lo_functions = co_hs_alv->get_functions(  ).
    lo_functions->set_all( abap_true ).

    co_hs_alv->set_screen_status( pfstatus = 'ZMM18VE' report = sy-repid set_functions = cl_salv_model_base=>c_functions_all ).
  endmethod.                    "set_pf_status

  method set_expand_option.
    data:
      lo_columns type ref to cl_salv_columns_hierseq,
      lo_column  type ref to cl_salv_column_hierseq.
    try.
        lo_columns = co_hs_alv->get_columns( 1 ).
        lo_columns->set_expand_column( 'EXPAND' ).
      catch cx_salv_data_error cx_root.                 "#EC NO_HANDLER
    endtry.
  endmethod.                    "set_expand_option


  method on_link_click.
        data lo_event type ref to cl_salv_events_hierseq.

        lo_event = o_hs_alv->get_event( ).
        field-symbols: <lfa_data> like line of lo_report->t_vekp.

        read table lo_report->t_vekp assigning <lfa_data> index row.
        check sy-subrc is initial.
        if <lfa_data>-expand is initial.
          <lfa_data>-expand = 'X'.
        else.
          clear <lfa_data>-expand.
        endif.

        lo_report->o_hs_alv->refresh( ).

  endmethod.

  method on_added_function.

  endmethod.
endclass.                    "lcl_report IMPLEMENTATION
Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
  • Can you explain the steps to reproduce from the user point of view? I don't understand what the user clicks, what actually happens, and what you expect. You currently describe technical stuff "if something is called, it does the same thing as if something else is called", so it's too much abstract. – Sandra Rossi Feb 29 '20 at 12:16
  • "Expand' button does not work. I can't get the clicked row in added_function event and event link_click does not react on 'Expand'. Maybe I can make 'expand' button also something like hotspot? – Dmytro Vedmid Mar 01 '20 at 05:51

1 Answers1

2

If I understand well the question, you want to catch the event when the Expand/Collapse button (+ or -) and determine on which line it is requested.

First of all, this feature is not supported at all, otherwise there would be a dedicated event.

I understand that you're trying to find out a non-standard workaround, so let me continue what you started.

The workaround I propose hereafter is not supported by SAP.

You noticed that clicking this button corresponds to positioning the cursor on the +/- button (which in fact is considered like a field with "hotspot") and pressing the F2 button.

The F2 button usually corresponds to the double-click (the event DOUBLE_CLICK is triggered when it's done on the text fields of the line), but in the case of the +/- button, this is handled internally and this event is not triggered.

Your initial idea of reassigning the F2 key to a custom function code via a custom GUI status is very good. It's to be copied from the GUI status SALV_TABLE_STANDARD from program SAPLSALV_METADATA_STATUS, and in the function keys, you enter any function code for F2, like ZZ&IC1 (instead of the one proposed, &IC1).

The only thing left is to determine which line is concerned. You need to mimic the standard way of retrieving the selected line, which is based on the hiding of the line number in the global variable GS_HIDE-INDEX of the program SAPLKKBL in each displayed line of the ABAP list, and its value is obtained by determining where the cursor is located and reading the line when a button or key is pressed, via the statement READ CURRENT LINE or READ LINE currentline (currentline is itself determined by GET CURSOR LINE currentline).

Hopefully, it's possible to read a global variable from any program via the statement ASSIGN ('(programname)globalvariablename'), although it's an internal statement which is not supported by SAP (don't complain if it's removed in a future version).

In the following program, the click of the + button on the fifth line displays the custom message "Request to expand line 5" then it forces the standard behavior of expanding the child nodes by simulating the standard function code &IC1 (remember, it corresponds to the original F2 key), via the method SET_FUNCTION:

enter image description here

enter image description here

CLASS lcl_report DEFINITION.
  PUBLIC SECTION.
    TYPES: BEGIN OF ty_scarr.
        INCLUDE TYPE scarr.
    TYPES: expand TYPE flag,
           END OF ty_scarr.
    DATA:
      t_scarr  TYPE STANDARD TABLE OF ty_scarr,
      t_spfli  TYPE STANDARD TABLE OF spfli,
      o_hs_alv TYPE REF TO cl_salv_hierseq_table.
    METHODS:
      get_data,
      generate_output.

  PRIVATE SECTION.
    METHODS:
      on_added_function FOR EVENT added_function OF cl_salv_events_hierseq
        IMPORTING e_salv_function sender.
ENDCLASS.

CLASS lcl_report IMPLEMENTATION.

  METHOD get_data.
    SELECT * FROM spfli INTO TABLE @t_spfli.
    SELECT * FROM scarr INTO TABLE @t_scarr.
    SORT t_scarr BY carrid.
    SORT t_spfli BY carrid connid.
  ENDMETHOD.

  METHOD generate_output.

    cl_salv_hierseq_table=>factory(
      EXPORTING
        t_binding_level1_level2 = VALUE #( ( master = 'CARRID' slave = 'CARRID' ) )
      IMPORTING
        r_hierseq               = o_hs_alv
      CHANGING
        t_table_level1          = t_scarr
        t_table_level2          = t_spfli ).

    SET HANDLER on_added_function FOR o_hs_alv->get_event( ).

    " ZMM18VE GUI status was created by copying the SALV_TABLE_STANDARD
    " from program SAPLSALV_METADATA_STATUS, and reassigning the
    " function key F2 to the new function code ZZ&IC1 (instead of &IC1).
    o_hs_alv->set_screen_status( pfstatus = 'ZMM18VE' report = sy-repid set_functions = cl_salv_model_base=>c_functions_all ).

    o_hs_alv->get_functions(  )->set_all( abap_true ).

    o_hs_alv->get_columns( 1 )->set_expand_column( 'EXPAND' ).

    o_hs_alv->display( ).

  ENDMETHOD.                    "generate_output

  METHOD on_added_function.
    DATA: cursor_field TYPE string.

    CASE e_salv_function.
      WHEN 'ZZ&IC1'.
        ASSIGN ('(SAPLKKBL)GS_HIDE-INDEX') TO FIELD-SYMBOL(<index>).
        CHECK sy-subrc = 0.
        GET CURSOR FIELD cursor_field.
        CASE cursor_field.
          WHEN 'SYM_MINUS_FOLDER'.
            MESSAGE |Request to collapse line { <index> }| TYPE 'I'.
          WHEN 'SYM_PLUS_FOLDER'.
            MESSAGE |Request to expand line { <index> }| TYPE 'I'.
        ENDCASE.
        " Execute standard Expand/Collapse
        o_hs_alv->set_function( '&IC1' ).
    ENDCASE.

  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
  DATA: lo_report TYPE REF TO lcl_report.
  CREATE OBJECT lo_report.
  lo_report->get_data( ).
  lo_report->generate_output( ).
Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48