ALV TREE 实例

ALV TREE 实例

 

REPORT  ZRPT_PS_PS021TREE                          .

TABLES: PROJ,          "项目定义数据
        PRPS,          "WBS元素数据
        ZCJ30,         "AFCEID
        TCJ04,         "项目负责人数据
        TCJ1,          "项目类型数据
        TJ30,          "项目状态数据
        TJ30T,         "项目状态文本
        TBP1T,         "预算参数文件文本
        EKKN,          "采购凭证中的帐户设置
        EKBE,          "采购凭证历史
        EKPO,          "采购订单明细
        COEP,          "成本控制对象
        BPGE,          "总计值的总计记录
        ZPS001,        "项目属性
        BSEG,          "会计凭证行项目
        RBKP,          "凭证表头:发票收据
        ZPS006,         "行业分类
        JEST.

DATA:T_GJAHR(6) TYPE C,
     H_GJAHR(6) TYPE C,
     G_MONTH  LIKE BSIK-MONAT,           "当前月份
     G_MONTH2 LIKE BSIK-MONAT,           "当前月份下一月
     G_DATE  LIKE SY-UCOMM,              "截止当前月份为止时间
     G_DATE2 LIKE SY-UCOMM,              "截止去年年底为止时间
     G_DATE3 LIKE SY-UCOMM,              "当月时间
     G_CONUT(4) TYPE N,                  "项目行数
     G_PSPHI LIKE PRPS-PSPHI,            "用来判断项目是否相同
     G_PSPNR LIKE PRPS-PSPNR,            "用来判断WBS是否相同
     G_NETPR LIKE BPGE-WTGES,            "WBS的凭证和PO金额合计
     G_NETPRSUM LIKE BPGE-WTGES.         "项目金额总记

*权限对象使用
DATA: BEGIN OF TAB_G_BUKRS OCCURS 0,
       BUKRS LIKE T001-BUKRS,
       END OF TAB_G_BUKRS.

*内表定义
DATA: BEGIN OF TAB_G_PROJ OCCURS 0,
         VBUKR     LIKE PROJ-VBUKR,        "公司代码
         PSPHI     LIKE PRPS-PSPHI,        "项目编号
         PSPNR     LIKE PRPS-PSPNR,        "WBS编号
         CON(4),                           "项目行数序号
         PSPID     LIKE PROJ-PSPID,        "项目定义
         POST1     LIKE PRPS-POST1,        "项目名称
         POSID     LIKE PRPS-POSID,        "WBS元素
         POST2     LIKE PRPS-POST1,        "项目名称
         STUFE     LIKE PRPS-STUFE,        "项目层次
         UP        LIKE PRHI-UP,            "层级关系
         EBELN     LIKE EKPO-EBELN,        "采购订单/凭证号
         TXZ01(100),        "采购订单文本/凭证文本/成本要素文本
         OBJNR     LIKE PRPS-OBJNR,        "项目对象号
         ZBMOUNT   LIKE BPGE-WTGES,        "预算金额(Budget)
         ZNETPR    LIKE BPGE-WTGES,        "PO总金额(含税)
         EXPSUM    LIKE ZPS001-EXPSUM,     "预计完工金额
         ZEMOUNT   LIKE BPGE-WTGES,        "剩余预算金额
         GJAHR     LIKE BSEG-GJAHR,        "年度
         ID        LIKE ICON-ID,            "层次打开图标
         COLOR(4)  TYPE  C,                 "颜色
       END OF TAB_G_PROJ.

*ALV输出用
DATA: TAB_G_OUT LIKE TAB_G_PROJ OCCURS 0 WITH HEADER LINE,
      REC_G_OUT LIKE TAB_G_OUT.
*计算总值
DATA: TAB_G_OUTSUM LIKE TAB_G_PROJ OCCURS 0 WITH HEADER LINE.
*展开WBS用
DATA:TAB_G_OUTID LIKE TAB_G_PROJ OCCURS 0 WITH HEADER LINE.
*判断数据重复用
DATA: TAB_G_OUTDEL LIKE TAB_G_PROJ OCCURS 0 WITH HEADER LINE.

*判断同一WBS元素不同凭证用数据用
DATA: TAB_G_OUTWBS LIKE TAB_G_PROJ OCCURS 0 WITH HEADER LINE.

*项目层级表
DATA:TAB_G_PSHI LIKE PRHI OCCURS 0 WITH HEADER LINE.
*实际合同金额用表
DATA TAB_G_RPSCO TYPE STANDARD TABLE OF RPSCO WITH HEADER LINE.

*带WBS的采购订单
DATA:BEGIN OF TAB_G_EKKN OCCURS 0,
     PSPNR LIKE EKKN-PS_PSP_PNR,"WBS元素
     EBELN LIKE EKPO-EBELN,"PO号
     EBELP LIKE EKPO-EBELP,"PO行项目
     END OF TAB_G_EKKN.
*PO金额表
DATA:BEGIN OF TAB_G_EKPO OCCURS 0,
     BUKRS LIKE EKPO-BUKRS,"公司
     PSPNR LIKE EKKN-PS_PSP_PNR,"WBS元素
     PSPID LIKE ZPS003-PSPID,"项目
     POSID LIKE ZPS003-POSID, "WBS元素
     EBELN LIKE EKPO-EBELN,"PO号
     EBELP LIKE EKPO-EBELP,"行项目
     GJAHR  LIKE COVP-GJAHR, "年度
     TXZ01 LIKE EKPO-TXZ01,"PO文本
     NETWR LIKE EKPO-NETWR,"PO金额
     RETPO LIKE EKPO-RETPO,"退货标识
     NETPR LIKE EKPO-NETWR, "净价格(以凭证货币计)
     MENGE LIKE EKPO-MENGE, "采购订单数量
     PEINH LIKE EKPO-PEINH, "价格单位
     MWSKZ LIKE EKPO-MWSKZ, "税代码
     WKURS LIKE EKKO-WKURS, "汇率
     KBETR LIKE KONP-KBETR, "
     WAERS LIKE EKKO-WAERS,      "货币符号
     KNUMV LIKE EKKO-KNUMV,      "单据条件数
     KBETR1 LIKE KONV-KBETR,      "运费
     END OF TAB_G_EKPO.

*运费计算
DATA:BEGIN OF TAB_G_KONV OCCURS 0,
     KNUMV LIKE KONV-KNUMV,
     KPOSN LIKE KONV-KPOSN,
     KSCHL LIKE KONV-KSCHL,
     KBETR LIKE KONV-KBETR,
     END OF TAB_G_KONV.

*PO项目文本用
DATA: TAB_G_EKPODEL LIKE TAB_G_EKPO OCCURS 0 WITH HEADER LINE.
*PO金额汇总表
DATA: TAB_G_EKPOSUM LIKE TAB_G_EKPO OCCURS 0 WITH HEADER LINE.
*合同期初用
DATA: TAB_G_ZPS003 LIKE TAB_G_EKPO OCCURS 0 WITH HEADER LINE.
*外币用
DATA:AMOUNT_EX  LIKE BAPICURR-BAPICURR,
     AMOUNT_IN LIKE BAPICURR-BAPICURR.
*无PO凭证表
DATA: BEGIN OF TAB_G_COVP OCCURS 0,
      BUKRS  LIKE T001-BUKRS,"公司
      OBJNR  LIKE PRPS-OBJNR,"对象号
      BELNR  LIKE COVP-REFBN,"凭证号
      BUDAT  LIKE BSIS-BUDAT,"记账日期
      GJAHR  LIKE COVP-GJAHR, "年度
      BUZEI  LIKE COVP-BUZEI,
      BELNR1 LIKE COVP-BELNR,
      KSTAR  LIKE COVP-KSTAR,"成本要素
      TXT20  LIKE SKAT-TXT20,"成本要素名称
      WOGBTR LIKE COVP-WOGBTR,"本位币
      SGTXT  LIKE COVP-SGTXT, "凭证文本
    END OF TAB_G_COVP.
* 无PO凭证项目文本用
DATA:TAB_G_COVPDEL LIKE TAB_G_COVP OCCURS 0 WITH HEADER LINE.
*无PO凭证金额汇总用
DATA:TAB_G_COVPSUM LIKE TAB_G_COVP OCCURS 0 WITH HEADER LINE.

*成本要素用
DATA:BEGIN OF TAB_G_SKAT OCCURS 0,
     SAKNR LIKE SKAT-SAKNR,"成本要素名称
     TXT20 LIKE SKAT-TXT20,"成本要素名称
     END OF TAB_G_SKAT.

DATA:  G_ALV_FIELDCAT  TYPE LVC_T_FCAT,
*参照 LVC_S_FCAT 结构定义字段列工作区
       G_ALV_FIELD  TYPE LVC_S_FCAT,
       G_TOOLBAR    TYPE REF TO CL_GUI_TOOLBAR.


DATA: G_ALV_TREE         TYPE REF TO CL_GUI_ALV_TREE,
      G_CUSTOM_CONTAINER TYPE REF TO CL_GUI_CUSTOM_CONTAINER.

TYPES: BEGIN OF TY_WBS,
        POSID  TYPE PRPS-POSID,           "WBS元素
        POST2(100)  TYPE C,           "WBS描述
        STUFE  TYPE PRPS-STUFE,           "层次
        ZBMOUNT   LIKE BPGE-WTGES,        "预算金额(Budget)
        ZNETPR    LIKE BPGE-WTGES,        "PO总金额(含税)
        EXPSUM    LIKE ZPS001-EXPSUM,     "预计完工金额
        ZEMOUNT   LIKE BPGE-WTGES,        "剩余预算金额
        VBUKR     LIKE PROJ-VBUKR,        "公司代码
        GJAHR     LIKE COVP-GJAHR, "年度
        EBELN     LIKE EKKO-EBELN,
       END OF TY_WBS.

DATA: GT_WBS TYPE STANDARD TABLE OF TY_WBS,
      GS_WBS TYPE TY_WBS.

DATA: OK_CODE LIKE SY-UCOMM,
      SAVE_OK LIKE SY-UCOMM,           "OK-Code
      G_MAX TYPE I VALUE 255.

DATA: GT_FCAT  TYPE  LVC_T_FCAT,
      GS_FCAT  TYPE  LVC_S_FCAT.
*下载抬头数据用
DATA: BEGIN OF TAB_G_XIZA OCCURS 0,
      TEXT(25) TYPE C,
     END OF TAB_G_XIZA.
DATA: BEGIN OF TAB_G_XIZAITEM OCCURS 0,
        POSID(30)   TYPE C,        "WBS元素
        POST2(100)   TYPE C,        "WBS描述
        ZBMOUNT(20) TYPE C,        "预算金额(Budget)
        ZNETPR(20)  TYPE C,        "PO总金额(含税)
        ZEMOUNT(20) TYPE C,        "剩余预算金额
        EXPSUM(20)  TYPE C,        "预计完工金额
     END OF TAB_G_XIZAITEM.
*---------------------------------------------------------------------*
*          SELECTION-SCREEN
*---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK A WITH FRAME TITLE TEXT-001.
PARAMETERS: P_GJAHR  LIKE BSIK-GJAHR DEFAULT SY-DATUM+0(4) OBLIGATORY,
            P_MONTH  LIKE BSIK-MONAT DEFAULT SY-DATUM+4(2) OBLIGATORY.
SELECT-OPTIONS: S_VBUKR  FOR PROJ-VBUKR OBLIGATORY,        "公司代码
                S_PSPID  FOR PROJ-PSPID,                   "项目定义
*                S_POSID  FOR PRPS-POSID,                   "WBS元素
                S_PRART  FOR TCJ1-PRART,                   "项目类型
                S_VERNR  FOR TCJ04-VERNR,                  "项目负责
                S_USR00  FOR ZPS006-USR00.                   "行业分类
*PARAMETERS: R1 AS CHECKBOX. "展开
SELECTION-SCREEN END OF BLOCK A.

SELECTION-SCREEN BEGIN OF BLOCK C WITH FRAME TITLE TEXT-003.
PARAMETERS: R3 RADIOBUTTON GROUP B DEFAULT 'X',          "显示全部
            R4 RADIOBUTTON GROUP B.                      "显示未完工
SELECTION-SCREEN END OF BLOCK C.

AT SELECTION-SCREEN.
*权限检查
  SELECT BUKRS FROM T001 INTO TABLE TAB_G_BUKRS
  WHERE BUKRS IN S_VBUKR.
  DELETE ADJACENT DUPLICATES FROM TAB_G_BUKRS COMPARING BUKRS.
  LOOP AT TAB_G_BUKRS.
    AUTHORITY-CHECK OBJECT 'ZPS021'
                        ID 'ACTVT' FIELD '03'
                        ID 'BUKRS' FIELD TAB_G_BUKRS-BUKRS.
    IF SY-SUBRC <> 0.
      MESSAGE '您没有权限!' TYPE 'E'.
    ENDIF.
  ENDLOOP.
*屏幕数据检查
  IF P_GJAHR = '0000' OR P_GJAHR+0(1) = 0.
    MESSAGE '输入年度不存在!' TYPE  'E'.
  ENDIF.
  IF P_MONTH > '12' OR P_MONTH = 0.
    MESSAGE '输入月份不存在!' TYPE  'E'.
  ENDIF.

*----------------------------------------------------------------------*
*       CLASS lcl_tree_event_receiver DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS LCL_TREE_EVENT_RECEIVER DEFINITION.

  PUBLIC SECTION.
    METHODS HANDLE_NODE_DOUBLE_CLICK
      FOR EVENT NODE_DOUBLE_CLICK OF CL_GUI_ALV_TREE
      IMPORTING NODE_KEY SENDER.
    METHODS HANDLE_ITEM_DOUBLE_CLICK
      FOR EVENT ITEM_DOUBLE_CLICK OF CL_GUI_ALV_TREE
      IMPORTING FIELDNAME NODE_KEY.
ENDCLASS.                    "lcl_tree_event_receiver DEFINITION
*----------------------------------------------------------------------*
*       CLASS lcl_toolbar_event_receive DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS LCL_TOOLBAR_EVENT_RECEIVER DEFINITION.

  PUBLIC SECTION.
* ?4. Define an event handler method to react to fired function codes
*     of the toolbar.                   .
    METHODS: ON_FUNCTION_SELECTED
               FOR EVENT FUNCTION_SELECTED OF CL_GUI_TOOLBAR
                 IMPORTING FCODE.

ENDCLASS.                    "lcl_toolbar_event_receiver DEFINITION
*----------------------------------------------------------------------*
*       CLASS LCL_TREE_EVENT_RECEIVER IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS LCL_TREE_EVENT_RECEIVER IMPLEMENTATION.

  METHOD HANDLE_NODE_DOUBLE_CLICK.
    DATA: LT_CHILDREN TYPE LVC_T_NKEY.

    CALL METHOD SENDER->GET_CHILDREN
      EXPORTING
        I_NODE_KEY  = NODE_KEY
      IMPORTING
        ET_CHILDREN = LT_CHILDREN.

    IF NOT LT_CHILDREN IS INITIAL.

      CALL METHOD SENDER->EXPAND_NODE
        EXPORTING
          I_NODE_KEY    = NODE_KEY
          I_LEVEL_COUNT = 2.
    ENDIF.

  ENDMETHOD.                    "handle_node_double_click

  METHOD HANDLE_ITEM_DOUBLE_CLICK.
    DATA: L_VALUE TYPE LVC_VALUE,
          L_LAYI  TYPE LVC_T_LAYI,
          L_LAYN  TYPE LVC_S_LAYN .
    DATA:G_EBELN LIKE EKKN-EBELN.
    CALL METHOD G_ALV_TREE->GET_OUTTAB_LINE
      EXPORTING
        I_NODE_KEY     = NODE_KEY
      IMPORTING
        E_OUTTAB_LINE  = GS_WBS
        E_NODE_TEXT    = L_VALUE
        ET_ITEM_LAYOUT = L_LAYI
        ES_NODE_LAYOUT = L_LAYN
      EXCEPTIONS
        NODE_NOT_FOUND = 1
        OTHERS         = 2.
    IF SY-SUBRC = 0.
      IF GS_WBS-POSID+0(2) = 'CN'.
        SET PARAMETER ID 'PRO' FIELD GS_WBS-POSID.
        CALL TRANSACTION 'CJ03' AND SKIP FIRST SCREEN.
      ELSEIF GS_WBS-POSID+0(1) = '9'.
        SET PARAMETER ID 'BLN' FIELD GS_WBS-POSID.
        SET PARAMETER ID 'BUK' FIELD GS_WBS-VBUKR.
        SET PARAMETER ID 'GJR' FIELD GS_WBS-GJAHR.
        CALL TRANSACTION 'FB03' AND SKIP FIRST SCREEN.
      ELSE.
        CLEAR:G_EBELN.
        SELECT SINGLE EBELN
        FROM EKKN
        INTO G_EBELN
        WHERE EBELN = GS_WBS-POSID.
        IF SY-SUBRC = 0.
          SET PARAMETER ID 'BES' FIELD GS_WBS-POSID.
          CALL TRANSACTION 'ME23N' AND SKIP FIRST SCREEN.
        ELSE.
          MESSAGE '无此PO!' TYPE  'S'.
        ENDIF.
      ENDIF.
    ENDIF.

  ENDMETHOD.                    "handle_item_double_click

ENDCLASS.                    "lcl_tree_event_receiver IMPLEMENTATION
*---------------------------------------------------------------------*
*       CLASS lcl_toolbar_event_receiver IMPLEMENTATION
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
CLASS LCL_TOOLBAR_EVENT_RECEIVER IMPLEMENTATION.
*
  METHOD ON_FUNCTION_SELECTED.
    DATA: LT_SELECTED_NODES TYPE LVC_T_NKEY,
          L_SELECTED_NODE   TYPE LVC_NKEY,
          L_RC              TYPE C.

* ?5. Query the function codes of the toolbar in your implementation.
    CASE FCODE.
      WHEN 'XIZA'."下载数据
        PERFORM XIZA_DATA.
    ENDCASE.
  ENDMETHOD.                    "on_function_selected

ENDCLASS.                    "lcl_toolbar_event_receiver IMPLEMENTATION

END-OF-SELECTION.

  CALL SCREEN 100.

*&---------------------------------------------------------------------*
*&      Module  PBO  OUTPUT
*&---------------------------------------------------------------------*
*       process before output
*----------------------------------------------------------------------*
MODULE PBO OUTPUT.

  SET PF-STATUS 'MAIN100'.
  SET TITLEBAR 'MAINTITLE'.

  IF G_ALV_TREE IS INITIAL.
    PERFORM INIT_TREE.

    CALL METHOD CL_GUI_CFW=>FLUSH
      EXCEPTIONS
        CNTL_SYSTEM_ERROR = 1
        CNTL_ERROR        = 2.
    IF SY-SUBRC NE 0.
      CALL FUNCTION 'POPUP_TO_INFORM'
        EXPORTING
          TITEL = 'Automation Queue failure'(801)
          TXT1  = 'Internal error:'(802)
          TXT2  = 'A method in the automation queue'(803)
          TXT3  = 'caused a failure.'(804).
    ENDIF.
  ENDIF.

ENDMODULE.                             " PBO  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  PAI  INPUT
*&---------------------------------------------------------------------*
*       process after input
*----------------------------------------------------------------------*
MODULE PAI INPUT.
  SAVE_OK = OK_CODE.
  CLEAR OK_CODE.

  CASE SAVE_OK.
    WHEN 'EXIT' OR 'BACK' OR 'CANC'.
      PERFORM EXIT_PROGRAM.

    WHEN OTHERS.
      CALL METHOD CL_GUI_CFW=>DISPATCH.

  ENDCASE.

  CALL METHOD CL_GUI_CFW=>FLUSH.
ENDMODULE.                             " PAI  INPUT

*&---------------------------------------------------------------------*
*&      Form  init_tree
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM INIT_TREE.

  DATA: L_TREE_CONTAINER_NAME(30) TYPE C.

  L_TREE_CONTAINER_NAME = 'CCONTAINER1'.

  CREATE OBJECT G_CUSTOM_CONTAINER
    EXPORTING
      CONTAINER_NAME              = L_TREE_CONTAINER_NAME
    EXCEPTIONS
      CNTL_ERROR                  = 1
      CNTL_SYSTEM_ERROR           = 2
      CREATE_ERROR                = 3
      LIFETIME_ERROR              = 4
      LIFETIME_DYNPRO_DYNPRO_LINK = 5.
  IF SY-SUBRC <> 0.
    MESSAGE X208(00) WITH 'ERROR'(100).
  ENDIF.

* create tree control
  CREATE OBJECT G_ALV_TREE
    EXPORTING
      PARENT                      = G_CUSTOM_CONTAINER
      NODE_SELECTION_MODE         = CL_GUI_COLUMN_TREE=>NODE_SEL_MODE_SINGLE
      ITEM_SELECTION              = 'X'
      NO_HTML_HEADER              = 'X'
      NO_TOOLBAR                  = ''
    EXCEPTIONS
      CNTL_ERROR                  = 1
      CNTL_SYSTEM_ERROR           = 2
      CREATE_ERROR                = 3
      LIFETIME_ERROR              = 4
      ILLEGAL_NODE_SELECTION_MODE = 5
      FAILED                      = 6
      ILLEGAL_COLUMN_NAME         = 7.
  IF SY-SUBRC <> 0.
    MESSAGE X208(00) WITH 'ERROR'.                          "#EC NOTEXT
  ENDIF.


*主节点抬头描述
  DATA L_HIERARCHY_HEADER TYPE TREEV_HHDR.
  PERFORM BUILD_HIERARCHY_HEADER CHANGING L_HIERARCHY_HEADER.
*项目内表抬头描述
  PERFORM BUILD_FIELDCATEGORY.
  DATA: G_LAYOUT1 TYPE LVC_S_LAYO."布局结构
  DATA: LS_VARIANT TYPE DISVARIANT."格式 (外部使用)
  LS_VARIANT-REPORT = SY-REPID."ABAP 程序名称


  CALL METHOD G_ALV_TREE->SET_TABLE_FOR_FIRST_DISPLAY
    EXPORTING
      I_SAVE              = 'A'
      IS_HIERARCHY_HEADER = L_HIERARCHY_HEADER
      IS_VARIANT          = LS_VARIANT
    CHANGING
      IT_OUTTAB           = GT_WBS   "table must be empty !
      IT_FIELDCATALOG     = GT_FCAT.

  PERFORM CREATE_HIERARCHY."读取数据

  PERFORM CHANGE_TOOLBAR."增加工具栏
  PERFORM REGISTER_EVENTS_TOOLBAR."增加工具栏触发
  PERFORM REGISTER_EVENTS.

  CALL METHOD G_ALV_TREE->FRONTEND_UPDATE.

ENDFORM.                               " init_tree
*&---------------------------------------------------------------------*
*&      Form  build_hierarchy_header
*&---------------------------------------------------------------------*
*       build hierarchy-header-information
*----------------------------------------------------------------------*
*      -->P_L_HIERARCHY_HEADER  strucxture for hierarchy-header
*----------------------------------------------------------------------*
FORM BUILD_HIERARCHY_HEADER CHANGING
                            P_HIERARCHY_HEADER TYPE TREEV_HHDR.
  P_HIERARCHY_HEADER-HEADING = 'WBS元素/合同号/凭证号'(300).
  P_HIERARCHY_HEADER-TOOLTIP = 'WBS'(400).
  P_HIERARCHY_HEADER-WIDTH = 50.
  P_HIERARCHY_HEADER-WIDTH_PIX = ' '.

ENDFORM.                               " build_hierarchy_header
*&---------------------------------------------------------------------*
*&      Form  exit_program
*&---------------------------------------------------------------------*
*       free object and leave program
*----------------------------------------------------------------------*
FORM EXIT_PROGRAM.

  CALL METHOD G_CUSTOM_CONTAINER->FREE.
  LEAVE PROGRAM.

ENDFORM.                               " exit_program
*&---------------------------------------------------------------------*
*&      Form  create_hierarchy
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM CREATE_HIERARCHY.

  DATA: LS_WBS TYPE TY_WBS,
        LT_WBS TYPE TY_WBS OCCURS 0.

  DATA: LT_NODES TYPE TABLE OF LVC_NKEY WITH HEADER LINE,
        L_CUR_NODE TYPE LVC_NKEY,
        L_FORMER_STUFE TYPE PRPS-STUFE,
        L_INDEX  TYPE I.

* 读取数据
  PERFORM FRM_DATA_GET.
  LOOP AT TAB_G_OUT.
    CLEAR:LS_WBS.
    MOVE-CORRESPONDING TAB_G_OUT TO LS_WBS.
    APPEND LS_WBS TO LT_WBS.
  ENDLOOP.

*  SELECT PRPS~POSID PRPS~POST1 PRPS~STUFE
*  FROM PRPS
*  INNER JOIN PROJ ON PROJ~PSPNR = PRPS~PSPHI
*  INTO TABLE LT_WBS
*  WHERE PROJ~PSPID = 'CNJX00A10001'.
*  UP TO 200 ROWS.

*  SORT LT_WBS BY POSID.

  LOOP AT LT_WBS INTO LS_WBS.

    IF LS_WBS-STUFE = '1'.
      REFRESH LT_NODES.
      L_INDEX = LS_WBS-STUFE.
      PERFORM ADD_NODES USING    LS_WBS
                                 ''
                        CHANGING L_CUR_NODE.
      READ TABLE LT_NODES INDEX L_INDEX.
      IF SY-SUBRC NE 0.
        APPEND L_CUR_NODE TO LT_NODES.
      ENDIF.

    ELSEIF LS_WBS-STUFE > L_FORMER_STUFE.      "on change of l_yyyymm
      L_INDEX = LS_WBS-STUFE - 1.
      READ TABLE LT_NODES INDEX L_INDEX.

      PERFORM ADD_NODES USING    LS_WBS
                                 LT_NODES
                        CHANGING L_CUR_NODE.
*---->保存新的当前节点
      APPEND L_CUR_NODE TO LT_NODES.
    ELSEIF LS_WBS-STUFE < L_FORMER_STUFE.
      L_INDEX = LS_WBS-STUFE - 1.
      READ TABLE LT_NODES INDEX L_INDEX.

      PERFORM ADD_NODES USING    LS_WBS
                                 LT_NODES
                        CHANGING L_CUR_NODE.
*---->将当前节点及之后后的所有临时存储节点KEY删除
      L_INDEX = L_INDEX + 1.
      DELETE LT_NODES INDEX L_INDEX.
      DO.
        READ TABLE LT_NODES INDEX L_INDEX.
        IF SY-SUBRC = 0.
          DELETE LT_NODES INDEX L_INDEX.
        ELSE.
          EXIT.
        ENDIF.
      ENDDO.
*---->保存新的当前节点
      APPEND L_CUR_NODE TO LT_NODES.
    ELSE.
      L_INDEX = LS_WBS-STUFE - 1.
      READ TABLE LT_NODES INDEX L_INDEX.
      PERFORM ADD_NODES USING    LS_WBS
                                 LT_NODES
                        CHANGING L_CUR_NODE.
    ENDIF.
    L_FORMER_STUFE = LS_WBS-STUFE.
    IF LS_WBS-EBELN IS INITIAL.
*---->将当前节点及之后后的所有临时存储节点KEY删除
      L_INDEX = L_INDEX + 1.
      DELETE LT_NODES INDEX L_INDEX.
      DO.
        READ TABLE LT_NODES INDEX L_INDEX.
        IF SY-SUBRC = 0.
          DELETE LT_NODES INDEX L_INDEX.
        ELSE.
          EXIT.
        ENDIF.
      ENDDO.
*---->保存新的当前节点
      APPEND L_CUR_NODE TO LT_NODES.
    ENDIF.
  ENDLOOP.

ENDFORM.                               " create_hierarchy
*&---------------------------------------------------------------------*
*&      Form  add_nodes
*&---------------------------------------------------------------------*
FORM ADD_NODES  USING     PS_WBS TYPE TY_WBS
                          P_CNODE_KEY TYPE LVC_NKEY
                CHANGING  P_NNODE_KEY TYPE LVC_NKEY.

  DATA: L_NODE_TEXT TYPE LVC_VALUE.

  CALL FUNCTION 'CONVERSION_EXIT_ABPSN_OUTPUT'
    EXPORTING
      INPUT  = PS_WBS-POSID
    IMPORTING
      OUTPUT = L_NODE_TEXT.

  CALL METHOD G_ALV_TREE->ADD_NODE
    EXPORTING
      I_RELAT_NODE_KEY = P_CNODE_KEY
      I_RELATIONSHIP   = CL_GUI_COLUMN_TREE=>RELAT_LAST_CHILD
      I_NODE_TEXT      = L_NODE_TEXT
      IS_OUTTAB_LINE   = PS_WBS
    IMPORTING
      E_NEW_NODE_KEY   = P_NNODE_KEY.

ENDFORM.                               " add_month
*&---------------------------------------------------------------------*
*&      Form  build_fieldcategory
*&---------------------------------------------------------------------*
FORM BUILD_FIELDCATEGORY .
  CLEAR:GS_FCAT,GT_FCAT,GT_FCAT[].
  GS_FCAT-FIELDNAME      =  'POST2'.
  GS_FCAT-SELTEXT        =  'WBS描述/合同描述/成本要素描述/凭证描述'.    " 字段输出名称
  GS_FCAT-COLTEXT        =  'WBS描述/合同描述/成本要素描述/凭证描述'.    " 字段输出名称
  GS_FCAT-JUST           =  'L'.
  GS_FCAT-OUTPUTLEN      =  '100'.        " 输出长度
  APPEND GS_FCAT TO GT_FCAT.
  CLEAR  GS_FCAT.

  GS_FCAT-FIELDNAME      =  'ZBMOUNT'.
  GS_FCAT-SELTEXT        =  '预算(元)'.    " 字段输出名称
  GS_FCAT-COLTEXT        =  '预算(元)'.    " 字段输出名称
  GS_FCAT-COL_OPT        = 'X'.
  GS_FCAT-JUST           =  'L'.
  GS_FCAT-DATATYPE       = 'CURR'.
  GS_FCAT-OUTPUTLEN      =  '20'.        " 输出长度
  APPEND GS_FCAT TO GT_FCAT.
  CLEAR  GS_FCAT.

  GS_FCAT-FIELDNAME      =  'ZNETPR'.
  GS_FCAT-SELTEXT        =  '合同金额/无PO金额(元)'.    " 字段输出名称
  GS_FCAT-COLTEXT        =  '合同金额/无PO金额(元)'.    " 字段输出名称
  GS_FCAT-COL_OPT        = 'X'.
  GS_FCAT-JUST           =  'L'.
  GS_FCAT-DATATYPE       = 'CURR'.
  GS_FCAT-OUTPUTLEN      =  '30'.        " 输出长度
  APPEND GS_FCAT TO GT_FCAT.
  CLEAR  GS_FCAT.

  GS_FCAT-FIELDNAME      =  'ZEMOUNT'.
  GS_FCAT-SELTEXT        =  '差额(元)'.    " 字段输出名称
  GS_FCAT-COLTEXT        =  '差额(元)'.    " 字段输出名称
  GS_FCAT-COL_OPT        = 'X'.
  GS_FCAT-JUST           =  'L'.
  GS_FCAT-DATATYPE       = 'CURR'.
  GS_FCAT-OUTPUTLEN      =  '20'.        " 输出长度
  APPEND GS_FCAT TO GT_FCAT.
  CLEAR  GS_FCAT.

  GS_FCAT-FIELDNAME      =  'EXPSUM'.
  GS_FCAT-SELTEXT        =  '项目预计完成(元)'.    " 字段输出名称
  GS_FCAT-COLTEXT        =  '项目预计完成(元)'.    " 字段输出名称
  GS_FCAT-COL_OPT        = 'X'.
  GS_FCAT-JUST           =  'L'.
  GS_FCAT-DATATYPE       = 'CURR'.
  GS_FCAT-OUTPUTLEN      =  '25'.        " 输出长度
  APPEND GS_FCAT TO GT_FCAT.
  CLEAR  GS_FCAT.

ENDFORM.                    " build_fieldcategory
*&---------------------------------------------------------------------*
*&      Form  register_events
*&---------------------------------------------------------------------*
FORM REGISTER_EVENTS .
  DATA: LT_EVENTS TYPE CNTL_SIMPLE_EVENTS,
        L_EVENT TYPE CNTL_SIMPLE_EVENT,
        L_EVENT_RECEIVER TYPE REF TO LCL_TREE_EVENT_RECEIVER.

  CALL METHOD G_ALV_TREE->GET_REGISTERED_EVENTS
    IMPORTING
      EVENTS = LT_EVENTS.

  L_EVENT-EVENTID = CL_GUI_COLUMN_TREE=>EVENTID_NODE_DOUBLE_CLICK.
  APPEND L_EVENT TO LT_EVENTS.
  L_EVENT-EVENTID = CL_GUI_COLUMN_TREE=>EVENTID_ITEM_DOUBLE_CLICK.
  APPEND L_EVENT TO LT_EVENTS.

  CALL METHOD G_ALV_TREE->SET_REGISTERED_EVENTS
    EXPORTING
      EVENTS                    = LT_EVENTS
    EXCEPTIONS
      CNTL_ERROR                = 1
      CNTL_SYSTEM_ERROR         = 2
      ILLEGAL_EVENT_COMBINATION = 3.
  IF SY-SUBRC <> 0.
    MESSAGE X208(00) WITH 'ERROR'.                          "#EC NOTEXT
  ENDIF.

  CREATE OBJECT L_EVENT_RECEIVER.
  SET HANDLER L_EVENT_RECEIVER->HANDLE_NODE_DOUBLE_CLICK FOR G_ALV_TREE.
  SET HANDLER L_EVENT_RECEIVER->HANDLE_ITEM_DOUBLE_CLICK FOR G_ALV_TREE.

ENDFORM.                    " register_events
*&---------------------------------------------------------------------*
*&      Form  FRM_DATA_GET
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM FRM_DATA_GET .
*  付款金额用时间设定
  G_MONTH  = P_MONTH.
  G_MONTH2 = P_MONTH + 1.
  CONCATENATE P_GJAHR G_MONTH2 '01' INTO G_DATE.          "截止当前月份为止时间
  CONCATENATE P_GJAHR '01' '01' INTO G_DATE2.             "截止去年年底为止时间
  CONCATENATE P_GJAHR P_MONTH '01' INTO G_DATE3.          "当月时间

*取已分配预算项目和AFCE数据
  SELECT PROJ~VBUKR            "公司
         PROJ~PSPID            "项目定义
         PROJ~POST1 AS POST1   "项目描述
         PRPS~PSPHI            "项目号码
         PRPS~POSID            "WBS元素
         PRPS~POST1 AS POST2   "WBS描述
         PRPS~PSPNR            "WBS编号
         PRPS~OBJNR            "项目对象号
         PRPS~STUFE            "项目层次
   FROM PROJ
   INNER JOIN PRPS  ON PRPS~PSPHI = PROJ~PSPNR
   INTO CORRESPONDING FIELDS OF TABLE TAB_G_PROJ
   WHERE PROJ~VBUKR IN S_VBUKR "公司
     AND PROJ~PSPID IN S_PSPID "项目定义
*     AND PRPS~POSID IN S_POSID "WBS元素
     AND PROJ~VERNR IN S_VERNR "项目负责人
     AND PRPS~PRART IN S_PRART "项目类型
     AND PRPS~USR00 IN S_USR00 "行业分类
     AND PRPS~LOEVM = ''."删除标识

*项目状态
  IF R4 = 'X'.
    LOOP AT TAB_G_PROJ.
      SELECT SINGLE *
      FROM JEST
      WHERE OBJNR = TAB_G_PROJ-OBJNR
        AND STAT = 'I0046'
        AND INACT = ''.
      IF SY-SUBRC = 0.
        DELETE TAB_G_PROJ.
      ENDIF.
      CLEAR:TAB_G_PROJ.
    ENDLOOP.
  ENDIF.

  IF NOT TAB_G_PROJ[] IS INITIAL.
*取项目层级关系
    SELECT *
    FROM PRHI
    INTO TABLE TAB_G_PSHI
    FOR ALL ENTRIES IN TAB_G_PROJ
    WHERE PSPHI = TAB_G_PROJ-PSPHI "项目定义编号
      AND POSNR = TAB_G_PROJ-PSPNR."WBS编号

*取带WBS的PO
    SELECT PS_PSP_PNR AS PSPNR "WBS编号
           EBELN                "PO号
           EBELP                "PO行项目
    FROM EKKN
    INTO TABLE TAB_G_EKKN
    FOR ALL ENTRIES IN TAB_G_PROJ
    WHERE AEDAT < G_DATE                "PO创建日期
      AND PS_PSP_PNR = TAB_G_PROJ-PSPNR "WBS编号
      AND PS_PSP_PNR <> ''.             "WBS编号

    SORT TAB_G_EKKN BY EBELN.
*PO总金额
    IF TAB_G_EKKN[] IS NOT INITIAL.
      SELECT EKPO~BUKRS "公司
             EKPO~EBELN "PO号
             EKPO~EBELP "PO项目
             EKPO~NETWR "PO货币的净订单价值
             EKPO~RETPO "退货项目
             EKPO~NETPR "净价格(以凭证货币计)
             EKPO~MENGE "采购订单数量
             EKPO~PEINH "价格单位
             EKPO~MWSKZ "税代码
             EKKO~WKURS "汇率
             EKKO~WAERS"货币符号
             EKPO~TXZ01 "PO文本
             EKKO~KNUMV "单据条件数
      FROM EKPO
      INNER JOIN EKKO ON EKKO~EBELN = EKPO~EBELN
      INTO CORRESPONDING FIELDS OF TABLE TAB_G_EKPO
      FOR ALL ENTRIES IN TAB_G_EKKN
      WHERE EKKO~BUKRS IN S_VBUKR         "公司
        AND EKPO~EBELN = TAB_G_EKKN-EBELN "PO号
        AND EKPO~EBELP = TAB_G_EKKN-EBELP "PO行项目
        AND EKPO~LOEKZ <> 'L'.            "删除标识

      SORT TAB_G_EKPO BY BUKRS EBELN.
      IF TAB_G_EKPO[] IS NOT INITIAL.

      ENDIF.
      LOOP AT TAB_G_EKPO.
        READ TABLE TAB_G_EKKN WITH KEY EBELN = TAB_G_EKPO-EBELN
                                       EBELP = TAB_G_EKPO-EBELP.
        IF SY-SUBRC = 0.
          TAB_G_EKPO-PSPNR = TAB_G_EKKN-PSPNR.
*取税率
          SELECT SINGLE KONP~KBETR
          FROM  A003
          INNER JOIN KONP ON KONP~KNUMH = A003~KNUMH
          INTO TAB_G_EKPO-KBETR
          WHERE A003~KAPPL = 'TX'
            AND A003~MWSKZ = TAB_G_EKPO-MWSKZ
            AND A003~KSCHL IN ('MWVS', 'MWCN')
            AND A003~ALAND = 'CN'
            AND KONP~KOPOS = '01'.
          MODIFY TAB_G_EKPO.

          IF TAB_G_EKPO-RETPO = 'X'."退货订单判断
*PO总金额(含税)
            IF TAB_G_EKPO-KBETR = ''.
              TAB_G_EKPO-NETPR  = TAB_G_EKPO-NETPR * TAB_G_EKPO-MENGE *
                         TAB_G_EKPO-WKURS / TAB_G_EKPO-PEINH.

              TAB_G_EKPO-NETPR  = 0 - TAB_G_EKPO-NETPR .
            ELSE.
              IF TAB_G_EKPO-MWSKZ = 'T0'.
                TAB_G_EKPO-NETPR = TAB_G_EKPO-NETPR * TAB_G_EKPO-MENGE *
              TAB_G_EKPO-WKURS / TAB_G_EKPO-PEINH / ( 1 - 7 / 100 ).
              ELSE.
                TAB_G_EKPO-NETPR = TAB_G_EKPO-NETPR * TAB_G_EKPO-MENGE *
                          TAB_G_EKPO-WKURS / TAB_G_EKPO-PEINH +  TAB_G_EKPO-NETPR *
                          TAB_G_EKPO-MENGE * TAB_G_EKPO-KBETR * TAB_G_EKPO-WKURS / 1000 /
                          TAB_G_EKPO-PEINH.
              ENDIF.
* 运费
              CLEAR:TAB_G_KONV,TAB_G_KONV[].
              SELECT KNUMV
                     KPOSN
                     KSCHL
                     KBETR
              FROM KONV
              INTO TABLE TAB_G_KONV
              WHERE KNUMV = TAB_G_EKPO-KNUMV
                AND KPOSN = TAB_G_EKPO-EBELP
                AND KSCHL IN ('FRB2','ZKG1').
              LOOP AT TAB_G_KONV.
                TAB_G_EKPO-KBETR1 = TAB_G_EKPO-KBETR1 + TAB_G_KONV-KBETR.
              ENDLOOP.
              TAB_G_EKPO-NETWR = TAB_G_EKPO-NETWR + TAB_G_EKPO-KBETR1.
              TAB_G_EKPO-NETPR = TAB_G_EKPO-NETPR + TAB_G_EKPO-KBETR1.
              TAB_G_EKPO-NETPR  = 0 - TAB_G_EKPO-NETPR ."PO总金额(含税)
              TAB_G_EKPO-NETWR = 0 - TAB_G_EKPO-NETWR."*PO总金额
            ENDIF.
*PO总金额
            TAB_G_EKPO-NETWR = TAB_G_EKPO-NETWR * TAB_G_EKPO-WKURS.
          ELSE.

*PO总金额(含税)
            IF TAB_G_EKPO-KBETR = ''.
              TAB_G_EKPO-NETPR = TAB_G_EKPO-NETPR * TAB_G_EKPO-MENGE *
                          TAB_G_EKPO-WKURS / TAB_G_EKPO-PEINH.
            ELSE.
              IF TAB_G_EKPO-MWSKZ = 'T0'.
                TAB_G_EKPO-NETPR = TAB_G_EKPO-NETPR * TAB_G_EKPO-MENGE *
              TAB_G_EKPO-WKURS / TAB_G_EKPO-PEINH / ( 1 - 7 / 100 ).
              ELSE.
                TAB_G_EKPO-NETPR = TAB_G_EKPO-NETPR * TAB_G_EKPO-MENGE *
                          TAB_G_EKPO-WKURS / TAB_G_EKPO-PEINH + TAB_G_EKPO-NETPR *
                          TAB_G_EKPO-MENGE * TAB_G_EKPO-KBETR * TAB_G_EKPO-WKURS /
                          1000 / TAB_G_EKPO-PEINH.
              ENDIF.
            ENDIF.
*PO总金额
            TAB_G_EKPO-NETWR = TAB_G_EKPO-NETWR * TAB_G_EKPO-WKURS.
* 运费
            CLEAR:TAB_G_KONV,TAB_G_KONV[].
            SELECT KNUMV
                   KPOSN
                   KSCHL
                   KBETR
            FROM KONV
            INTO TABLE TAB_G_KONV
            WHERE KNUMV = TAB_G_EKPO-KNUMV
              AND KPOSN = TAB_G_EKPO-EBELP
              AND KSCHL IN ('FRB2','ZKG1').
            LOOP AT TAB_G_KONV.
              TAB_G_EKPO-KBETR1 = TAB_G_EKPO-KBETR1 + TAB_G_KONV-KBETR.
            ENDLOOP.
            TAB_G_EKPO-NETWR = TAB_G_EKPO-NETWR + TAB_G_EKPO-KBETR1.
            TAB_G_EKPO-NETPR = TAB_G_EKPO-NETPR + TAB_G_EKPO-KBETR1.
          ENDIF.
        ENDIF.
        MODIFY TAB_G_EKPO.
        CLEAR:TAB_G_EKPO.
      ENDLOOP.

*取合同期初金额
      CLEAR:TAB_G_ZPS003,TAB_G_ZPS003[].
      SELECT VBUKR AS BUKRS
             PSPID
             EBELN
             POSID
             GJAHR
             NETPRALL AS NETPR
             TXZ01
      FROM ZPS003
      INTO CORRESPONDING FIELDS OF TABLE TAB_G_ZPS003
      FOR ALL ENTRIES IN TAB_G_PROJ
      WHERE VBUKR = TAB_G_PROJ-VBUKR "公司
        AND PSPID = TAB_G_PROJ-PSPID "项目定义
        AND GJAHR =< SY-DATUM+0(4).

*查找WBS编号
      LOOP AT TAB_G_ZPS003.
        CALL FUNCTION 'CONVERSION_EXIT_ABPSN_INPUT'
          EXPORTING
            INPUT  = TAB_G_ZPS003-POSID
          IMPORTING
            OUTPUT = TAB_G_ZPS003-POSID.
        READ TABLE TAB_G_PROJ WITH KEY PSPID = TAB_G_ZPS003-PSPID
                                       POSID = TAB_G_ZPS003-POSID.
        IF SY-SUBRC = 0.
          TAB_G_ZPS003-PSPNR = TAB_G_PROJ-PSPNR.
          CLEAR:TAB_G_ZPS003-PSPID,TAB_G_ZPS003-POSID.
          MODIFY TAB_G_ZPS003.
        ELSE.
          DELETE TAB_G_ZPS003.
        ENDIF.
      ENDLOOP.

*根据PO,年度确定最新数据
      SORT TAB_G_ZPS003 BY BUKRS PSPNR EBELN GJAHR DESCENDING.
*删除重复数据取出最新PO期初
      DELETE ADJACENT DUPLICATES FROM TAB_G_ZPS003 COMPARING BUKRS PSPNR EBELN.

      APPEND LINES OF TAB_G_ZPS003 TO TAB_G_EKPO.
*PO总金额汇总
      APPEND LINES OF TAB_G_EKPO TO TAB_G_EKPODEL.
      CLEAR:TAB_G_EKPO-EBELP,TAB_G_EKPO-RETPO,TAB_G_EKPO-TXZ01,
      TAB_G_EKPO-WKURS,TAB_G_EKPO-MWSKZ,TAB_G_EKPO-KBETR,
      TAB_G_EKPO-PSPID,TAB_G_EKPO-POSID, TAB_G_EKPO-WAERS, TAB_G_EKPO-KNUMV.
      MODIFY TAB_G_EKPO TRANSPORTING EBELP TXZ01 RETPO WKURS MWSKZ KBETR PSPID POSID WAERS KNUMV
                               WHERE EBELN <> ''.
      SORT TAB_G_EKPO BY BUKRS PSPNR EBELN.
      LOOP AT TAB_G_EKPO.
        COLLECT TAB_G_EKPO INTO TAB_G_EKPOSUM.
        APPEND TAB_G_EKPOSUM.
      ENDLOOP.
    ENDIF.
  ENDIF.
  DELETE TAB_G_EKPOSUM WHERE BUKRS = ''.

*无PO凭证
  IF TAB_G_PROJ[] IS NOT INITIAL.
    SELECT BUKRS   "公司代码
           BELNR AS BELNR1
           BUZEI
           OBJNR   "对象号
           GJAHR   "年度
           REFBN AS BELNR   "凭证号
           BUDAT   "记账日期
           KSTAR   "成本要素
           WOGBTR  "本位币
           SGTXT
    FROM COVP
    INTO CORRESPONDING FIELDS OF TABLE TAB_G_COVP
    FOR ALL ENTRIES IN TAB_G_PROJ
    WHERE KOKRS = 'YHGP' "控制范围
      AND LEDNR = '00'
      AND BUKRS = TAB_G_PROJ-VBUKR "公司
      AND OBJNR = TAB_G_PROJ-OBJNR "对象
      AND VERSN = '000'
      AND AWTYP = 'BKPF'
      AND WRTTP = '04'
      AND BUDAT < G_DATE "凭证日期
      AND AWREF_REV = ''
              %_HINTS
        DB2    '&SUBSTITUTE VALUES&'
        ORACLE '&SUBSTITUTE VALUES&'.
  ENDIF.

*成本要素
  IF TAB_G_COVP[] IS NOT INITIAL.
    SELECT SAKNR   "成本要素
           TXT20   "成本要素名称
    FROM SKAT
    INTO TABLE TAB_G_SKAT
    FOR ALL ENTRIES IN TAB_G_COVP
    WHERE KTOPL = 'YHGP'  "控制范围
      AND SPRAS = SY-LANGU "语言
      AND SAKNR = TAB_G_COVP-KSTAR.   "成本要素
  ENDIF.

  LOOP AT TAB_G_COVP.
*判断是否有现金,银行科目
    SELECT SINGLE *
    FROM BSEG
    WHERE BUKRS = TAB_G_COVP-BUKRS  "公司
      AND BELNR = TAB_G_COVP-BELNR  "凭证号
      AND GJAHR = TAB_G_COVP-GJAHR  "年度
      AND HKONT BETWEEN '0002000001' AND '0002109999'."科目
    IF SY-SUBRC <> 0.
*判断是否有供应商
      SELECT SINGLE *
      FROM BSEG
      WHERE BUKRS = TAB_G_COVP-BUKRS "公司
        AND BELNR = TAB_G_COVP-BELNR "凭证号
        AND GJAHR = TAB_G_COVP-GJAHR "年度
        AND LIFNR <> ''.             "供应商
      IF SY-SUBRC <> 0.
        DELETE TAB_G_COVP.
      ELSE.
*成本要素名称
        READ TABLE TAB_G_SKAT WITH KEY SAKNR = TAB_G_COVP-KSTAR.   "成本要素
        IF SY-SUBRC = 0.
          TAB_G_COVP-TXT20 = TAB_G_SKAT-TXT20."成本要素名称
          MODIFY TAB_G_COVP.
        ENDIF.
      ENDIF.
    ELSE.
*成本要素名称
      READ TABLE TAB_G_SKAT WITH KEY SAKNR = TAB_G_COVP-KSTAR.   "成本要素
      IF SY-SUBRC = 0.
        TAB_G_COVP-TXT20 = TAB_G_SKAT-TXT20."成本要素名称
        MODIFY TAB_G_COVP.
      ENDIF.
    ENDIF.
    CLEAR:TAB_G_COVP.
  ENDLOOP.
  SORT TAB_G_COVP BY OBJNR BELNR GJAHR.
  APPEND LINES OF TAB_G_COVP TO TAB_G_COVPDEL.

  CLEAR: TAB_G_COVP-BELNR1,   "凭证号
         TAB_G_COVP-BUDAT,   "记账日期
         TAB_G_COVP-KSTAR,   "成本要素
         TAB_G_COVP-SGTXT.   " 文本
  MODIFY TAB_G_COVP TRANSPORTING BELNR1 BUDAT KSTAR SGTXT
                          WHERE BELNR <> ''.
  SORT TAB_G_COVP BY OBJNR BELNR.

*凭证金额汇总
  LOOP AT TAB_G_COVP.
    COLLECT TAB_G_COVP INTO TAB_G_COVPSUM.
    APPEND TAB_G_COVPSUM.
  ENDLOOP.
*删除为空的凭证
  DELETE TAB_G_COVPSUM WHERE BELNR = ''.


  CLEAR:TAB_G_OUT,TAB_G_OUT[].
*无PO凭证金额明细
  LOOP AT TAB_G_COVPSUM.
    READ TABLE TAB_G_PROJ WITH KEY OBJNR = TAB_G_COVPSUM-OBJNR.
    IF SY-SUBRC = 0.
      TAB_G_OUT-VBUKR  = TAB_G_PROJ-VBUKR.            "公司
      TAB_G_OUT-PSPID  = TAB_G_PROJ-PSPID.            "项目定义
      TAB_G_OUT-PSPHI  = TAB_G_PROJ-PSPHI.            "项目定义
      TAB_G_OUT-POST1  = TAB_G_PROJ-POST1.            "项目描述
      TAB_G_OUT-PSPNR  = TAB_G_PROJ-PSPNR.            "WBS号码
      TAB_G_OUT-OBJNR  = TAB_G_PROJ-OBJNR.            "对象号
      TAB_G_OUT-POSID  = TAB_G_PROJ-POSID.            "WBS元素
      TAB_G_OUT-POST2  = TAB_G_PROJ-POST2.            "WBS描述
      TAB_G_OUT-STUFE  = TAB_G_PROJ-STUFE.            "层次
    ENDIF.
*合并同WBS元素及同一凭证不同行项目文本
    LOOP AT TAB_G_COVPDEL  WHERE OBJNR = TAB_G_COVPSUM-OBJNR
                             AND BELNR = TAB_G_COVPSUM-BELNR.
      IF TAB_G_OUT-TXZ01 IS INITIAL.
        CONCATENATE TAB_G_COVPDEL-TXT20 ';' TAB_G_COVPDEL-SGTXT INTO TAB_G_OUT-TXZ01.
      ELSE.
        CONCATENATE TAB_G_OUT-TXZ01 '/'  TAB_G_COVPDEL-TXT20 ';' TAB_G_COVPDEL-SGTXT INTO TAB_G_OUT-TXZ01.
      ENDIF.
      CLEAR:TAB_G_COVPDEL.
    ENDLOOP.
    TAB_G_OUT-EBELN = TAB_G_COVPSUM-BELNR.  "无PO凭证
    TAB_G_OUT-ZNETPR = TAB_G_COVPSUM-WOGBTR. "无PO金额
    TAB_G_OUT-GJAHR = TAB_G_COVPSUM-GJAHR.
    COLLECT TAB_G_OUT.
    CLEAR:TAB_G_OUT,TAB_G_COVPSUM,TAB_G_PROJ.
  ENDLOOP.

* PO金额明细
  LOOP AT TAB_G_EKPOSUM.
    READ TABLE TAB_G_PROJ WITH KEY PSPNR = TAB_G_EKPOSUM-PSPNR.
    IF SY-SUBRC = 0.
      TAB_G_OUT-VBUKR  = TAB_G_PROJ-VBUKR.            "公司
      TAB_G_OUT-PSPID  = TAB_G_PROJ-PSPID.            "项目定义
      TAB_G_OUT-PSPHI  = TAB_G_PROJ-PSPHI.            "项目定义
      TAB_G_OUT-POST1  = TAB_G_PROJ-POST1.            "项目描述
      TAB_G_OUT-PSPNR  = TAB_G_PROJ-PSPNR.            "WBS号码
      TAB_G_OUT-OBJNR  = TAB_G_PROJ-OBJNR.            "对象号
      TAB_G_OUT-POSID  = TAB_G_PROJ-POSID.            "WBS元素
      TAB_G_OUT-POST2  = TAB_G_PROJ-POST2.            "WBS描述
      TAB_G_OUT-STUFE  = TAB_G_PROJ-STUFE.            "层次
    ENDIF.
* 取出PO项目文本
    LOOP AT TAB_G_EKPODEL WHERE PSPNR = TAB_G_EKPOSUM-PSPNR
                            AND EBELN = TAB_G_EKPOSUM-EBELN.
      IF TAB_G_OUT-TXZ01 IS INITIAL.
        TAB_G_OUT-TXZ01 = TAB_G_EKPODEL-TXZ01.
      ELSE.
        CONCATENATE TAB_G_OUT-TXZ01 '/' TAB_G_EKPODEL-TXZ01 INTO TAB_G_OUT-TXZ01.
      ENDIF.
      CLEAR:TAB_G_EKPODEL.
    ENDLOOP.

    TAB_G_OUT-EBELN = TAB_G_EKPOSUM-EBELN.  "PO号
    TAB_G_OUT-ZNETPR = TAB_G_EKPOSUM-NETPR. "PO金额(含税)
    APPEND TAB_G_OUT.
    CLEAR:TAB_G_OUT,TAB_G_PROJ,TAB_G_EKPOSUM.
  ENDLOOP.

  SORT TAB_G_OUT BY PSPHI PSPNR.
  CLEAR:G_NETPR,TAB_G_OUTSUM,TAB_G_OUTSUM[],G_NETPRSUM.
*汇总凭证及PO金额
  LOOP AT TAB_G_OUT.
    G_NETPR = G_NETPR + TAB_G_OUT-ZNETPR.  "WBS金额汇总
    G_NETPRSUM = G_NETPRSUM + TAB_G_OUT-ZNETPR. "项目金额汇总
*汇总同一WBS的凭证及PO金额
    AT END OF PSPNR.
      TAB_G_OUTSUM-PSPNR = TAB_G_OUT-PSPNR.
      TAB_G_OUTSUM-ZNETPR = G_NETPR.
      APPEND TAB_G_OUTSUM.
      CLEAR:G_NETPR,TAB_G_OUTSUM.
    ENDAT.
*汇总同一项目凭证及PO金额
    AT END OF PSPHI.
      TAB_G_OUTSUM-PSPHI = TAB_G_OUT-PSPHI.
      TAB_G_OUTSUM-ZNETPR = G_NETPRSUM.
      APPEND TAB_G_OUTSUM.
      CLEAR:G_NETPRSUM,TAB_G_OUTSUM.
    ENDAT.
  ENDLOOP.

*无凭证的WBS元素
  SORT TAB_G_PROJ BY PSPID POSID.
  APPEND LINES OF TAB_G_PROJ TO TAB_G_OUT.
  SORT TAB_G_OUT BY PSPID POSID EBELN.

  CLEAR:TAB_G_OUTDEL,TAB_G_OUTDEL[],G_CONUT,G_PSPHI.
  LOOP AT TAB_G_OUT.
*计算同一项目的WBS行数
    G_CONUT = G_CONUT + 1.
    IF G_PSPHI <> TAB_G_OUT-PSPHI."不同项目时行数为1
      G_CONUT = 1.
    ENDIF.
    TAB_G_OUT-CON = G_CONUT.

*层级关系
    READ TABLE TAB_G_PSHI WITH KEY  POSNR = TAB_G_OUT-PSPNR.
    IF SY-SUBRC = 0.
      TAB_G_OUT-UP = TAB_G_PSHI-UP.
    ENDIF.

*PO和凭证为空时代表此行为同一WBS多凭证和PO的汇总行.
    IF TAB_G_OUT-EBELN = ''.
      READ TABLE TAB_G_OUTDEL WITH KEY OBJNR = TAB_G_OUT-OBJNR.
      IF SY-SUBRC <> 0.
        APPEND TAB_G_OUT TO TAB_G_OUTDEL.
*项目预算
        SELECT SINGLE WTGES
        FROM BPGE
        INTO TAB_G_OUT-ZBMOUNT
        WHERE OBJNR = TAB_G_OUT-OBJNR
          AND WRTTP = '41'
          AND VORGA = 'KBUD'.
      ENDIF.

* 凭证及合同金额
      READ TABLE TAB_G_OUTSUM WITH KEY PSPNR = TAB_G_OUT-PSPNR.
      IF SY-SUBRC = 0.
        TAB_G_OUT-ZNETPR = TAB_G_OUTSUM-ZNETPR."凭证及合同金额
*差额=预算金额-凭证及PO金额
        TAB_G_OUT-ZEMOUNT = TAB_G_OUT-ZBMOUNT - TAB_G_OUTSUM-ZNETPR. "差额
      ELSE.
*无PO及凭证金额时,直接取预算金额
        TAB_G_OUT-ZEMOUNT = TAB_G_OUT-ZBMOUNT."差额
      ENDIF.
    ENDIF.

    IF TAB_G_OUT-STUFE = '1'."主项目相关处理
      READ TABLE TAB_G_OUTSUM WITH KEY PSPHI = TAB_G_OUT-PSPHI.
      IF SY-SUBRC = 0.
        TAB_G_OUT-ZNETPR = TAB_G_OUTSUM-ZNETPR."凭证及合同金额
*差额=预算金额-凭证及PO金额
        TAB_G_OUT-ZEMOUNT = TAB_G_OUT-ZBMOUNT - TAB_G_OUTSUM-ZNETPR."差额
      ELSE.
*无PO及凭证金额时,直接取预算金额
        TAB_G_OUT-ZEMOUNT = TAB_G_OUT-ZBMOUNT."差额
      ENDIF.

*读取工程相关数据
      SELECT SINGLE EXPSUM        "预计完工金额
        FROM ZPS001
        INTO TAB_G_OUT-EXPSUM
        WHERE PSPID = TAB_G_OUT-PSPID.
      TAB_G_OUT-ID = '@0E@'."主项目的展开标志
      TAB_G_OUT-COLOR = 'C310'."颜色设置
    ELSE.
      TAB_G_OUT-COLOR = 'C100'."颜色设置
    ENDIF.

* WBS相同时,凭证及PO号,描述放入WBS元素及WBS描述字段
    IF G_PSPNR = TAB_G_OUT-PSPNR.
      TAB_G_OUT-POSID = TAB_G_OUT-EBELN.
      TAB_G_OUT-POST2 = TAB_G_OUT-TXZ01.
      TAB_G_OUT-STUFE = TAB_G_OUT-STUFE + 1.
      TAB_G_OUT-COLOR = 'C101'."颜色设置
    ENDIF.

    G_PSPNR = TAB_G_OUT-PSPNR. "WBS编号
    G_PSPHI = TAB_G_OUT-PSPHI. "项目编号

    MODIFY TAB_G_OUT.
    CLEAR:TAB_G_OUT.
  ENDLOOP.

  SORT TAB_G_OUT BY VBUKR PSPHI STUFE DESCENDING.
  CLEAR:TAB_G_OUTID,TAB_G_OUTID[],G_NETPR,G_NETPRSUM,REC_G_OUT.

*把WBS元素的下层WBS元素的PO及凭证金额汇总放入上一层.
  LOOP AT TAB_G_OUT WHERE STUFE <> '1'
                       AND EBELN = ''.
    LOOP AT TAB_G_OUT INTO REC_G_OUT  WHERE UP = TAB_G_OUT-PSPNR
                                        AND EBELN = ''.
      G_NETPR = G_NETPR + REC_G_OUT-ZNETPR.
      CLEAR:REC_G_OUT.
    ENDLOOP.
    TAB_G_OUT-ZNETPR =  TAB_G_OUT-ZNETPR + G_NETPR.
    TAB_G_OUT-ZEMOUNT = TAB_G_OUT-ZBMOUNT - TAB_G_OUT-ZNETPR.
    MODIFY  TAB_G_OUT.
    CLEAR: G_NETPR,TAB_G_OUT.
  ENDLOOP.
  SORT TAB_G_OUT BY VBUKR PSPHI CON ASCENDING.

ENDFORM.                    " FRM_DATA_GET
*&---------------------------------------------------------------------*
*&      Form  CHANGE_TOOLBAR
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM CHANGE_TOOLBAR .

  CALL METHOD G_ALV_TREE->GET_TOOLBAR_OBJECT
    IMPORTING
      ER_TOOLBAR = G_TOOLBAR.

  CHECK NOT G_TOOLBAR IS INITIAL. "could happen if you do not use the
  "standard toolbar

  CALL METHOD G_TOOLBAR->ADD_BUTTON
    EXPORTING
      FCODE     = ''
      ICON      = ''
      BUTN_TYPE = CNTB_BTYPE_SEP.

* add Standard Button to toolbar (for Delete Subtree)
  CALL METHOD G_TOOLBAR->ADD_BUTTON
    EXPORTING
      FCODE     = 'XIZA'
      ICON      = '@49@'
      BUTN_TYPE = CNTB_BTYPE_BUTTON
      TEXT      = '下载数据'
      QUICKINFO = TEXT-901.   "Delete subtree
ENDFORM.                    " CHANGE_TOOLBAR
*&---------------------------------------------------------------------*
*&      Form  REGISTER_EVENTS_TOOLBAR
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM REGISTER_EVENTS_TOOLBAR .
  DATA: IT_EVENTS TYPE CNTL_SIMPLE_EVENTS,
        I_EVENT TYPE CNTL_SIMPLE_EVENT,
        I_EVENT_RECEIVER TYPE REF TO LCL_TOOLBAR_EVENT_RECEIVER.

  CALL METHOD G_ALV_TREE->GET_REGISTERED_EVENTS
    IMPORTING
      EVENTS = IT_EVENTS.

* register events on frontend
  CALL METHOD G_ALV_TREE->SET_REGISTERED_EVENTS
    EXPORTING
      EVENTS                    = IT_EVENTS
    EXCEPTIONS
      CNTL_ERROR                = 1
      CNTL_SYSTEM_ERROR         = 2
      ILLEGAL_EVENT_COMBINATION = 3.
  IF SY-SUBRC <> 0.
    MESSAGE X208(00) WITH 'ERROR'.                          "#EC NOTEXT
  ENDIF.

  CREATE OBJECT I_EVENT_RECEIVER.
  SET HANDLER I_EVENT_RECEIVER->ON_FUNCTION_SELECTED FOR G_TOOLBAR.
ENDFORM.                    " REGISTER_EVENTS_TOOLBAR
*&---------------------------------------------------------------------*
*&      Form  XIZA_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM XIZA_DATA .
  DATA: V_PASS_PATH1 LIKE RLGRAP-FILENAME .
  DATA: V_PASS_PATH TYPE STRING .
  DATA: FILENAME TYPE STRING .
  DATA: ACTION TYPE I.
  DATA:G_STUFE LIKE PRPS-STUFE.

*抬头数据
  CLEAR:TAB_G_XIZA,TAB_G_XIZA[],GS_FCAT.
  TAB_G_XIZA-TEXT = 'WBS元素/合同号/凭证号'.
  APPEND TAB_G_XIZA.
  LOOP AT GT_FCAT INTO GS_FCAT.
    TAB_G_XIZA-TEXT = GS_FCAT-SELTEXT.
    APPEND TAB_G_XIZA.
    CLEAR:GS_FCAT,TAB_G_XIZA.
  ENDLOOP.

*项目数据
  CLEAR:TAB_G_XIZAITEM,TAB_G_XIZAITEM[],GS_WBS,G_STUFE.
  LOOP AT GT_WBS INTO GS_WBS.
    IF  G_STUFE IS NOT INITIAL.
      IF GS_WBS-STUFE = 1.
        IF GS_WBS-STUFE <> G_STUFE.
          APPEND TAB_G_XIZAITEM.
        ENDIF.
      ENDIF.
    ENDIF.
    TAB_G_XIZAITEM-POSID   = GS_WBS-POSID. "WBS元素
    TAB_G_XIZAITEM-POST2   = GS_WBS-POST2. "WBS描述
    TAB_G_XIZAITEM-ZBMOUNT = GS_WBS-ZBMOUNT."预算金额(Budget)
    TAB_G_XIZAITEM-ZNETPR  = GS_WBS-ZNETPR. "PO总金额(含税)
    TAB_G_XIZAITEM-ZEMOUNT = GS_WBS-ZEMOUNT."剩余预算金额
    TAB_G_XIZAITEM-EXPSUM  = GS_WBS-EXPSUM. "预计完工金额

    CONDENSE:TAB_G_XIZAITEM-ZBMOUNT,TAB_G_XIZAITEM-ZNETPR,TAB_G_XIZAITEM-EXPSUM, TAB_G_XIZAITEM-ZEMOUNT.
    APPEND TAB_G_XIZAITEM.
    G_STUFE = GS_WBS-STUFE.
    CLEAR:GS_WBS,TAB_G_XIZAITEM.
  ENDLOOP.

  CLEAR FILENAME .
  CALL FUNCTION 'GUI_FILE_SAVE_DIALOG'
    EXPORTING
      FILE_FILTER       = '.XLS'
      DEFAULT_EXTENSION = 'DAT'
      DEFAULT_FILE_NAME = 'PS项目工程月报表'
    IMPORTING
      FULLPATH          = V_PASS_PATH
      USER_ACTION       = ACTION.
  IF ACTION <> 9 .
    V_PASS_PATH1 = V_PASS_PATH .
    CALL FUNCTION 'MS_EXCEL_OLE_STANDARD_DAT'
      EXPORTING
        FILE_NAME  = V_PASS_PATH1
      TABLES
        DATA_TAB   = TAB_G_XIZAITEM[]
        FIELDNAMES = TAB_G_XIZA.
  ENDIF.
ENDFORM.                    " XIZA_DATA

 

posted @ 2017-12-01 11:05  明大叔  阅读(3291)  评论(0编辑  收藏  举报