ALV 树

ALV树形结构可以显示多个层级,每个层级在相同的栏位名称下显示。

适用范围:

  1. 一般在输出物料清单等层级结构比较明显的数据时使用,ALV树每格最多支持128个字符。
  2. 不支持格合并,没有过滤的功能,系统标准没有下载功能,需要自己写代码。
  3. 只能显示1000个节点,只支持平面表,不支持多维表。

实现方式:

  1. 创建并绘制屏幕和容器;容器可以不手动绘制,直接指定属性CL_GUI_CONTAINER=>SCREEN0,可全屏显示
  2. 构建栏位名称,可以用宏、PERFORM、或者用函数'LVC_FIELDCATALOG_MERGE'构建
  3. 实例化容器对象,和ALV树控件
  4. CALL METHOD 'SET_TABLE_FOR_FIRST_DISPLAY' 方法
  5. 设置根节点,填充叶节点数据
  6. 注册事件(双击事件/其他)
  7. 更新汇总字段
  8. 前端显示数据

 效果图:

程序的主要架构:

程序代码:

*&---------------------------------------------------------------------*
*& Report  ZAQ_OO_ALV_TREE_TEST
*&
*&---------------------------------------------------------------------*
*&  OO ALV 树
*&
*&---------------------------------------------------------------------*

REPORT ZAQ_OO_ALV_TREE_TEST.

INCLUDE ZAQ_OO_ALV_TREE_TEST_TOP."定义数据类型

INCLUDE ZAQ_OO_ALV_TREE_TEST_CLASS."自定义类

INCLUDE ZAQ_OO_ALV_TREE_TEST_FRM."子例程,子例程FORM一定要放在INCLUDE CLASS后面,因为在实例化对象的时候要用到子例程的类

INCLUDE ZAQ_OO_ALV_TREE_TEST_PBO."PBO事件

INCLUDE ZAQ_OO_ALV_TREE_TEST_PAI."PAI事件

START-OF-SELECTION.
  CALL SCREEN 100.

对应的INCLUDE代码ZAQ_OO_ALV_TREE_TEST_TOP:

*&---------------------------------------------------------------------*
*&  包含                ZAQ_OO_ALV_TREE_TEST_TOP
*&---------------------------------------------------------------------*

TYPES:BEGIN OF GTY_ALV,
    WERKS TYPE MARD-WERKS,"工厂
    LGORT TYPE MARD-LGORT,"库存地点
    MATNR TYPE MARD-MATNR,"物料编码
    MAKTX TYPE MAKT-MAKTX,"物料描述
    LABST TYPE MARD-LABST,"非限制性库存
    MEINS TYPE MARA-MEINS,"基本单位
  END OF GTY_ALV.

DATA GT_ALV        TYPE TABLE OF GTY_ALV.
DATA LT_ALV        TYPE TABLE OF GTY_ALV.
DATA LS_ALV        TYPE GTY_ALV.
DATA LS_NODE       TYPE GTY_ALV.

DATA OK_CODE       TYPE SY-UCOMM."获取100屏幕触发的功能代码
DATA SAVE_CODE     TYPE SY-UCOMM.

DATA LCL_CONTAINER TYPE REF TO CL_GUI_CONTAINER. "容器对象
DATA LCL_ALV_TREE  TYPE REF TO CL_GUI_ALV_TREE.  "ALV树对象


DATA GS_FIELDCAT   TYPE LVC_S_FCAT."ALV字段存储结构
DATA GT_FIELDCAT   TYPE LVC_T_FCAT."ALV字段存储内表

CLASS LCL_HANDLE DEFINITION DEFERRED. "这句代码的意思是,有一个类在后面定义,因为如果没有这句代码,下面那句代码就会失效
DATA  L_EVENT_RECEIVER TYPE REF TO LCL_HANDLE.

对应的INCLUDE代码ZAQ_OO_ALV_TREE_TEST_CLASS:

*&---------------------------------------------------------------------*
*&  包含                ZAQ_OO_ALV_TREE_TEST_CLASS
*&---------------------------------------------------------------------*

CLASS LCL_HANDLE DEFINITION.
  PUBLIC SECTION.
*   定义双击节点事件触发时的处理方法
    METHODS HANDLE_NODE_DCLICK FOR EVENT NODE_DOUBLE_CLICK OF CL_GUI_ALV_TREE
                                        IMPORTING
                                          NODE_KEY
                                          SENDER.
    "NODE_KEY 双击时双击的节点的位置数
    "其中SENDER这个参数是一个隐式的事件参数,是由ABAP对象运行系统提供,它指向了触发这个事件的实例,可以直接使用它来调用这个实例的方法。
    "说白了,这个SENDER参数指向了CL_GUI_ALV_TREE的实例,可以用SENDER这个参数直接调用CL_GUI_ALV_TREE实例的方法,也就是说这个参数可以直接
    "调用CL_GUI_ALV_TREE这个类的方法,其实这个参数能直接被CL_GUI_ALV_TREE的对象LCL_TREE代替
ENDCLASS.

CLASS LCL_HANDLE IMPLEMENTATION.

* 定义处理方法的具体实施
  METHOD HANDLE_NODE_DCLICK.
    DATA:LT_CHILDREN TYPE LVC_T_NKEY.
    "调用获取节点方法
    CALL METHOD SENDER->GET_CHILDREN
      EXPORTING
        I_NODE_KEY  = NODE_KEY    "双击的节点位置
      IMPORTING
        ET_CHILDREN = LT_CHILDREN."返回节点下的子节点

    IF LT_CHILDREN IS NOT INITIAL."如果子节点不为空展开节点
      "调用展开节点方法
      CALL METHOD SENDER->EXPAND_NODE
        EXPORTING
          I_NODE_KEY    = NODE_KEY "双击节点的位置
          I_LEVEL_COUNT = '2'.     "一次性展开的层数(这个参数表示,当双击的时候,且节点下有值,展开的层数 (如果树为3层结构,那么双击的时候展开2层))
    ENDIF.
  ENDMETHOD.

ENDCLASS.

对应的INCLUDE代码ZAQ_OO_ALV_TREE_TEST_FRM:

*&---------------------------------------------------------------------*
*&  包含                ZAQ_OO_ALV_TREE_TEST_FRM
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&      Form  BUILD_OBJECT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM BUILD_OBJECT .
* 实例化容器对象
*  CREATE OBJECT LCL_CONTAINER
*    EXPORTING
*      CLSID = 'ZCONTAINER'.
  LCL_CONTAINER = CL_GUI_CONTAINER=>SCREEN0."必须是SCREEN0

* 实例化ALV树对象
  CREATE OBJECT LCL_ALV_TREE
    EXPORTING
*     LIFETIME                    =
      PARENT                      = LCL_CONTAINER "将容器对象赋值给树对象
*     SHELLSTYLE                  =
*     NODE_SELECTION_MODE         = CL_GUI_COLUMN_TREE=>NODE_SEL_MODE_SIN
*     HIDE_SELECTION              =
*     ITEM_SELECTION              = 'X'
*     NO_TOOLBAR                  =
*     NO_HTML_HEADER              =
*     I_PRINT                     =
*     I_FCAT_COMPLETE             =
*     I_MODEL_MODE                =
    EXCEPTIONS
      CNTL_ERROR                  = 1
      CNTL_SYSTEM_ERROR           = 2
      CREATE_ERROR                = 3
      LIFETIME_ERROR              = 4
      ILLEGAL_NODE_SELECTION_MODE = 5
      FAILED                      = 6
      ILLEGAL_COLUMN_NAME         = 7
      OTHERS                      = 8.
  IF SY-SUBRC <> 0.
    MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
               WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  ENDIF.

ENDFORM.                    " BUILD_OBJECT
*&---------------------------------------------------------------------*
*&      Form  BUILD_FIELDCAT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM BUILD_FIELDCAT USING P_FIELDNAME TYPE LVC_FNAME
                          P_COLTEXT   TYPE LVC_TXTCOL.

  CLEAR GS_FIELDCAT.
  GS_FIELDCAT-FIELDNAME = P_FIELDNAME.
  GS_FIELDCAT-COLTEXT   = P_COLTEXT.

* 隐藏工厂 / 库存地点 / 物料编码字段,在ALV上不显示
  IF P_FIELDNAME = 'WERKS' OR P_FIELDNAME = 'LGORT' OR P_FIELDNAME = 'MATNR' .
    GS_FIELDCAT-NO_OUT = 'X'.

  ELSEIF P_FIELDNAME       = 'LABST'.
    GS_FIELDCAT-QFIELDNAME = 'MEINS'.
    GS_FIELDCAT-DO_SUM     = 'X'."汇总可用库存字段
    GS_FIELDCAT-H_FTYPE    = 'SUM'.
    GS_FIELDCAT-REF_FIELD  = 'LABST'.
    GS_FIELDCAT-REF_TABLE  = 'MARD'.
    GS_FIELDCAT-OUTPUTLEN  = '30'.
  ELSEIF P_FIELDNAME       = 'MAKTX'.
    GS_FIELDCAT-OUTPUTLEN  = '30'.
  ENDIF.

  APPEND GS_FIELDCAT TO GT_FIELDCAT.

ENDFORM.                    " BUILD_FIELDCAT
*&---------------------------------------------------------------------*
*&      Form  BUILD_ALV
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM BUILD_ALV .

  CALL METHOD LCL_ALV_TREE->SET_TABLE_FOR_FIRST_DISPLAY
*    EXPORTING
*      I_STRUCTURE_NAME     =
*      IS_VARIANT           =
*      I_SAVE               =
*      I_DEFAULT            = 'X'
*      IS_HIERARCHY_HEADER  =
*      IS_EXCEPTION_FIELD   =
*      IT_SPECIAL_GROUPS    =
*      IT_LIST_COMMENTARY   =
*      I_LOGO               =
*      I_BACKGROUND_ID      =
*      IT_TOOLBAR_EXCLUDING =
*      IT_EXCEPT_QINFO      =
    CHANGING
      IT_OUTTAB       = GT_ALV "此表必须一直为空,且为全局变量
*     IT_FILTER       =
      IT_FIELDCATALOG = GT_FIELDCAT.


ENDFORM.                    " BUILD_ALV
*&---------------------------------------------------------------------*
*&      Form  BUILD_HIERARCHY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM BUILD_HIERARCHY .

  DATA: L_LAST_WERKS TYPE MARD-WERKS,
        L_LAST_LGORT TYPE MARD-LGORT.

  DATA: L_WERKS_KEY TYPE LVC_NKEY,
        L_LGORT_KEY TYPE LVC_NKEY,
        L_LAST_KEY  TYPE LVC_NKEY,
        L_TOP_KEY   TYPE LVC_NKEY.

  DATA L_NODE_TEXT TYPE LVC_VALUE.

* 取数
  SELECT D~MATNR
         D~WERKS
         D~LGORT
         D~LABST
         A~MEINS
         T~MAKTX
  INTO CORRESPONDING FIELDS OF TABLE LT_ALV UP TO 200 ROWS
  FROM MARD AS D INNER JOIN MARA AS A
  ON D~MATNR  = A~MATNR
  LEFT OUTER JOIN MAKT AS T
  ON D~MATNR  = T~MATNR
  AND T~SPRAS = SY-LANGU.

* 根据 WERKS LGORT做排序,因为这两个字段说节点区分的字段
  SORT LT_ALV BY WERKS LGORT.

* 添加祖节点
  CALL METHOD LCL_ALV_TREE->ADD_NODE
    EXPORTING
      I_RELAT_NODE_KEY     = '' "因为是祖节点,不存在于任何节点下面
      I_RELATIONSHIP       = CL_GUI_COLUMN_TREE=>RELAT_LAST_CHILD
*     IS_OUTTAB_LINE       =
*     IS_NODE_LAYOUT       =
*     IT_ITEM_LAYOUT       =
      I_NODE_TEXT          = '可用库存' "祖节点描述
    IMPORTING
      E_NEW_NODE_KEY       = L_TOP_KEY  "祖节点标识
    EXCEPTIONS
      RELAT_NODE_NOT_FOUND = 1
      NODE_NOT_FOUND       = 2
      OTHERS               = 3.
  IF SY-SUBRC <> 0.
*    Implement suitable error handling here
  ENDIF.


  "按照工厂->仓库层次设置节点,设置”叶片“,填充"叶片"数据
  LOOP AT LT_ALV INTO LS_ALV.
    "设置工厂节点
    IF L_LAST_WERKS NE LS_ALV-WERKS.
      L_LAST_WERKS = LS_ALV-WERKS.
      "若此次循环到的工厂与上一次不相同,则创造新的工厂节点
      "ADD NODE
      CLEAR L_NODE_TEXT.
      L_NODE_TEXT = LS_ALV-WERKS.
      CALL METHOD LCL_ALV_TREE->ADD_NODE
        EXPORTING
          I_RELAT_NODE_KEY = L_TOP_KEY "处于祖节点之下
          I_RELATIONSHIP   = CL_GUI_COLUMN_TREE=>RELAT_LAST_CHILD
          I_NODE_TEXT      = L_NODE_TEXT "节点描述,把工厂作为节点描述
          IS_OUTTAB_LINE   = LS_NODE     "因为不是最后的节点,不传递数据,所以LS_NODE为空
        IMPORTING
          E_NEW_NODE_KEY   = L_WERKS_KEY. "工厂节点标识
      CLEAR L_LAST_LGORT."当创建新的工厂节点时,清空上一个库存节点
    ENDIF.

*   设置库存节点
    IF L_LAST_LGORT NE  LS_ALV-LGORT.
      L_LAST_LGORT = LS_ALV-LGORT.
      "若此次循环到的库存节点与上一次不相同,则创造新的库存节点
      "ADD NODE
      CLEAR L_NODE_TEXT.
      L_NODE_TEXT = LS_ALV-LGORT.
      CALL METHOD LCL_ALV_TREE->ADD_NODE
        EXPORTING
          I_RELAT_NODE_KEY = L_WERKS_KEY "处于工厂节点之下
          I_RELATIONSHIP   = CL_GUI_COLUMN_TREE=>RELAT_LAST_CHILD
          I_NODE_TEXT      = L_NODE_TEXT "节点描述,把库存地点作为节点描述
          IS_OUTTAB_LINE   = LS_NODE     "因为不是最后的节点,不传递数据,所以LS_NODE为空
        IMPORTING
          E_NEW_NODE_KEY   = L_LGORT_KEY. "库存节点标识
    ENDIF.

    "设置”叶片“,填充"叶片"数据
    CLEAR L_NODE_TEXT.
    L_NODE_TEXT = LS_ALV-MATNR.
    CALL METHOD LCL_ALV_TREE->ADD_NODE
      EXPORTING
        I_RELAT_NODE_KEY = L_LGORT_KEY "处于库存节点之下
        I_RELATIONSHIP   = CL_GUI_COLUMN_TREE=>RELAT_LAST_CHILD
        I_NODE_TEXT      = L_NODE_TEXT "叶片描述:把物料号作为每行数据的叶片描述
        IS_OUTTAB_LINE   = LS_ALV      "有数据
      IMPORTING
        E_NEW_NODE_KEY   = L_LAST_KEY. "叶片节点标识

  ENDLOOP.

ENDFORM.                    " BUILD_HIERARCHY
*&---------------------------------------------------------------------*
*&      Form  REGISTER_EVENTS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM REGISTER_EVENTS .
  "注册前端后后端事件
  DATA: LT_EVENTS        TYPE CNTL_SIMPLE_EVENTS,
        L_EVENT          TYPE CNTL_SIMPLE_EVENT.

*1.获取已注册的前端事件
  CALL METHOD LCL_ALV_TREE->GET_REGISTERED_EVENTS
    IMPORTING
      EVENTS = LT_EVENTS.
  "2.添加前端双击事件
  L_EVENT-EVENTID = CL_GUI_COLUMN_TREE=>EVENTID_NODE_DOUBLE_CLICK.
  APPEND L_EVENT TO LT_EVENTS.

*3.重新设置前端注册事件
  CALL METHOD LCL_ALV_TREE->SET_REGISTERED_EVENTS
    EXPORTING
      EVENTS                    = LT_EVENTS
    EXCEPTIONS
      CNTL_ERROR                = 1
      CNTL_SYSTEM_ERROR         = 2
      ILLEGAL_EVENT_COMBINATION = 3.
  IF SY-SUBRC <> 0.
    MESSAGE E208(00) WITH '注册前端事件失败!'.                      "#EC NOTEXT
  ENDIF.
*--------------------
  "4.注册后端事件
  CREATE OBJECT L_EVENT_RECEIVER.
  SET HANDLER L_EVENT_RECEIVER->HANDLE_NODE_DCLICK FOR LCL_ALV_TREE.
ENDFORM.                    " REGISTER_EVENTS

对应的INCLUDE代码ZAQ_OO_ALV_TREE_TEST_PBO:

*&---------------------------------------------------------------------*
*&  包含                ZAQ_OO_ALV_TREE_TEST_PBO
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&      Module  STATUS_0100  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
  SET PF-STATUS 'STATUS'.
  SET TITLEBAR  'T01'.
ENDMODULE.                 " STATUS_0100  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  INIT_ALV_TREE  OUTPUT
*&---------------------------------------------------------------------*
*       text    初始化ALV树
*----------------------------------------------------------------------*
MODULE INIT_ALV_TREE OUTPUT.

  IF LCL_ALV_TREE IS INITIAL.
*   初始化对象
    PERFORM BUILD_OBJECT.
*   设置ALV字段(FIELDCAT)
    PERFORM BUILD_FIELDCAT USING:'WERKS' '工厂',
                                 'LGORT' '库存地点',
                                 'MATNR' '物料编码',
                                 'MAKTX' '物料描述',
                                 'LABST' '非限制性使用库存',
                                 'MEINS' '数量单位'.
*   显示ALV 树
    PERFORM BUILD_ALV.
*   设置根节点,填充叶节点数据
    PERFORM BUILD_HIERARCHY.
  ENDIF.

  "注册事件
  PERFORM REGISTER_EVENTS.
* 更新汇总字段
  CALL METHOD LCL_ALV_TREE->UPDATE_CALCULATIONS.
* 前端显示数据
  CALL METHOD LCL_ALV_TREE->FRONTEND_UPDATE.

ENDMODULE.                 " INIT_ALV_TREE  OUTPUT

对应的INCLUDE代码ZAQ_OO_ALV_TREE_TEST_PAI:

*&---------------------------------------------------------------------*
*&  包含                ZAQ_OO_ALV_TREE_TEST_PAI
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0100  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.

  SAVE_CODE = OK_CODE.
  CLEAR OK_CODE.

  CASE SAVE_CODE.
    WHEN 'BACK' OR 'CANCEL' OR 'EXIT'.
      LEAVE PROGRAM.
    WHEN '&F12'.
    WHEN OTHERS.
  ENDCASE.

ENDMODULE.                 " USER_COMMAND_0100  INPUT

 本文摘借了其他博主的例子:http://www.cnblogs.com/jianglaizhen/p/8870859.html

 

猜你喜欢

转载自www.cnblogs.com/aqsyc/p/10747611.html
alv