在ALV树中更改节点的站点

时间:2017-06-23 12:12:15

标签: sap abap alv

我有一个ALV树,基本上我需要做的是将特定节点滑动(拖动)到顶部或底部或ALV树中的特定位置。

如何实现这一目标?

例如,在这里,我想在 AFFECTATIONS 节点之前滑动 IF 节点: enter image description here

预期节点的安排:

enter image description here

2 个答案:

答案 0 :(得分:1)

TL; DR cl_gui_alv_tree无法像您希望的那样执行此操作。

由于ALV控制框架中拖放实现的细节,树中的节点可以 可拖动(源)可放置(目标) , 不是都。因此,将节点拖动到另一个节点位于同一级别的层次结构中是不可能的,因此也不可能在运行时(相互)更改节点及其兄弟节点。

但是,我想为您提供一段有用的代码,其中显示了如何通过将节点拖到父级层次结构上来实现与问题接近的smth。

在SAP ALV Framework中实施DND功能的步骤:

  1. 创建事件类,其中实现了ondragondrop事件的处理程序。
  2. 创建DND存储对象lcl_dragdropobj,这是一个空类,通过它传递内存中的网格对象(叶子,节点)。
  3. 为源对象和目标对象创建behavior definition
  4. 借助上述行为对象,通过is_node_layout参数为每个节点/叶子分配布局。该布局将定义节点行为:要么是可拖动的,要么是可放置的。
  5. 以下是基于spfli / sflight数据库构建的示例代码:

    REPORT  zyyz.
    
    DATA: g_alv_tree         TYPE REF TO cl_gui_alv_tree,
          g_custom_container TYPE REF TO cl_gui_custom_container,
          g_drag_behaviour   TYPE REF TO cl_dragdrop,
          g_drop_behaviour   TYPE REF TO cl_dragdrop.
    DATA: gt_sflight      TYPE TABLE OF sflight INITIAL SIZE 0,      "Output-Table
          gt_fieldcatalog TYPE lvc_t_fcat,
          g_top_key       TYPE lvc_nkey,
          ok_code         LIKE sy-ucomm,
          save_ok         LIKE sy-ucomm,           "OK-Code
          g_max           TYPE i VALUE 255.
    
    CLASS lcl_dragdropobj DEFINITION.
      PUBLIC SECTION.
        DATA: cp_sflight_root     TYPE sflight,
              cp_sflights         TYPE TABLE OF sflight,
              cp_node_text_root   TYPE lvc_value,
              cp_node_texts       TYPE salv_t_value,
              lt_selected_carrids TYPE lvc_t_nkey,
              lt_selected_leafs   TYPE lvc_t_nkey.
    ENDCLASS.
    
    CLASS lcl_event_receiver DEFINITION.
      PUBLIC SECTION.                .
        METHODS:
          on_drag
          FOR EVENT on_drag
                        OF cl_gui_alv_tree
            IMPORTING sender node_key drag_drop_object,
          on_drop
          FOR EVENT on_drop
                        OF cl_gui_alv_tree
            IMPORTING drag_drop_object.
    ENDCLASS.
    *---------------------------------------------------------------------*
    *       CLASS lcl_toolbar_event_receiver IMPLEMENTATION
    *---------------------------------------------------------------------*
    CLASS lcl_event_receiver IMPLEMENTATION.
    
      METHOD on_drag.
        DATA: dataobj           TYPE REF TO lcl_dragdropobj,
              l_sflight         TYPE sflight,
              l_node_text       TYPE lvc_value.
    * create and fill dataobject for event ON_DROP.
        CREATE OBJECT dataobj.
    
    * Get dragged month
        CALL METHOD sender->get_outtab_line
          EXPORTING
            i_node_key    = node_key
          IMPORTING
            e_outtab_line = dataobj->cp_sflight_root
            e_node_text   = dataobj->cp_node_text_root.
    
        CALL METHOD g_alv_tree->get_children
          EXPORTING
            i_node_key  = node_key
          IMPORTING
            et_children = dataobj->lt_selected_carrids.
    
        LOOP AT dataobj->lt_selected_carrids ASSIGNING FIELD-SYMBOL(<carrid>).
          CLEAR: l_sflight, l_node_text.
          CALL METHOD sender->get_outtab_line
            EXPORTING
              i_node_key    = <carrid>
            IMPORTING
              e_outtab_line = l_sflight
              e_node_text   = l_node_text.
          APPEND l_node_text TO dataobj->cp_node_texts.
    
          CALL METHOD g_alv_tree->get_children
            EXPORTING
              i_node_key  = <carrid>
            IMPORTING
              et_children = dataobj->lt_selected_leafs.
    
          LOOP AT dataobj->lt_selected_leafs ASSIGNING FIELD-SYMBOL(<node>).
            CLEAR: l_sflight, l_node_text.
            CALL METHOD sender->get_outtab_line
              EXPORTING
                i_node_key    = <node>
              IMPORTING
                e_outtab_line = l_sflight
                e_node_text   = l_node_text.
            APPEND l_sflight TO dataobj->cp_sflights.
          ENDLOOP.
    
        ENDLOOP.
    
        drag_drop_object->object = dataobj.
    
      ENDMETHOD.
    
      METHOD on_drop.
        DATA: dataobj           TYPE REF TO lcl_dragdropobj,
              l_root_key        TYPE lvc_nkey,
              l_carrid_key      TYPE lvc_nkey,
              l_new_key         TYPE lvc_nkey,
              lt_sflights       TYPE TABLE OF sflight.
    
        CATCH SYSTEM-EXCEPTIONS move_cast_error = 1.
          dataobj ?= drag_drop_object->object.
    
          PERFORM add_month USING dataobj->cp_node_text_root
                                                        g_top_key
                                                        cl_gui_column_tree=>relat_first_child
                                      CHANGING l_root_key.
    *
          LOOP AT dataobj->lt_selected_carrids ASSIGNING FIELD-SYMBOL(<node>).
            READ TABLE dataobj->cp_node_texts ASSIGNING FIELD-SYMBOL(<text>) INDEX sy-tabix.
            DATA(sflight) = VALUE sflight( carrid = <text> ).
            PERFORM add_carrid_line USING sflight
                                                              l_root_key
                                                              cl_gui_column_tree=>relat_last_child
                                  CHANGING l_carrid_key.
            CLEAR lt_sflights.
            INSERT LINES OF dataobj->cp_sflights INTO TABLE lt_sflights.
            DELETE lt_sflights WHERE carrid NE <text>.
            LOOP AT lt_sflights ASSIGNING FIELD-SYMBOL(<flight>).
              PERFORM add_complete_line USING <flight>
                                                                       l_carrid_key
                                                    CHANGING l_new_key.
            ENDLOOP.
          ENDLOOP.
          PERFORM delete_node.
        ENDCATCH.
        IF sy-subrc <> 0.
          CALL METHOD drag_drop_object->abort.
        ENDIF.
      ENDMETHOD.
    ENDCLASS.
    
    START-OF-SELECTION.
    
    END-OF-SELECTION.
      CALL SCREEN 100.
    *&---------------------------------------------------------------------*
    *&      Module  PBO  OUTPUT
    *&---------------------------------------------------------------------*
    MODULE pbo OUTPUT.
      SET PF-STATUS 'MAIN100'.
      SET TITLEBAR 'MAINTITLE'.
      IF g_alv_tree IS INITIAL.
        PERFORM init_tree.
        CALL METHOD cl_gui_cfw=>flush
          EXCEPTIONS
            cntl_system_error = 1
            cntl_error        = 2.
      ENDIF.
    ENDMODULE.                             " PBO  OUTPUT
    *&---------------------------------------------------------------------*
    *&      Module  PAI  INPUT
    *&---------------------------------------------------------------------*
    *       process after input
    *----------------------------------------------------------------------*
    MODULE pai INPUT.
      save_ok = ok_code.
      CLEAR ok_code.
      CASE save_ok.
        WHEN 'EXIT' OR 'BACK' OR 'CANC'.
          PERFORM exit_program.
        WHEN OTHERS.
          CALL METHOD cl_gui_cfw=>dispatch.
      ENDCASE.
      CALL METHOD cl_gui_cfw=>flush.
    ENDMODULE.                             " PAI  INPUT
    *&---------------------------------------------------------------------*
    *&      Form  init_tree
    *&---------------------------------------------------------------------*
    FORM init_tree.
    * create container for alv-tree
      DATA: l_tree_container_name(30) TYPE c.
      l_tree_container_name = 'CCONTAINER1'.
      CREATE OBJECT g_custom_container
        EXPORTING
          container_name              = l_tree_container_name.
      IF sy-subrc <> 0.
        MESSAGE x208(00) WITH 'ERROR'(100).
      ENDIF.
    * create tree control
      CREATE OBJECT g_alv_tree
        EXPORTING
          parent                      = g_custom_container
          node_selection_mode         = cl_gui_column_tree=>node_sel_mode_single
          item_selection              = ' '
          no_html_header              = 'X'
          no_toolbar                  = ''.
      IF sy-subrc <> 0.
        MESSAGE x208(00) WITH 'ERROR'.                          "#EC NOTEXT
      ENDIF.
      DATA l_hierarchy_header TYPE treev_hhdr.
      l_hierarchy_header-width = 35.
      PERFORM build_fieldcatalog.
      CALL METHOD g_alv_tree->set_table_for_first_display
        EXPORTING
          is_hierarchy_header = l_hierarchy_header
        CHANGING
          it_fieldcatalog     = gt_fieldcatalog
          it_outtab           = gt_sflight.
      PERFORM define_dnd_behaviour.
      PERFORM create_hierarchy.
      PERFORM register_events.
      CALL METHOD g_alv_tree->update_calculations.
      CALL METHOD g_alv_tree->frontend_update.
    ENDFORM.                               " init_tree
    
    FORM register_events.
      DATA: lt_events        TYPE cntl_simple_events,
            l_event_receiver TYPE REF TO lcl_event_receiver.
      CALL METHOD g_alv_tree->get_registered_events
        IMPORTING
          events = lt_events.
      CALL METHOD g_alv_tree->set_registered_events
        EXPORTING
          events                    = lt_events.
      IF sy-subrc <> 0.
        MESSAGE x208(00) WITH 'ERROR'.                          "#EC NOTEXT
      ENDIF.
      CREATE OBJECT l_event_receiver.
      SET HANDLER l_event_receiver->on_drop FOR g_alv_tree.
      SET HANDLER l_event_receiver->on_drag FOR g_alv_tree.
    ENDFORM.                               " register_events
    *&---------------------------------------------------------------------*
    *&      Form  exit_program
    *&---------------------------------------------------------------------*
    *       free object and leave program
    *----------------------------------------------------------------------*
    FORM exit_program.
      CALL METHOD g_custom_container->free.
      LEAVE PROGRAM.
    ENDFORM.                               " exit_program
    *--------------------------------------------------------------------
    FORM build_fieldcatalog.
      CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
        EXPORTING
          i_structure_name = 'SFLIGHT'
        CHANGING
          ct_fieldcat      = gt_fieldcatalog.
    ENDFORM.                               " build_fieldcatalog
    *&---------------------------------------------------------------------*
    *&      Form  create_hierarchy
    *&---------------------------------------------------------------------*
    FORM create_hierarchy.
      DATA: ls_sflight       TYPE sflight,
            lt_sflight       TYPE TABLE OF sflight INITIAL SIZE 0,
            l_yyyymm         TYPE c LENGTH 8,            "year and month of sflight-fldate
            l_yyyymm_last(6) TYPE c,
            l_carrid         LIKE sflight-carrid,
            l_carrid_last    LIKE sflight-carrid.
      DATA: l_month_key   TYPE lvc_nkey,
            l_carrid_key  TYPE lvc_nkey,
            l_last_key    TYPE lvc_nkey,
            l_top_key     TYPE lvc_nkey,
            l_layout_node TYPE lvc_s_layn.
    * Select data
      SELECT * FROM sflight INTO TABLE lt_sflight UP TO g_max ROWS.
    * sort table according to conceived hierarchy
      SORT lt_sflight BY fldate+0(6) carrid fldate+6(2).
    
      PERFORM make_drop CHANGING l_layout_node.
    
      CALL METHOD g_alv_tree->add_node
        EXPORTING
          i_relat_node_key = ''
          i_relationship   = cl_gui_column_tree=>relat_last_child
          i_node_text      = text-050
          is_node_layout   = l_layout_node
        IMPORTING
          e_new_node_key   = l_top_key.
    
      g_top_key = l_top_key.
    
      LOOP AT lt_sflight INTO ls_sflight.
        l_yyyymm = ls_sflight-fldate+0(6).
        l_carrid = ls_sflight-carrid.
        IF l_yyyymm <> l_yyyymm_last.      "on change of l_yyyymm
          l_yyyymm_last = l_yyyymm.
    * month nodes
          PERFORM add_month USING l_yyyymm
                                                        l_top_key
                                                        cl_gui_column_tree=>relat_last_child
                                 CHANGING l_month_key.
    * The month changed, thus, there is no predecessor carrier
          CLEAR l_carrid_last.
        ENDIF.
    * Carrier nodes:
        IF l_carrid <> l_carrid_last.      "on change of l_carrid
          l_carrid_last = l_carrid.
          PERFORM add_carrid_line USING    ls_sflight
                                                                 l_month_key
                                                                 cl_gui_column_tree=>relat_last_child
                                  CHANGING l_carrid_key.
        ENDIF.
    * Leaf:
        PERFORM add_complete_line USING  ls_sflight
                                         l_carrid_key
                                CHANGING l_last_key.
      ENDLOOP.
    
      CALL METHOD g_alv_tree->expand_node
        EXPORTING
          i_node_key = l_top_key.
    ENDFORM.                               " create_hierarchy
    *&---------------------------------------------------------------------*
    *&      Form  add_month
    *&---------------------------------------------------------------------*
    FORM add_month  USING     p_yyyymm TYPE clike
                                                 p_relat_key TYPE lvc_nkey
                                                 p_relationship TYPE int4
                             CHANGING  p_node_key TYPE lvc_nkey.
      DATA: l_node_text   TYPE lvc_value,
            ls_sflight    TYPE sflight,
            l_month       TYPE c LENGTH 25,
            l_layout_node TYPE lvc_s_layn.
      IF p_yyyymm CO ' 0123456789'.
        p_yyyymm = p_yyyymm && '01'.
        CALL FUNCTION 'CONVERSION_EXIT_LDATE_OUTPUT'
          EXPORTING
            input  = p_yyyymm
          IMPORTING
            output = l_month.
        REPLACE REGEX `(\d\d\.\s)([[:alpha:]]*)(\s\d{4})` IN l_month WITH '$2'.
        l_node_text = p_yyyymm(4) && `/` && l_month.
      ELSE.
        l_node_text = p_yyyymm.
      ENDIF.
    
      PERFORM make_drag CHANGING l_layout_node.
    * add node
      CALL METHOD g_alv_tree->add_node
        EXPORTING
          i_relat_node_key = p_relat_key
          i_relationship   = p_relationship
          i_node_text      = l_node_text
          is_outtab_line   = ls_sflight
          is_node_layout   = l_layout_node
        IMPORTING
          e_new_node_key   = p_node_key.
    ENDFORM.                               " add_month
    *-----------------------------------------------------------------------
    FORM add_carrid_line USING     ps_sflight TYPE sflight
                                                      p_relat_key TYPE lvc_nkey
                                                      p_relationship TYPE int4
                         CHANGING  p_node_key TYPE lvc_nkey.
      DATA: l_node_text   TYPE lvc_value,
            ls_sflight    TYPE sflight,
            l_layout_node TYPE lvc_s_layn.
    
      l_node_text =  ps_sflight-carrid.
      CALL METHOD g_alv_tree->add_node
        EXPORTING
          i_relat_node_key = p_relat_key
          i_relationship   = p_relationship
          i_node_text      = l_node_text
          is_outtab_line   = ls_sflight
          is_node_layout   = l_layout_node
        IMPORTING
          e_new_node_key   = p_node_key.
    ENDFORM.                               " add_carrid_line
    *&---------------------------------------------------------------------*
    *&      Form  add_complete_line
    *&---------------------------------------------------------------------*
    FORM add_complete_line USING   ps_sflight TYPE sflight
                                   p_relat_key TYPE lvc_nkey
                         CHANGING  p_node_key TYPE lvc_nkey.
      DATA: l_node_text   TYPE lvc_value,
            l_layout_node TYPE lvc_s_layn.
      WRITE ps_sflight-fldate TO l_node_text MM/DD/YYYY.
      CALL METHOD g_alv_tree->add_node
        EXPORTING
          i_relat_node_key = p_relat_key
          i_relationship   = cl_gui_column_tree=>relat_last_child
          is_outtab_line   = ps_sflight
          i_node_text      = l_node_text
          is_node_layout   = l_layout_node
        IMPORTING
          e_new_node_key   = p_node_key.
    ENDFORM.                               " add_complete_line
    
    FORM define_dnd_behaviour.
      DATA: effect TYPE i.
      CREATE OBJECT g_drag_behaviour.
      effect = cl_dragdrop=>move.
      CALL METHOD g_drag_behaviour->add
        EXPORTING
          flavor     = 'default'                  "#EC NOTEXT
          dragsrc    = 'X'
          droptarget = ' '
          effect     = effect.
      CREATE OBJECT g_drop_behaviour.
      effect = cl_dragdrop=>move.
      CALL METHOD g_drop_behaviour->add
        EXPORTING
          flavor     = 'default'                  "#EC NOTEXT
          dragsrc    = ' '
          droptarget = 'X'
          effect     = effect.
    ENDFORM.                    " DEFINE_DND_BEHAVIOUR
    
    FORM delete_node.
      DATA: lt_selected_nodes TYPE lvc_t_nkey,
            l_selected_node   TYPE lvc_nkey.
      CALL METHOD g_alv_tree->get_selected_nodes
        CHANGING
          ct_selected_nodes = lt_selected_nodes.
      CALL METHOD cl_gui_cfw=>flush.
      READ TABLE lt_selected_nodes INTO l_selected_node INDEX 1.
      IF sy-subrc EQ 0.
        CALL METHOD g_alv_tree->delete_subtree
          EXPORTING
            i_node_key = l_selected_node.
        CALL METHOD g_alv_tree->frontend_update.
      ELSE. "sy-subrc EQ 0
        MESSAGE i000(0k) WITH 'Please select a node.'(900).
      ENDIF.
    ENDFORM.
    
    FORM make_drag CHANGING p_layout_node TYPE lvc_s_layn.
      DATA l_handle_line TYPE i.
      CALL METHOD g_drag_behaviour->get_handle
        IMPORTING
          handle = l_handle_line.
      p_layout_node-dragdropid = l_handle_line.
    ENDFORM.
    
    FORM make_drop CHANGING p_layout_node TYPE lvc_s_layn.
      DATA l_handle_line TYPE i.
      CALL METHOD g_drop_behaviour->get_handle
        IMPORTING
          handle = l_handle_line.
      p_layout_node-dragdropid = l_handle_line.
    ENDFORM.
    

    在上面的示例中,月份可以拖放到根航班节点上。将它们拖到它上面时,拖动节点在层次结构中的位置变为第一位。这不是你问的行为,但是!通过 N 对话框,您可以将任何节点放置在该级别层次结构中的任何位置。

    可以通过 BCALV_TREE _ * 模式找到更多有用的DND示例。

答案 1 :(得分:0)

CL_GUI_ALV_TREE实现了经典的Control Framework拖放功能(参见concept in the SAP Library)。

它允许在任何其他节点上删除任何节点(无论级别如何),但不能在其自身上删除节点。这是通过为每个节点提供允许拖放的行为来实现的。

以下是最小程序,以便快速了解实现基本拖放操作所需的内容。我不移动节点,因为它不是特定于拖放操作的(例如,使用方法MOVE_NODE)。 SFLIGHT表必须通过运行程序SAPBC_DATA_GENERATOR来填充。注意:我不建议像我一样编写代码,它只是一个演示程序,而应像@Suncatcher的程序那样做。

REPORT.
CLASS lcl_app DEFINITION.
  PUBLIC SECTION.
    METHODS at_selection_screen_output.
    METHODS at_selection_screen_exit.
  PRIVATE SECTION.
    METHODS on_drag FOR EVENT on_drag OF cl_gui_alv_tree
      IMPORTING sender node_key drag_drop_object.
    METHODS on_drop FOR EVENT on_drop OF cl_gui_alv_tree
      IMPORTING sender node_key drag_drop_object.
    DATA: g_alv_tree TYPE REF TO cl_gui_alv_tree,
          gt_sflight TYPE TABLE OF sflight,
          dragged    TYPE sflight.
ENDCLASS.

CLASS lcl_app IMPLEMENTATION.

  METHOD at_selection_screen_output.
    DATA lt_fieldcatalog TYPE lvc_t_fcat.

    IF g_alv_tree IS INITIAL.
      g_alv_tree = NEW #( parent              = cl_gui_container=>screen0
                          node_selection_mode = cl_gui_column_tree=>node_sel_mode_single ).

      CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
        EXPORTING
          i_structure_name = 'SFLIGHT'
        CHANGING
          ct_fieldcat      = lt_fieldcatalog.

      g_alv_tree->set_table_for_first_display(
        EXPORTING is_hierarchy_header = VALUE #( width = 35 )
        CHANGING  it_fieldcatalog     = lt_fieldcatalog
                  it_outtab           = gt_sflight ).

      SET HANDLER on_drop FOR g_alv_tree.
      SET HANDLER on_drag FOR g_alv_tree.

      DATA(dnd_move_source_target) = NEW cl_dragdrop( ).
      dnd_move_source_target->add(
          flavor     = 'SINGLE'
          dragsrc    = abap_true
          droptarget = abap_true
          effect     = cl_dragdrop=>move ).
      dnd_move_source_target->get_handle( IMPORTING handle = DATA(dnd_move_source_target_id) ).

      SELECT * FROM sflight INTO TABLE @DATA(lt_sflight).
      LOOP AT lt_sflight ASSIGNING FIELD-SYMBOL(<ls_sflight>).
        g_alv_tree->add_node(
          EXPORTING i_relat_node_key = ''
                    i_relationship   = cl_gui_column_tree=>relat_last_child
                    i_node_text      = |{ <ls_sflight>-carrid }-{ <ls_sflight>-connid }-{ <ls_sflight>-fldate }|
                    is_outtab_line   = <ls_sflight>
                    is_node_layout   = VALUE #( dragdropid = dnd_move_source_target_id ) ).
      ENDLOOP.

      g_alv_tree->frontend_update( ).
    ENDIF.
  ENDMETHOD.

  METHOD at_selection_screen_exit.
    cl_gui_container=>screen0->free( ).
  ENDMETHOD.

  METHOD on_drag.

    sender->get_outtab_line(
      EXPORTING i_node_key    = node_key
      IMPORTING e_outtab_line = dragged ).

    drag_drop_object->object = me. " must be bound to trigger drop event when user drops

  ENDMETHOD.

  METHOD on_drop.
    DATA dropped TYPE sflight.

    sender->get_outtab_line(
      EXPORTING i_node_key    = node_key
      IMPORTING e_outtab_line = dropped ).

    MESSAGE |{ dragged-carrid }-{ dragged-connid }-{ dragged-fldate
            } dropped on { dropped-carrid }-{ dropped-connid }-{ dropped-fldate }| TYPE 'I'.

  ENDMETHOD.

ENDCLASS.

PARAMETERS dummy.
DATA go_app TYPE REF TO lcl_app.

LOAD-OF-PROGRAM.
  CREATE OBJECT go_app.

AT SELECTION-SCREEN OUTPUT.
  go_app->at_selection_screen_output( ).

AT SELECTION-SCREEN ON EXIT-COMMAND.
  go_app->at_selection_screen_exit( ).