一个简单的动态内表应用实例

这个报表实现的效果是子选择界面中选择要显示的列(此程序为月份),内表会动态的形成需要的结构并输出在ALV中。

REPORT ysun_fs_001.
*&---------------------------------------------------------------------*
*&  ysun_fs_001_top
*&---------------------------------------------------------------------*
"ZSUN_ICOME_01
DATA: gt_income TYPE TABLE OF zsun_icome_01,
      gs_income TYPE zsun_icome_01.

"FIELDCAT
DATA:gt_fieldcat TYPE lvc_t_fcat,
     gs_fieldcat TYPE lvc_s_fcat.

RANGES r_month FOR gs_income-zmonth .

DATA gv_fieldname   TYPE c LENGTH 20 .
DATA gv_description TYPE c LENGTH 20 .
DATA gv_number      TYPE i .
DATA gv_low         TYPE c LENGTH 2 .

"动态内表字段符号
FIELD-SYMBOLS :<ft_vb>     TYPE STANDARD TABLE,  "内表
               <fs_vb>     TYPE any,             "结构
               <dyn_field> TYPE any.             "字段

" ADD FIELDCAT
DATA gv_pos TYPE i .
DEFINE %%add_fieldcat .
  CLEAR gs_fieldcat.
  gv_pos = gv_pos + 1.
  gs_fieldcat-col_pos    = gv_pos .
  gs_fieldcat-fieldname  = &1 .
  gs_fieldcat-scrtext_m  = &2 .
  gs_fieldcat-cfieldname = &3 .
  gs_fieldcat-outputlen  = 15 .
  APPEND gs_fieldcat TO gt_fieldcat .
END-OF-DEFINITION.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
PARAMETERS    :p_year  TYPE zsun_icome_01-zyear OBLIGATORY .                                   "公司代码 1
SELECT-OPTIONS:s_comp  FOR  gs_income-company   OBLIGATORY .                                   "利润中心 1
SELECT-OPTIONS:s_month FOR  gs_income-zmonth    OBLIGATORY .                                   "利润中心 1
SELECTION-SCREEN END   OF BLOCK b1.

*&---------------------------------------------------------------------*
*&  ysun_fs_001_form
*&---------------------------------------------------------------------*
FORM field_symbol_basic .

  "一般类型
  FIELD-SYMBOLS : <fs_field>    TYPE any , "任意变量/结构
                  <fs_field_02>  ,
                  <fs_table>    TYPE ANY TABLE . "任意表

  "完整类型

  TYPES gty_makt TYPE TABLE OF makt.

  FIELD-SYMBOLS : <fs_char> TYPE c,
                  <fs_makt> TYPE makt,
                  "<FS_MAKT01> like line of MAKT,
                  <ft_makt> TYPE gty_makt . "makt类型的内表

  DATA gv_char TYPE c LENGTH 13 VALUE '北京'.
  DATA gv_numc TYPE n LENGTH 10 VALUE '123456'.
  DATA gs_makt TYPE makt.

  "分配变量
  ASSIGN gv_char TO <fs_field>.

  WRITE:/  gv_char,
        / <fs_field>.

  ASSIGN gv_numc TO <fs_field>.

  "分配结构体
  SELECT SINGLE *
    FROM makt
    INTO CORRESPONDING FIELDS OF gs_makt.
  IF sy-subrc = 0 .
    ASSIGN gs_makt TO <fs_field>.
  ELSE.
  ENDIF.
  WRITE: / <fs_field>.

  "分配变量
  ASSIGN gv_char TO <fs_char> .
  WRITE: / <fs_char>.

  "ASSIGN GV_NUMC to <FS_CHAR>.  "类型不匹配

  "分配结构
  ASSIGN gs_makt TO <fs_makt> .
  WRITE: / <fs_makt>-matnr , <fs_makt>-maktx .

  "动态指定
  DATA: gv_char01 TYPE c LENGTH 10 VALUE 'A',
        gv_char02 TYPE c LENGTH 10 VALUE 'B',
        gv_char03 TYPE c LENGTH 10 VALUE 'C',
        gv_char04 TYPE c LENGTH 10 VALUE 'D',
        gv_char05 TYPE c LENGTH 10 VALUE 'E',
        gv_char06 TYPE c LENGTH 10 VALUE 'F',
        gv_char07 TYPE c LENGTH 10 VALUE 'G',
        gv_char08 TYPE c LENGTH 10 VALUE 'H',
        gv_char09 TYPE c LENGTH 10 VALUE 'I'.

  DATA gv_index TYPE n LENGTH 2.

  DATA gv_fieldname TYPE c LENGTH 30. "放置变量的名称

  gv_fieldname = 'GV_CHAR' .

  ASSIGN (gv_fieldname) TO <fs_field> . "动态指定,用小括号表示变量的值

  WRITE : / <fs_field>.

  DO 9 TIMES.
    gv_index = sy-index .
    CONCATENATE 'GV_CHAR' gv_index INTO gv_fieldname.
    ASSIGN (gv_fieldname) TO <fs_field> .
    WRITE : / gv_index, ':',<fs_field>.
  ENDDO.

  "结构体GS_MAKT通过FS进行输出
  "ASSIGN GS_MAKT to <FS_FIELD>.
  ASSIGN COMPONENT 'MATNR' OF STRUCTURE gs_makt TO <fs_field>."通过字段名分配
  WRITE : / <fs_field>.

  ASSIGN COMPONENT 1 OF STRUCTURE gs_makt TO <fs_field>."通过字段号分配
  WRITE : / <fs_field>.

  DO 5 TIMES.
    ASSIGN COMPONENT sy-index OF STRUCTURE gs_makt TO <fs_field>."通过字段号分配
    WRITE :/ sy-index,':',  <fs_field>.
  ENDDO.

  "结构体GS_MAKT字段 动态分配
  gv_fieldname = 'MATNR'.
  ASSIGN COMPONENT gv_fieldname OF STRUCTURE gs_makt TO <fs_field>.
  IF <fs_field> IS ASSIGNED.
    WRITE:/ <fs_field>.
  ENDIF.

  "fs_field 一般类型
  "fs_field makt类型
  ASSIGN gs_makt TO <fs_makt> .
  WRITE:/ <fs_makt>-matnr.

  "一般定义的 field symbois 不能够直接使用组件
  "ASSIGN gs_makt to <FS_FIELD> .
  "WRITE:/ <FS_FIELD>-MATNR.

  ASSIGN COMPONENT 'MATNR'OF STRUCTURE <fs_field> TO <fs_field_02>.
  WRITE:/ <fs_field_02>.

  gv_fieldname = 'MATNR'.
  ASSIGN COMPONENT gv_fieldname OF STRUCTURE <fs_field> TO <fs_field_02>.
  WRITE:/ <fs_field_02>.

  "强制类型转换
  ASSIGN gv_numc TO <fs_char> CASTING .
  "ASSIGN GV_NUMC TO <FS_FIELD> CASTING TYPE GTY_MAKT.

  TYPES: BEGIN OF gty_score,
           name  TYPE c LENGTH 4,
           score TYPE n LENGTH 3,
         END OF gty_score.

  gv_char = 'ABCD100'.

  ASSIGN gv_char TO <fs_field_02> CASTING TYPE gty_score .
  DO 2 TIMES.
    ASSIGN COMPONENT sy-index OF STRUCTURE <fs_field_02> TO <fs_field>.
    WRITE:/ <fs_field>.
  ENDDO.

  TYPES :BEGIN OF gty_col,
           col1 TYPE c LENGTH 5,
           col2 TYPE c LENGTH 10,
           col3 TYPE c LENGTH 15,
         END OF gty_col.

  DATA gs_col TYPE gty_col.

  gs_col-col1 = 'CHINA' .
  gs_col-col2 = 'BEIJING' .
  gs_col-col3 = 'GREAT WALL'.

  ASSIGN gs_col TO <fs_field_02> CASTING TYPE gty_col.

  "方法1 使用行编号分配
  WRITE:/ '使用行编号分配'.
  DO 3 TIMES.
    ASSIGN COMPONENT sy-index OF STRUCTURE <fs_field_02> TO <fs_field> .
    WRITE:/ <fs_field>.
  ENDDO.

  "方法2 使用字段名分配
  DATA gv_index01 TYPE n LENGTH 1.

  WRITE:/ '使用字段名分配'.

  DO 3 TIMES.
    CLEAR :gv_index01,gv_fieldname.
    gv_index01 = sy-index .
    CONCATENATE 'COL' gv_index01 INTO gv_fieldname.
    ASSIGN COMPONENT gv_fieldname OF STRUCTURE <fs_field_02> TO <fs_field> .
    WRITE:/ <fs_field>.
  ENDDO.

  "分配-内表
  DATA gt_makt TYPE TABLE OF makt .

  SELECT *
    FROM makt
    INTO CORRESPONDING FIELDS OF TABLE gt_makt
      UP TO 10 ROWS
   WHERE spras = sy-langu.
  FIELD-SYMBOLS <fs_wa> TYPE any .

  "向一般类型的字段符号分配
  ASSIGN gt_makt TO <fs_table>.
  "ASSIGN GT_MAKT TO <FS_FIELD>.类型都要参照 any table
  LOOP AT <fs_table> ASSIGNING <fs_field_02>.

  ENDLOOP.

  "向特定类型
  ASSIGN gt_makt TO <ft_makt>.

  "内表的读取
  READ TABLE <ft_makt> ASSIGNING <fs_wa> INDEX 1. "使用索引
  IF  sy-subrc = 0.
    ASSIGN COMPONENT 'MATNR' OF STRUCTURE <fs_wa> TO <fs_field>.
    WRITE:/ <fs_field>.
  ENDIF.

  READ TABLE <ft_makt> ASSIGNING <fs_wa> WITH KEY mandt = '400'. "使用索引
  IF  sy-subrc = 0.
    ASSIGN COMPONENT 'MANDT' OF STRUCTURE <fs_wa> TO <fs_field>.
    WRITE:/ <fs_field> ,/.
  ENDIF.

  "内表读取 一般类型
  "READ TABLE <FS_TABLE> ASSIGNING <FS_WA> INDEX 1. "any table 不能使用索引
  "READ TABLE <FS_FIELD> ASSIGNING <FS_WA> WITH KEY MANDT = '400'. "any table 不能直接指明某一个字段
  gv_fieldname = 'MANDT'.
  READ TABLE <fs_table> ASSIGNING <fs_wa> WITH KEY (gv_fieldname) = '400'. "any table 可动态指明某一个字段

  LOOP AT  gt_makt INTO gs_makt.

    IF gs_makt-mandt = '400'.
      gs_makt-mandt  = 'X'.
      MODIFY gt_makt FROM gs_makt.
      CLEAR: gs_makt.
    ENDIF.

  ENDLOOP.

  "FIELD-SYMBOLS : <FS_MAKT> TYPE MAKT.
  LOOP AT  gt_makt ASSIGNING <fs_makt>.

    IF <fs_makt>-mandt = '400'.
      <fs_makt>-mandt  = 'X'.
      "MODIFY GT_MAKT FROM GS_MAKT. LOOP ASSIGNING,不需要FODIFY
      "CLEAR: GS_MAKT.
    ENDIF.

  ENDLOOP.

  DATA: gv_alpha TYPE c VALUE 'A',
        gv_num   TYPE i VALUE 256.
  FIELD-SYMBOLS: <f_s> TYPE x ."定义为十六进制字段符号

  DO 26 TIMES.
    ASSIGN gv_alpha TO <f_s> CASTING. "强制类型转换
    WRITE:gv_alpha.
    <f_s> = <f_s> + gv_num .
  ENDDO.

ENDFORM.                    " FIELD_SYMBOL_BASIC
*&---------------------------------------------------------------------*
*&      Form  GET_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
* 数据获取
FORM get_data .

  SELECT *
    FROM zsun_icome
    INTO CORRESPONDING FIELDS OF TABLE gt_income
   WHERE  zyear   = p_year
     AND  company IN s_comp
     AND  zmonth  IN s_month .

ENDFORM.                    " GET_DATA
*&---------------------------------------------------------------------*
*&      Form  BUILD_RANGE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
* 获取月份数据
FORM build_range .

  r_month[] = s_month[] .

  READ TABLE r_month INDEX 1 .        "读取第一行
  IF sy-subrc = 0.
    IF r_month-option = 'BT'.
      IF r_month-low IS INITIAL .     "只输入高值
        gv_number = r_month-high .
        gv_low    = '01' .
      ELSE.                           "高值低值均输入
        gv_number = r_month-high - r_month-low + 1.   "循环次数
        gv_low    = r_month-low .     "03
      ENDIF.
    ELSEIF r_month-option = 'EQ'.     "只输入单一值
      gv_number   =  1 .
      gv_low      = r_month-low .
    ENDIF.
  ELSEIF r_month[] IS INITIAL.        "从一月份开始
    gv_number     =  12 .
    gv_low        = '01'.
  ENDIF.

ENDFORM.                    " BUILD_RANGE
*&---------------------------------------------------------------------*
*&      Form  BUILD_FIELDCAT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
* 创建 fieldcat
FORM build_fieldcat .

  "1. 公司
  %%add_fieldcat  'COMPANY' '公司' space .

  "2. 年份
  %%add_fieldcat  'ZYEAR'   '年份' space .

  "3. 月份
  DO gv_number TIMES .
    CONCATENATE 'MONTH_' gv_low INTO gv_fieldname .
    CONCATENATE  gv_low  '月份' INTO gv_description .
    %%add_fieldcat  gv_fieldname  gv_description   'WAERS' .
    gv_low = gv_low + 1 .
    " IF LV_INDEX = R_MONTH-HIGH.
    " EXIT .
    " ENDIF.
  ENDDO.

  "4. 货币单位
  %%add_fieldcat  'WAERS' '货币单位' space .

ENDFORM.                    " BUILD_FIELDCAT
*&---------------------------------------------------------------------*
*&      Form  BUILD_FIELDCAT_02
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
* 创建 fieldcat_02
FORM build_fieldcat_02 .

  DATA lv_month TYPE c LENGTH 2 .
  "1. 公司
  %%add_fieldcat  'COMPANY' '公司' space .

  "2. 年份
  %%add_fieldcat  'ZYEAR'   '年份' space .

  "3. 月份
  DO 12 TIMES .
    lv_month = sy-index .
    IF lv_month IN s_month .
      CONCATENATE 'MONTH_' lv_month INTO gv_fieldname .
      CONCATENATE  lv_month  '月份' INTO gv_description .
      %%add_fieldcat  gv_fieldname  gv_description   'WAERS' .
    ENDIF.
  ENDDO.

  "4. 货币单位
  %%add_fieldcat  'WAERS' '货币单位' space .

ENDFORM.                    " BUILD_FIELDCAT_02
*&---------------------------------------------------------------------*
*&      Form  BUILD_DYNMIC_TABLE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
* 创建动态内表
FORM build_dynamic_table . "调用静态方法 :CREATE_DYNAMIC_TABLE

  DATA lt_new_table TYPE REF TO data .
  DATA ls_new_line  TYPE REF TO data .

  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
*     I_STYLE_TABLE             =
      it_fieldcatalog           = gt_fieldcat   "输入FIELDCATALOG 将返回一个动态内表
*     I_LENGTH_IN_BYTE          =
    IMPORTING
      ep_table                  = lt_new_table  "获取返回的动态内表 (类)
*     E_STYLE_FNAME             =
    EXCEPTIONS
      generate_subpool_dir_full = 1
      OTHERS                    = 2.

  IF sy-subrc <> 0.
    EXIT.
* Implement suitable error handling here
  ENDIF.

  ASSIGN lt_new_table->* TO <ft_vb> .     "LT_NEW_TABLE 中的所有都被指向<FT_VB>(动态内表)

  CREATE DATA ls_new_line LIKE LINE OF <ft_vb> .
  ASSIGN ls_new_line->* TO <fs_vb> .      "LS_NEW_LINE 中的所有都被指向<FS_VB> (动态内表结构)


ENDFORM.                    " BUILD_DYNMIC_TABLE
*&---------------------------------------------------------------------*
*&      Form  ADD_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
* 向动态内表增加数据
FORM add_data .

  DATA ls_income TYPE zsun_icome_01 .

  " 首先根据年份,公司 排序
  SORT gt_income BY zyear company .
  LOOP AT gt_income INTO ls_income .
    MOVE-CORRESPONDING ls_income TO gs_income . "AT事件后字段为*需要从 LS_INCOME 转存到 GS_INCOME

    AT NEW company .                  " 当公司变更时 先录入 公司 ,年份 ,货币

      "<FS_VB>-COMPANY = GS_INCOME-COMPANY
      ASSIGN COMPONENT 'COMPANY' OF STRUCTURE <fs_vb> TO <dyn_field> .
      IF sy-subrc = 0 .
        <dyn_field> = gs_income-company .
      ENDIF .

      "<FS_VB>-ZYEAR = GS_INCOME-ZYEAR
      ASSIGN COMPONENT 'ZYEAR'   OF STRUCTURE <fs_vb> TO <dyn_field> .
      IF sy-subrc = 0 .
        <dyn_field> = gs_income-zyear .
      ENDIF.

      "<FS_VB>-WAERS = GS_INCOME-WAERS
      ASSIGN COMPONENT 'WAERS'   OF STRUCTURE <fs_vb> TO <dyn_field> .
      IF sy-subrc = 0 .
        <dyn_field> = gs_income-waers .
      ENDIF .

    ENDAT .

    " 再根据月份的值,把收入写入对应字段(每一行都执行)
    " <FS_VB>-MONTH_XX = GS_INCOME-INCOME
    CONCATENATE 'MONTH_'gs_income-zmonth INTO gv_fieldname .
    ASSIGN COMPONENT gv_fieldname OF STRUCTURE <fs_vb> TO <dyn_field> .
    IF sy-subrc = 0 .
      <dyn_field> = gs_income-income .
    ENDIF .

    AT END OF company .
      " 当公司的值到达最后一行时
      APPEND <fs_vb> TO <ft_vb> .
      CLEAR  <fs_vb> .
    ENDAT .
  ENDLOOP .

ENDFORM.                    " ADD_DATA
*&---------------------------------------------------------------------*
*&      Form  DISPLAY_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
* DISPLAY
FORM display_data .

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
*     I_INTERFACE_CHECK                 = ' '
*     I_BYPASSING_BUFFER                =
*     I_BUFFER_ACTIVE =
*     I_CALLBACK_PROGRAM                = ' '
*     I_CALLBACK_PF_STATUS_SET          = ' '
*     I_CALLBACK_USER_COMMAND           = ' '
*     I_CALLBACK_TOP_OF_PAGE            = ' '
*     I_CALLBACK_HTML_TOP_OF_PAGE       = ' '
*     I_CALLBACK_HTML_END_OF_LIST       = ' '
*     I_STRUCTURE_NAME                  =
*     I_BACKGROUND_ID = ' '
*     I_GRID_TITLE    =
*     I_GRID_SETTINGS =
*     IS_LAYOUT_LVC   =
      it_fieldcat_lvc = gt_fieldcat
*     IT_EXCLUDING    =
*     IT_SPECIAL_GROUPS_LVC             =
*     IT_SORT_LVC     =
*     IT_FILTER_LVC   =
*     IT_HYPERLINK    =
*     IS_SEL_HIDE     =
*     I_DEFAULT       = 'X'
*     I_SAVE          = ' '
*     IS_VARIANT      =
*     IT_EVENTS       =
*     IT_EVENT_EXIT   =
*     IS_PRINT_LVC    =
*     IS_REPREP_ID_LVC                  =
*     I_SCREEN_START_COLUMN             = 0
*     I_SCREEN_START_LINE               = 0
*     I_SCREEN_END_COLUMN               = 0
*     I_SCREEN_END_LINE                 = 0
*     I_HTML_HEIGHT_TOP                 =
*     I_HTML_HEIGHT_END                 =
*     IT_ALV_GRAPHICS =
*     IT_EXCEPT_QINFO_LVC               =
*     IR_SALV_FULLSCREEN_ADAPTER        =
* IMPORTING
*     E_EXIT_CAUSED_BY_CALLER           =
*     ES_EXIT_CAUSED_BY_USER            =
    TABLES
      t_outtab        = <ft_vb>
    EXCEPTIONS
      program_error   = 1
      OTHERS          = 2.
  IF sy-subrc <> 0.
    EXIT .
* Implement suitable error handling here
  ENDIF.


ENDFORM.                    " DISPLAY_DATA

INITIALIZATION.

START-OF-SELECTION.
  PERFORM get_data.             "数据获取
  PERFORM build_range.          "获取月份数据
  PERFORM build_fieldcat_02.    "创建 fieldcat_02
  PERFORM build_dynamic_table.  "创建动态内表
  PERFORM add_data.             "向动态内表增加数据

END-OF-SELECTION.
  PERFORM display_data.       "DISPLAY

实现的效果为:


前台选择1~7月



ALV输出对应的1-7月的数据(表数据是乱建的)


猜你喜欢

转载自blog.csdn.net/Sundam/article/details/78458169