**1、应用场景**
当创建报表遇到行转列,或根据查询到的数据来确定显示ALV列时,可以使用动态内表,在运行 时 确定列数。
本实例,当查询的采购订单时,根据每个采购订单最大的行数,作为要显示的最大列,将每个采购订单的行,一列一列的显示,而不是一行行显示。
### **2、代码详解**
1、查询数据,获取采购订单,获取这批数据的采购订单最多有多少行,将来就要展示多少列
"-----------------------------@斌将军-----------------------------FORM frm_get_data.
DATA:lv_count TYPE i.
SELECT ebeln ebelp matnr"物料 FROM ekpo INTO TABLE gt_alv WHERE ebeln IN s_ebeln.
IF gt_alv IS NOT INITIAL. SORT gt_alv BY ebeln ebelp. "判断最大的列 CLEAR:gv_line. LOOP AT gt_alv INTO DATA(ls_alv). CLEAR:gs_alv. gs_alv = ls_alv. lv_count = lv_count + 1. AT END OF ebeln. IF gv_line < lv_count. gv_line = lv_count. ENDIF. CLEAR:lv_count. ENDAT. ENDLOOP. ELSE. MESSAGE '没有数据' TYPE 'S' DISPLAY LIKE 'E'. STOP. ENDIF.ENDFORM. " FRM_GET_DATA"-----------------------------@斌将军-----------------------------
"-----------------------------@斌将军----------------------------- init_fill_fcat 'CHECKBOX' '状态栏' '' '' '' '' '' '' ''. init_fill_fcat 'EBELN' '采购订单' '' '' '' '' '' 'X' ''. "循环最多行项目的行数 DO gv_line TIMES. CLEAR:lv_fieldname. lv_fieldname = 'EBELP' && sy-index. init_fill_fcat lv_fieldname '行号' '' '' '' '' '' 'X' ''.
CLEAR:lv_fieldname. lv_fieldname = 'MATNR' && sy-index. init_fill_fcat lv_fieldname '物料编号' '' '' '' '' '' 'X' ''. ENDDO."-----------------------------@斌将军-----------------------------
"-----------------------------@斌将军----------------------------- CALL METHOD cl_alv_table_create=>create_dynamic_table EXPORTING it_fieldcatalog = gt_fieldcat IMPORTING ep_table = dy_table." 用表类型指针 <dyn_table> 指向 数据对象的内容. ASSIGN dy_table->* TO <dyn_alv>. " 建立一个与动态内表结构相同的数据对象,且数据对象为是一个结构 CREATE DATA gs_line LIKE LINE OF <dyn_alv>. ASSIGN gs_line->* TO <dyn_wa>. " 用<dyn_wa>指针指向该结构"-----------------------------@斌将军-----------------------------
"-----------------------------@斌将军-----------------------------CLEAR:lv_count. LOOP AT gt_alv INTO DATA(ls_alv). CLEAR:gs_alv. gs_alv = ls_alv. MOVE-CORRESPONDING gs_alv TO <dyn_wa>.
lv_count = lv_count + 1.
CLEAR:lv_fieldname. lv_fieldname = 'EBELP' && lv_count. CONDENSE lv_fieldname NO-GAPS. ASSIGN COMPONENT lv_fieldname OF STRUCTURE <dyn_wa> TO <dyn_field>. IF sy-subrc EQ 0. <dyn_field> = gs_alv-ebelp. ENDIF.
CLEAR:lv_fieldname. lv_fieldname = 'MATNR' && lv_count. CONDENSE lv_fieldname NO-GAPS. ASSIGN COMPONENT lv_fieldname OF STRUCTURE <dyn_wa> TO <dyn_field>. IF sy-subrc EQ 0. <dyn_field> = gs_alv-matnr. ENDIF.AT END OF ebeln. APPEND <dyn_wa> TO <dyn_alv>. CLEAR:<dyn_wa>. CLEAR:lv_count. ENDAT. CLEAR:ls_alv. ENDLOOP.
"-----------------------------@斌将军-----------------------------
5、为了获取选择框的列需要在fieldcat中添加,因为又在layout中声明了,所以要将fieldcat中的选择框去掉
"-----------------------------@斌将军----------------------------- "在layout中已经定义,不需要在fieldcat中定义 DELETE gt_fieldcat WHERE fieldname = 'CHECKBOX'.
"-----------------------------@斌将军-----------------------------
"-----------------------------@斌将军----------------------------- "针对动态内表排序 ls_sort-name = 'EBELN'. ls_sort-descending = ''. APPEND ls_sort TO lt_sort. SORT <dyn_alv> BY (lt_sort)."-----------------------------@斌将军-----------------------------
### **3、效果展示**
### **4、源代码**
"-----------------------------@斌将军-----------------------REPORT ylcctest039.
*&----------------------------------------------------------**表声明*&----------------------------------------------------------*TABLES:sscrfields,ekpo."
*&----------------------------------------------------------**类型池声明*&----------------------------------------------------------*TYPE-POOLS:slis.
*&----------------------------------------------------------** 类型定义*&----------------------------------------------------------*
TYPES:BEGIN OF ty_alv, ebeln TYPE ekpo-ebeln, "采购凭证编号 ebelp TYPE ekpo-ebelp, "采购凭证编行号 matnr TYPE ekpo-matnr, "物料checkbox TYPE char1, "复选框 END OF ty_alv.
*&----------------------------------------------------------** 声明内表和工作区*&----------------------------------------------------------*DATA:gt_alv TYPE STANDARD TABLE OF ty_alv, gs_alv TYPE ty_alv.
DATA:gv_line TYPE i.
DATA:dy_table TYPE REF TO data, gs_line TYPE REF TO data.FIELD-SYMBOLS:<dyn_alv> TYPE STANDARD TABLE, <dyn_wa>, <dyn_field>.*&----------------------------------------------------------**ALV参数声明*&----------------------------------------------------------*
DATA: gt_fieldcat TYPE lvc_t_fcat, "字段目录内表 gs_fieldcat TYPE lvc_s_fcat, "字段目录工作区 gs_layout TYPE lvc_s_layo. "用于定义ALV表单的相关格式、属性*&----------------------------------------------------------**选 择 屏 幕 定 义 块*&----------------------------------------------------------*SELECTION-SCREEN BEGIN OF BLOCK blk0 WITH FRAME TITLE TEXT-001. SELECT-OPTIONS:s_ebeln FOR ekpo-ebeln."采购凭证编号SELECTION-SCREEN END OF BLOCK blk0.
*&----------------------------------------------------------**& AT SELECTION-SCREEN OUTPUT:在屏幕输出前*&----------------------------------------------------------*AT SELECTION-SCREEN OUTPUT.* LOOP AT SCREEN.* IF SCREEN-GROUP1 = 'S'.* IF P_HTCS = 'X'.* IF SCREEN-GROUP1 = 'S'.* SCREEN-ACTIVE = '0'.* ENDIF.* ELSE.* IF SCREEN-GROUP1 = 'S'.* SCREEN-ACTIVE = '1'.* ENDIF.* ENDIF.* ENDIF.** IF SCREEN-NAME = 'P_WERKS'.* SCREEN-REQUIRED = '2'."外观上打钩必输,但不自动校验* ENDIF.* MODIFY SCREEN.*ENDLOOP.*&----------------------------------------------------------** ALV逻辑流*&----------------------------------------------------------*START-OF-SELECTION.
"屏幕检查 PERFORM frm_check_srceen.
"权限检查 PERFORM frm_check_authority.
"获取取数 PERFORM frm_get_data.
"设置字段属性 PERFORM frm_set_fieldcat.
"设置输出格式 PERFORM frm_set_layout.
"创建动态内表 PERFORM frm_create_table.
"显示ALV PERFORM frm_display_alv.
*&----------------------------------------------------------**& Form FRM_CHECK_SRCEEN*&----------------------------------------------------------** text 检查必输字段*&----------------------------------------------------------*FORM frm_check_srceen.ENDFORM.
*&----------------------------------------------------------**& Form FRM_CHECK_AUTHORITY*&----------------------------------------------------------** text 权限检查*&----------------------------------------------------------*FORM frm_check_authority.* DATA:LV_MESSAGE TYPE CHAR200.** AUTHORITY-CHECK OBJECT 'M_MSEG_WMB' ID 'WERKS' FIELD P_WERKS.* IF SY-SUBRC <> 0.* CONCATENATE '你没有' P_WERKS '工厂的权限' INTO LV_MESSAGE.* MESSAGE LV_MESSAGE TYPE 'S' DISPLAY LIKE 'E'.* STOP.* ENDIF.ENDFORM.
*&----------------------------------------------------------**& Form FRM_GET_DATA*&----------------------------------------------------------** text 获取数据*&----------------------------------------------------------*FORM frm_get_data.
DATA:lv_count TYPE i.
SELECT ebeln ebelp matnr"物料 FROM ekpo INTO TABLE gt_alv WHERE ebeln IN s_ebeln...