ABAP 动态列表(动态ALV)超简单实际案例,模板


一、项目背景。

  研发需要有个报表来对账,

汇总时,alv后面的标题是用RD项目号来做标题,所以这里需要用到动态列表。前两列的数据是固定的,后面可能改。

 然后是明细显示(参考KOB1,但有不同,KOB1是参考凭证,有物料凭证和会计凭证等,主要以成本元素为主,从COVP视图取数。

实际是需要会计凭证号,所以直接关联ACDOCA和AUFK)

 还有订单和RD号的对应关系,一个RD号可对应多个订单。

二、解决方案

  1、先在KO03增加了个字段(RD号,ZRDTXT),在结构CI_AUFK中增加ZRDTXT,然后直接在屏幕上画。

验证

   2、开发报表

  动态列表部分可以直接看汇总部分,主要用到cl_alv_table_create=>create_dynamic_table创建动态列表,

其它都有注释,建议直接看程序,可把AUFK-ZRDTXT替换成其它字段后,直接保存调试。

ZFICOR055

*&---------------------------------------------------------------------*
*& Report ZFICOR055
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zficor055.

INCLUDE zficor055_head.
INCLUDE zficor055_screen.
INCLUDE zficor055_form.

START-OF-SELECTION.
  IF r1 EQ 'X'."委外清单明细
    PERFORM frm_check_auth.
    IF lv_auth EQ 'X'.
      MESSAGE lv_msg TYPE 'S' DISPLAY LIKE 'E'.
      RETURN.
    ENDIF.
    PERFORM frm_get_data."获取明细
  ENDIF.

  IF r2 EQ 'X'."汇总
    PERFORM frm_check_auth.
    IF lv_auth EQ 'X'.
      MESSAGE lv_msg TYPE 'S' DISPLAY LIKE 'E'.
      RETURN.
    ENDIF.
    PERFORM frm_get_data."获取明细
    PERFORM frm_get_data3."创建结构
    PERFORM frm_get_data4."获取数据
  ENDIF.

  IF r3 EQ 'X'."委外清单明细
    PERFORM frm_check_auth.
    IF lv_auth EQ 'X'.
      MESSAGE lv_msg TYPE 'S' DISPLAY LIKE 'E'.
      RETURN.
    ENDIF.
    PERFORM frm_get_data2.
  ENDIF.

END-OF-SELECTION.
  PERFORM f_display_data.

包含文件ZFICOR055_HEAD

*&---------------------------------------------------------------------*
*& 包含               ZFICOR055_HEAD
*&---------------------------------------------------------------------*
TABLES:sscrfields,aufk,acdoca.
DATA: d_ref      TYPE REF TO data,
      d_ref2     TYPE REF TO data,
      lt_alv_cat TYPE TABLE OF lvc_s_fcat,
      ls_alv_cat LIKE LINE OF lt_alv_cat.

DATA: lt_table LIKE TABLE OF dntab.
DATA: ls_table TYPE dntab.

DATA: dyn_table TYPE REF TO data.
DATA: dyn_wa TYPE REF TO data.
FIELD-SYMBOLS : TYPE table,
                   TYPE any,
                TYPE any,
                   TYPE any,
                  TYPE any.


DATA: dyn_table2 TYPE REF TO data.
DATA: dyn_wa2 TYPE REF TO data.


FIELD-SYMBOLS : TYPE table,
                   TYPE any,
                TYPE any,
                   TYPE any.
DATA: go_excel    TYPE ole2_object,
      go_workbook TYPE ole2_object,
      go_sheet    TYPE ole2_object.
DATA: gs_layout   TYPE lvc_s_layo,
      gt_fieldcat TYPE lvc_t_fcat.

TYPES: BEGIN OF sy_output.
    INCLUDE STRUCTURE zficos055a. "ALV显示
TYPES:
  zcolor(4),
  message   TYPE char200, "
*  cellcolor TYPE lvc_t_scol,
  zsel      TYPE c,
  slbox,
  END OF sy_output.

DATA: gt_output  TYPE TABLE OF sy_output,
      gt_output2 TYPE TABLE OF sy_output,
      gs_output  TYPE sy_output.


DATA: BEGIN OF gs_vbpa,
        vbeln TYPE vbpa-vbeln,
        posnr TYPE vbpa-posnr,
        parvw TYPE vbpa-parvw,
        kunnr TYPE vbpa-kunnr,
      END OF gs_vbpa.
DATA: gt_vbpa LIKE TABLE OF gs_vbpa.
DATA: gt_zficot054_1 LIKE TABLE OF zficot054_1.
*DATA: gt_zficot054_2 LIKE TABLE OF zficot054_2.
RANGES: r_fkdat FOR vbrk-fkdat.

TYPES: BEGIN OF sy_output3.
    INCLUDE STRUCTURE zficos055b. "ALV显示
TYPES:
  zcolor(4),
  message   TYPE char200, "
*       cellcolor TYPE lvc_t_scol,
  zsel      TYPE c,
  slbox,
  END OF sy_output3.

DATA: gt_output3 TYPE TABLE OF sy_output3,
      gt_output4 TYPE TABLE OF sy_output3,
      gs_output3 TYPE sy_output3.


DATA: lv_auth TYPE c,
      lv_msg  TYPE bapi_msg.
CONSTANTS: c_x TYPE c VALUE 'X'.
DATA: flag(1).

DATA: p_param TYPE char5.

TYPES: BEGIN OF sy_node,
         mnode TYPE tv_nodekey, "母节点
         znode TYPE tv_nodekey, "自身节点
         zstr1 TYPE skat-txt50, "文本1
         txt50 TYPE skat-txt50, "科目文本
         zstr3 TYPE string, "科目范围
       END OF sy_node.
DATA: gt_node TYPE TABLE OF sy_node,
      gs_node TYPE sy_node.
RANGES: gr_racct FOR acdoca-racct."科目

DATA: BEGIN OF gs_zrdtxt,
        zrdtxt TYPE zficos055a-zrdtxt,
        racct  TYPE zficos055a-racct,
*        txt50  TYPE zficos055a-txt50,
        hsl    TYPE zficos055a-hsl,
      END OF gs_zrdtxt.
DATA: gt_zrdtxt  LIKE TABLE OF gs_zrdtxt,
      gt_zrdtxt2 LIKE TABLE OF gs_zrdtxt.
DATA: lv_num       TYPE sy-tabix.
DATA: lv_fieldname TYPE lvc_s_fcat-fieldname.

包含文件ZFICOR055_SCREEN

*&---------------------------------------------------------------------*
*& 包含               ZFICOR055_SCREEN
*&---------------------------------------------------------------------*
SELECTION-SCREEN: BEGIN OF BLOCK b01 WITH FRAME TITLE TEXT-001.
*PARAMETERS: p_name TYPE dd03l-tabname OBLIGATORY.
*PARAMETERS: p_file1 TYPE string MODIF ID m0."线下(导入)
*
*PARAMETERS: p_file2 TYPE string MODIF ID m1."线上(导入)
*
*PARAMETERS: p_bukrs TYPE bseg-bukrs MODIF ID m2, "公司代码
*            p_gjahr TYPE bseg-gjahr MODIF ID m2,
*            p_monat TYPE bseg-h_monat MODIF ID m2,
*            p_budat TYPE bseg-h_budat MODIF ID m2,
*            p_bktxt TYPE bkpf-bktxt MODIF ID m2.
**            p_werks TYPE bseg-werks MODIF ID m2. "工厂
**            r1      RADIOBUTTON GROUP g1.
PARAMETERS: p_bukrs TYPE acdoca-rbukrs MODIF ID m0 DEFAULT '1000'."公司代码

SELECT-OPTIONS: s_gjahr FOR acdoca-gjahr MODIF ID m1 DEFAULT sy-datum+0(4), "年度
                s_poper FOR acdoca-poper MODIF ID m1, "期间
                s_racct FOR acdoca-racct MODIF ID m1,"科目
                s_aufnr FOR aufk-aufnr MODIF ID m0,"订单
                s_rdtxt FOR aufk-zrdtxt MODIF ID m0,"RD描述
                s_erdat FOR aufk-erdat MODIF ID m0,"订单创建日期
                s_ernam FOR aufk-ernam MODIF ID m0."订单创建人
*                s_budat FOR bseg-h_budat MODIF ID m4."过账日期
*                s_erdat FOR zficot053-erdat MODIF ID m4,
*                s_kunnr FOR kna1-kunnr MODIF ID m1,
*                s_vtweg FOR vbak-vtweg MODIF ID m1.

*SELECTION-SCREEN: FUNCTION KEY 1.
*SELECTION-SCREEN: FUNCTION KEY 2.
SELECTION-SCREEN: END OF BLOCK b01.

SELECTION-SCREEN: BEGIN OF BLOCK b02 WITH FRAME TITLE TEXT-002.
*PARAMETERS: p_name TYPE dd03l-tabname OBLIGATORY.
*PARAMETERS: p_file2 TYPE string MODIF ID m2.
PARAMETERS:
*            r0 RADIOBUTTON GROUP g1 USER-COMMAND u1,
  r1 RADIOBUTTON GROUP g1 USER-COMMAND u1,
  r2 RADIOBUTTON GROUP g1,
  r3 RADIOBUTTON GROUP g1.
*            r3 RADIOBUTTON GROUP g1,
*            r4 RADIOBUTTON GROUP g1,
*            r5 RADIOBUTTON GROUP g1.
*SELECTION-SCREEN: FUNCTION KEY 1.
SELECTION-SCREEN: END OF BLOCK b02.

包含文件ZFICOR055_FORM

 实际效果:
*&---------------------------------------------------------------------*
*& 包含               ZFICOR055_FORM
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form FRM_CHECK_AUTH
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_check_auth .
*  IF r1 EQ 'X'.
  SELECT bukrs
    INTO TABLE @DATA(lt_t001)
    FROM t001
   WHERE bukrs EQ @p_bukrs..
  LOOP AT lt_t001 INTO DATA(ls_t001).
    AUTHORITY-CHECK OBJECT 'ZHL_AUTHOR'
        ID 'ZBUKRS' FIELD ls_t001-bukrs.
    IF sy-subrc NE 0.
      lv_msg = |您没有该公司代码{ ls_t001-bukrs }的权限,如有需求,请联系信息部|.
      lv_auth = 'X'.
    ENDIF.
  ENDLOOP.
*  ENDIF.
*  IF p_yearm IS INITIAL.
*    lv_msg = |请填写'年/月'|.
*    lv_auth = 'X'.
*  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_DATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_data.

  SELECT a~aufnr,a~ktext,a~zrdtxt,
         b~belnr,b~gjahr,b~rbukrs,b~buzei,b~budat,b~racct,b~hsl,b~msl,b~runit,b~sgtxt
    INTO CORRESPONDING FIELDS OF TABLE @gt_output
    FROM aufk AS a JOIN acdoca AS b ON a~aufnr EQ b~aufnr
   WHERE a~aufnr IN @s_aufnr
     AND a~auart EQ 'Z100'
     AND a~zrdtxt IN @s_rdtxt
     AND a~ernam IN @s_ernam
     AND a~erdat IN @s_erdat
     AND b~rbukrs EQ @p_bukrs
     AND b~gjahr IN @s_gjahr
     AND b~poper IN @s_poper
     AND b~racct IN @s_racct
     AND b~racct not in ('0069999999','0022020900').

  IF gt_output[] IS NOT INITIAL.
    SELECT *
      INTO TABLE @DATA(lt_skat)
      FROM skat
       FOR ALL ENTRIES IN @gt_output
     WHERE saknr EQ @gt_output-racct
       AND spras EQ @sy-langu
       AND ktopl EQ 'HL00'.
    SORT lt_skat[] BY saknr.
  ENDIF.

  LOOP AT gt_output ASSIGNING FIELD-SYMBOL().
    READ TABLE lt_skat INTO DATA(ls_skat) WITH KEY saknr = -racct BINARY SEARCH.
    IF sy-subrc EQ 0.
      -txt50 = ls_skat-txt50."总账科目长文本
    ENDIF.
  ENDLOOP.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form F_DISPLAY_DATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM f_display_data .
  PERFORM f_set_layout.
  IF r1 EQ 'X'.
    PERFORM f_set_fieldcat USING 'ZFICOS055A'.
    PERFORM f_alv_display TABLES gt_output.
  ELSEIF r2 EQ 'X'.
    DELETE lt_alv_cat WHERE fieldname EQ 'MNODE'.
    DELETE lt_alv_cat WHERE fieldname EQ 'ZNODE'.
    PERFORM f_alv_display TABLES .
  ELSEIF r3 EQ 'X'.
    PERFORM f_set_fieldcat USING 'ZFICOS055B'.
    PERFORM f_alv_display TABLES gt_output3.
  ENDIF.
ENDFORM.

FORM f_set_layout.
  CLEAR: gs_layout.
*  IF r0 EQ 'X'.
  IF r2 EQ ''.
    gs_layout-box_fname = 'SLBOX'.
  ENDIF.

*    gs_layout-ctab_fname = 'CELLCOLOR'.
*  ENDIF.
  gs_layout-zebra = 'X'.
  gs_layout-cwidth_opt = 'X'.

ENDFORM.
FORM f_set_fieldcat USING i_tabname TYPE dntab-tabname.
*取出表结构的字段目录

  CALL FUNCTION 'NAMETAB_GET'
    EXPORTING
      langu          = sy-langu
      tabname        = i_tabname
    TABLES
      nametab        = lt_table
    EXCEPTIONS
      no_texts_found = 1.
*根据取出的字段目录生成参考字段目录

  CLEAR lt_alv_cat.

*内表创建

*  CALL METHOD cl_alv_table_create=>create_dynamic_table
*    EXPORTING
*      it_fieldcatalog = lt_alv_cat
*    IMPORTING
*      ep_table        = d_ref.
*
*
**指定生成的内表到字段符号
*  ASSIGN d_ref->* TO .
*
**创建动态工作区结构
*  CREATE DATA dyn_wa LIKE LINE OF .
*
**创建动态工作区
*  ASSIGN dyn_wa->* TO .

* zcolor


  DATA: ls_fieldcat TYPE lvc_s_fcat.
  DEFINE set_fieldcat.
    CLEAR: ls_fieldcat.
    ls_fieldcat-fieldname = &1.
    ls_fieldcat-ref_field = &2.
    ls_fieldcat-ref_table = &3.
    ls_fieldcat-edit  = &4.
    ls_fieldcat-checkbox    = &5.
    ls_fieldcat-seltext   = &6.
    ls_fieldcat-scrtext_l = &6.
    ls_fieldcat-scrtext_m = &6.
    ls_fieldcat-scrtext_s = &6.
    ls_fieldcat-coltext   = &6.
    APPEND ls_fieldcat TO lt_alv_cat.
  END-OF-DEFINITION.
*显示内容
*  set_fieldcat 'ZSEL'      ''      ''     'X' 'X'  '选择'.
*  set_fieldcat 'ZCOLOR'    ''      ''     '' ''  '更新结果'.
*  set_fieldcat 'MESSAGE'   ''      ''     '' ''  '更新信息'.
*  set_fieldcat 'INV'       'VBELN' 'VBRK' '' ''  '发票号'.


  LOOP AT lt_table INTO ls_table.
*    IF LS_TABLE-FIELDNAME NE 'MANDT'.
    ls_alv_cat-fieldname = ls_table-fieldname.
    ls_alv_cat-ref_table = i_tabname.
    ls_alv_cat-ref_field = ls_table-fieldname.
    IF ls_table-fieldname EQ 'MEINS' OR ls_table-fieldname EQ 'KMEIN'.
      ls_alv_cat-no_convext = 'X'.
*      CLEAR: ls_alv_cat-ref_field,ls_alv_cat-ref_table.
    ENDIF.
    ls_alv_cat-seltext   = ls_table-fieldtext.
    ls_alv_cat-scrtext_l = ls_table-fieldtext.
    ls_alv_cat-scrtext_m = ls_table-fieldtext.
    ls_alv_cat-scrtext_s = ls_table-fieldtext.
    APPEND ls_alv_cat TO lt_alv_cat.
*    ENDIF.
    CLEAR ls_alv_cat.
  ENDLOOP.
  DELETE lt_alv_cat[] WHERE fieldname EQ 'MANDT'.
*  DELETE lt_alv_cat[] WHERE fieldname EQ 'ZTABIX'.
*  DELETE lt_alv_cat[] WHERE fieldname EQ 'CHECKBOX'.
*  DELETE lt_alv_cat[] WHERE fieldname EQ 'STATUS'.
*  DELETE lt_alv_cat[] WHERE fieldname EQ 'MES_01'.
*  DELETE lt_alv_cat[] WHERE fieldname EQ 'MES_02'.
ENDFORM.
FORM f_alv_display TABLES it_table.
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program      = sy-repid
*     i_callback_pf_status_set = 'F_SET_PF_STATUS'
      i_callback_user_command = 'F_USER_COMMAND'
      is_layout_lvc           = gs_layout
      it_fieldcat_lvc         = lt_alv_cat
      i_save                  = 'U'
    TABLES
      t_outtab                = it_table
    EXCEPTIONS
      program_error           = 1
      OTHERS                  = 2.
  IF sy-subrc <> 0.
  ENDIF.
ENDFORM.
*-----------------------------------------------------------------------* *
*-----------------------------------------------------------------------*
FORM f_set_pf_status USING rt_extab TYPE slis_t_extab.
*  SET PF-STATUS 'STD'.
  DATA: itab TYPE TABLE OF sy-ucomm.
*  IF r0 EQ 'X'.
**    APPEND 'ZCREAT' TO itab.
**    APPEND 'ZSEL' TO itab.
**    APPEND 'ZUNSEL' TO itab.
**    APPEND 'ZADDBZ' TO itab.
*    SET PF-STATUS 'STD' EXCLUDING itab."'ZDEL'.
*  ENDIF.
*  IF r1 EQ 'X'.
*    APPEND 'ZCREAT' TO itab.
*    APPEND 'ZSEL' TO itab.
*    APPEND 'ZUNSEL' TO itab.
**    APPEND 'ZADDBZ' TO itab.
*    SET PF-STATUS 'STD' EXCLUDING itab."'ZDEL'.
*  ENDIF.
*  IF r2 EQ 'X'.
*    APPEND 'ZCREAT' TO itab.
*    APPEND 'ZSEL' TO itab.
*    APPEND 'ZUNSEL' TO itab.
**    APPEND 'ZADDBZ' TO itab.
*    SET PF-STATUS 'STD' EXCLUDING itab."'ZDEL'.
*  ENDIF.
ENDFORM.
*-----------------------------------------------------------------------* *
*-----------------------------------------------------------------------*
FORM f_user_command USING r_ucomm LIKE sy-ucomm
 rs_selfield TYPE slis_selfield.
  PERFORM f_check_change_data.
  CASE r_ucomm.
*    WHEN 'ZCHANGE'.
*      PERFORM frm_save_zchange. "保存资产更改数据
    WHEN 'ZCREAT'.
*      PERFORM frm_zcreag_inv."同一个交货单创建一张发票
    WHEN 'ZSEL'.
*      PERFORM frm_zsel. "全选
    WHEN 'ZUNSEL'.
*      PERFORM frm_zunsel. "取消全选
    WHEN '&IC1'."双击事件
      READ TABLE gt_output INTO DATA(gs_output) INDEX rs_selfield-tabindex.
      IF sy-subrc EQ 0.
        CASE rs_selfield-tabname.
          WHEN 'MBLNR'.
*            CALL FUNCTION 'MIGO_DIALOG'
*              EXPORTING
*                i_action            = 'A04'
*                i_refdoc            = 'R02'
*                i_mblnr             = gs_output-mblnr
*                i_mjahr             = gs_output-mjahr
*              EXCEPTIONS
*                illegal_combination = 1
*                OTHERS              = 2.
*            IF sy-subrc <> 0.
** Implement suitable error handling here
*            ENDIF.
          WHEN 'EBELN'.
*            SET PARAMETER ID 'BES' FIELD gs_output-ebeln.
*            CALL TRANSACTION 'ME23N' AND SKIP FIRST SCREEN.
          WHEN OTHERS.
        ENDCASE.
      ENDIF.
  ENDCASE.
  PERFORM f_refresh_alv.
ENDFORM.
*-----------------------------------------------------------------------* *
*-----------------------------------------------------------------------*
FORM f_check_change_data.
  DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid = lo_grid.
  lo_grid->check_changed_data( ).
ENDFORM.
*-----------------------------------------------------------------------* *
*-----------------------------------------------------------------------*
FORM f_refresh_alv.
  DATA: lo_grid      TYPE REF TO cl_gui_alv_grid,
        ls_is_stable TYPE lvc_s_stbl.
  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid = lo_grid.
  ls_is_stable-col = 'X'.
  ls_is_stable-row = 'X'.
  lo_grid->refresh_table_display(
  EXPORTING
  is_stable = ls_is_stable
  EXCEPTIONS
  finished = 1
  OTHERS = 2 ).
  IF sy-subrc <> 0.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_DATA2
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_data2.

  SELECT a~aufnr,a~ktext,a~zrdtxt
*         b~belnr,b~gjahr,b~rbukrs,b~buzei,b~budat,b~racct,b~hsl,b~msl,b~runit,b~sgtxt
    INTO CORRESPONDING FIELDS OF TABLE @gt_output3
    FROM aufk AS a
*                   JOIN acdoca AS b ON a~aufnr EQ b~aufnr
   WHERE a~aufnr IN @s_aufnr
     AND a~zrdtxt IN @s_rdtxt
     AND a~ernam IN @s_ernam
     AND a~erdat IN @s_erdat
     AND a~auart EQ 'Z100'.
*     AND b~rbukrs EQ @p_bukrs
*     AND b~gjahr IN @s_gjahr
*     AND b~poper IN @s_poper
*     AND b~racct IN @s_racct.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_DATA3
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_data3.
*  DATA(lo_table_basic) = CAST cl_abap_tabledescr( cl_abap_tabledescr=>describe_by_data( gt_output ) ).
*  DATA(lo_struct_basic) = CAST cl_abap_structdescr( lo_table_basic->get_table_line_type( ) ).
*  DATA(lt_component_basic_all) = lo_struct_basic->get_components( ).
*
*  DATA(lt_component_include) = lt_component_basic_all.
*  DATA: lv_fieldname TYPE lvc_s_fcat-fieldname.
*  BREAK-POINT.
  CLEAR: lt_alv_cat[],gt_zrdtxt.


  LOOP AT gt_output INTO DATA(ls_output).
    gs_zrdtxt-zrdtxt = ls_output-zrdtxt."RD描述
    gs_zrdtxt-racct = ls_output-racct."科目号
*    gs_zrdtxt-txt50  = ls_output-txt50."科目长文本
    gs_zrdtxt-hsl    = ls_output-hsl."金额
    COLLECT gs_zrdtxt INTO gt_zrdtxt[].
    CLEAR: gs_zrdtxt,ls_output.
  ENDLOOP.

  gt_zrdtxt2 = gt_zrdtxt[].
  SORT gt_zrdtxt2[] BY zrdtxt.
  DELETE ADJACENT DUPLICATES FROM gt_zrdtxt2[] COMPARING zrdtxt.

  DATA: ls_fieldcat TYPE lvc_s_fcat.
  DEFINE set_fieldcat.
    CLEAR: ls_fieldcat.
    ls_fieldcat-fieldname = &1.
    ls_fieldcat-ref_field = &2.
    ls_fieldcat-ref_table = &3.
    ls_fieldcat-edit  = &4.
    ls_fieldcat-checkbox    = &5.
    ls_fieldcat-seltext   = &6.
    ls_fieldcat-scrtext_l = &6.
    ls_fieldcat-scrtext_m = &6.
    ls_fieldcat-scrtext_s = &6.
    ls_fieldcat-coltext   = &6.
    APPEND ls_fieldcat TO lt_alv_cat.
  END-OF-DEFINITION.

  set_fieldcat 'MNODE'       'NODE_KEY' 'MTREESNODE' '' ''  '母节点'.
  set_fieldcat 'ZNODE'       'NODE_KEY' 'MTREESNODE' '' ''  '自身节点'.
  set_fieldcat 'ZSTR1'       'JSONSTR1' 'ZRFC_LOGS'  '' ''  '内部研究开发投入额'.
  set_fieldcat 'TXT50'       'TXT50'    'SKAT'       '' ''  '科目名称'.
*  set_fieldcat 'ZSTR3'       'JSONSTR1' 'ZRFC_LOGS'  '' ''  '科目范围'.

  LOOP AT gt_zrdtxt2 INTO DATA(ls_zrdtxt2).
    ADD 1 TO lv_num.

    lv_fieldname = |NODE{ sy-tabix }|.
    set_fieldcat lv_fieldname  'HSL' 'ACDOCA' '' ''  ls_zrdtxt2-zrdtxt.
  ENDLOOP.

*内表创建

  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = lt_alv_cat
    IMPORTING
      ep_table        = d_ref.


*指定生成的内表到字段符号
  ASSIGN d_ref->* TO .

*创建动态工作区结构
  CREATE DATA dyn_wa LIKE LINE OF .

*创建动态工作区
  ASSIGN dyn_wa->* TO .
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_DATA4
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_data4 .
  DATA: ls_node   TYPE sy_node, "记录上一行的节点
        lv_tabix2 TYPE sy-tabix.
  FIELD-SYMBOLS :  TYPE any,
                   TYPE any.

  RANGES: r_racct FOR acdoca-racct.
  DATA: lv_str3 TYPE string,
        lv_str1 TYPE string,
        lv_str2 TYPE string.
  DATA: lv_tabix TYPE sy-tabix.
  DATA: lt_str  LIKE TABLE OF lv_str3 WITH HEADER LINE.

  CLEAR: gt_node[].
  DEFINE set_node.
    CLEAR: gs_node.
    IF &1 EQ ''.
      gs_node-mnode = ls_node-znode."母节点
    ELSE.
      gs_node-mnode = &1."母节点
    ENDIF.
    IF &2 EQ '' OR &2 EQ 'X'.
      ADD 1 TO lv_tabix.
      gs_node-znode = |{ gs_node-mnode+0(1) }{ lv_tabix }|.
    ELSE.
      gs_node-znode = &2."自身节点
      IF gs_node-mnode EQ gs_node-znode.
        CLEAR: lv_tabix.
      ENDIF.
    ENDIF.

    IF &2 EQ 'X' OR &2 NE ''.
      ls_node-mnode = &1.
      ls_node-znode = gs_node-znode."
    ENDIF.
    gs_node-zstr1 = &3."文本1
    gs_node-txt50 = &4."科目文本
    gs_node-zstr3 = &5."科目范围。格式, A~B;C;D;E,用;分隔,范围用~连接
    APPEND gs_node TO gt_node[].
  END-OF-DEFINITION.

  "合计的不填科目范围,额外写个嵌套循环,获取下阶节点金额,方便后续增减节点
  "自身节点将作为新的母节点时,打个'X'
  "最后额外循环一次,计算总计,累加'母节点'和'自身节点'相等的数值。
  set_node 'A' 'A' '1、人员人工'                 '合计'                   ''.
  set_node 'A' ''  ''                            '间接人员薪资-自有'      '0066010000'.
  set_node 'A' '' ''                             '间接人员奖金-年终奖'    '0066010045'.
  set_node 'A' '' ''                             '间接人员奖金-其他'      '0066010050'.
  set_node 'A' '' ''                             '补偿金'                 '0066010052'.
  set_node 'A' '' ''                             '间接人员奖金-提成奖'    '0066010072'.
  set_node 'A' '' ''                             '加班费'                 '0066010049'.
  set_node 'A' 'X' '     五险一金'               '合计'                   ''.
  set_node ''  '' ''                             '住房公积金'             '0066010051'.
  set_node ''  '' ''                             '社会基本养老保险'       '0066010065'.
  set_node ''  '' ''                             '基本医疗保险'           '0066010066'.
  set_node ''  '' ''                             '失业保险'               '0066010067'.
  set_node ''  '' ''                             '工伤保险'               '0066010068'.
  set_node ''  '' ''                             '生育保险'               '0066010069'.
  set_node 'B' 'B' '2、直接投入'                 '合计'                   ''.
  set_node 'B'  '' '其中:材料'                  '物料消耗'               '0066010004'.
  set_node 'B'  'X' '     产品试制模具费'        '合计'                   ''.
  set_node ''  '' ''                             '修模费'                 '0066010034'.
  set_node ''  '' ''                             '开模费'                 '0066010038'.
  set_node ''  '' '   样品、样机测试购置'        '样品费'                 '0066010037'.
  set_node ''  '' '     测试、检测费用'          '检测费'                 '0066010060'.
  set_node ''  '' '     低值易耗品'              '低值易耗品'             '0066010031'.
  set_node ''  '' '     水费'                    '水费'                   '0066010008'.
  set_node ''  '' '     电费'                    '电费'                   '0066010014'.
  set_node ''  '' '     房租'                    '房屋租赁'               '0066010003'.
  set_node ''  '' '     设备安装调试费'          ''                       ''.
  set_node 'C' 'C' '3、折旧费用与长期费用摊销'   '合计'                   ''.
  set_node 'C' '' ''                             '折旧费-其它'            '0066010007'.
  set_node 'C' '' ''                             '折旧费-机器'            '0066010011'.
  set_node 'C' '' ''                             '折旧费-模具'            '0066010042'.
  set_node 'D' 'D' '4、其他费用'                 '合计'                   ''.
  set_node 'D'  '' ''                            '职工福利-福利费'        '0066010001'.
  set_node 'D'  '' ''                            '伙食费'                 '0066010002'.
  set_node 'D'  '' ''                            '运输费-外部车辆'        '0066010005'.
  set_node 'D'  '' ''                            '维修保养'               '0066010006'.
  set_node 'D'  '' ''                            '办公费'                 '0066010010'.
  set_node 'D'  '' ''                            '其他费用'               '0066010012'.
  set_node 'D'  '' ''                            '差旅费'                 '0066010016'.
  set_node 'D'  '' ''                            '通讯费'                 '0066010017'.
  set_node 'D'  '' ''                            '业务招待费'             '0066010018'.
  set_node 'D'  '' ''                            '培训及企业文化费'       '0066010026'.
  set_node 'D'  '' ''                            '运输费-公司车辆'        '0066010028'.
  set_node 'D'  '' ''                            '商标注册与认证费'       '0066010033'.
  set_node 'D'  '' ''                            '费用摊销'               '0066010035'.
  set_node 'D'  '' ''                            '消耗品'                 '0066010039'.
  set_node 'D'  '' ''                            '装修费'                 '0066010041'.
  set_node 'D'  '' ''                            '劳务费'                 '0066010053'.
  set_node 'D'  '' ''                            '包装费'                 '0066010057'.
  set_node 'D'  '' ''                            '夹治具耗材'             '0066010061'.
  set_node 'D'  '' ''                            '设备租赁'               '0066010063'.
  set_node 'D'  '' ''                            '长摊费用摊销'           '0066010070'.
  set_node 'D'  '' ''                            'APP服务费'              '0066010073'.
  set_node 'D'  '' ''                            '快递费'                 '0066010074'.
  set_node 'Z' 'Z' '总计'                        '总计'                   ''.

  DEFINE set_dyn_wa.
    IF &1 NE ''.
      ASSIGN COMPONENT &1 OF STRUCTURE  TO .
      IF sy-subrc EQ 0.
          = &2.
      ENDIF.
    ENDIF.
    IF &3 NE ''.
      ASSIGN COMPONENT &3 OF STRUCTURE  TO .
      IF sy-subrc EQ 0.
         = &4.
      ENDIF.
    ENDIF.
  END-OF-DEFINITION.

  DEFINE set_dyn_wa_node.
*    CLEAR: .
    IF &1 NE ''.
      ASSIGN COMPONENT &1 OF STRUCTURE  TO .
      IF sy-subrc EQ 0.
          =  + &2.
      ENDIF.
    ENDIF.
  END-OF-DEFINITION.

  CLEAR gs_node.
  DATA: lv_racct1 TYPE acdoca-racct,
        lv_racct2 TYPE acdoca-racct.
  LOOP AT gt_node INTO gs_node.
    CLEAR: .
    set_dyn_wa 'MNODE' gs_node-mnode 'ZNODE' gs_node-znode.
    set_dyn_wa 'ZSTR1' gs_node-zstr1 'TXT50' gs_node-txt50.
    "处理并获取 科目号
    CLEAR: lt_str,r_racct[].
    SPLIT gs_node-zstr3 AT ';' INTO TABLE lt_str.
    LOOP AT lt_str INTO DATA(ls_str)."table_line
      CLEAR: lv_str1,lv_str2,r_racct.
      IF ls_str NE ''.
        SPLIT ls_str AT '~' INTO lv_str1 lv_str2.
        IF lv_str2 NE ''.
          r_racct = 'IBT'.
          r_racct-low = lv_str1.
          r_racct-high = lv_str2.
        ELSE.
          r_racct = 'IEQ'.
          r_racct-low = lv_str1.
        ENDIF.
        APPEND r_racct.
      ENDIF.
    ENDLOOP.

    IF r_racct[] IS NOT INITIAL.
      LOOP AT gt_zrdtxt INTO gs_zrdtxt WHERE racct IN r_racct."根据RD描述匹配字段
        READ TABLE gt_zrdtxt2 WITH KEY zrdtxt = gs_zrdtxt TRANSPORTING NO FIELDS BINARY SEARCH.
        IF sy-subrc EQ 0.
          lv_tabix2 = sy-tabix.
          lv_fieldname = |NODE{ lv_tabix2 }|.
          set_dyn_wa_node lv_fieldname gs_zrdtxt-hsl.
        ENDIF.
      ENDLOOP.
    ENDIF.
    APPEND  TO [].
  ENDLOOP.

  LOOP AT  ASSIGNING .
*    lv_tabix2 = sy-tabix.
    ASSIGN COMPONENT 'ZNODE' OF STRUCTURE  TO .
    IF sy-subrc EQ 0.
*      ASSIGN COMPONENT 'ZNODE' OF STRUCTURE  TO .
      PERFORM frm_get_hj USING  ."计算合计金额
    ENDIF.
*    READ TABLE
  ENDLOOP.
*  BREAK-POINT.
  "计算最后一行的 总计

  DATA(lv_lines) = lines(  ).
  READ TABLE  ASSIGNING  INDEX lv_lines.
  IF sy-subrc EQ 0.
    LOOP AT  ASSIGNING FIELD-SYMBOL().
      CLEAR lv_tabix2.
      ASSIGN COMPONENT 'ZNODE' OF STRUCTURE  TO .
      IF sy-subrc EQ 0.
        CASE .
          WHEN 'A' OR 'B' OR 'C' OR 'D' OR 'E' OR 'F' OR 'G'.
            CLEAR lv_tabix2.
            DO lv_num TIMES.
              ADD 1 TO lv_tabix2.
              lv_fieldname = |NODE{ lv_tabix2 }|.
              ASSIGN COMPONENT lv_fieldname OF STRUCTURE  TO .
              IF sy-subrc EQ 0.
                ASSIGN COMPONENT lv_fieldname OF STRUCTURE  TO .
                IF sy-subrc EQ 0.
                   =  + .
                ENDIF.
              ENDIF.
            ENDDO.
*            WHEN .
          WHEN OTHERS.
        ENDCASE.
      ENDIF.
    ENDLOOP.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_HJ
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_hj USING lv_znode TYPE tv_nodekey.
  DATA: lv_tabix  TYPE sy-tabix,
        lv_tabix2 TYPE sy-tabix.
  DATA: lv_znode2 TYPE tv_nodekey.
  FIELD-SYMBOLS :  TYPE any,
                   TYPE any.
  LOOP AT gt_node INTO gs_node WHERE mnode = lv_znode.
    lv_tabix = sy-tabix.
    IF gs_node-znode NE gs_node-mnode ."不计算自身
      READ TABLE gt_node WITH KEY mnode = gs_node-znode TRANSPORTING NO FIELDS.
      IF sy-subrc NE 0.
        "自身没有下阶节点时
        READ TABLE  ASSIGNING FIELD-SYMBOL() INDEX lv_tabix.
        IF sy-subrc EQ 0.
          CLEAR lv_tabix2.
          DO lv_num TIMES.
            ADD 1 TO lv_tabix2.
            lv_fieldname = |NODE{ lv_tabix2 }|.
            ASSIGN COMPONENT lv_fieldname OF STRUCTURE  TO .
            IF sy-subrc EQ 0.
              ASSIGN COMPONENT lv_fieldname OF STRUCTURE  TO .
              IF sy-subrc EQ 0.
                 =  + .
              ENDIF.
            ENDIF.
          ENDDO.
        ENDIF.
      ELSE.
        "自身也为合计时,或者还有下阶节点时
        lv_znode2 = gs_node-znode.
        PERFORM frm_get_hj USING lv_znode2.
      ENDIF.
    ENDIF.
  ENDLOOP.

ENDFORM.