ABAP 动态内表模板

********************************************************************
* 事务代码:ZFIR004                                                *
* 程序名称:ZFIR004                                                *
* 程序目的:项目进度表                                             *
* 设 计 人:                                                 *
* 开 发 人:Seele                                                  *
* 设计时间:2022-09-19                                             *
* 程序类型: ABAP/4 程序                                            *
* 应用类型: FI                                                     *
* 描    述: 项目进度表                                             *
*(修改日志)--------------------------------------------------------*
*                                                                  *
* 日志号   修改人  修改时间       修改说明              传输号码   *
*  ----    ----    ------         -----------
*   001    Seele   2022-09-19     创建程序             DS4K900374  *
********************************************************************

REPORT zfir004.

*----------------------------------------------------------------------*
* 数据库表声明/Database table declaration
*----------------------------------------------------------------------*
TABLES:prps.  " WBS(工作中断结构) 元素主数据

*----------------------------------------------------------------------*
* 结构声明类型/Structure type declaration
*----------------------------------------------------------------------*
*&---主表数据/master table data
TYPES:BEGIN OF ty_main,

        posid   TYPE prps-posid,   " WBS元素
        post1   TYPE prps-post1,   " WBS描述
        prart   TYPE prps-prart,   " 项目类型
        txt30   TYPE tj02t-txt30,  " 项目状态
        psphi   TYPE prps-psphi,   " 项目定义
        post1j  TYPE proj-post1,   " 项目定义描述
        fkstl   TYPE prps-fkstl,   " 负责的成本中心
        pbukr   TYPE prps-pbukr,   " 公司代码
        verna   TYPE prps-verna,   " 项目负责人
        wtjhr_y TYPE bpja-wtjhr,   " 预算金额
        wtjhr_x TYPE bpja-wtjhr,   " 已下达预算
        wtjhr_h TYPE bpja-wtjhr,   " 已花费预算
        gjahr   TYPE acdoca-gjahr, " 会计年度
        poper   TYPE acdoca-poper, " 期间
        total   TYPE acdoca-ksl,   " 小计

      END OF ty_main.

TYPES:BEGIN OF ty_config,

      account_name  TYPE zfit004-account_name,  " 成本要素组
      account_from  TYPE zfit004-account_from,  " 从成本要素
      account_to    TYPE zfit004-account_to  ,  " 到成本要素

      END OF ty_config.

TYPES:BEGIN OF ty_acdoca,

*      rldnr     TYPE acdoca-rldnr,     " 分类账
*      rbukrs    TYPE acdoca-rbukrs,    " 公司代码
*      gjahr     TYPE acdoca-gjahr,     " 会计年度
*      belnr     TYPE acdoca-belnr,     " 凭证编号
*      docln     TYPE acdoca-docln,     " 行项目
      ksl       TYPE acdoca-ksl     ,  "
      ps_posid  TYPE acdoca-ps_posid,  " WBS元素
*      ksl       TYPE acdoca-ksl,       " 本币金额

      END OF ty_acdoca.

*     保存内表的字段名称
TYPES:BEGIN OF ty_field,
        fieldnm TYPE txt30,
      END OF ty_field.

*----------------------------------------------------------------------*
* 全局变量定义/Global variable definition
*----------------------------------------------------------------------*
*&---全局内表定义
DATA:gt_main   TYPE STANDARD TABLE OF ty_main.  " 主数据表
DATA:gt_config TYPE STANDARD TABLE OF ty_config.  " 配置表
DATA:gt_acdoca TYPE STANDARD TABLE OF ty_acdoca.
DATA:gt_field  TYPE STANDARD TABLE OF ty_field.  " 动态内表字段列表
DATA:gr_toutput TYPE REF TO data,         " 动态内表
     gr_soutput TYPE REF TO data.         " 动态工作区


*&---全局结构定义
DATA:gs_main TYPE ty_main.           " 主数据结构
DATA:gs_config TYPE ty_config.           " 配置表结构
DATA:gs_acdoca TYPE ty_acdoca.            " 合计

*&---------------------------------------------------------------------*
*& 字段串定义/Field-symbols                                            *
*&---------------------------------------------------------------------*
FIELD-SYMBOLS:<fs_main>    TYPE ty_main,
              <fs_toutput>  TYPE table, " ALV动态内表
              <fs_soutput>  TYPE ANY,   " ALV动态工作区
              <fs_foutput>  TYPE ANY.   " ALV动态表头

*&---------------------------------------------------------------------*
*&  ALV TYPE/ALV 类型定义
*&---------------------------------------------------------------------*
*&---ALV数据组,类型池
TYPE-POOLS:slis,
           vrm.

*&---定义ALV显示的字段列及其描述等属性
DATA:gt_fieldcat TYPE STANDARD TABLE OF lvc_s_fcat, " ALV 控制: 字段目录
     gs_fieldcat TYPE lvc_s_fcat,          " ALV 控制: 字段目录
     gs_layout   TYPE lvc_s_layo.          " ALV 控制: 布局结构

*&---------------------------------------------------------------------*
*&  Macro 宏定义
*&---------------------------------------------------------------------*
DEFINE mcr_set_catalog.
  gs_fieldcat-fieldname  = &1. " 字段技术名称
  gs_fieldcat-coltext    = &2. " 显示名称
  gs_fieldcat-ref_table  = &3. " 参照表
  gs_fieldcat-ref_field  = &4. " 参照表字段
  gs_fieldcat-qfieldname = &5. " 参考计量单位的字段名称
  gs_fieldcat-key        = &6. " key 值
  gs_fieldcat-edit       = &7. " 可编辑

  APPEND gs_fieldcat TO gt_fieldcat.
  CLEAR  gs_fieldcat.
END-OF-DEFINITION.

*&---------------------------------------------------------------------*
*& Selection Screen/选择屏幕
*&---------------------------------------------------------------------*
*&---选择屏幕块
SELECTION-SCREEN BEGIN OF BLOCK blk01 WITH FRAME TITLE TEXT-101.

*&---范围
  SELECT-OPTIONS:s_pbukr FOR prps-pbukr,  " 公司代码
                 s_posid FOR prps-posid.  " WBS元素

*&---单值
  PARAMETERS:p_gjahr LIKE acdoca-gjahr OBLIGATORY DEFAULT sy-datum+0(4), " 会计年度
             p_poper LIKE acdoca-poper OBLIGATORY DEFAULT sy-datum+4(2). " 期间

SELECTION-SCREEN END OF BLOCK blk01.

*&---------------------------------------------------------------------*
*& Start-of-selection/开始选择屏幕                                     *
*&---------------------------------------------------------------------*
START-OF-SELECTION.
*&---内表数据获取

  PERFORM frm_get_data.

  IF gt_main IS INITIAL.
    MESSAGE s001(zfi001). " 未查找到符合条件的数据
    EXIT.
  ENDIF.

*&---------------------------------------------------------------------*
*& end-of-selection/结束选择屏幕(程序结束处理,输出等)               *
*&---------------------------------------------------------------------*
END-OF-SELECTION.

*&===ALV 输出
*&---设置ALV输出格式
  PERFORM frm_init_layout.
*&---设置ALV输出字段
  PERFORM frm_set_fieldcat.
*&---设置
*&---ALV 显示
  PERFORM frm_display_alv.

*&---------------------------------------------------------------------*
*&      Form  frm_get_data
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_10     text
*----------------------------------------------------------------------*
FORM frm_get_data.
  FREE:gt_main.
*&---获取主数据表内容PRPS PROJ

  SELECT
    prps~posid,  " WBS元素
    prps~post1,  " WBS描述
    prps~prart,  " 项目类型
    prps~psphi,  " 项目定义
    prps~fkstl,  " 负责的成本中心
    prps~pbukr,  " 公司代码
    prps~verna,  " 项目负责人
    prps~objnr,  " 对象编号
    proj~post1 AS post1j   " 项目定义描述
  FROM prps
    LEFT JOIN proj   ON prps~pspnr = proj~pspnr
  WHERE
    prps~pbukr IN @s_pbukr AND
    prps~posid IN @s_posid
  INTO TABLE @DATA(lt_data).

*&---主数据表为空则终止取数
  IF sy-subrc <> 0.
    EXIT.
  ENDIF.

*&---主数据表属性信息获取
  IF lt_data IS NOT INITIAL.

*&---项目状态
    SELECT
      tj02t~txt30,  " 项目状态
      jest~stat,    " 对象状态
      jest~objnr    " 对象编号
    FROM jest
      LEFT JOIN tj02t ON jest~stat = tj02t~istat
    FOR ALL ENTRIES IN @lt_data
    WHERE
      jest~stat IN ( 'I0001','I0002','I0045','I0046','I0076' ) AND
      tj02t~spras = @sy-langu AND
      jest~objnr  = @lt_data-objnr
    INTO TABLE @DATA(lt_jest).
    SORT lt_jest BY objnr.

*&---预算金额 已下达预算 已花费预算
    SELECT
      objnr, " 对象编号
      wrttp, " 值类型
      wtjhr  " 业务货币中的年度值
    FROM bpja
    FOR ALL ENTRIES IN @lt_data
    WHERE
      objnr = @lt_data-objnr AND
      wrttp IN ( '41','45','42' )
    INTO TABLE @DATA(lt_bpja).
    SORT lt_bpja BY objnr wrttp.

  ENDIF.

*&---主表数据组织
*&---循环内表,赋值物料组,物料描述
  LOOP AT lt_data INTO DATA(ls_data).
*&---初始化
    CLEAR gs_main.

*&---赋值主数据
    MOVE-CORRESPONDING ls_data TO gs_main.
    gs_main-gjahr = p_gjahr.
    gs_main-poper = p_poper.

*&---赋值项目状态
    READ TABLE lt_jest INTO DATA(ls_jest) WITH KEY objnr = ls_data-objnr BINARY SEARCH.
    IF sy-subrc = 0.
      MOVE-CORRESPONDING ls_jest TO gs_main.
    ENDIF.

*&---赋值预算金额
    READ TABLE lt_bpja INTO DATA(ls_bpja) WITH KEY objnr = ls_data-objnr wrttp = '41' BINARY SEARCH.
    IF sy-subrc = 0.
      gs_main-wtjhr_y = ls_bpja-wtjhr.
    ENDIF.

*&---赋值已下达预算
    READ TABLE lt_bpja INTO ls_bpja WITH KEY objnr = ls_data-objnr wrttp = '45' BINARY SEARCH.
    IF sy-subrc = 0.
      gs_main-wtjhr_x = ls_bpja-wtjhr.
    ENDIF.

*&---赋值已花费预算
    READ TABLE lt_bpja INTO ls_bpja WITH KEY objnr = ls_data-objnr wrttp = '42' BINARY SEARCH.
    IF sy-subrc = 0.
      gs_main-wtjhr_h = ls_bpja-wtjhr.
    ENDIF.

    APPEND gs_main TO gt_main.
  ENDLOOP.
  SORT gt_main BY posid.

ENDFORM.                    " frm_get_data
*&---------------------------------------------------------------------*
*&      Form  frm_init_layout
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_init_layout .
  CLEAR gs_layout.
  gs_layout-zebra      = 'X' .    " 斑马线
  gs_layout-cwidth_opt = 'X' .    " 自动调整ALVL列宽
  gs_layout-sel_mode   = 'A' .    " 选择行列
ENDFORM.                    " frm_init_layout
*&---------------------------------------------------------------------*
*&      Form  frm_fieldcat
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_set_fieldcat .
  DATA: lt_key TYPE STANDARD TABLE OF ty_config.
  DATA: lv_fieldname TYPE string.
  DATA: lr_descr TYPE REF TO cl_abap_structdescr.

*&---配置表中取出动态表头
  SELECT
    account_name
    account_from
    account_to
  FROM zfit004
  INTO CORRESPONDING FIELDS OF TABLE gt_config.
  SORT gt_config BY account_name.

  lt_key = gt_config.
  DELETE ADJACENT DUPLICATES FROM lt_key COMPARING account_name.

*&---ALV 输出字段目录,涉及字段必须大写
  mcr_set_catalog: 'POSID'   TEXT-A01    'PRPS'   'POSID'   '' 'X' '',       " WBS元素
                   'POST1'   TEXT-A02    'PRPS'   'POST1'   '' 'X' '',       " WBS描述
                   'PRART'   TEXT-A03    'PRPS'   'PRART'   '' ''  '',       " 项目类型
                   'TXT30'   TEXT-A04    'TJ02T'  'TXT30'   '' ''  '',       " 项目状态
                   'PSPHI'   TEXT-A05    'PRPS'   'PSPHI'   '' ''  '',       " 项目定义
                   'POST1J'  TEXT-A06    'PROJ'   'POST1'   '' ''  '',        " 项目定义描述
                   'FKSTL'   TEXT-A07    'PRPS'   'FKSTL'   '' ''  '',       " 负责的成本中心
                   'PBUKR'   TEXT-A08    'PRPS'   'PBUKR'   '' ''  '',       " 公司代码
                   'VERNA'   TEXT-A09    'PRPS'   'VERNA'   '' ''  '',       " 项目负责人
                   'WTJHR_Y' TEXT-A10    'BPJA'   'WTJHR'   '' ''  '',       " 预算金额
                   'WTJHR_X' TEXT-A11    'BPJA'   'WTJHR'   '' ''  '',       " 已下达预算
                   'WTJHR_H' TEXT-A12    'BPJA'   'WTJHR'   '' ''  '',       " 已花费预算
                   'GJAHR'   TEXT-A13    'ACDOCA' 'GJAHR'   '' ''  '',       " 会计年度
                   'POPER'   TEXT-A14    'ACDOCA' 'POPER'   '' ''  ''.       " 期间
*                   'KSL'     TEXT-A16    'ACDOCA' 'KSL'     '' ''  ''.       " 本币金额

*&---ALV 增加动态表头
  LOOP AT lt_key INTO gs_config.
    lv_fieldname = 'KSL' && sy-tabix.
    mcr_set_catalog:  lv_fieldname   gs_config-account_name   'ACDOCA'   'KSL' '' '' ''.       " 成本要素组-->本币金额
  ENDLOOP.
  mcr_set_catalog: 'TOTAL'   TEXT-A15    'ACDOCA' 'KSL'     '' ''  ''.       " 小计

*&---创建动态内表
  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = gt_fieldcat
    IMPORTING
      ep_table        = gr_toutput.


  ASSIGN gr_toutput->* TO <fs_toutput>. " 分配生成的内表地址给指针
  CREATE DATA gr_soutput LIKE LINE OF <fs_toutput>.
  ASSIGN gr_soutput->* TO <fs_soutput>. " 分配生成的工作区地址给指针

  PERFORM frm_process_data.

ENDFORM.                    " frm_fieldcat

*&---------------------------------------------------------------------*
*&      Form  frm_display_alv
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_display_alv .
*&---ALV 显示函数
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program       = sy-repid
      is_layout_lvc            = gs_layout
      it_fieldcat_lvc          = gt_fieldcat[]
      i_callback_pf_status_set = 'FRM_USER_STATUS'
      i_default                = 'X'
      i_save                   = 'A'
    TABLES
      t_outtab                 = <fs_toutput>
    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

*&---------------------------------------------------------------------*
*&      Form  frm_user_status
*&---------------------------------------------------------------------*
*       设置用户菜单栏状态
*----------------------------------------------------------------------*
*  -->  pt_extab        需要排除的菜单按钮
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_user_status USING ps_extab TYPE slis_t_extab.  "GUI
  SET PF-STATUS 'STATUS_1000' EXCLUDING ps_extab.
ENDFORM.

*&---------------------------------------------------------------------*
*& Form frm_process_data
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_process_data .

  RANGES lr_racct FOR acdoca-racct.
  DATA: lv_fieldname TYPE string,
        lv_tabix  TYPE i,
        lv_count  TYPE i, " 动态内表字段计数(只针对科目余额)
        ls_rracct LIKE LINE OF lr_racct,
        lt_key    TYPE STANDARD TABLE OF ty_config,
        lt_acdoca TYPE STANDARD TABLE OF ty_acdoca.
  FIELD-SYMBOLS: <fs_ksl>   TYPE ANY,
                 <fs_total> TYPE ANY.

*&---主数据转移至动态内表
  SORT gt_main BY posid.
  LOOP AT gt_main INTO gs_main.
    MOVE-CORRESPONDING gs_main TO <fs_soutput>.
    APPEND <fs_soutput> TO <fs_toutput>.
  ENDLOOP.

*&---汇总相同类型行项目
  lt_key = gt_config.
  SORT lt_key BY account_name.
  SORT gt_config BY account_name.
  DELETE ADJACENT DUPLICATES FROM lt_key COMPARING account_name.

*&---汇总科目余额相同的区间至range
  LOOP AT lt_key INTO DATA(ls_key).
    READ TABLE gt_config TRANSPORTING NO FIELDS WITH KEY account_name = ls_key-account_name BINARY SEARCH.
    IF sy-subrc = 0.
      lv_tabix = sy-tabix.
      CLEAR lr_racct[].

      LOOP AT gt_config INTO gs_config FROM lv_tabix.
        IF gs_config-account_name <> ls_key-account_name.
          EXIT.
        ENDIF.

        CLEAR ls_rracct.
        ls_rracct-low  = gs_config-account_from.
        ls_rracct-high = gs_config-account_to.
        ls_rracct-option = 'BT'.
        ls_rracct-sign = 'I'.

        APPEND ls_rracct TO lr_racct.
      ENDLOOP.
    ENDIF.

*---根据range获取表动态内表数据
    lv_count = lv_count + 1.

    SELECT
      rldnr   ,
      rbukrs  ,
      gjahr   ,
      belnr   ,
      docln   ,
      ps_posid,
      ksl     ,
      ksl
    FROM acdoca
    FOR ALL ENTRIES IN @gt_main
    WHERE
      ps_posid = @gt_main-posid  AND
      rbukrs   = @gt_main-pbukr  AND
      poper    = @p_poper        AND
      gjahr    = @p_gjahr        AND
      racct    IN @lr_racct
    INTO CORRESPONDING FIELDS OF TABLE @lt_acdoca.

    CLEAR gt_acdoca.
    LOOP AT lt_acdoca INTO DATA(ls_acdoca).
      MOVE-CORRESPONDING ls_acdoca TO gs_acdoca.
      COLLECT gs_acdoca INTO gt_acdoca.
    ENDLOOP.


*---根据变量名<fs_soutput>-ksl*动态给成本要素组赋值
    LOOP AT gt_acdoca INTO ls_acdoca.
      READ TABLE gt_main TRANSPORTING NO FIELDS WITH KEY posid = ls_acdoca-ps_posid BINARY SEARCH.
      IF sy-subrc = 0.
        lv_tabix = sy-tabix.
        MOVE-CORRESPONDING ls_acdoca TO <FS_SOUTPUT>.
        READ TABLE <fs_toutput> ASSIGNING <fs_soutput> INDEX lv_tabix. " <fs_toutput> 和 gt_main 具有相同的顺序,所以直接取对应位置
        IF sy-subrc = 0.
          lv_fieldname = '<FS_SOUTPUT>-' && 'KSL' && lv_count.
          ASSIGN (lv_fieldname) TO <fs_ksl>.  " 静态编译,将动态内表ksl*的值赋值给<fs_ksl>
          <fs_ksl> = ls_acdoca-ksl.           " 操作<fs_ksl>就等同于操作<fs_soutput>-ksl*
          lv_fieldname = '<FS_SOUTPUT>-TOTAL'.
          ASSIGN (lv_fieldname) TO <fs_total>.
          <fs_total> = <fs_total> + ls_acdoca-ksl. " 合计
        ENDIF.
      ENDIF.
    ENDLOOP.
  ENDLOOP.

ENDFORM.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值