动态内表
一、应用场景
当创建报表遇到行转列,或根据查询到的数据,确定显示ALV列时,可以使用动态内表,在运行是确定列数。
本实例,当查询的采购订单时,根据每个采购订单最大的行数,作为要显示的最大列,将每个采购订单的行,一列一列的显示,而不是一行行显示。
二、代码详解
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 "-----------------------------@斌将军-----------------------------
2、通过fieldcat设置报表列
"-----------------------------@斌将军----------------------------- 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. "-----------------------------@斌将军-----------------------------
3、根据fieldcat生成要展示的ALV内表结构
"-----------------------------@斌将军----------------------------- CALL METHOD cl_alv_table_create=>create_dynamic_table EXPORTING it_fieldcatalog = gt_fieldcat IMPORTING ep_table = dy_table. ASSIGN dy_table->* TO <dyn_alv>. " 用表类型指针 <dyn_table> 指向 数据对象的内容. CREATE DATA gs_line LIKE LINE OF <dyn_alv>. " 建立一个与动态内表结构相同的数据对象,且数据对象为是一个结构 ASSIGN gs_line->* TO <dyn_wa>. " 用<dyn_wa>指针指向该结构 "-----------------------------@斌将军-----------------------------
4、根据查询的数据,将行项目和物料对应到每行的列上
"-----------------------------@斌将军----------------------------- 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'. "-----------------------------@斌将军-----------------------------
6、动态内表排序
"-----------------------------@斌将军----------------------------- "针对动态内表排序 ls_sort-name = 'EBELN'. ls_sort-descending = ''. APPEND ls_sort TO lt_sort. SORT <dyn_alv> BY (lt_sort). "-----------------------------@斌将军-----------------------------
三、效果展示
四、源代码
"-----------------------------@斌将军----------------------------- 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. 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 *&---------------------------------------------------------------------* *& Form FRM_SET_FIELDCAT *&---------------------------------------------------------------------* * text 字段属性定义 *----------------------------------------------------------------------* FORM frm_set_fieldcat . REFRESH gt_fieldcat. DEFINE init_fill_fcat. CLEAR gs_fieldcat. gs_fieldcat-fieldname = &1. gs_fieldcat-coltext = &2. gs_fieldcat-scrtext_l = &2. gs_fieldcat-scrtext_m = &2. gs_fieldcat-scrtext_s = &2. gs_fieldcat-reptext = &2. gs_fieldcat-ref_table = &3. gs_fieldcat-ref_field = &4. gs_fieldcat-f4availabl = &5. gs_fieldcat-icon = &6. gs_fieldcat-edit = &7. gs_fieldcat-no_zero = &8. gs_fieldcat-inttype = &9. APPEND gs_fieldcat TO gt_fieldcat. END-OF-DEFINITION. DATA:lv_fieldname TYPE char30. 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. ENDFORM. " FRM_SET_FIELDCAT *&---------------------------------------------------------------------* *& Form FRM_SET_LAYOUT *&---------------------------------------------------------------------* * text 界面格式属性 *----------------------------------------------------------------------* FORM frm_set_layout . CLEAR gs_layout. gs_layout-sel_mode = 'A'. "选择行模式 gs_layout-cwidth_opt = 'A'. "优化列宽设置 gs_layout-zebra = 'X'. "设置斑马线 gs_layout-box_fname = 'CHECKBOX'. ENDFORM. " FRM_SET_LAYOUT *&---------------------------------------------------------------------* *& Form frm_create_table *&---------------------------------------------------------------------* * 创建动态内表 *----------------------------------------------------------------------* FORM frm_create_table. DATA:lt_sort TYPE abap_sortorder_tab, ls_sort TYPE abap_sortorder. DATA:lv_count TYPE i, lv_fieldname TYPE char30, lv_coltext TYPE char40. CALL METHOD cl_alv_table_create=>create_dynamic_table EXPORTING it_fieldcatalog = gt_fieldcat IMPORTING ep_table = dy_table. ASSIGN dy_table->* TO <dyn_alv>. " 用表类型指针 <dyn_table> 指向 数据对象的内容. 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. "在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). ENDFORM. " *&---------------------------------------------------------------------* *& Form FRM_DISPLAY_ALV *&---------------------------------------------------------------------* * text 界面显示 *----------------------------------------------------------------------* FORM frm_display_alv . CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC' EXPORTING i_callback_program = sy-repid is_layout_lvc = gs_layout * i_callback_pf_status_set = 'FRM_SET_STATUS' * i_callback_user_command = 'FRM_USER_COMMAND' it_fieldcat_lvc = gt_fieldcat i_save = 'A' TABLES t_outtab = <dyn_alv> EXCEPTIONS program_error = 1 OTHERS = 2. 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. " FRM_DISPLAY_ALV "-----------------------------@斌将军-----------------------------
定期更文,欢迎关注