ABAP OO - ALV_TREE例程

大步甩起來~發表於2020-12-25

專案上比較少有用到ALV_TREE的報表功能,剛好專案上有寫了一次,也查閱大量的範例,整合了一寫法,給自己做一下筆記。

程式包含功能按鈕,按鈕下拉,F4幫助,讀取選中行,欄位雙擊觸發事件,欄位前置圖示,更新節點,獲取節點資料,獲取全部子節點,遞迴演算法,DMS模組:建立文件功能,建立文件連結,SNRO建立流水號,快取資料,下次使用者載入進來繼續操作。
在這裡插入圖片描述

*&---------------------------------------------------------------------*
*& Report ZPLM001
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zplm001.
TABLES:sscrfields,zplm001.
TYPE-POOLS: icon.
TYPES:BEGIN OF ty_disp,
        xh            TYPE char20,
        dh            TYPE char20,
        dhmc          TYPE char20,
        cl            TYPE char20,
        sszp          TYPE char20,
        sl            TYPE char20,
        zsl           TYPE char20,
        bz            TYPE char20,
        jth           TYPE char20,
        matnr         TYPE char20,
        o_matnr       TYPE char20,
        zl            TYPE char20,
        "EXCEL上傳資料
        stuas         TYPE icon_d,
        doknr         TYPE draw-doknr, "文件編號
        dokar         TYPE draw-dokar, "文件型別
        dokvr         TYPE draw-dokvr, "文件版本
        doktl         TYPE draw-doktl, "憑證部分 3位數
        dktxt         TYPE drat-dktxt, "文件描述
        zbod          TYPE icon_d,
        bmeng         TYPE stko-bmeng,
        bmein         TYPE stko-bmein,
        dokst         TYPE draw-dokst, "文件狀態
        zcomm         TYPE icon_d, "下達
        datuv         TYPE stko-datuv, "有效期起
        begru         TYPE draw-begru, "許可權組
        dwnam         TYPE draw-dwnam, "使用者
        g_matnr       TYPE mara-matnr,
        maktx         TYPE makt-maktx,
        l_matnr_image TYPE tv_image,
        zxh           TYPE n LENGTH 5,
        flag          TYPE n LENGTH 5,
      END OF ty_disp,
      BEGIN OF ty_stuas,
        sel   TYPE c,
        doknr TYPE draw-doknr, "文件編號
        dokar TYPE draw-dokar, "文件型別
        dokvr TYPE draw-dokvr, "文件版本
        doktl TYPE draw-doktl, "憑證部分 3位數
        dktxt TYPE drat-dktxt, "文件描述
      END OF ty_stuas,
      BEGIN OF ty_link,
        sel   TYPE c,
        doknr TYPE draw-doknr, "文件編號
        dokar TYPE draw-dokar, "文件型別
        dokvr TYPE draw-dokvr, "文件版本
        doktl TYPE draw-doktl, "憑證部分 3位數
        dktxt TYPE drat-dktxt, "文件描述
        dokob TYPE drad-dokob,
        objky TYPE drad-objky,
        maktx TYPE makt-maktx,
      END OF ty_link.

*----------------------------------------------------------------------*
* Global Data Declaration
*----------------------------------------------------------------------*
DATA:wt_disp TYPE TABLE OF ty_disp, "全域性內表 ,全域性必須保持為空表,為 TREE ALV 準備
     ws_disp TYPE ty_disp.
DATA:gt_disp TYPE TABLE OF ty_disp, "處理全域性資料
     gs_disp TYPE ty_disp.
DATA:gs_fcat TYPE lvc_s_fcat,
     gt_fcat TYPE lvc_t_fcat.
DATA:lcl_container TYPE REF TO cl_gui_container, "容器類引用變數
     lcl_tree      TYPE REF TO cl_gui_alv_tree, "樹形ALV控制器引用變數
     lcl_layout    TYPE REF TO cl_salv_layout.
DATA:ok_code   TYPE sy-ucomm, "獲取100螢幕觸發的功能碼
     save_code TYPE sy-ucomm.
DATA:g_toolbar TYPE REF TO cl_gui_toolbar.
DATA:g_dh_key TYPE lvc_nkey.
*&---------------------------------------------------------------------*
*&事件接受類定義
*&---------------------------------------------------------------------*
CLASS lcl_handle DEFINITION.

  PUBLIC SECTION.
    "定義雙擊節點事件觸發時的處理方法
    METHODS handle_node_dclick
                  FOR EVENT node_double_click OF cl_gui_alv_tree
      IMPORTING node_key sender.
    "其中SENDER這個引數是一個隱式的事件引數,是由ABAP物件執行系統提供,它指向了觸發這個事件的例項,可以直接使用它來呼叫這個例項的方法。
    METHODS: on_function_selected  "選中行
                  FOR EVENT function_selected OF cl_gui_toolbar
      IMPORTING fcode.

    METHODS:on_toolbar_dropdown"標題欄
                  FOR EVENT dropdown_clicked OF cl_gui_toolbar
      IMPORTING fcode
                  posx
                  posy.

    METHODS handle_item_double_click"雙擊行專案
                  FOR EVENT item_double_click OF cl_gui_alv_tree
      IMPORTING fieldname node_key .

ENDCLASS.
CLASS lcl_handle IMPLEMENTATION.

  "定義處理方法的具體實施
  METHOD handle_node_dclick.
    DATA: lt_children TYPE lvc_t_nkey.
*檢查被點選的NODE幾點下面有無子節點,有則展開節點。
    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.

*
  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 'DELETE'.
* Determine which line is selected
        CALL METHOD lcl_tree->get_selected_nodes
          CHANGING
            ct_selected_nodes = lt_selected_nodes.


        CALL METHOD cl_gui_cfw=>flush.
        .
        READ TABLE lt_selected_nodes INTO l_selected_node INDEX 1.
        IF sy-subrc <> 0.

          MESSAGE i000(0k) WITH '請選擇一行節點.'(900).
        ENDIF.
        CALL FUNCTION 'POPUP_TO_CONFIRM_STEP'
          EXPORTING
            textline1      = '準備刪除選擇的資料'(902)
            textline2      = '刪除此資料及附屬的子資料?'(903)
            titel          = '確認'(904)
            cancel_display = ' '
          IMPORTING
            answer         = l_rc.
        IF l_rc EQ 'J'.
          LOOP AT lt_selected_nodes INTO l_selected_node.
            CALL METHOD lcl_tree->delete_subtree
              EXPORTING
                i_node_key = l_selected_node.
*   update frontend
          ENDLOOP.
          CALL METHOD lcl_tree->frontend_update.
        ENDIF.

      WHEN 'CREATE'.
        PERFORM create_item_bom.”建立文件
      WHEN 'UPDATE'.
        PERFORM update_item_bod.”建立文件結構
      WHEN 'F4_HELP'.
        PERFORM frm_f4_help.”CV03N的F4幫助
      WHEN 'SAVE'.
        PERFORM frm_save_data.”儲存資料
      WHEN 'REFRESH'.
        PERFORM frm_refresh_data.”更新
    ENDCASE.
  ENDMETHOD.
  METHOD  handle_item_double_click.”雙擊事件
*    G_EVENT = 'ITEM_DOUBLE_CLICK'.
    DATA: g_event(30),
          g_node_key  TYPE tv_nodekey,
          g_item_name TYPE tv_itmname.
    g_node_key = node_key.
    g_item_name = fieldname.

    IF g_item_name = 'STUAS'.

      PERFORM display_alv USING g_node_key.”檢視文件
    ENDIF.

    IF g_item_name = 'G_MATNR'.
      PERFORM display_alv_matnr USING g_node_key.”檢視關聯物料
    ENDIF.

    IF g_item_name = 'ZBOD'.
      PERFORM display_alv_bod USING g_node_key.”檢視文件結構
    ENDIF.
  ENDMETHOD.                    "HANDLE_ITEM_DOUBLE_CLICK


  METHOD on_toolbar_dropdown.“標題欄設定
* create contextmenu
    DATA: l_menu       TYPE REF TO cl_ctmenu,
          l_fc_handled TYPE as4flag.

    CREATE OBJECT l_menu.
    CLEAR l_fc_handled.

    CASE fcode .
      WHEN  'CREATE'.
        l_fc_handled = 'X'.
“按鈕下拉框設定
        CALL METHOD l_menu->add_function
          EXPORTING
            fcode = 'CREATE'
            text  = '建立文件'.  "#EC NOTEXT
        CALL METHOD l_menu->add_function
          EXPORTING
            fcode = 'CREATE_1'
            text  = '建立文件新卷號'.  "#EC NOTEXT
        CALL METHOD l_menu->add_function
          EXPORTING
            fcode = 'CREATE_2'
            text  = '建立文件版本'.  "#EC NOTEXT
        CALL METHOD l_menu->add_function
          EXPORTING
            fcode = 'CREATE_3'
            text  = '選擇對應的文件'.  "#EC NOTEXT
        CALL METHOD l_menu->add_function
          EXPORTING
            fcode = 'CREATE_4'
            text  = '檢視關聯的物料'.  "#EC NOTEXT


    ENDCASE.
* show dropdownbox
    IF l_fc_handled = 'X'.
      CALL METHOD g_toolbar->track_context_menu
        EXPORTING
          context_menu = l_menu
          posx         = posx
          posy         = posy.
    ENDIF.

  ENDMETHOD.
ENDCLASS.

*-----------------------------------------------------------------------*
*選擇螢幕定義
*-----------------------------------------------------------------------*
PARAMETERS r1 RADIOBUTTON  GROUP  grp USER-COMMAND sele DEFAULT  'X'."上傳模板
PARAMETERS r2 RADIOBUTTON  GROUP  grp."快取查詢

PARAMETERS p_files TYPE rlgrap-filename MODIF ID m1.

PARAMETERS p_serial TYPE zplm001-zplm_serial MODIF ID  m2.

*應用工具欄按鈕增加  ‘下載模板’
SELECTION-SCREEN FUNCTION KEY 1. "1~5 對應介面5個按鈕"
*應用工具欄按鈕增加  ‘刪除暫存記錄’
SELECTION-SCREEN FUNCTION KEY 2. "1~5 對應介面5個按鈕"

INITIALIZATION.

  sscrfields-functxt_01 = '@0Q@下載模板'.
  sscrfields-functxt_02 = '@11@刪除暫存記錄'.

AT  SELECTION-SCREEN  OUTPUT .
  LOOP  AT  SCREEN .
    CASE  screen-group1.                    "螢幕組
      WHEN  'M1' .
        IF  r1 EQ  'X' .
          screen-active = 1 .                "設定螢幕顯示
        ELSE .
          screen-active = 0 .                "設定螢幕隱藏
        ENDIF .
      WHEN  'M2' .
        IF  r2 EQ  'X' .
          screen-active = 1 .
        ELSE .
          screen-active = 0 .
        ENDIF .
    ENDCASE.
    MODIFY SCREEN.
  ENDLOOP.

AT SELECTION-SCREEN.
  PERFORM frm_screen_pai.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_files."給使用者一個選擇路徑的幫助 pov
  PERFORM frm_get_filename.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_serial."F4
  PERFORM frm_f4 USING 'P_SERIAL'.

START-OF-SELECTION .
*1.從EXCEL上傳的資料
  IF r1 = 'X'.
    PERFORM frm_get_data.
  ELSE.
    PERFORM frm_set_table.
    IF gt_disp IS NOT INITIAL.
*      "處理資料
      PERFORM frm_deal_data.
    ENDIF.
  ENDIF.
  CALL SCREEN 100.

END-OF-SELECTION.
*&---------------------------------------------------------------------*
*& Form FRM_GET_FILENAME
*&---------------------------------------------------------------------*
*& 獲取路徑
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_filename .
*1.獲取本地檔案路勁
  CALL FUNCTION 'WS_FILENAME_GET'
    EXPORTING
*     DEF_FILENAME     = ' '  “預設的檔名稱”
*     DEF_PATH         = ' '   “預設的檔案路徑”
      mask             = 'excel.xls,*.xls.' "excel.xlsx,*.xlsx,
      mode             = 'O' "S 儲存   O開啟
      title            = '開啟檔案'  "視窗的開啟名稱
    IMPORTING
      filename         = p_files
*     RC               =
    EXCEPTIONS
      inv_winsys       = 1
      no_batch         = 2
      selection_cancel = 3
      selection_error  = 4
      OTHERS           = 5.
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SCREEN_PAI
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_screen_pai .
  CASE sscrfields-ucomm .
    WHEN 'FC01'.
      PERFORM frm_download_template . "模板下載
    WHEN 'FC02'.
      PERFORM frm_del_table.
  ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_DOWNLOAD_TEMPLATE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_download_template .
  DATA lv_file TYPE string.
  DATA: lv_objdata     LIKE wwwdatatab,
        lv_obj_name    LIKE wwwdatatab-objid,
        lv_destination LIKE rlgrap-filename,
        lv_objid       LIKE sy-repid,
        lv_subrc       LIKE sy-subrc.
  DATA:l_ret TYPE abap_bool.

  CONSTANTS:c_yes TYPE c VALUE 'X'.
  DATA:g_excel    TYPE ole2_object,
       g_applica  TYPE ole2_object,
       g_sheet    TYPE ole2_object,
       g_cell     TYPE ole2_object,
       g_workbook TYPE ole2_object.
  DATA c_path TYPE char128.

*1.獲取檔案路徑
  CALL FUNCTION 'WS_FILENAME_GET'
    EXPORTING
*     DEF_FILENAME     = ' '
*     DEF_PATH         = ' '
      mask             = ',EXCEL,*.xls.'
      mode             = 'S'
      title            = '選擇檔案 '
    IMPORTING
      filename         = lv_file
*     RC               =
    EXCEPTIONS
      inv_winsys       = 1
      no_batch         = 2
      selection_cancel = 3
      selection_error  = 4
      OTHERS           = 5.
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.

  CHECK lv_file IS NOT INITIAL .

*2.將內表下載到檔案指定路徑的檔案中

  CALL METHOD cl_gui_frontend_services=>file_exist
    EXPORTING
      file                 = lv_file
    RECEIVING
      result               = l_ret  
    EXCEPTIONS
      cntl_error           = 1
      error_no_gui         = 2
      wrong_parameter      = 3
      not_supported_by_gui = 4
      OTHERS               = 5.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    EXIT.
  ENDIF.
  IF sy-subrc = 0.
    lv_obj_name = 'ZPLM001'.
    c_path = lv_file.
    SELECT relid objid
      FROM wwwdata
      INTO  CORRESPONDING FIELDS OF lv_objdata
      UP TO 1 ROWS
      WHERE srtf2 = 0 AND relid = 'MI'
        AND objid = lv_obj_name.
    ENDSELECT.
    CALL FUNCTION 'DOWNLOAD_WEB_OBJECT'
      EXPORTING
        key         = lv_objdata
        destination = c_path
      IMPORTING
        rc          = lv_subrc.

  ENDIF.

  CALL METHOD OF
    g_workbook
    'open'
    EXPORTING
      #1 = c_path.

  CALL METHOD OF
      g_excel
      'worksheets' = g_sheet
    EXPORTING
      #1           = 1.
  CALL METHOD OF
    g_sheet
    'activate'.

  SET PROPERTY OF g_excel 'visible' = 1.

  FREE OBJECT g_sheet.
  FREE OBJECT g_applica.
  FREE OBJECT g_workbook.
  FREE OBJECT g_excel.



ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_DATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_data .

*2.從檔案中獲取資料
  DATA  lt_raw TYPE truxs_t_text_data .
  CHECK p_files IS NOT INITIAL.
*EXCEL檔案上傳
  CALL FUNCTION 'TEXT_CONVERT_XLS_TO_SAP'
    EXPORTING
      i_field_seperator    = 'X'
      i_line_header        = 'X'
      i_tab_raw_data       = lt_raw
      i_filename           = p_files
    TABLES
      i_tab_converted_data = gt_disp
    EXCEPTIONS
      conversion_failed    = 1
      OTHERS               = 2.
  DELETE gt_disp INDEX 1.

  IF gt_disp IS NOT INITIAL.
    "處理資料
    PERFORM frm_deal_data.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
  SET PF-STATUS 'MAIN100'.
  SET TITLEBAR 'TITLE'.

  IF lcl_tree IS INITIAL.
    PERFORM frm_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'
          txt1  = 'Internal error:'
          txt2  = 'A method in the automation queue'
          txt3  = 'caused a failure.'.
    ENDIF.
  ENDIF.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Form FRM_INIT_TREE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_init_tree .
  DATA:ls_disvariant TYPE disvariant.
  "1.例項化容器物件
  lcl_container = cl_gui_container=>screen0.

  "2.例項化TREE控制器

  CREATE OBJECT lcl_tree
    EXPORTING
      parent                      = lcl_container "繫結容器
      node_selection_mode         = cl_gui_column_tree=>node_sel_mode_multiple " SINGLE單選 MULTIPLE 多選
      item_selection              = 'X'
      no_html_header              = 'X'
*     MC_FC_SAVE_VARIANT          = '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 e208(00) WITH '例項化ALV TREE控制器失敗!'.     "
  ENDIF.

  "3.設定NODE描述欄位資訊
  DATA l_hierarchy_header TYPE treev_hhdr.
  PERFORM build_hierarchy_header CHANGING l_hierarchy_header.
  "4.設定ALV欄位
  PERFORM frm_fillfield USING: 'XH' '序號',
                               'DH' '代號',
                               'DHMC' '代號名稱',
                               'CL' '材料',
                               'SSZP' '所屬裝配',
                               'SL' '數量',
                               'ZSL' '總數量',
                               'BZ' '備註',
                               'JTH' '舊圖號',
                               'MATNR' '物料編號',
                               'O_MATNR' '舊物料號',
                               'ZL' '重量',
                               'STUAS' '對應狀態',
                               'DOKNR' '文件編號',
                               'DOKAR' '文件型別',
                               'DOKVR' '文件版本',
                               'DOKTL' '憑證部分',
                               'DKTXT' '文件描述',
                               'ZBOD' '文件/BOD',
                               'BMENG' 'BOD數量',
                               'DOKST' '文件狀態',
                               'ZCOMM ' '下達標識',
                               'DATUV' '有效期起',
                               'BEGRU' '許可權組',
                               'DWNAM' '使用者',
                               'G_MATNR' '關聯物料',
*                               'L_MATNR_IMAGE' '關聯物料',
                               'MAKTX' '物料描述'.
  "設定layout
  ls_disvariant-report = sy-repid.
  "5設定ALV顯示欄位
  CALL METHOD lcl_tree->set_table_for_first_display
    EXPORTING
      is_hierarchy_header = l_hierarchy_header
      is_variant          = ls_disvariant
      i_default           = 'X'
      i_save              = 'X'
    CHANGING
      it_fieldcatalog     = gt_fcat
      it_outtab           = wt_disp. "此表必須一直為空,且為全域性變數

  "6.設定根節點,填充葉節點資料
  PERFORM create_hierarchy.
  "7.擴充套件標準工具欄的功能
  PERFORM change_toolbar.
  "8.註冊事件
  PERFORM register_events.
* 更新彙總欄位
  CALL METHOD lcl_tree->update_calculations.
*前端顯示資料
  CALL METHOD lcl_tree->frontend_update.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form BUILD_HIERARCHY_HEADER
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      <-- L_HIERARCHY_HEADER
*&---------------------------------------------------------------------*
FORM build_hierarchy_header  CHANGING p_hierarchy_header TYPE treev_hhdr.
  p_hierarchy_header-heading = '代號'.
  p_hierarchy_header-tooltip = '節點依據'.
  p_hierarchy_header-width = 50.
  p_hierarchy_header-width_pix = ''.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_FILLFIELD
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> P_
*&      --> P_
*&---------------------------------------------------------------------*
FORM frm_fillfield  USING  p_fieldname TYPE lvc_fname
                           p_coltext TYPE lvc_txtcol.

  CLEAR gs_fcat.
  gs_fcat-fieldname = p_fieldname.
  gs_fcat-coltext = p_coltext.
  gs_fcat-outputlen = '20'.
  IF p_fieldname = 'DATUV'.
    gs_fcat-no_zero = 'X'.
  ENDIF.
  IF p_fieldname = 'G_MATNR'.
    gs_fcat-convexit = 'ALPHA'.
  ENDIF.
  IF p_fieldname = 'STUAS' OR p_fieldname = 'ZBOD' OR p_fieldname = 'ZCOMM'.
    gs_fcat-icon = 'X'.
  ENDIF.
  IF  p_fieldname = 'XH' OR p_fieldname = 'DH' .
    gs_fcat-no_out = 'X'."隱藏右側輸出的XH/DH欄位
  ENDIF.
  IF p_fieldname = 'l_MATNR_IMAGE'.
    gs_fcat-icon = 'X'.
  ENDIF.
  APPEND gs_fcat TO gt_fcat.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form CREATE_HIERARCHY
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM create_hierarchy .
  DATA:lasr_dh TYPE char20.
  DATA:l_dh_key TYPE lvc_nkey.
  DATA l_node_text TYPE lvc_value.
  DATA l_top_key   TYPE lvc_nkey.
  DATA:lt_disp TYPE TABLE OF ty_disp,
       ls_disp TYPE ty_disp.
  CLEAR:ws_disp.
  DATA: l_layout_node  TYPE lvc_s_layn,
        lt_layout_item TYPE lvc_t_layi,
        ls_layout_item TYPE lvc_s_layi.
  DATA:lv_num TYPE i.
  DATA:lv_last TYPE i VALUE '99999'.
  "確認子檔 父檔關係
*--------此段邏輯根據距離遠近判斷子文件所屬的父文件,原因是有寫相同的父檔指向不同的祖檔,造成 父檔和子檔資料相同引發資料錯亂
  LOOP AT gt_disp INTO gs_disp. "子檔找父檔
    LOOP AT  gt_disp INTO DATA(is_disp) WHERE dh = gs_disp-sszp.
      lv_num = gs_disp-xh - is_disp-xh.
      IF lv_num <= 0 .
        lv_num = '9999'.
      ENDIF.
      IF lv_last > lv_num.
        lv_last = lv_num.
        gs_disp-zxh = is_disp-xh.
      ENDIF.
      CLEAR:is_disp.
    ENDLOOP.
    MODIFY gt_disp FROM gs_disp.
    CLEAR:lv_num,gs_disp,is_disp.
    lv_last = '99999'."復位
  ENDLOOP.
*------------------------------
  SORT gt_disp BY xh.
  LOOP AT gt_disp INTO gs_disp.
    "建立祖節點 所屬裝配欄位為空的為祖檔
    CLEAR l_node_text.
    l_node_text = gs_disp-dh.”節點名稱
    IF gs_disp-sszp IS INITIAL.
      l_dh_key = gs_disp-dh.”	節點KEY值
      IF gs_disp-g_matnr <> gs_disp-l_matnr_image.”前置圖片設定
        l_layout_node-n_image = '@FZ@'.
        ls_layout_item-fieldname = 'G_MATNR'.
        ls_layout_item-t_image = '@FZ@'.
        APPEND ls_layout_item TO lt_layout_item.
      ENDIF.
      CALL METHOD lcl_tree->add_node
        EXPORTING
          i_relat_node_key = ''”祖節點KEY為空
          i_relationship   = cl_gui_column_tree=>relat_last_child
          i_node_text      = l_node_text
          is_outtab_line   = gs_disp
          it_item_layout   = lt_layout_item
          is_node_layout   = l_layout_node
        IMPORTING
          e_new_node_key   = l_dh_key. "節點標識
      G_DH_KEY = l_dh_key."祖節點為全域性節點,因為此程式只會有一個祖節點,方便查詢全部子節點
      CLEAR:l_layout_node, lt_layout_item.
      "遞迴
      PERFORM set_recursive USING gs_disp l_dh_key.”進入遞迴
    ENDIF.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form SET_RECURSIVE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> GS_DISP
*&      --> L_DH_KEY
*&---------------------------------------------------------------------*
FORM set_recursive  USING    p_disp TYPE ty_disp
                             p_dh_key TYPE lvc_nkey.
  DATA:lasr_matnr TYPE mara-matnr.
  DATA:l_dh_key TYPE lvc_nkey.
  DATA l_node_text TYPE lvc_value.
  DATA l_top_key   TYPE lvc_nkey.
  DATA:lt_disp TYPE TABLE OF ty_disp,
       ls_disp TYPE ty_disp.
  DATA: l_layout_node  TYPE lvc_s_layn,
        lt_layout_item TYPE lvc_t_layi,
        ls_layout_item TYPE lvc_s_layi.
  DATA zt_disp LIKE TABLE OF gs_disp.
  DATA:qs_disp LIKE gs_disp.
  DATA:lv_xh TYPE i.
  DATA:lv_flag TYPE c.
  LOOP AT  gt_disp INTO qs_disp WHERE sszp = p_disp-dh
                                    AND zxh = p_disp-xh.XH為文件中的x
序號
    l_node_text = qs_disp-dh.
    IF qs_disp-dh <> qs_disp-sszp.
      l_dh_key = qs_disp-dh.
      IF qs_disp-g_matnr <> qs_disp-l_matnr_image AND qs_disp-l_matnr_image IS NOT INITIAL.
        l_layout_node-n_image = '@FZ@'.
        ls_layout_item-fieldname = 'G_MATNR'.
        ls_layout_item-t_image = '@FZ@'.
        APPEND ls_layout_item TO lt_layout_item.
      ENDIF.
      CALL METHOD lcl_tree->add_node”新增節點
        EXPORTING
          i_relat_node_key = p_dh_key”上一層節點的KEY
          i_relationship   = cl_gui_column_tree=>relat_last_child
          i_node_text      = l_node_text
          is_outtab_line   = qs_disp
          is_node_layout   = l_layout_node
          it_item_layout   = lt_layout_item
        IMPORTING
          e_new_node_key   = l_dh_key. "本層節點標識
      qs_disp-flag = 'X'.
      MODIFY gt_disp FROM qs_disp.
      CLEAR:l_layout_node, lt_layout_item.
      "遞迴
      PERFORM set_recursive USING qs_disp l_dh_key.
    ENDIF.


  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form REGISTER_EVENTS
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM register_events .
  "註冊前端後後端事件
  DATA: lt_events        TYPE cntl_simple_events,
        l_event          TYPE cntl_simple_event,
        l_event_receiver TYPE REF TO lcl_handle.

*1。獲取已註冊的前端事件
  CALL METHOD lcl_tree->get_registered_events
    IMPORTING
      events = lt_events.
  "2.新增前端雙擊時間
  l_event-eventid = cl_gui_column_tree=>eventid_node_double_click.
  APPEND l_event TO lt_events.
  " item double click
  l_event-eventid = cl_gui_column_tree=>eventid_item_double_click.
  l_event-appl_event = 'X'.
  APPEND l_event TO lt_events.
*3.重新設定前端註冊時間
  CALL METHOD lcl_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 e208(00) WITH '註冊前端事件失敗!'.                      "#EC NOTEXT
  ENDIF.
*--------------------
  "4.註冊後端事件
  CREATE OBJECT l_event_receiver.
  SET HANDLER l_event_receiver->handle_node_dclick FOR lcl_tree.
  SET HANDLER l_event_receiver->handle_item_double_click FOR lcl_tree.
  SET HANDLER l_event_receiver->on_function_selected FOR g_toolbar.
  SET HANDLER l_event_receiver->on_toolbar_dropdown FOR g_toolbar.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0100  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.
  save_code = ok_code.
  CLEAR ok_code.

  CASE save_code.
    WHEN 'EXIT' OR 'BACK' OR 'CANC'.
      "釋放容器,退出程式
      CALL METHOD lcl_container->free.
      LEAVE PROGRAM.
    WHEN OTHERS.
      "為正確呼叫工具欄按鈕功能,必須呼叫該方法
      CALL METHOD cl_gui_cfw=>dispatch.

  ENDCASE.

  CALL METHOD cl_gui_cfw=>flush.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Form CHANGE_TOOLBAR
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM change_toolbar .
  CALL METHOD lcl_tree->get_toolbar_object "獲取ALV樹的工具欄例項。
    IMPORTING
      er_toolbar = g_toolbar.

  "使用CL_GUI_TOOLBAR方法修改工具欄:
  CALL METHOD g_toolbar->add_button
    EXPORTING
      fcode     = ''
      icon      = ''
      butn_type = cntb_btype_sep.

  CALL METHOD g_toolbar->add_button
    EXPORTING
      fcode     = 'CREATE'
      icon      = '@0Y@'
      butn_type = cntb_btype_dropdown
      text      = '建立文件'
      quickinfo = '建立文件'.   "Delete subtree

  CALL METHOD g_toolbar->add_button
    EXPORTING
      fcode     = 'DELETE'
      icon      = '@11@'
      butn_type = cntb_btype_button
      text      = '刪除'
      quickinfo = '刪除文件'.   "Delete subtree

  CALL METHOD g_toolbar->add_button
    EXPORTING
      fcode     = 'UPDATE'
      icon      = '@39@'
      butn_type = cntb_btype_button
      text      = '建立/更新文件結構'
      quickinfo = '建立/更新文件結構'.   "Delete subtree

  CALL METHOD g_toolbar->add_button
    EXPORTING
      fcode     = 'F4_HELP'
      icon      = '@VJ@'
      butn_type = cntb_btype_button
      text      = '搜尋幫助'
      quickinfo = '搜尋幫助'.

  CALL METHOD g_toolbar->add_button
    EXPORTING
      fcode     = 'SAVE'
      icon      = '@2L@'
      butn_type = cntb_btype_button
      text      = '儲存'
      quickinfo = '儲存資料並解鎖'.
  CALL METHOD g_toolbar->add_button
    EXPORTING
      fcode     = 'REFRESH'
      icon      = '@42@'
      butn_type = cntb_btype_button
      text      = '重新整理'
      quickinfo = '重新整理'.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form CREATE_ITEM_BOM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM create_item_bom .
  DATA: lt_selected_nodes TYPE lvc_t_nkey,
        l_selected_node   TYPE lvc_nkey,
        l_rc              TYPE c.
  DATA:ls_disp TYPE ty_disp.
  DATA: qt_drat TYPE TABLE OF bapi_doc_drat.
  DATA: lt_drad TYPE TABLE OF bapi_doc_drad.
  DATA:lt_data TYPE  bapi_doc_draw2 .
  DATA:lw_return          TYPE bapiret2.
  DATA:ls_documenttype    TYPE bapi_doc_aux-doctype,
       ls_documentnumber  TYPE bapi_doc_aux-docnumber,
       ls_documentpart    TYPE bapi_doc_aux-docpart,
       ls_documentversion TYPE bapi_doc_aux-docversion.
  DATA:ls_doctype TYPE bapi_doc_aux-doctype,
       ls_docnum  TYPE bapi_doc_aux-docnumber,
       ls_docpart TYPE bapi_doc_aux-docpart,
       ls_docvrs  TYPE bapi_doc_aux-docversion.
  DATA:lw_docdata  TYPE bapi_doc_draw2,
       lw_docdatax TYPE bapi_doc_drawx2.
  DATA:lv_lines TYPE i.
* Determine which line is selected
  CALL METHOD lcl_tree->get_selected_nodes "獲取選中行
    CHANGING
      ct_selected_nodes = lt_selected_nodes.
  CALL METHOD cl_gui_cfw=>flush.

  READ TABLE lt_selected_nodes INTO l_selected_node INDEX 1."判斷有沒有選中
  IF sy-subrc <> 0.
    MESSAGE i000(0k) WITH '請選擇一行節點.'(900).
  ENDIF.
  CLEAR:l_selected_node.
  LOOP AT lt_selected_nodes INTO l_selected_node .


    CALL METHOD lcl_tree->get_outtab_line "獲取行資料
      EXPORTING
        i_node_key    = l_selected_node
      IMPORTING
        e_outtab_line = ls_disp.

    SELECT
      *
    INTO TABLE @DATA(lt_drat)
    FROM drat
    WHERE dokar = 'DRW'
    AND doknr = @ls_disp-dh.


    IF lt_drat IS INITIAL.
      "建立文件
      PERFORM frm_set_data TABLES lt_drad qt_drat CHANGING ls_disp lt_data.
      CALL FUNCTION 'BAPI_DOCUMENT_CREATE2'”建立文件
        EXPORTING
          documentdata         = lt_data
        IMPORTING
          documenttype         = ls_documenttype
          documentnumber       = ls_documentnumber
          documentpart         = ls_documentpart
          documentversion      = ls_documentversion
          return               = lw_return
        TABLES
          documentdescriptions = qt_drat.
*          objectlinks          = lt_drad[].
    ELSE.
      "判斷描述是否一致
      PERFORM frm_set_dart TABLES lt_drat USING ls_disp
                                          CHANGING lw_return
                                                 ls_documenttype
                                                 ls_documentnumber
                                                 ls_documentpart
                                                 ls_documentversion .

    ENDIF.


    IF lw_return-type = 'E'.
      MESSAGE e398(00) WITH lw_return-message.
    ELSE.
      COMMIT WORK AND WAIT.
      MESSAGE s398(00) WITH ls_documentnumber '文件建立成功'.
      ls_disp-stuas = '@01@'.
      ls_disp-doknr = ls_documentnumber.
      ls_disp-dokar = ls_documenttype.
      ls_disp-dokvr = ls_documentversion.
      ls_disp-doktl = ls_documentpart.
      IF ls_documentnumber IS INITIAL.
        ls_disp-dokar   = ls_doctype.
        ls_disp-doknr  = ls_docnum.
        ls_disp-doktl   = ls_docpart.
        ls_disp-dokvr = ls_docvrs.
      ENDIF.

      PERFORM change_item_data USING lv_lines CHANGING ls_disp.”更新節點所對應的內表
注意你更新了節點,但是內表不會更新,需要自己寫程式碼更新

      CALL METHOD cl_gui_cfw=>flush.
      CALL METHOD lcl_tree->change_node “更改節點資料
        EXPORTING
          i_node_key    = l_selected_node
          i_outtab_line = ls_disp.

    ENDIF.
    CLEAR:l_selected_node,ls_disp,ls_documentnumber,ls_documenttype,ls_documentversion,ls_documentpart,ls_doctype,ls_docnum,ls_docpart,ls_docpart,lt_drat,qt_drat.
  ENDLOOP.
  CALL METHOD lcl_tree->frontend_update.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_DEAL_DATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_deal_data .
  DATA:lv_num TYPE i.
  DATA:lv_lines TYPE i.
  LOOP AT gt_disp INTO DATA(ls_disp).
    lv_lines = sy-tabix.
    SELECT COUNT(*) INTO lv_num FROM draw WHERE doknr = ls_disp-dh.
    IF lv_num = 0.
      ls_disp-stuas = '@02@'.
    ELSEIF lv_num = 1.
      ls_disp-stuas = '@01@'.
      ls_disp-zbod = '@F7@'.
    ELSEIF lv_num > 1.
      ls_disp-stuas = '@1F@'.
      ls_disp-zbod = '@F7@'.
    ENDIF.
    CLEAR:lv_num.
    SELECT
      dokar
      doknr
      dokvr
      doktl
      dktxt
     INTO (ls_disp-dokar,ls_disp-doknr,ls_disp-dokvr,ls_disp-doktl,ls_disp-dktxt) UP TO 1 ROWS
     FROM drat
     WHERE dokar = 'DRW'
       AND doknr = ls_disp-dh
       AND dktxt = ls_disp-dhmc
       AND langu = sy-langu.
    ENDSELECT.

    IF ls_disp-doknr IS INITIAL.
      SELECT
         dokar
         doknr
         dokvr
         doktl
         dwnam
         dokst
         begru
       INTO (ls_disp-dokar,ls_disp-doknr,ls_disp-dokvr,ls_disp-doktl,ls_disp-dwnam,ls_disp-dokst,ls_disp-begru) UP TO 1 ROWS
       FROM draw
       WHERE dokar = 'DRW'
         AND doknr = ls_disp-dh.
      ENDSELECT.
    ELSE.
      SELECT
        dwnam
        dokst
        begru
      INTO (ls_disp-dwnam,ls_disp-dokst,ls_disp-begru) UP TO 1 ROWS
      FROM draw
      WHERE dokar = 'DRW'
        AND doknr = ls_disp-doknr
        AND dokvr = ls_disp-dokvr
        AND doktl = ls_disp-doktl.
      ENDSELECT.
    ENDIF.



    PERFORM change_item_data USING lv_lines CHANGING ls_disp.

*    MODIFY gt_disp FROM ls_disp.
    CLEAR:ls_disp.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form DISPLAY_ALV
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM display_alv USING g_node_key  TYPE tv_nodekey.
  DATA:ls_disp TYPE ty_disp.
  DATA:lt_data TYPE TABLE OF ty_stuas,
       ls_data TYPE ty_stuas.
  DATA:lt_fieldcat TYPE slis_t_fieldcat_alv.
  DATA lwa_fieldcat TYPE slis_fieldcat_alv.
  DATA: ls_layout   TYPE slis_layout_alv.
  DATA:lv_lines TYPE i.
  DEFINE add_field.
    CLEAR lwa_fieldcat.
    lwa_fieldcat-col_pos   = &1.
    lwa_fieldcat-fieldname = &2.
    lwa_fieldcat-seltext_l = &3.
*    IF lwa_fieldcat-fieldname = 'SEL'.
*      lwa_fieldcat-checkbox = 'X'.
*    ENDIF.
    APPEND lwa_fieldcat TO lt_fieldcat.
  END-OF-DEFINITION.
  ls_layout-zebra         = 'X'.
  ls_layout-colwidth_optimize    = 'X'.
*  ls_layout-sel_mode      = 'D'.
*  ls_layout-totals_bef    ='X'.
  ls_layout-box_fieldname     = 'SEL'.

  CALL METHOD lcl_tree->get_outtab_line "獲取行資料
    EXPORTING
      i_node_key    = g_node_key
    IMPORTING
      e_outtab_line = ls_disp.
*  IF ls_disp IS NOT INITIAL AND ls_disp-stuas = '@1F@'.
  SELECT
    dokar
    doknr
    dokvr
    doktl
    dktxt
  FROM drat
   INTO CORRESPONDING FIELDS OF TABLE lt_data
  WHERE langu = sy-langu
  AND  doknr = ls_disp-dh.

*  add_field 1  'SEL'  '選擇 '.
  add_field 1  'DOKNR'  '文件編號'.
  add_field 2  'DOKAR'  '文件型別'.
  add_field 3  'DOKVR'  '文件版本'.
  add_field 4  'DOKTL'  '憑證部分'.
  add_field 5  'DKTXT'  '文件描述'.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
    EXPORTING
      it_fieldcat           = lt_fieldcat
      is_layout             = ls_layout
      i_screen_start_column = 10
      i_screen_start_line   = 1
      i_screen_end_column   = 80
      i_screen_end_line     = 25
    TABLES
      t_outtab              = lt_data.
  IF sy-ucomm = '&ONT'.
    READ TABLE lt_data INTO ls_data WITH KEY sel = 'X'.
    IF sy-subrc = 0.
      ls_disp-dokar = ls_data-dokar.
      ls_disp-doknr = ls_data-doknr.
      ls_disp-dokvr = ls_data-dokvr.
      ls_disp-doktl = ls_data-doktl.
      ls_disp-dktxt = ls_data-dktxt.
      ls_disp-stuas = '@01@'.
      PERFORM change_item_data USING lv_lines CHANGING ls_disp.
      CALL METHOD cl_gui_cfw=>flush.
      CALL METHOD lcl_tree->change_node
        EXPORTING
          i_node_key    = g_node_key
          i_outtab_line = ls_disp.
      CALL METHOD lcl_tree->frontend_update.
    ENDIF.
  ENDIF.
*  ENDIF.
  CLEAR:lt_fieldcat,ls_layout.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form CHANGE_ITEM_DATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      <-- LS_DISP
*&---------------------------------------------------------------------*
FORM change_item_data USING lv_lines TYPE i  CHANGING ls_disp TYPE ty_disp.
  DATA:lv_stlnr TYPE dost-stlnr.
  DATA:lv_stlal TYPE dost-stlal.
  DATA:lv_num TYPE i.
  DATA:lv_char TYPE c.
  CLEAR:lv_stlnr,lv_stlal,lv_num.
  ls_disp-zxh = ls_disp-xh.
  IF ls_disp-doknr IS NOT INITIAL.
    CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
      EXPORTING
        input  = ls_disp-doknr
      IMPORTING
        output = ls_disp-doknr.
  ENDIF.
  SELECT COUNT(*) INTO lv_num FROM draw WHERE doknr = ls_disp-doknr.
  IF lv_num = 0.
    ls_disp-stuas = '@02@'.
  ELSEIF lv_num = 1.
    ls_disp-stuas = '@01@'.
    ls_disp-zbod = '@F7@'.
  ELSEIF lv_num > 1.
    ls_disp-stuas = '@1F@'.
    ls_disp-zbod = '@F7@'.
  ENDIF.
  CLEAR:lv_num.
  IF ls_disp-doknr is INITIAL.
    SELECT DOKAR DOKNR DOKVR DOKTL DKTXT FROM drat into ( ls_disp-dokar,ls_disp-doknr,ls_disp-dokvr,ls_disp-doktl,ls_disp-dktxt ) WHERE doknr = ls_disp-dh and DOKAR = 'DRW' and dktxt = ls_disp-dhmc.ENDSELECT.
  ENDIF.
  IF ls_disp-dh  IS NOT INITIAL.
    "取表
    IF ls_disp-doknr IS NOT INITIAL.
      SELECT  stlnr stlal  INTO ( lv_stlnr , lv_stlal ) UP TO 1 ROWS FROM dost WHERE dokar = ls_disp-dokar AND doknr = ls_disp-doknr AND dokvr = ls_disp-dokvr AND doktl = ls_disp-doktl. ENDSELECT.
    ENDIF.
    IF lv_stlnr IS NOT INITIAL.
      SELECT  stlnr stlal INTO ( lv_stlnr , lv_stlal ) UP TO 1 ROWS FROM dost WHERE  doknr = ls_disp-dh . ENDSELECT.
    ENDIF.

    IF lv_stlnr IS NOT INITIAL.
      ls_disp-zbod = '@3M@'.

      "數量
      SELECT SINGLE bmeng FROM stko INTO ls_disp-bmeng WHERE stlty = 'D' AND stlnr = lv_stlnr AND stlal = lv_stlal.
      "有效期起
      SELECT SINGLE datuv FROM stko INTO ls_disp-datuv WHERE stlty = 'D' AND stlnr = lv_stlnr AND stlal = lv_stlal.
    ENDIF.
  ENDIF.

  IF ls_disp-doknr IS NOT INITIAL.
    SELECT SINGLE dokst INTO ls_disp-dokst FROM draw WHERE dokar = ls_disp-dokar AND doknr = ls_disp-doknr AND dokvr = ls_disp-dokvr AND doktl = ls_disp-doktl.
    "BOM數量
    READ TABLE gt_disp INTO DATA(ts_disp) WITH  KEY dh = ls_disp-sszp.
    IF sy-subrc = 0.
      SELECT SINGLE
          stpo~menge
       INTO ls_disp-bmeng
       FROM stpo INNER JOIN dost
       ON stpo~stlnr = dost~stlnr
       WHERE stpo~stlty = 'D'
        AND  dost~dokar = ts_disp-dokar
        AND  dost~dokvr = ts_disp-dokvr
        AND  dost~doknr = ts_disp-doknr
        AND  dost~doktl = ts_disp-doktl
        AND  stpo~dokar = ls_disp-dokar
        AND  stpo~dokvr = ls_disp-dokvr
        AND  stpo~doknr = ls_disp-doknr
        AND  stpo~doktl = ls_disp-doktl.
    ENDIF.
  ENDIF.
  IF ls_disp-dokst IS NOT INITIAL ."文件狀態
    SELECT SINGLE frknz INTO lv_char FROM tdws WHERE dokar = ls_disp-dokar AND dokst = ls_disp-dokst. "ls_disp-zcomm
    IF lv_char = 'X'.
      ls_disp-zcomm = '@5B@'."綠燈
    ENDIF.
    "替換成TDWST得狀態碼
    SELECT SINGLE stabk INTO ls_disp-dokst FROM tdwst WHERE dokst = ls_disp-dokst.
  ENDIF.

  IF ls_disp-doknr IS NOT INITIAL.
    SELECT  objky INTO  ls_disp-g_matnr FROM drad UP TO 1 ROWS WHERE dokar = ls_disp-dokar AND doknr = ls_disp-doknr AND dokvr = ls_disp-dokvr AND doktl = ls_disp-doktl.ENDSELECT.
    SELECT SINGLE dktxt INTO ls_disp-dktxt FROM drat WHERE dokar = ls_disp-dokar AND doknr = ls_disp-doknr AND dokvr = ls_disp-dokvr AND doktl = ls_disp-doktl AND langu = sy-langu .
  ENDIF.
  IF ls_disp-g_matnr IS NOT INITIAL.
    SELECT SINGLE maktx INTO ls_disp-maktx FROM makt WHERE spras = sy-langu AND matnr = ls_disp-g_matnr.
  ENDIF.

  IF ls_disp-doknr IS NOT INITIAL.
    SELECT COUNT(*) INTO lv_num FROM drad WHERE dokar = ls_disp-dokar AND doknr = ls_disp-doknr AND dokvr = ls_disp-dokvr AND doktl = ls_disp-doktl.
    IF lv_num > 1.
      ls_disp-l_matnr_image = '@FZ@' .
    ELSEIF lv_num = 1.
      ls_disp-l_matnr_image = ls_disp-g_matnr.
    ENDIF.
    ls_disp-stuas = '@01@'.
  ENDIF.
  IF ls_disp-doknr IS NOT INITIAL.
    CALL FUNCTION 'CONVERSION_EXIT_ALPHA_OUTPUT'
      EXPORTING
        input  = ls_disp-doknr
      IMPORTING
        output = ls_disp-doknr.
  ENDIF.
  READ TABLE gt_disp INTO DATA(qs_disp) WITH  KEY xh = ls_disp-xh
                                             dh = ls_disp-dh
                                             sszp = ls_disp-sszp.
  IF sy-subrc = 0.
    lv_lines = sy-tabix.
    MODIFY gt_disp FROM ls_disp INDEX lv_lines.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form DISPLAY_ALV_MATNR
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> G_NODE_KEY
*&---------------------------------------------------------------------*
FORM display_alv_matnr  USING  g_node_key.
  DATA:ls_disp TYPE ty_disp.
  DATA:lt_data TYPE TABLE OF ty_link,
       ls_data TYPE ty_link.
  DATA:lt_fieldcat TYPE slis_t_fieldcat_alv.
  DATA lwa_fieldcat TYPE slis_fieldcat_alv.
  DATA: ls_layout   TYPE slis_layout_alv.
  DEFINE add_field.
    CLEAR lwa_fieldcat.
    lwa_fieldcat-col_pos   = &1.
    lwa_fieldcat-fieldname = &2.
    lwa_fieldcat-seltext_l = &3.
    APPEND lwa_fieldcat TO lt_fieldcat.
  END-OF-DEFINITION.
  ls_layout-zebra         = 'X'.
  ls_layout-colwidth_optimize    = 'X'.
  ls_layout-box_fieldname     = 'SEL'.
  CALL METHOD lcl_tree->get_outtab_line "獲取行資料
    EXPORTING
      i_node_key    = g_node_key
    IMPORTING
      e_outtab_line = ls_disp.
  IF ls_disp IS NOT INITIAL AND ls_disp-l_matnr_image = '@FZ@'.
    SELECT
      drad~dokar
      drad~doknr
      drad~dokvr
      drad~doktl
      drad~dokob
      drad~objky
      makt~maktx
    FROM drad
    INNER JOIN makt
    ON makt~matnr = drad~objky
    INTO CORRESPONDING FIELDS OF TABLE lt_data
     WHERE
    doknr = ls_disp-dh
    AND spras = sy-langu.

    LOOP AT lt_data INTO ls_data.
      CALL FUNCTION 'CONVERSION_EXIT_ALPHA_OUTPUT'
        EXPORTING
          input  = ls_data-objky
        IMPORTING
          output = ls_data-objky.
      MODIFY lt_data FROM ls_data.
      CLEAR:ls_data.
    ENDLOOP.

*  add_field 1  'SEL'  '選擇 '.
    add_field 1  'DOKNR'  '文件編號'.
    add_field 2  'DOKAR'  '文件型別'.
    add_field 3  'DOKVR'  '文件版本'.
    add_field 4  'DOKTL'  '憑證部分'.
    add_field 5  'DOKOB'  '連結物件'.
    add_field 6  'OBJKY'  '物料編碼'.
    add_field 7  'MAKTX'  '物料描述'.

    CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
      EXPORTING
        it_fieldcat           = lt_fieldcat
        is_layout             = ls_layout
        i_screen_start_column = 10
        i_screen_start_line   = 1
        i_screen_end_column   = 80
        i_screen_end_line     = 25
      TABLES
        t_outtab              = lt_data.
    IF sy-ucomm = '&ONT'."功能未定
    ENDIF.
  ENDIF.

  CLEAR:lt_fieldcat,ls_layout.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SET_DATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LT_DRAD
*&      --> LT_DRAT
*&      <-- LS_DATA
*&---------------------------------------------------------------------*
FORM frm_set_data  TABLES   lt_drad STRUCTURE bapi_doc_drad
                            lt_drat STRUCTURE bapi_doc_drat
                   CHANGING ls_disp TYPE ty_disp
                            lt_data TYPE bapi_doc_draw2.
  DATA:ls_drat TYPE bapi_doc_drat.
  DATA:ls_drad TYPE bapi_doc_drad.
  lt_data-documenttype = 'DRW'.
  lt_data-documentnumber = ls_disp-dh.
  lt_data-documentversion = '00'.
  lt_data-description = ls_disp-dhmc.
  lt_data-username = sy-uname.
  ls_drat-language = sy-langu.
  CALL FUNCTION 'CONVERSION_EXIT_ISOLA_OUTPUT'
    EXPORTING
      input  = sy-langu
    IMPORTING
      output = ls_drat-language_iso.
  ls_drat-description = ls_disp-dhmc.
  APPEND ls_drat TO lt_drat.
  CLEAR:ls_drat.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form UPDATE_ITEM_BOD
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM update_item_bod .
  DATA: ls_disp TYPE ty_disp.
  DATA: lt_selected_nodes TYPE lvc_t_nkey,
        l_selected_node   TYPE lvc_nkey.
  DATA: lt_doc      TYPE STANDARD TABLE OF bapi_doc_structure,
        ls_doc      TYPE bapi_doc_structure,
        lt_messages TYPE STANDARD TABLE OF messages.
  DATA:lt_nkey TYPE lvc_t_nkey.
  DATA:lv_num TYPE i.
  DATA:lv_lines TYPE i.
  "獲取選擇行節點
  CALL METHOD lcl_tree->get_selected_nodes
    CHANGING
      ct_selected_nodes = lt_selected_nodes.
  CALL METHOD cl_gui_cfw=>flush.
  "檢查節點下是否有 子節點
  lv_num = lines( lt_selected_nodes ).
  IF lv_num > 1.
    MESSAGE e398(00) WITH '建立文件結構時,不能多行選擇,請選中父節點一鍵建立'.
  ENDIF.
  READ TABLE lt_selected_nodes INTO l_selected_node INDEX 1.
  IF sy-subrc = 0.
    CALL METHOD lcl_tree->get_outtab_line "獲取行資料
      EXPORTING
        i_node_key    = l_selected_node
      IMPORTING
        e_outtab_line = ls_disp.
    IF ls_disp-stuas <> '@01@'.
      MESSAGE e398(00) WITH '建立此文件結構,不存在圖號,請檢查'.
    ENDIF.
    IF ls_disp-doknr IS NOT INITIAL.
      READ TABLE gt_disp INTO DATA(ws_disp) WITH KEY sszp = ls_disp-dh.
      IF sy-subrc <> 0.
        "如果沒有就返回報錯
        MESSAGE e398(00) WITH '請選擇組裝圖'.
      ELSE.
        "遞迴找到最底層結構
        CLEAR:ws_disp.
        CALL FUNCTION 'CSAP_DOC_BOM_DELETE'
          EXPORTING
            document           = ls_disp-doknr
            doc_type           = ls_disp-dokar
            doc_part           = ls_disp-doktl
            doc_vers           = ls_disp-dokvr
            fl_no_change_doc   = 'X'
            fl_commit_and_wait = 'X'
          EXCEPTIONS
            error              = 1.
        LOOP AT gt_disp INTO ws_disp WHERE sszp = ls_disp-dh AND stuas = '@01@'.
          IF ws_disp-doknr IS NOT INITIAL.
            lv_lines = sy-tabix.
            CALL FUNCTION 'CSAP_DOC_BOM_DELETE' "刪除此節點下所有的BOD結構
              EXPORTING
                document           = ws_disp-doknr
                doc_type           = ws_disp-dokar
                doc_part           = ws_disp-doktl
                doc_vers           = ws_disp-dokvr
                fl_no_change_doc   = 'X'
                fl_commit_and_wait = 'X'
              EXCEPTIONS
                error              = 1.
            PERFORM change_item_bom  USING ws_disp.
            CLEAR:lv_lines.
            ls_doc-documenttype = ws_disp-dokar.
            ls_doc-documentnumber = ws_disp-doknr.
            ls_doc-documentpart = ws_disp-doktl.
            ls_doc-documentversion = ws_disp-dokvr.
            ls_doc-quantity = ws_disp-sl.
            APPEND ls_doc TO lt_doc.
          ELSE.
            MESSAGE e398(00) WITH ws_disp-dh  '沒有生成文件,請檢查'.
          ENDIF.
        ENDLOOP.
        IF sy-subrc = 0.
          CALL FUNCTION 'API_DOCUMENT_SAVE_BOM'
            EXPORTING
              pf_dokar             = ls_disp-dokar
              pf_doknr             = ls_disp-doknr
              pf_doktl             = ls_disp-doktl
              pf_dokvr             = ls_disp-dokvr
            TABLES
              pt_documentstructure = lt_doc
              pt_messages          = lt_messages
            EXCEPTIONS
              error                = 1
              OTHERS               = 2.
          READ TABLE lt_messages INTO DATA(ls_message) WITH KEY msg_type = 'E'.
          IF sy-subrc = 0.
            ROLLBACK WORK.
            MESSAGE e398(00) WITH ls_message-msg_txt.
          ELSE.
            COMMIT WORK AND WAIT.
            MESSAGE s398(00) WITH '文件結構成功生成,文件未選擇或不存在的圖號未組成'.
*            CALL SCREEN 100.
            "重新整理
            CALL METHOD lcl_tree->get_children "獲取全部子節點
              EXPORTING
                i_node_key         = l_selected_node
              IMPORTING
                et_children        = lt_nkey
              EXCEPTIONS
                historic_error     = 1
                node_key_not_found = 2
                OTHERS             = 3.
            IF sy-subrc <> 0.

            ELSE.
              "更新父節點資料
              CALL METHOD lcl_tree->get_outtab_line "獲取行資料
                EXPORTING
                  i_node_key    = l_selected_node
                IMPORTING
                  e_outtab_line = ls_disp.
              PERFORM change_item_data USING lv_lines CHANGING ls_disp.
              CALL METHOD cl_gui_cfw=>flush.
              CALL METHOD lcl_tree->change_node
                EXPORTING
                  i_node_key    = l_selected_node
                  i_outtab_line = ls_disp.
              CALL METHOD lcl_tree->frontend_update.
              IF lt_nkey IS NOT INITIAL.
                LOOP AT lt_nkey INTO DATA(ls_nkey)."更新子節點資料
                  CLEAR:ls_disp.
                  CALL METHOD lcl_tree->get_outtab_line "獲取行資料
                    EXPORTING
                      i_node_key    = ls_nkey
                    IMPORTING
                      e_outtab_line = ls_disp.
               PERFORM change_item_data USING lv_lines CHANGING ls_disp.
                  CALL METHOD cl_gui_cfw=>flush.
                  CALL METHOD lcl_tree->change_node
                    EXPORTING
                      i_node_key    = ls_nkey
                      i_outtab_line = ls_disp.
                  CALL METHOD lcl_tree->frontend_update.
                ENDLOOP.
              ENDIF.
            ENDIF.
          ENDIF.
        ENDIF.
      ENDIF.
    ELSE.
      MESSAGE e398(00) WITH ls_disp-dh  '沒有生成文件,請檢查'.
    ENDIF.
  ENDIF.


ENDFORM.
*&---------------------------------------------------------------------*
*& Form CHANGE_ITEM_BOM
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> WS_DISP
*&---------------------------------------------------------------------*
FORM change_item_bom  USING ws_disp TYPE ty_disp.
  DATA: ls_doc      TYPE bapi_doc_structure,
        lt_doc      TYPE STANDARD TABLE OF bapi_doc_structure,
        lt_messages TYPE STANDARD TABLE OF messages.
  LOOP AT gt_disp INTO DATA(ls_disp) WHERE sszp = ws_disp-dh AND stuas = '@01@'.
    IF ls_disp-doknr IS NOT INITIAL.
      CALL FUNCTION 'CSAP_DOC_BOM_DELETE'
        EXPORTING
          document           = ls_disp-doknr
          doc_type           = ls_disp-dokar
          doc_part           = ls_disp-doktl
          doc_vers           = ls_disp-dokvr
          fl_no_change_doc   = 'X'
          fl_commit_and_wait = 'X'
        EXCEPTIONS
          error              = 1.
      PERFORM change_item_bom USING ls_disp.
      ls_doc-documenttype = ws_disp-dokar.
      ls_doc-documentnumber = ws_disp-doknr.
      ls_doc-documentpart = ws_disp-doktl.
      ls_doc-documentversion = ws_disp-dokvr.
      ls_doc-quantity = ws_disp-sl.
      APPEND ls_doc TO lt_doc.
    ELSE.
      MESSAGE e398(00) WITH ws_disp-dh  '沒有生成文件,請檢查'.
    ENDIF.
  ENDLOOP.
  IF sy-subrc = 0.
    CALL FUNCTION 'API_DOCUMENT_SAVE_BOM'
      EXPORTING
        pf_dokar             = ws_disp-dokar
        pf_doknr             = ws_disp-doknr
        pf_doktl             = ws_disp-doktl
        pf_dokvr             = ws_disp-dokvr
      TABLES
        pt_documentstructure = lt_doc
        pt_messages          = lt_messages
      EXCEPTIONS
        error                = 1
        OTHERS               = 2.

    READ TABLE lt_messages INTO DATA(ls_message) WITH KEY msg_type = 'E'.
    IF sy-subrc = 0.
      ROLLBACK WORK.
      MESSAGE e398(00) WITH ls_message-msg_txt.
    ELSE.
      COMMIT WORK AND WAIT.
    ENDIF.

  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_F4_HELP
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_f4_help .
  DATA: ls_disp TYPE ty_disp.
  DATA: lt_selected_nodes TYPE lvc_t_nkey,
        l_selected_node   TYPE lvc_nkey.
  DATA:lt_nkey TYPE lvc_t_nkey.
  DATA:lt_ddshretval TYPE TABLE OF ddshretval.
  DATA:lv_lines TYPE i.
  "獲取選擇行節點
  CALL METHOD lcl_tree->get_selected_nodes
    CHANGING
      ct_selected_nodes = lt_selected_nodes.
  CALL METHOD cl_gui_cfw=>flush.
  "檢查節點下是否有 子節點
  READ TABLE lt_selected_nodes INTO l_selected_node INDEX 1.
  IF sy-subrc = 0.
    CALL METHOD lcl_tree->get_outtab_line "獲取行資料
      EXPORTING
        i_node_key    = l_selected_node
      IMPORTING
        e_outtab_line = ls_disp.
  ELSE.
    MESSAGE e398(00) WITH '請選中一行'.
  ENDIF.
  CALL FUNCTION 'F4IF_FIELD_VALUE_REQUEST'
    EXPORTING
      tabname           = 'DRAW'
      fieldname         = 'DOKNR'
      dynpprog          = sy-repid
      dynpnr            = sy-dynnr
      dynprofield       = 'ZCV1'
      stepl             = 0
    TABLES
      return_tab        = lt_ddshretval
    EXCEPTIONS
      field_not_found   = 1
      no_help_for_field = 2
      inconsistent_help = 3
      no_values_found   = 4
      OTHERS            = 5.
  IF sy-subrc = 0.
    LOOP AT lt_ddshretval INTO DATA(ls_ddshretval).
      CASE ls_ddshretval-fieldname.
        WHEN 'DOKNR'.
          ls_disp-doknr = ls_ddshretval-fieldval.
        WHEN 'DOKAR'.
          ls_disp-dokar = ls_ddshretval-fieldval.
        WHEN 'DOKTL' .
          ls_disp-doktl = ls_ddshretval-fieldval.
        WHEN 'DOKVR'.
          ls_disp-dokvr = ls_ddshretval-fieldval.
      ENDCASE.
      IF ls_ddshretval-fieldname = 'DOKNR'.
        ls_disp-doknr = ls_ddshretval-fieldval.
      ELSEIF ls_ddshretval-fieldname = 'DOKAR'.
        ls_disp-dokar = ls_ddshretval-fieldval.
      ENDIF.
    ENDLOOP.

    PERFORM change_item_data USING lv_lines CHANGING ls_disp.


    CALL METHOD cl_gui_cfw=>flush.
    CALL METHOD lcl_tree->change_node
      EXPORTING
        i_node_key    = l_selected_node
        i_outtab_line = ls_disp.
    CALL METHOD lcl_tree->frontend_update.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form DISPLAY_ALV_BOD
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> G_NODE_KEY
*&---------------------------------------------------------------------*
FORM display_alv_bod  USING    g_node_key.
  DATA:ls_disp TYPE ty_disp.
  DATA:lt_data TYPE TABLE OF ty_link,
       ls_data TYPE ty_link.
  DATA:lt_fieldcat TYPE slis_t_fieldcat_alv.
  DATA lwa_fieldcat TYPE slis_fieldcat_alv.
  DATA: ls_layout   TYPE slis_layout_alv.
  DEFINE add_field.
    CLEAR lwa_fieldcat.
    lwa_fieldcat-col_pos   = &1.
    lwa_fieldcat-fieldname = &2.
    lwa_fieldcat-seltext_l = &3.
    APPEND lwa_fieldcat TO lt_fieldcat.
  END-OF-DEFINITION.
  ls_layout-zebra         = 'X'.
  ls_layout-colwidth_optimize    = 'X'.
  CALL METHOD lcl_tree->get_outtab_line "獲取行資料
    EXPORTING
      i_node_key    = g_node_key
    IMPORTING
      e_outtab_line = ls_disp.

  SELECT
    stpo~stlty,
    stpo~stlnr,
    stpo~stpoz,
    stpo~dokar,
    stpo~doknr,
    stpo~dokvr,
    stpo~doktl,
    stpo~posnr,
    stpo~menge,
    drat~dktxt
  FROM stpo
  INNER JOIN dost
  ON dost~stlnr = stpo~stlnr
  LEFT  JOIN drat
    ON stpo~dokar = drat~dokar
   AND stpo~doknr = drat~doknr
   AND stpo~dokvr = drat~dokvr
   AND stpo~doktl = drat~doktl
  INTO TABLE @DATA(lt_stpo)
  WHERE   dost~dokar = @ls_disp-dokar
    AND   dost~doknr = @ls_disp-doknr
    AND   dost~dokvr = @ls_disp-dokvr
    AND   dost~doktl = @ls_disp-doktl
    AND   stpo~stlty = 'D'
    AND drat~langu = @sy-langu.
  SORT lt_stpo BY posnr.
  add_field 1  'POSNR'  '專案號'.
  add_field 2  'DOKNR'  '文件編號'.
  add_field 3  'DOKAR'  '文件型別'.
  add_field 4  'DOKVR'  '文件版本'.
  add_field 5  'DOKTL'  '憑證部分'.
  add_field 6  'DKTXT'  '文件描述'.
  add_field 7  'MENGE'  'BOM數量'.
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
    EXPORTING
      it_fieldcat           = lt_fieldcat
      is_layout             = ls_layout
      i_screen_start_column = 10
      i_screen_start_line   = 1
      i_screen_end_column   = 80
      i_screen_end_line     = 25
    TABLES
      t_outtab              = lt_stpo.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SAVE_DATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_save_data .
  DATA:lt_zplm001 TYPE TABLE OF zplm001,
       ls_zplm001 TYPE zplm001.
  DATA:lv_sernum TYPE char10.
  IF r1 = 'X'.
    "獲取流水號
    CALL FUNCTION 'NUMBER_RANGE_ENQUEUE '
      EXPORTING
        object           = 'ZPLM001'
      EXCEPTIONS
        foreign_lock     = 1
        object_not_found = 2
        system_failure   = 3
        OTHERS           = 4.
    IF sy-subrc EQ 0 .
      CALL FUNCTION 'NUMBER_GET_NEXT '
        EXPORTING
          nr_range_nr             = '01'                "這個就是維護的間隔號
          object                  = 'ZPLM001' "這個就是流水號物件
        IMPORTING
          number                  = lv_sernum "獲得的流水號
        EXCEPTIONS
          interval_not_found      = 1
          number_range_not_intern = 2
          object_not_found        = 3
          quantity_is_0           = 4
          quantity_is_not_1       = 5
          interval_overflow       = 6
          buffer_overflow         = 7
          OTHERS                  = 8.
      IF sy-subrc EQ 0.

        CALL FUNCTION 'NUMBER_RANGE_DEQUEUE '
          EXPORTING
            object           = 'ZPLM001'
          EXCEPTIONS
            object_not_found = 1
            OTHERS           = 2.

      ENDIF.
    ELSE.
      RAISE num_range_error .
    ENDIF.
  ELSE.
    lv_sernum = p_serial.
  ENDIF.

  LOOP AT gt_disp INTO DATA(ls_disp).
    MOVE-CORRESPONDING ls_disp TO ls_zplm001.
    ls_zplm001-mandt = sy-mandt.
    ls_zplm001-bname = sy-uname.
    ls_zplm001-trdat = sy-datum.
    ls_zplm001-zplm_serial = lv_sernum.
    APPEND ls_zplm001 TO lt_zplm001.
    CLEAR:ls_zplm001.
  ENDLOOP.
  "解鎖
  IF r2 = 'X'.
    CALL FUNCTION 'DEQUEUE_EZ_ZPLM001'
      EXPORTING
        mode_zplm001 = 'E'
        mandt        = sy-mandt
        zplm_serial  = p_serial
      .
  ENDIF.

  IF lt_zplm001 IS NOT INITIAL.
    MODIFY zplm001 FROM TABLE lt_zplm001.
    IF sy-subrc = 0.
      COMMIT WORK AND WAIT.
      MESSAGE s398(00) WITH '儲存成功'.
    ELSE.
      ROLLBACK WORK.
    ENDIF.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_DEL_TABLE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_del_table .
  DATA:BEGIN OF ls_zplm001,
         sel TYPE c.
      INCLUDE TYPE zplm001.
  DATA END OF ls_zplm001.
  DATA:lt_zplm001 LIKE TABLE OF ls_zplm001.
  DATA:lt_fieldcat TYPE slis_t_fieldcat_alv.
  DATA lwa_fieldcat TYPE slis_fieldcat_alv.
  DATA: ls_layout   TYPE slis_layout_alv.
  DATA: l_rc TYPE c.
  DEFINE add_field.
    CLEAR lwa_fieldcat.
    lwa_fieldcat-col_pos   = &1.
    lwa_fieldcat-fieldname = &2.
    lwa_fieldcat-seltext_l = &3.
    APPEND lwa_fieldcat TO lt_fieldcat.
  END-OF-DEFINITION.
  ls_layout-zebra         = 'X'.
  ls_layout-colwidth_optimize    = 'X'.
  ls_layout-box_fieldname = 'SEL'.
  CLEAR:l_rc.
  SELECT
    zplm_serial,
    dh,
    sszp,
    cl,
    bname,
    trdat
  FROM zplm001
  INTO CORRESPONDING FIELDS OF TABLE @lt_zplm001
  WHERE bname = @sy-uname
  AND sszp = @space.


*  add_field 1  'SEL'  '選擇 '.
  add_field 1  'ZPLM_SERIAL'  'CAXA流水號'.
  add_field 2  'DH'  '代號'.
  add_field 3  'SSZP'  '所屬裝配'.
  add_field 4  'CL'  '材料'.
  add_field 5  'BNAME'  '使用者名稱稱'.
  add_field 6  'TRDAT'  '更改日期'.


  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
    EXPORTING
      it_fieldcat           = lt_fieldcat
      is_layout             = ls_layout
      i_screen_start_column = 10
      i_screen_start_line   = 1
      i_screen_end_column   = 80
      i_screen_end_line     = 25
    TABLES
      t_outtab              = lt_zplm001.
  IF sy-ucomm = '&ONT'.
    READ TABLE lt_zplm001 INTO ls_zplm001 WITH KEY sel = 'X'.
    IF sy-subrc = 0.
      CALL FUNCTION 'POPUP_TO_CONFIRM_STEP'
        EXPORTING
          textline1      = '準備刪除快取的資料'(902)
          textline2      = '刪除此資料會導致您儲存的資料消失,您確認已經處理完資料了?'(903)
          titel          = '確認'(904)
          cancel_display = ' '
        IMPORTING
          answer         = l_rc.
      IF l_rc EQ 'J'.
        DELETE FROM zplm001 WHERE zplm_serial = ls_zplm001-zplm_serial.
        IF sy-subrc = 0.
          COMMIT WORK AND WAIT.
          MESSAGE s398(00) WITH '刪除成功'.
        ELSE.
          MESSAGE e398(00) WITH '刪除失敗'.
        ENDIF.
      ENDIF.

    ENDIF.
  ENDIF.

  CLEAR:lt_fieldcat,ls_layout.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SET_TABLE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_set_table .
  IF r2 = 'X'.
    CALL FUNCTION 'ENQUEUE_EZ_ZPLM001'
      EXPORTING
        mode_zplm001   = 'E'
        mandt          = sy-mandt
        zplm_serial    = p_serial
      EXCEPTIONS
        foreign_lock   = 1
        system_failure = 2
        OTHERS         = 3.
    IF sy-subrc <> 0.
*** Implement suitable error handling here
    ENDIF.
  ENDIF.
  SELECT
    *
  FROM zplm001
  INTO TABLE @DATA(lt_zplm001)
  WHERE zplm_serial = @p_serial.
  SORT lt_zplm001 BY xh.
  LOOP AT lt_zplm001 INTO DATA(ls_zplm001).
    MOVE-CORRESPONDING ls_zplm001 TO gs_disp.
    APPEND gs_disp TO gt_disp.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_F4
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      <-- P_SERIAL
*&---------------------------------------------------------------------*
FORM frm_f4  USING ls_serial TYPE help_info-dynprofld.
  DATA: BEGIN OF lt_value OCCURS 0,
          zplm_serial LIKE zplm001-zplm_serial,
          dh          LIKE zplm001-dh,
          sszp        LIKE zplm001-sszp,
          bname       LIKE zplm001-bname,
          trdat       LIKE zplm001-trdat,
        END OF lt_value.
  DATA: lt_retuen LIKE TABLE OF  ddshretval WITH HEADER LINE.
  DATA: lt_dfies LIKE TABLE OF dfies WITH HEADER LINE.
  DATA: lv_retfield TYPE dfies-fieldname VALUE 'ZPLM_SERIAL'.
  DATA:lv_num TYPE i.
  SELECT
    *
  FROM zplm001
  INTO CORRESPONDING FIELDS OF TABLE lt_value
  WHERE bname = sy-uname
    AND sszp = space.
  IF lt_value[] IS NOT INITIAL.
    PERFORM get_fields_of_value_tab(saplsdhi) TABLES   lt_value
                                                        lt_dfies
                                               CHANGING lv_retfield.

    LOOP AT lt_dfies.
      lv_num = sy-tabix.
      CASE lt_dfies-fieldname.
        WHEN 'F0001'.
          lt_dfies-reptext = 'CAXA流水號'.
        WHEN 'F0002'.
          lt_dfies-reptext = '代號'.
        WHEN 'F0003'.
          lt_dfies-reptext = '所屬裝配'.
        WHEN 'F0004'.
          lt_dfies-reptext = '使用者名稱稱'.
        WHEN 'F0005'.
          lt_dfies-reptext = '更改日期'.
      ENDCASE.
      MODIFY lt_dfies  INDEX lv_num TRANSPORTING reptext.
    ENDLOOP.
    CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
      EXPORTING
*       DDIC_STRUCTURE  = ' '
        retfield        = lv_retfield
        dynpprog        = sy-repid
        dynpnr          = sy-dynnr
        dynprofield     = ls_serial
        value_org       = 'S'
      TABLES
        value_tab       = lt_value
        field_tab       = lt_dfies
        return_tab      = lt_retuen
      EXCEPTIONS
        parameter_error = 1
        no_values_found = 2
        OTHERS          = 3.
    IF sy-subrc <> 0.
* Implement suitable error handling here
    ENDIF.
  ELSE.
    MESSAGE s398(00) WITH '無快取資料' DISPLAY LIKE 'E'.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SET_DART
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LS_DISP
*&      --> TABLE
*&      --> LT_DRAT
*&---------------------------------------------------------------------*
FORM frm_set_dart TABLES lt_drat STRUCTURE drat
                    USING ls_disp LIKE gs_disp
                    CHANGING lw_return TYPE bapiret2
                             ls_documenttype  TYPE bapi_doc_aux-doctype
                             ls_documentnumber  TYPE bapi_doc_aux-docnumber
                             ls_documentpart  TYPE bapi_doc_aux-docpart
                             ls_documentversion TYPE bapi_doc_aux-docversion .
  DATA:ls_doctype TYPE bapi_doc_aux-doctype,
       ls_docnum  TYPE bapi_doc_aux-docnumber,
       ls_docpart TYPE bapi_doc_aux-docpart,
       ls_docvrs  TYPE bapi_doc_aux-docversion.
  DATA:lw_docdata  TYPE bapi_doc_draw2,
       lw_docdatax TYPE bapi_doc_drawx2.
  DATA: lt_drad TYPE TABLE OF bapi_doc_drad WITH HEADER LINE.
  DATA:lt_data TYPE  bapi_doc_draw2 .
  DATA: lt_doc_drat TYPE TABLE OF bapi_doc_drat,
        ls_doc_drat TYPE bapi_doc_drat.
  "已經存在檔案
  READ TABLE lt_drat INTO DATA(ls_drat) WITH KEY doknr = ls_disp-dh.
  "dktxt = ls_data-maktx.
  IF sy-subrc = 0.
    IF ls_disp-dh(2) <> 'Q/' AND  ls_disp-dh(3) <> ( 'GB/') AND ls_disp-dh(3) <> ( 'JB/') .
      "文件已經存在,直接掛資料
      CLEAR:lt_drad.

      ls_doctype = ls_drat-dokar.
      ls_docnum = ls_drat-doknr.
      ls_docpart = ls_drat-doktl.
       ls_docvrs =  ls_docvrs.
          CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
            EXPORTING
              input  = ls_docpart
            IMPORTING
              output = ls_docpart.
      ls_docvrs = ls_drat-dokvr.
      ls_doc_drat-language = sy-langu.
      CALL FUNCTION 'CONVERSION_EXIT_ISOLA_OUTPUT'
        EXPORTING
          input  = sy-langu
        IMPORTING
          output = ls_doc_drat-language_iso.
      ls_doc_drat-description = ls_disp-dhmc.
      APPEND ls_doc_drat TO lt_doc_drat.
      CLEAR:ls_doc_drat.
      lw_docdata-DOCUMENTTYPE = ls_drat-DOKAR.
      lw_docdata-DOCUMENTNUMBER = ls_drat-DOKNR.
      lw_docdata-DOCUMENTVERSION = ls_drat-DOKVR.
      lw_docdata-DOCUMENTPART = ls_drat-doktl.
      lw_docdata-DESCRIPTION = ls_drat-DKTXT.

      lw_docdataX-DOCUMENTTYPE = 'X'.
      lw_docdataX-DOCUMENTNUMBER = 'X'.
      lw_docdataX-DOCUMENTVERSION = 'X'.
      lw_docdataX-DOCUMENTPART = 'X'.
      lw_docdataX-DESCRIPTION = 'X'.
      CALL FUNCTION 'BAPI_DOCUMENT_CHANGE2'
        EXPORTING
          documenttype         = ls_doctype
          documentnumber       = ls_docnum
          documentpart         = ls_docpart
          documentversion      = ls_docvrs
          documentdata         = lw_docdata
          documentdatax        = lw_docdatax
        IMPORTING
          return               = lw_return.
*        TABLES
*          documentdescriptions = lt_doc_drat.
      CLEAR:lt_doc_drat.
      IF lw_return-type = 'E'.
        CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.

        lw_return-message =  ls_disp-dh && '文件建立失敗:' && lw_return-message.
        MESSAGE e398(00) WITH lw_return-message.

      ELSE.
        CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
          EXPORTING
            wait = 'X'.
        ls_documenttype =  ls_doctype .
        ls_documentnumber = ls_docnum .
        ls_documentpart = ls_docpart .
        ls_documentversion = ls_docvrs .
      ENDIF.
    ELSEIF ls_disp-dh(2) = 'Q/' OR  ls_disp-dh(3) = ( 'GB/') OR ls_disp-dh(3) = ( 'JB/').
      CLEAR:ls_drat.
      READ TABLE lt_drat INTO ls_drat WITH KEY doknr = ls_disp-dh
                                               dktxt = ls_disp-dhmc.
      IF sy-subrc <> 0.
        "文件和描述不匹配
        SORT lt_drat BY doktl DESCENDING.
        CLEAR:ls_drat.
        READ TABLE lt_drat INTO ls_drat INDEX 1.
        IF sy-subrc = 0.

          lt_data-documentpart = ls_drat-doktl + 1.
          CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
            EXPORTING
              input  = lt_data-documentpart
            IMPORTING
              output = lt_data-documentpart.
          DATA:qs_drat TYPE bapi_doc_drat,
               qt_drat TYPE TABLE OF bapi_doc_drat.
          lt_data-documenttype = 'DRW'.
          lt_data-documentnumber = ls_disp-dh.
          lt_data-documentversion = '00'.
          lt_data-description = ls_disp-dhmc.
          lt_data-username = sy-uname.
          qs_drat-language = sy-langu.
          CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
            EXPORTING
              input  = lt_data-documentnumber
            IMPORTING
              output = lt_data-documentnumber.
          CALL FUNCTION 'CONVERSION_EXIT_ISOLA_OUTPUT'
            EXPORTING
              input  = sy-langu
            IMPORTING
              output = qs_drat-language_iso.
          qs_drat-description = ls_disp-dhmc.
          APPEND qs_drat TO qt_drat.
          CLEAR:qs_drat.

          CALL FUNCTION 'BAPI_DOCUMENT_CREATE2'
            EXPORTING
              documentdata         = lt_data
            IMPORTING
              documenttype         = ls_documenttype
              documentnumber       = ls_documentnumber
              documentpart         = ls_documentpart
              documentversion      = ls_documentversion
              return               = lw_return
            TABLES
              documentdescriptions = qt_drat.
*              objectlinks          = lt_drad[].
          IF lw_return-type = 'E'.
            CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
            lw_return-message =  ls_disp-dh && '文件建立失敗:' && lw_return-message.
            MESSAGE e398(00) WITH lw_return-message.
          ELSE.
            CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
              EXPORTING
                wait = 'X'.

          ENDIF.
        ENDIF.
      ELSE.
        lt_data-documentpart = ls_drat-doktl .
        ls_doctype = ls_drat-dokar.
        ls_docnum = ls_drat-doknr.
        ls_docpart = ls_drat-doktl.
        ls_docvrs = ls_drat-dokvr.
        ls_doc_drat-language = sy-langu.
        CALL FUNCTION 'CONVERSION_EXIT_ISOLA_OUTPUT'
          EXPORTING
            input  = sy-langu
          IMPORTING
            output = ls_doc_drat-language_iso.
        ls_doc_drat-description = ls_disp-dhmc.
        APPEND ls_doc_drat TO lt_doc_drat.
        CLEAR:ls_doc_drat.
        CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
          EXPORTING
            input  = ls_docnum
          IMPORTING
            output = ls_docnum.
      lw_docdata-DOCUMENTTYPE = ls_drat-DOKAR.
      lw_docdata-DOCUMENTNUMBER = ls_drat-DOKNR.
      lw_docdata-DOCUMENTVERSION = ls_drat-DOKVR.
      lw_docdata-DOCUMENTPART = ls_drat-doktl.
      lw_docdata-DESCRIPTION = ls_drat-DKTXT.

      lw_docdataX-DOCUMENTTYPE = 'X'.
      lw_docdataX-DOCUMENTNUMBER = 'X'.
      lw_docdataX-DOCUMENTVERSION = 'X'.
      lw_docdataX-DOCUMENTPART = 'X'.
      lw_docdataX-DESCRIPTION = 'X'.
        CALL FUNCTION 'BAPI_DOCUMENT_CHANGE2'
          EXPORTING
            documenttype         = ls_doctype
            documentnumber       = ls_docnum
            documentpart         = ls_docpart
            documentversion      = ls_docvrs
            documentdata         = lw_docdata
            documentdatax        = lw_docdatax
          IMPORTING
            return               = lw_return.
        IF lw_return-type = 'E'.
          CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
          lw_return-message =  ls_disp-dh && '文件建立失敗:' && lw_return-message.
          MESSAGE e398(00) WITH lw_return-message.
        ELSE.
          CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
            EXPORTING
              wait = 'X'.
          ls_documenttype =  ls_doctype .
          ls_documentnumber = ls_docnum .
          ls_documentpart = ls_docpart .
          ls_documentversion = ls_docvrs .
        ENDIF.

      ENDIF.
    ENDIF.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_REFRESH_DATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_refresh_data .
  DATA:l_selected_node TYPE lvc_nkey,
       s_node_key TYPE lvc_nkey.
  DATA:t_node_key TYPE  lvc_t_nkey.
  DATA:lv_lines TYPE i.
  DATA:ls_disp TYPE ty_disp.
*  E_node_key = cl_alv_tree_base=>c_virtual_root_node."獲取全部節點

  CALL METHOD lcl_tree->get_children "獲取全部子節點
    EXPORTING
      i_node_key         = g_dh_key
    IMPORTING
      et_children        = t_node_key
    EXCEPTIONS
      historic_error     = 1
      node_key_not_found = 2
      OTHERS             = 3.
  LOOP AT t_node_key INTO s_node_key.
    CALL METHOD lcl_tree->get_outtab_line "獲取行資料
      EXPORTING
        i_node_key    = s_node_key
      IMPORTING
        e_outtab_line = ls_disp.

    PERFORM change_item_data USING lv_lines CHANGING ls_disp.

    CALL METHOD cl_gui_cfw=>flush.
    CALL METHOD lcl_tree->change_node
      EXPORTING
        i_node_key    = s_node_key
        i_outtab_line = ls_disp.
    PERFORM update_node_key USING S_NODE_KEY.
  ENDLOOP.

  CALL METHOD lcl_tree->frontend_update.




ENDFORM.
*&---------------------------------------------------------------------*
*& Form UPDATE_NODE_KEY
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> S_NODE_KEY
*&---------------------------------------------------------------------*
FORM update_node_key  USING  s_node_key TYPE lvc_nkey.
  DATA:l_selected_node TYPE lvc_nkey.
  DATA:t_node_key TYPE  lvc_t_nkey.
  data:ls_disp TYPE ty_disp.
  data:lv_lines TYPE i.
  CALL METHOD lcl_tree->get_children "獲取全部子節點
    EXPORTING
      i_node_key         = s_node_key
    IMPORTING
      et_children        = t_node_key
    EXCEPTIONS
      historic_error     = 1
      node_key_not_found = 2
      OTHERS             = 3.

    LOOP AT t_node_key INTO l_selected_node.
    CALL METHOD lcl_tree->get_outtab_line "獲取行資料
      EXPORTING
        i_node_key    = l_selected_node
      IMPORTING
        e_outtab_line = ls_disp.

    PERFORM change_item_data USING lv_lines CHANGING ls_disp.

    CALL METHOD cl_gui_cfw=>flush.

    CALL METHOD lcl_tree->change_node
      EXPORTING
        i_node_key    = l_selected_node
        i_outtab_line = ls_disp.
    PERFORM update_node_KEY USING l_selected_node.
  ENDLOOP.
  IF T_NODE_KEY IS INITIAL.
    CALL METHOD lcl_tree->get_outtab_line "獲取行資料
      EXPORTING
        i_node_key    = s_node_key
      IMPORTING
        e_outtab_line = ls_disp.

    PERFORM change_item_data USING lv_lines CHANGING ls_disp.

    CALL METHOD cl_gui_cfw=>flush.

    CALL METHOD lcl_tree->change_node
      EXPORTING
        i_node_key    = s_node_key
        i_outtab_line = ls_disp.
  ENDIF.
  CALL METHOD lcl_tree->frontend_update.
ENDFORM.

相關文章