ALV树形结构可以显示多个层级,每个层级在相同的栏位名称下显示。
适用范围:
- 一般在输出物料清单等层级结构比较明显的数据时使用,ALV树每格最多支持128个字符。
- 不支持格合并,没有过滤的功能,系统标准没有下载功能,需要自己写代码。
- 只能显示1000个节点,只支持平面表,不支持多维表。
实现方式:
- 创建并绘制屏幕和容器;容器可以不手动绘制,直接指定属性CL_GUI_CONTAINER=>SCREEN0,可全屏显示
- 构建栏位名称,可以用宏、PERFORM、或者用函数'LVC_FIELDCATALOG_MERGE'构建
- 实例化容器对象,和ALV树控件
- CALL METHOD 'SET_TABLE_FOR_FIRST_DISPLAY' 方法
- 设置根节点,填充叶节点数据
- 注册事件(双击事件/其他)
- 更新汇总字段
- 前端显示数据
效果图:
程序的主要架构:
程序代码:
*&---------------------------------------------------------------------* *& 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:
扫描二维码关注公众号,回复:
5966369 查看本文章
*&---------------------------------------------------------------------* *& 包含 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