ABAP OO - ALV_TREE例程

项目上比较少有用到ALV_TREE的报表功能,刚好项目上有写了一次,也查阅大量的范例,整合了一写法,给自己做一下笔记。

程序包含功能按钮,按钮下拉,F4帮助,读取选中行,字段双击触发事件,字段前置图标,更新节点,获取节点数据,获取全部子节点,递归算法,DMS模块:创建文档功能,创建文档链接,SNRO创建流水号,缓存数据,下次用户加载进来继续操作。
ABAP OO - ALV_TREE例程_第1张图片

*&---------------------------------------------------------------------*
*& Report ZPLM001
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zplm001.
TABLES:sscrfields,zplm001.
TYPE-POOLS: icon.
TYPES:BEGIN OF ty_disp,
        xh            TYPE char10,
        dh            TYPE char50,
        dhmc          TYPE char50,
        cl            TYPE char50,
        sszp          TYPE char50,
        sl            TYPE char50,
        zsl           TYPE char50,
        bz            TYPE char50,
        jth           TYPE char50,
        matnr         TYPE char50,
        o_matnr       TYPE char50,
        zl            TYPE char50,
        "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 10,
        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.
            "获取节点数据,删除全局内表
            CLEAR:gs_disp.
            CALL METHOD lcl_tree->get_outtab_line "获取行数据
              EXPORTING
                i_node_key    = l_selected_node
              IMPORTING
                e_outtab_line = gs_disp.
            DELETE gt_disp WHERE xh = gs_disp-xh.
            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.
      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.

  LOOP AT gt_disp INTO gs_disp.
    translate gs_disp-DH to upper case.
    translate gs_disp-SSZP to upper case.
    MODIFY gt_disp FROM gs_disp.
    CLEAR:gs_disp.
  ENDLOOP.
  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.
*  ls_DISVARIANT-handle   = 'TREE'.
*  ls_DISVARIANT-variant  = '/NEW_VARIANT'.
*  CALL METHOD lcl_tree->set_variant_key
*    EXPORTING
*      is_variant = ls_DISVARIANT
*      .

  "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.
      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 = ''
          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.
      "递归
*      gs_disp-flag = 'X'.
*      MODIFY gt_disp FROM gs_disp.
      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.
*  zt_disp = gt_disp.


*  LOOP AT  gt_disp INTO qs_disp WHERE dh = p_disp-dh.
*    LOOP AT gt_disp INTO DATA(IS_DISP) WHERE DH = p_disp-DH "取最近的一条
*                                         AND zxh > p_disp-zxh.
*
*    qs_disp-flag = Is_disp-zxh.
*      EXIT.
*    ENDLOOP.
*    IF qs_disp-flag IS INITIAL.
*      qs_disp-flag = Qs_disp-zxh.
*    ENDIF.
*    MODIFY gt_disp FROM qs_disp.
*    CLEAR:qs_disp,IS_DISP.
*  ENDLOOP.

*  LOOP AT gt_disp INTO qs_disp WHERE DH = p_disp-DH.
*    IF qs_disp-flag IS INITIAL.
*    qs_disp-flag = qs_disp-zxh.
*    MODIFY gt_disp FROM qs_disp.
*    CLEAR:qs_disp.
*    ENDIF.
*  ENDLOOP.

*  LOOP AT gt_disp INTO DATA(as_disp) WHERE sszp = p_disp-dh.
*
*    LOOP AT zt_disp INTO DATA(zs_disp) WHERE dh = as_disp-dh
*                                          AND zxh > as_disp-zxh.
*      lv_xh = zs_disp-zxh.
*      EXIT.
*    ENDLOOP.
*    IF lv_xh IS NOT INITIAL.
*      LOOP AT  gt_disp INTO qs_disp WHERE DH = as_disp-dh
*                                      AND  zxh  >= as_disp-xh
*                                      AND  zxh  < lv_xh.
*        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
*              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. "节点标识
*          lv_flag = 'X'.
*          CLEAR:l_layout_node, lt_layout_item.
*          "递归
*          qs_disp-FLAG = 'X'.
*          MODIFY gt_disp FROM qs_disp.
*          PERFORM set_recursive USING qs_disp l_dh_key.
*
*        ENDIF.
*      ENDLOOP.
*    ELSE.
*      LOOP AT  gt_disp INTO qs_disp WHERE dh = as_disp-dh
*                                      AND  flag  <> '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
*              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.
*    ENDIF.
*
*    CLEAR:lv_xh,as_disp,qs_disp.
*  ENDLOOP.

  LOOP AT  gt_disp INTO qs_disp WHERE sszp = p_disp-dh
                                    AND zxh = p_disp-xh.
*      IF qs_disp-ZXH

    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
          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 TO SCREEN 0.
    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 .

*      READ TABLE lt_drat INTO DATA(ls_drat) WITH KEY doknr = ls_disp-dh
*                                                     dktxt = ls_disp-dhmc.
*      IF sy-subrc = 0.
*        "更新
*        ls_doctype = ls_drat-dokar.
*        ls_docnum = ls_drat-doknr.
*        ls_docpart = ls_drat-doktl.
*        ls_docvrs = ls_drat-dokvr.
*        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
**              objectlinks     = lt_drad[].
*
*      ELSE.
*        "分卷加1
*        SORT lt_drat BY doktl DESCENDING.
*        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.
*          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 = lt_drat.
**                  objectlinks          = lt_drad[].
*        ENDIF.
*      ENDIF.
    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).
    translate ls_disp-dh to upper case.
    translate ls_disp-sszp to upper case.
    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
     SINGLE
      dokar
      doknr
      dokvr
      doktl
      dktxt
     FROM drat
     INTO  CORRESPONDING FIELDS OF ls_disp "(ls_disp-dokar,ls_disp-doknr,ls_disp-dokvr,ls_disp-doktl,ls_disp-dktxt)
     WHERE dokar = 'DRW'
       AND doknr = ls_disp-dh
       AND dktxt = ls_disp-dhmc
       AND langu = sy-langu.

  IF ls_disp-dh(2) <> 'Q/' AND  ls_disp-dh(3) <> ( 'GB/') AND ls_disp-dh(3) <> ( 'JB/') .
    "非标件再用代号去查
    IF ls_disp-doknr IS INITIAL.
      SELECT
       SINGLE
         dokar
         doknr
         dokvr
         doktl
         dwnam
         dokst
         begru
        FROM draw
       INTO CORRESPONDING FIELDS OF ls_disp " (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
       WHERE dokar = 'DRW'
         AND doknr = ls_disp-dh.

    ELSE.
      SELECT
       SINGLE
        dwnam
        dokst
        begru
       FROM draw
      INTO CORRESPONDING FIELDS OF ls_disp " (ls_disp-dwnam,ls_disp-dokst,ls_disp-begru) UP TO 1 ROWS
      WHERE dokar = 'DRW'
        AND doknr = ls_disp-doknr
        AND dokvr = ls_disp-dokvr
        AND doktl = ls_disp-doktl.

    ENDIF.
    ELSE.
      if ls_disp-MATNR is not INITIAL.
     CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT'
       EXPORTING
         input              = ls_disp-MATNR
      IMPORTING
        OUTPUT             = ls_disp-MATNR
      EXCEPTIONS
        LENGTH_ERROR       = 1
        OTHERS             = 2
               .
     IF sy-subrc <> 0.
* Implement suitable error handling here
     ENDIF.

     SELECT
     SINGLE
      dokar
      doknr
      dokvr
      doktl
     FROM draD
     INTO  CORRESPONDING FIELDS OF ls_disp "(ls_disp-dokar,ls_disp-doknr,ls_disp-dokvr,ls_disp-doktl,ls_disp-dktxt)
     WHERE dokar = 'DRW'
       AND doknr = ls_disp-dh
       AND DOKOB = 'MARA'
       AND OBJKY = ls_disp-MATNR.
       IF SY-SUBRC = 0.
          SELECT
           SINGLE
            dokar
            doknr
            dokvr
            doktl
            dktxt
           FROM drat
           INTO  CORRESPONDING FIELDS OF ls_disp "(ls_disp-dokar,ls_disp-doknr,ls_disp-dokvr,ls_disp-doktl,ls_disp-dktxt)
           WHERE dokar = 'DRW'
             AND doknr = ls_disp-doknr
             AND  dokvr  = ls_disp-DOKVR
             AND doktl = ls_disp-DOKTL
             AND langu = sy-langu.
       ENDIF.
       endif.
 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'."功能未定
*      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@'.
*        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 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.
  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.
  clear:lv_num.
  "获取选择行节点
  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 DH = ls_disp-dh AND stuas = '@01@' AND xh = ls_disp-xh.
          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  CHANGING 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.
  DATA:WA_DISP LIKE gs_disp.
  LOOP AT gt_disp INTO DATA(ls_disp) WHERE sszp = ws_disp-dh AND stuas = '@01@' AND zxh = ws_disp-xh.
    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.
      WA_DISP = ls_disp.
      PERFORM change_item_bom CHANGING wa_disp.
      ls_doc-documenttype = wa_disp-dokar.
      ls_doc-documentnumber = wa_disp-doknr.
      ls_doc-documentpart = wa_disp-doktl.
      ls_doc-documentversion = wa_disp-dokvr.
      ls_doc-quantity = wa_disp-sl.
      clear:WA_DISP.
      WA_DISP = 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'
*     SEARCHHELP        = ' '
*     SHLPPARAM         = ' '
      dynpprog          = sy-repid
      dynpnr            = sy-dynnr
      dynprofield       = 'ZCV1'
      stepl             = 0
*     VALUE             = ' '
*     MULTIPLE_CHOICE   = ' '
*     DISPLAY           = ' '
*     SUPPRESS_RECORDLIST       = ' '
*     CALLBACK_PROGRAM  = ' '
*     CALLBACK_FORM     = ' '
*     CALLBACK_METHOD   =
*     SELECTION_SCREEN  = ' '
*   IMPORTING
*     USER_RESET        =
    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'.
*  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.

  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数量'.
*    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_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 "获得的流水号
*         quantity                = quant
*         returncode              = code
        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
****       DH           =
****       SSZP         =
****       X_ZPLM_SERIAL       = ' '
****       X_DH         = ' '
****       X_SSZP       = ' '
****       _SCOPE       = '3'
****       _SYNCHRON    = ' '
****       _COLLECT     = ' '
      .
  ENDIF.

*  SELECT COUNT(*) FROM ZPLM001 WHERE zplm_serial = lv_sernum.
*  IF sy-subrc = 0.
*    DELETE FROM ZPLM001 WHERE zplm_serial = lv_sernum.
*    IF sy-subrc = 0.
*      COMMIT WORK AND WAIT .
*      insert ZPLM001 from table lt_ZPLM001 .
*      IF sy-subrc = 0.
*        COMMIT WORK AND WAIT .
*        MESSAGE s398(00) WITH '保存成功'.
*      ELSE.
*        ROLLBACK WORK.
*      ENDIF.
*    ELSE.
*      ROLLBACK WORK.
*    ENDIF.
*  ELSE.
*    CLEAR:sy-subrc .
*    insert ZPLM001 from table lt_ZPLM001.
*    IF sy-subrc = 0.
*      COMMIT WORK AND WAIT .
*      MESSAGE s398(00) WITH '保存成功'.
*    ELSE.
*      ROLLBACK WORK.
*    ENDIF.
*  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
***       DH             =
***       SSZP           =
***       X_ZPLM_SERIAL  = ' '
***       X_DH           = ' '
***       X_SSZP         = ' '
***       _SCOPE         = '2'
***       _WAIT          = ' '
***       _COLLECT       = ' '
      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: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,
*       lw_return          TYPE bapiret2.
  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.
*          lt_drad-objecttype = 'MARA'.
*          lt_drad-objectkey = ls_data-matnr.
*      APPEND lt_drad.
      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.

          "创建文档
*          PERFORM frm_set_data TABLES lt_drad lt_drat CHANGING lt_data ls_data lv_doknr.
          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.
*            SORT lt_draw BY doktl DESCENDING.
*            CLEAR:ls_draw.
*            READ TABLE lt_draw INTO ls_draw INDEX 1.
*            IF sy-subrc = 0.
        lt_data-documentpart = ls_drat-doktl .

*                "创建文档
*              PERFORM frm_set_data TABLES lt_drad lt_drat CHANGING lt_data ls_data lv_doknr.
        ls_doctype = ls_drat-dokar.
        ls_docnum = ls_drat-doknr.
        ls_docpart = ls_drat-doktl.
        ls_docvrs = ls_drat-dokvr.
*        lt_drad-objecttype = 'MARA'.
**        lt_drad-objectkey = ls_data-matnr.
*        APPEND lt_drad.
        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.
*            documentdescriptions = lt_doc_drat.
*            objectlinks     = lt_drad[].
        IF lw_return-type = 'E'.
          CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
*          ls_return-matnr   = ls_data-matnr.
*          ls_return-zstatus = 'E'.
          lw_return-message =  ls_disp-dh && '文档创建失败:' && lw_return-message.
          MESSAGE e398(00) WITH lw_return-message.
*          APPEND ls_return TO it_return.
        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.

你可能感兴趣的:(ABAP,OO,abap)