物料主数据批导

*&---------------------------------------------------------------------*
*& Report  ZMAINTAIN_MATERAIL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zmaintain_materail.

CONSTANTS cnst_excel_file_path_name TYPE string VALUE '物料主数据导入Excel文件路径'.
CONSTANTS cnst_button_text TYPE string VALUE '执行物料导入'.
CONSTANTS cnst_button_text_test TYPE string VALUE '导入测试,不提交数据库'.
CONSTANTS cnst_button_text_bg TYPE string VALUE '提交后台执行'.
CONSTANTS cnst_button_text_job_info TYPE string VALUE '查看JOB信息'.
CONSTANTS cnst_template_name TYPE string VALUE '物料主数据导入模板'.

*//***************************************************************************
TABLES sscrfields.
DATA functxt TYPE smp_dyntxt.
TYPE-POOLS icon.
SELECTION-SCREEN: FUNCTION KEY 1,FUNCTION KEY 2.
*//***************************************************************************
PARAMETERS p_file TYPE rlgrap-filename.
PARAMETERS p_bg TYPE abap_bool DEFAULT abap_false NO-DISPLAY."// 用于标识后台执行,创建job时赋值ABAP_TRUE
PARAMETERS p_srtfd TYPE indx_srtfd NO-DISPLAY."//用于保存内表
PARAMETERS p_srtfd1 TYPE indx_srtfd NO-DISPLAY. "//用于保存内表结构
*//***************************************************************************
DATA: BEGIN OF gs_field,
        fieldname TYPE fieldname,
      END OF gs_field.
DATA gt_fields LIKE TABLE OF gs_field.
*//***************************************************************************
DATA: BEGIN OF gs_field_list,
        fieldname TYPE string,
        fielddesc TYPE string,
      END OF gs_field_list,
      gt_fields_list LIKE TABLE OF gs_field_list.
*//***************************************************************************
DATA gs_job TYPE tbtcjob.
DATA gs_job_return TYPE bapiret2.
DATA go_job TYPE REF TO zcl_job.
*//***************************************************************************

DATA gr_error TYPE REF TO cx_root.

DATA gv_test_run TYPE char1 VALUE IS INITIAL.
DATA gv_background TYPE abap_bool VALUE abap_false.

FIELD-SYMBOLS <gt_output> TYPE STANDARD TABLE.
DATA gt_output_table TYPE REF TO data.

*//***************************************************************************
*//***************************************************************************
CLASS lcl_process DEFINITION.
  PUBLIC SECTION.
    CLASS-DATA: lo_salv      TYPE REF TO cl_salv_table,
                lo_container TYPE REF TO cl_gui_container,
                lo_docking   TYPE REF TO cl_gui_docking_container,
                lo_events    TYPE REF TO cl_salv_events_table.
    CLASS-DATA: lr_columns TYPE REF TO cl_salv_columns.
    CLASS-DATA lr_column TYPE REF TO cl_salv_column.
    CLASS-DATA lr_columns_table TYPE REF TO cl_salv_columns_table.
    CLASS-DATA lr_column_table TYPE REF TO cl_salv_column_table.

    CLASS-DATA component_tab TYPE cl_abap_structdescr=>component_table.

    CLASS-METHODS read_excel IMPORTING i_file   TYPE rlgrap-filename
                             CHANGING  it_table TYPE STANDARD TABLE OPTIONAL.

    CLASS-METHODS display
      IMPORTING button_text TYPE string OPTIONAL
      CHANGING  it_table    TYPE STANDARD TABLE OPTIONAL.

    CLASS-METHODS on_user_command FOR EVENT added_function OF cl_salv_events IMPORTING e_salv_function.
    CLASS-METHODS on_link_click FOR EVENT if_salv_events_actions_table~link_click OF cl_salv_events_table
      IMPORTING row column.
    CLASS-METHODS on_doubleclick FOR EVENT if_salv_events_actions_table~double_click OF cl_salv_events_table
      IMPORTING sender row column.
    CLASS-METHODS refresh.


    CLASS-DATA: BEGIN OF gwa_field_relation,
                  excel_original_text TYPE string,
                  excel_fieldname     TYPE string,
                  excel_column_seq    TYPE i,
                  tab_desc            TYPE string.
                  INCLUDE TYPE dfies.
    CLASS-DATA:END OF gwa_field_relation.
    CLASS-DATA gt_field_relation LIKE TABLE OF gwa_field_relation.

    CLASS-METHODS prepare_field_relation_logic IMPORTING tabname TYPE char30.
    CLASS-METHODS prepare_field_relation.

    CLASS-DATA: BEGIN OF gs_bapi_ext_relation,
                  tabname            TYPE        char30,
                  fieldname          TYPE        char30,
                  tabname_bapi_ext   TYPE        char30,
                  fieldname_bapi_ext TYPE        char30,
                  tabname_bapi_extx  TYPE        char30,
                  bapi_ext_row       TYPE REF TO data,
                  bapi_ext_rowx      TYPE REF TO data,
                END OF gs_bapi_ext_relation,
                gt_bapi_ext_relation LIKE TABLE OF gs_bapi_ext_relation.

ENDCLASS.
*//***************************************************************************
*//***************************************************************************
START-OF-SELECTION.
  IF p_bg = abap_false.
    gv_background = abap_false.
    lcl_process=>read_excel( i_file = p_file ).
    CHECK <gt_output> IS ASSIGNED.
    CHECK <gt_output> IS NOT INITIAL.
    lcl_process=>display( EXPORTING button_text = cnst_button_text CHANGING it_table = <gt_output> ).
  ELSE.
    CLEAR gt_fields.
    IMPORT itab_structure = gt_fields FROM DATABASE indx(zx) ID p_srtfd1.
    IF gt_fields IS INITIAL.
      MESSAGE '无法获取所处理的内表的结构' TYPE 'S' DISPLAY LIKE 'E'.
      RETURN.
    ENDIF.
    DATA go_structdescr TYPE REF TO cl_abap_structdescr.
    DATA go_tabledesc TYPE REF TO cl_abap_tabledescr.
    DATA go_datadescr TYPE REF TO cl_abap_datadescr.
    DATA gt_components TYPE abap_component_tab.
    CLEAR gt_components.
    go_datadescr ?= cl_abap_datadescr=>describe_by_name( 'STRING' ).
    LOOP AT gt_fields ASSIGNING FIELD-SYMBOL(<ls_field>).
      APPEND INITIAL LINE TO gt_components ASSIGNING FIELD-SYMBOL(<gs_component>).
      IF <ls_field>-fieldname <> '_RETURN'.
        <gs_component>-name = <ls_field>-fieldname.
        <gs_component>-type = go_datadescr.
      ELSE.
        DATA return_temp TYPE TABLE OF bapi_matreturn2.
        <gs_component>-name = <ls_field>-fieldname.
        <gs_component>-type ?= cl_abap_datadescr=>describe_by_data( return_temp )..
      ENDIF.
    ENDLOOP.
    TRY.
        go_structdescr = cl_abap_structdescr=>create( gt_components ).
        go_tabledesc = cl_abap_tabledescr=>create( go_structdescr ).
      CATCH cx_root INTO DATA(lv_create_error).
        MESSAGE |构建内表失败:{ lv_create_error->get_text( ) }| TYPE 'S' DISPLAY LIKE 'E'.
        RETURN.
    ENDTRY.
    CREATE DATA gt_output_table TYPE HANDLE go_tabledesc.
    ASSIGN gt_output_table->* TO <gt_output>.
    TRY.
        IMPORT itab = <gt_output> FROM DATABASE indx(zx) ID p_srtfd.
      CATCH cx_root INTO DATA(lx_import_error).
        MESSAGE |导入内表内容失败:{ lx_import_error->get_text( ) }| TYPE 'S' DISPLAY LIKE 'E'.
        RETURN.
    ENDTRY.
    IF <gt_output> IS INITIAL.
      MESSAGE '没有找到合适的数据,无法后台执行处理,请确认!' TYPE 'S' DISPLAY LIKE 'E'.
    ELSE.
      PERFORM frm_exec.
      MESSAGE |{ repeat( val = '*'  occ = 80 ) }| TYPE 'S'.
      MESSAGE '处理完成,请检查' TYPE 'S'.
      MESSAGE |{ repeat( val = '*'  occ = 80 ) }| TYPE 'S'.
    ENDIF.

  ENDIF.
*//***************************************************************************
*//***************************************************************************
INITIALIZATION.
  %_p_file_%_app_%-text = cnst_excel_file_path_name.

  functxt-text = ''."最多四十个字符.如果有按钮icon_text的话,就不显示了
  functxt-icon_id = icon_xxl.
  functxt-quickinfo = '指定导入字段,生成导入模板'.
  functxt-icon_text = '指定导入字段,生成导入模板'.
  sscrfields-functxt_01 = functxt.
  functxt-text = ''."最多四十个字符.如果有按钮icon_text的话,就不显示了
  functxt-icon_id = icon_history.
  functxt-quickinfo = '查看设置的模板'.
  functxt-icon_text = '查看设置的模板'.
  sscrfields-functxt_02 = functxt.
*//***************************************************************************
*//***************************************************************************
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
  p_file = zcl_excel_tools=>get_upload_path( ).
*//***************************************************************************
*//***************************************************************************
AT SELECTION-SCREEN.
  CASE sy-ucomm.
    WHEN 'FC01'.
*      CALL SELECTION-SCREEN 9000  STARTING AT 20 1 ENDING AT 170 22.
      lcl_process=>prepare_field_relation( ).
      DATA(gdt_selected) = zcl_tabbed=>select(
        is_alv = VALUE #(
            io_tabbed = zcl_tabbed=>new( lcl_process=>gt_field_relation )
            iv_alv_except_fields = |excel_original_text,excel_field_name,excel_column_seq,| &&
                                   |excel_fieldname,authorid,keyflag,lowercase,mac,genkey,noforkey,| &&
                                   |noauthch,sign,ltrflddis,bidictrlc,outputstyle,nohistory,ampmformat,checktable,precfield,| &&
                                   |mask,masklen,comptype,lfieldname,dynpfld,f4availabl,valexi,reptext,logflag,scrlen1,scrlen2,| &&
                                   |scrlen3,headlen,langu,position,offset|
            iv_alv_fields_desc = |tab_desc:BAPI结构名| &&
                                 ||
            iv_alv_fields_position = |fieldtext:3,fieldname:3,tab_Desc:5,rollname:5,domname:5,leng:5,intlen:5|
        )
      ).
      PERFORM frm_get_selected_fields USING gdt_selected.
    WHEN 'FC02'.
      PERFORM frm_view_templates.
  ENDCASE.
*//***************************************************************************
*//***************************************************************************
AT SELECTION-SCREEN OUTPUT.
*//***************************************************************************
*//***************************************************************************

*//***************************************************************************
*//***************************************************************************
FORM frm_get_selected_fields USING idt_selected TYPE REF TO data.

  FIELD-SYMBOLS <lt_selected> TYPE STANDARD TABLE.
  ASSIGN idt_selected->* TO <lt_selected>.
  CHECK sy-subrc = 0.
  DATA lt_selected LIKE lcl_process=>gt_field_relation.
  CLEAR lt_selected.
  MOVE-CORRESPONDING <lt_selected> TO lt_selected.
  CHECK lt_selected IS NOT INITIAL.

  DATA lo_struct TYPE REF TO cl_abap_structdescr.
  DATA lo_table TYPE REF TO cl_abap_tabledescr.
  DATA lo_data TYPE REF TO cl_abap_datadescr.

  DATA components TYPE cl_abap_structdescr=>component_table.
  CLEAR: components.
  lo_data ?= cl_abap_datadescr=>describe_by_name( 'STRING' ).
  DO lines( lt_selected ) TIMES.
    APPEND INITIAL LINE TO components ASSIGNING FIELD-SYMBOL(<ls_comp>).
    <ls_comp>-name = 'COL' && sy-tabix.
    <ls_comp>-type = lo_data.
  ENDDO.
  lo_struct = cl_abap_structdescr=>create( components ).
  lo_table = cl_abap_tabledescr=>create( lo_struct ).

  DATA t_table TYPE REF TO data.
  FIELD-SYMBOLS <t_table> TYPE STANDARD TABLE.
  DATA ls_row1 TYPE REF TO data.
  FIELD-SYMBOLS <ls_row1> TYPE any.
  DATA ls_row2 TYPE REF TO data.
  FIELD-SYMBOLS <ls_row2> TYPE any.

  CREATE DATA ls_row1 TYPE HANDLE lo_struct.
  ASSIGN ls_row1->* TO <ls_row1>.
  CREATE DATA ls_row2 TYPE HANDLE lo_struct.
  ASSIGN ls_row2->* TO <ls_row2>.

  CREATE DATA t_table TYPE HANDLE lo_table.
  ASSIGN t_table->* TO <t_table>.

  DATA lv_counter TYPE i VALUE IS INITIAL.
  CLEAR gt_fields_list.

  LOOP AT lt_selected ASSIGNING FIELD-SYMBOL(<ls_selected>).
    lv_counter = lv_counter + 1.
    ASSIGN COMPONENT lv_counter OF STRUCTURE <ls_row1> TO FIELD-SYMBOL(<value1>).
    <value1> = <ls_selected>-tabname && '-' && <ls_selected>-fieldname.
    ASSIGN COMPONENT lv_counter OF STRUCTURE <ls_row2> TO FIELD-SYMBOL(<value2>).
    <value2> = <ls_selected>-scrtext_l.
    APPEND INITIAL LINE TO gt_fields_list ASSIGNING FIELD-SYMBOL(<ls_field_list>).
    <ls_field_list>-fieldname = <value1>.
    <ls_field_list>-fielddesc = <value2>.
  ENDLOOP.

  APPEND <ls_row1> TO <t_table>.
  APPEND <ls_row2> TO <t_table>.

  "//弹出框,输入模板名称
  DATA ls_name TYPE j_3gbelk.
  CLEAR ls_name.
  zcl_xhl=>get_input_values( EXPORTING iv_structure_name = 'J_3GBELK'
                                       iv_fields = 'J_3GVVCOM1'
                             CHANGING cs_structure = ls_name ).
  IF ls_name-j_3gvvcom1 IS INITIAL.
    ls_name-j_3gvvcom1 = |物料主数据导入模板-{ sy-datum }-{ sy-uzeit }|.
  ENDIF.

  DATA ls_indx TYPE indx.
  CLEAR ls_indx.
  TRY.
      ls_indx-srtfd = cl_system_uuid=>create_uuid_c22_static( ).
    CATCH cx_root.
  ENDTRY.
  ls_indx-relid  = 'ZX'.
  ls_indx-usera = 'MAT_MAINTAIN'.
  ls_indx-aedat = sy-datum.
  ls_indx-pgmid = ls_name-j_3gvvcom1.
  EXPORT itab = gt_fields_list TO DATABASE indx(zx) FROM ls_indx ID ls_indx-srtfd.
  COMMIT WORK.

  PERFORM download_template USING <t_table> ''.

ENDFORM.

*//***************************************************************************
*//***************************************************************************
CLASS lcl_process IMPLEMENTATION.
*//********************************************************************
  METHOD read_excel.

    DATA(lo_excel) = zcl_excel_tools=>upload_by_fdt( CONV #( i_file ) ).
    ASSIGN lo_excel->gt_excel->* TO FIELD-SYMBOL(<lt_excel>).

    DATA lo_struct TYPE REF TO cl_abap_structdescr.
    DATA lo_table TYPE REF TO cl_abap_tabledescr.
    DATA lo_data TYPE REF TO cl_abap_datadescr.

    DATA components TYPE cl_abap_structdescr=>component_table.
    FIELD-SYMBOLS <component> TYPE LINE OF cl_abap_structdescr=>component_table.
    DATA component TYPE LINE OF cl_abap_structdescr=>component_table.

    lo_data ?= cl_abap_datadescr=>describe_by_name( 'STRING' ).
    lo_table ?= cl_abap_tabledescr=>describe_by_data( <lt_excel> ).
    lo_struct ?= lo_table->get_table_line_type( ).
    component_tab = lo_struct->get_components( ).
    MOVE-CORRESPONDING component_tab TO components.

    component-name = '_SEQ'.
    component-type = lo_data.
    APPEND component TO components.

    component-name = '_ICON'.
    component-type = lo_data.
    APPEND component TO components.

    component-name = '_MSG'.
    component-type = lo_data.
    APPEND component TO components.

    component-name = '_CLICK'.
    component-type = lo_data.
    APPEND component TO components.

    DATA return_temp TYPE TABLE OF bapi_matreturn2.
    component-name = '_RETURN'.
    component-type ?= cl_abap_datadescr=>describe_by_data( return_temp )..
    APPEND component TO components.

    lo_struct = cl_abap_structdescr=>create( components ).
    lo_table = cl_abap_tabledescr=>create( lo_struct ).
    CREATE DATA gt_output_table TYPE HANDLE lo_table.
    ASSIGN gt_output_table->* TO <gt_output>.

    MOVE-CORRESPONDING <lt_excel> TO <gt_output>.

    LOOP AT <gt_output> ASSIGNING FIELD-SYMBOL(<row>).
      CHECK sy-tabix > 2.
      ASSIGN COMPONENT '_SEQ' OF STRUCTURE <row> TO FIELD-SYMBOL(<value>).
      IF <value> IS ASSIGNED.
        <value> = sy-tabix - 2.
      ENDIF.
      ASSIGN COMPONENT '_MSG' OF STRUCTURE <row> TO <value>.
      IF <value> IS ASSIGNED.
        <value> = '等待导入'.
      ENDIF.

      ASSIGN COMPONENT '_ICON' OF STRUCTURE <row> TO <value>.
      IF <value> IS ASSIGNED.
        <value> = icon_yellow_light.
      ENDIF.

      ASSIGN COMPONENT '_CLICK' OF STRUCTURE <row> TO <value>.
      IF <value> IS ASSIGNED.
        <value> = '点击查看'.
      ENDIF.

    ENDLOOP.

  ENDMETHOD.
*//********************************************************************
  METHOD display.
    WRITE space.
    DATA lv_style TYPE i.
    lv_style = cl_gui_control=>ws_child
              + cl_gui_control=>ws_border
              + cl_gui_control=>ws_visible.
    IF lo_docking IS INITIAL.
      CREATE OBJECT lo_docking
        EXPORTING
          parent                  = cl_gui_custom_container=>default_screen
          no_autodef_progid_dynnr = 'X'
          style                   = lv_style.
      CALL METHOD lo_docking->set_extension
        EXPORTING
          extension = 10000.
      lo_container ?= lo_docking.
    ENDIF.

    TRY.
        CALL METHOD cl_salv_table=>factory
          EXPORTING
            r_container  = lo_container
          IMPORTING
            r_salv_table = lo_salv
          CHANGING
            t_table      = it_table.
      CATCH cx_salv_msg INTO DATA(lo_err01).
    ENDTRY.

    DATA functions TYPE REF TO cl_salv_functions_list.
    functions = lo_salv->get_functions( ).
    functions->set_all( 'X' ).

    TRY.
        functions->add_function( EXPORTING
            name     = 'EXEC'
            icon     =  '@15@'
            text     = button_text
            tooltip  = button_text
            position = if_salv_c_function_position=>left_of_salv_functions  ).
      CATCH cx_salv_existing INTO DATA(lo_err02).
      CATCH cx_salv_wrong_call INTO DATA(lo_err03).
    ENDTRY.

    TRY.
        functions->add_function( EXPORTING
            name     = 'EXEC_TEST'
            icon     =  '@15@'
            text     = cnst_button_text_test
            tooltip  = cnst_button_text_test
            position = if_salv_c_function_position=>left_of_salv_functions  ).
      CATCH cx_salv_existing INTO DATA(lo_err04).
      CATCH cx_salv_wrong_call INTO DATA(lo_err05).
    ENDTRY.

    TRY.
        functions->add_function( EXPORTING
            name     = 'BACKGROUND'
            icon     =  '@M4@'
            text     = cnst_button_text_bg
            tooltip  = cnst_button_text_bg
            position = if_salv_c_function_position=>right_of_salv_functions ).
      CATCH cx_salv_existing INTO DATA(lo_err16).
      CATCH cx_salv_wrong_call INTO DATA(lo_err17).
    ENDTRY.

    TRY.
        functions->add_function( EXPORTING
            name     = 'JOB_INFO'
            icon     =  '@M5@'
            text     = cnst_button_text_job_info
            tooltip  = cnst_button_text_job_info
            position = if_salv_c_function_position=>right_of_salv_functions ).
      CATCH cx_salv_existing INTO DATA(lo_err18).
      CATCH cx_salv_wrong_call INTO DATA(lo_err19).
    ENDTRY.

    lo_events = lo_salv->get_event( ).
    SET HANDLER on_user_command FOR lo_events.
    SET HANDLER on_link_click FOR lo_events.
    SET HANDLER on_doubleclick FOR lo_events.

    lr_columns = lo_salv->get_columns( ).
    lr_columns_table ?= lr_columns.
    lr_columns_table->set_column_position( columnname = '_CLICK' position = 1 ).
    lr_columns_table->set_column_position( columnname = '_MSG' position = 1 ).
    lr_columns_table->set_column_position( columnname = '_ICON' position = 1 ).
    lr_columns_table->set_column_position( columnname = '_SEQ' position = 1 ).
    TRY.
        lr_column_table ?= lr_columns_table->get_column( '_SEQ' ).
        lr_column_table->set_long_text( '数据序号' ).
        lr_column_table->set_medium_text( '数据序号' ).
        lr_column_table->set_short_text( '数据序号' ).
      CATCH cx_salv_not_found INTO DATA(lo_err06).
    ENDTRY.
    TRY.
        lr_column_table ?= lr_columns_table->get_column( '_ICON' ).
        lr_column_table->set_long_text( '状态' ).
        lr_column_table->set_medium_text( '状态' ).
        lr_column_table->set_short_text( '状态' ).
        lr_column_table->set_icon( 'X' ).
      CATCH cx_salv_not_found INTO DATA(lo_err07).
    ENDTRY.
    TRY.
        lr_column_table ?= lr_columns_table->get_column( '_MSG' ).
        lr_column_table->set_long_text( '消息' ).
        lr_column_table->set_medium_text( '消息' ).
        lr_column_table->set_short_text( '消息' ).
      CATCH cx_salv_not_found INTO DATA(lo_err08).
    ENDTRY.
    TRY.
        lr_column_table ?= lr_columns_table->get_column( '_CLICK' ).
        lr_column_table->set_long_text( 'BAPI消息' ).
        lr_column_table->set_medium_text( 'BAPI消息' ).
        lr_column_table->set_short_text( 'BAPI消息' ).
        lr_column_table->set_cell_type( if_salv_c_cell_type=>hotspot ).
      CATCH cx_salv_not_found INTO DATA(lo_err09).
    ENDTRY.
    lr_columns_table->set_optimize( 'X' ).

    DATA lo_err TYPE REF TO cx_root.
    FIELD-SYMBOLS <component> TYPE LINE OF cl_abap_structdescr=>component_table.
    DATA fname TYPE lvc_fname.
    DATA txt_long TYPE scrtext_l.
    DATA txt_medium TYPE scrtext_m.
    DATA txt_short TYPE scrtext_s.
    DATA txt_tip TYPE lvc_tip.
    LOOP AT component_tab ASSIGNING <component>.
      fname = <component>-name.
      TRY.
          lr_column = lr_columns->get_column( fname ).
          txt_long = fname.
          txt_medium = fname.
          txt_short = fname.
          lr_column->set_long_text( txt_long ).
          lr_column->set_medium_text( txt_medium ).
          lr_column->set_short_text( txt_short ).
          txt_tip = fname && ''.
          lr_column->set_tooltip( txt_tip ).
        CATCH cx_salv_not_found INTO lo_err.
      ENDTRY.
    ENDLOOP.

    DATA: lr_display TYPE REF TO cl_salv_display_settings,
          ls_layout  TYPE        salv_s_layout_key,
          lr_layout  TYPE REF TO cl_salv_layout.
    DATA lv_header_text TYPE lvc_title.
    lv_header_text = 'Excel内容'.
    lr_display = lo_salv->get_display_settings( )..
    lr_display->set_striped_pattern( cl_salv_display_settings=>true ).
    lr_display->set_list_header( lv_header_text ).
    lr_layout = lo_salv->get_layout( ).
    ls_layout-report = sy-repid.
    lr_layout->set_key( ls_layout ).
    lr_layout->set_default( 'X' )..
    lr_layout->set_save_restriction( cl_salv_layout=>restrict_none ).

    DATA lo_selections TYPE REF TO cl_salv_selections.
    lo_selections = lo_salv->get_selections( ).
    lo_selections->set_selection_mode( if_salv_c_selection_mode=>row_column ).

    CALL METHOD lo_salv->display( ).

  ENDMETHOD.
*//********************************************************************
  METHOD on_user_command.

    CASE e_salv_function.
      WHEN 'EXEC'.
        IF gv_background = abap_true.
          MESSAGE '已经提交后台,不能重复提交' TYPE 'S' DISPLAY LIKE 'W'.
        ELSE.
          gv_test_run = ''.
          PERFORM frm_exec IN PROGRAM (sy-repid) IF FOUND.
        ENDIF.
      WHEN 'EXEC_TEST'.
        IF gv_background = abap_true.
          MESSAGE '已经提交后台,不能重复提交' TYPE 'S' DISPLAY LIKE 'W'.
        ELSE.
          gv_test_run = 'X'.
          PERFORM frm_exec IN PROGRAM (sy-repid) IF FOUND.
        ENDIF.
      WHEN 'BACKGROUND'.
        IF gv_background = abap_true.
          IF zcl_xhl=>confirm( '已经提交后台任务,确定要再次提交?' ) = abap_true.
            PERFORM frm_prepare_2_bg.
          ENDIF.
        ELSE.
          PERFORM frm_prepare_2_bg.
        ENDIF.
      WHEN 'JOB_INFO'.
        PERFORM frm_display_job.
    ENDCASE.

  ENDMETHOD.
*//********************************************************************
  METHOD on_doubleclick.

    CHECK row > 2.
    CHECK <gt_output> IS ASSIGNED.
    CHECK lines( <gt_output> ) > 2.
    READ TABLE <gt_output> ASSIGNING FIELD-SYMBOL(<ls_row>) INDEX 2.
    CHECK sy-subrc = 0.

    READ TABLE <gt_output> ASSIGNING FIELD-SYMBOL(<ls_currrent_row>) INDEX row.
    CHECK sy-subrc = 0.

    DATA lo_structdescr TYPE REF TO cl_abap_structdescr.
    lo_structdescr ?= cl_abap_structdescr=>describe_by_data( <ls_currrent_row> ).
    DATA(lt_components) = lo_structdescr->get_included_view( ).
    DATA lv_matnr TYPE char18.
    CLEAR lv_matnr.
    LOOP AT lt_components ASSIGNING FIELD-SYMBOL(<ls_comp>).
      ASSIGN COMPONENT <ls_comp>-name OF STRUCTURE <ls_row> TO FIELD-SYMBOL(<lv_mat>).
      IF <lv_mat> CS 'MATERIAL'.
        ASSIGN COMPONENT <ls_comp>-name OF STRUCTURE <ls_currrent_row> TO FIELD-SYMBOL(<lv_mat_value>).
        lv_matnr = <lv_mat_value>.
        EXIT.
      ENDIF.
    ENDLOOP.
    CHECK lv_matnr IS NOT INITIAL.
    DATA ls_return TYPE bapiret1.
    lv_matnr = |{ lv_matnr ALPHA = IN }|.
    CALL FUNCTION 'BAPI_MATERIAL_DISPLAY'
      EXPORTING
        material = lv_matnr
*       MATERIAL_EVG        =
*       MATERIAL_LONG       =
      IMPORTING
        return   = ls_return.
    .

  ENDMETHOD.
*//********************************************************************
  METHOD on_link_click.
    CHECK row > 0.
    READ TABLE <gt_output> ASSIGNING FIELD-SYMBOL(<row>) INDEX row.
    CHECK <row> IS ASSIGNED.
    ASSIGN COMPONENT '_RETURN' OF STRUCTURE <row> TO FIELD-SYMBOL(<bapi>).
    CHECK <bapi> IS ASSIGNED.
    DATA lr_salv TYPE REF TO cl_salv_table.
    IF lr_salv IS INITIAL.
      TRY.
          CALL METHOD cl_salv_table=>factory
            IMPORTING
              r_salv_table = lr_salv
            CHANGING
              t_table      = <bapi>.
        CATCH cx_salv_existing INTO DATA(lo_err10).
        CATCH cx_salv_msg INTO DATA(lo_err11).
      ENDTRY.
    ENDIF.
    lr_salv->set_screen_popup(
      start_column = 15
      end_column = 120
      start_line = 1
      end_line = 10 ).
    DATA lr_columns TYPE REF TO cl_salv_columns.
    lr_columns = lr_salv->get_columns( ).
    lr_columns->set_optimize( 'X' ).
    lr_salv->display( ).
  ENDMETHOD.
*//********************************************************************
  METHOD refresh.
    IF lo_salv IS NOT INITIAL.
      lr_columns = lo_salv->get_columns( ).
      lr_columns->set_optimize( 'X' ).
      CALL METHOD lo_salv->refresh( ).
    ENDIF.
  ENDMETHOD.
*//********************************************************************
  METHOD prepare_field_relation_logic.
    DATA lt_dfies TYPE TABLE OF dfies.
    CLEAR lt_dfies.
    CALL FUNCTION 'DDIF_FIELDINFO_GET'
      EXPORTING
        tabname   = tabname
        langu     = sy-langu
      TABLES
        dfies_tab = lt_dfies.
    CLEAR gwa_field_relation.

    DATA ls_dd02v TYPE dd02v.
    CALL FUNCTION 'DDIF_TABL_GET'
      EXPORTING
        name     = tabname
        state    = 'A'
        langu    = '1'
      IMPORTING
        dd02v_wa = ls_dd02v.

    LOOP AT lt_dfies ASSIGNING FIELD-SYMBOL(<dfies>).
      MOVE-CORRESPONDING <dfies> TO gwa_field_relation.
      gwa_field_relation-tab_desc = ls_dd02v-ddtext.
      APPEND gwa_field_relation TO gt_field_relation.
      CLEAR gwa_field_relation.
    ENDLOOP.

  ENDMETHOD.
*//********************************************************************
  METHOD prepare_field_relation.
    CLEAR gt_field_relation.
    prepare_field_relation_logic( 'BAPIMATHEAD' ).
    prepare_field_relation_logic( 'BAPI_MAKT' ).
    prepare_field_relation_logic( 'BAPI_MARA' ).
    prepare_field_relation_logic( 'BAPI_MARC' ).
    prepare_field_relation_logic( 'BAPI_MPOP' ).
    prepare_field_relation_logic( 'BAPI_MPGD' ).
    prepare_field_relation_logic( 'BAPI_MARD' ).
    prepare_field_relation_logic( 'BAPI_MBEW' ).
    prepare_field_relation_logic( 'BAPI_MLGN' ).
    prepare_field_relation_logic( 'BAPI_MVKE' ).
    prepare_field_relation_logic( 'BAPI_MLGT' ).
    prepare_field_relation_logic( 'BAPI_MEAN' ).
    prepare_field_relation_logic( 'BAPI_MLAN' ).
    prepare_field_relation_logic( 'BAPI_MFHM' ).
  ENDMETHOD.

ENDCLASS.

*//***************************************************************************
*//***************************************************************************
FORM download_template USING it_table TYPE STANDARD TABLE
                             iv_file_name TYPE string.

*  DATA(lv_path) = zcl_excel_tools=>set_download_path( '物料主数据导入模板' ).
*  CHECK lv_path IS NOT INITIAL.
*  zcl_excel_tools=>download_template( EXPORTING iv_path = lv_path
*                                                id_data = it_table
*                                                iv_fields_desc = ''
**                                                IT_FIELDS_DESC
*                                                 ).
*  RETURN.

  DATA lo_salv TYPE REF TO cl_salv_table.
  DATA lo_columns TYPE REF TO cl_salv_columns_table.
  DATA lo_column TYPE REF TO cl_salv_column_table.
  DATA l_columns TYPE salv_t_column_ref.
  FIELD-SYMBOLS <l_column> TYPE LINE OF salv_t_column_ref.
  DATA: lo_result_data TYPE REF TO cl_salv_ex_result_data_table.
  DATA e_xstring TYPE xstring.
  DATA it_sort TYPE lvc_t_sort.
  DATA it_filt TYPE lvc_t_filt.
  DATA is_layout TYPE lvc_s_layo.
  DATA lo_aggreg TYPE REF TO cl_salv_aggregations.
  DATA lt_fcat TYPE lvc_t_fcat.
  FIELD-SYMBOLS <fcat> TYPE lvc_s_fcat.

  DATA: l_size TYPE i.
  DATA: lt_bintab TYPE solix_tab.
  DATA: l_filename TYPE string.
  IF iv_file_name IS INITIAL.
    CONCATENATE cnst_template_name  '-'  sy-datum  '-'  sy-uzeit INTO l_filename.
  ELSE.
    CONCATENATE iv_file_name '-' sy-datum '-' sy-uzeit INTO l_filename.
  ENDIF.
  DATA: l_path TYPE string.
  DATA: f_path TYPE string.

  DATA: mt_data TYPE REF TO data.
  FIELD-SYMBOLS <mt_data> TYPE STANDARD TABLE.
  CREATE DATA mt_data LIKE it_table.
  ASSIGN mt_data->* TO <mt_data>.

  <mt_data> = it_table.
  DELETE <mt_data> INDEX 2.

  TRY.
      CALL METHOD cl_salv_table=>factory
        IMPORTING
          r_salv_table = lo_salv
        CHANGING
          t_table      = <mt_data>.
    CATCH cx_salv_msg INTO DATA(lo_err15).
  ENDTRY.
  CHECK lo_salv IS NOT INITIAL.
  DATA lr_columns TYPE REF TO cl_salv_columns.
  DATA lr_column TYPE REF TO cl_salv_column.
  DATA lr_salv_error TYPE REF TO cx_salv_not_found.
  lr_columns = lo_salv->get_columns( ).

  DEFINE coltext.
    TRY.
      lr_column = lr_columns->get_column( &1 ).
      lr_column->set_short_text( &2 ).
      lr_column->set_medium_text( &2 ).
      lr_column->set_long_text( &2 ).
    CATCH cx_salv_not_found INTO lr_salv_error.
    ENDTRY.
  END-OF-DEFINITION.

  FIELD-SYMBOLS <row> TYPE any.
  READ TABLE it_table ASSIGNING <row> INDEX 2.
  DATA lo_struct TYPE REF TO cl_abap_structdescr.
  DATA component_tab TYPE cl_abap_structdescr=>component_table.
  lo_struct ?= cl_abap_structdescr=>describe_by_data( <row> ).
  component_tab = lo_struct->get_components( ).
  DATA fname TYPE lvc_fname VALUE IS INITIAL.

  DATA txt_long TYPE scrtext_l.
  DATA txt_medium TYPE scrtext_m.
  DATA txt_short TYPE scrtext_s.

  DEFINE ctext.
    TRY.
      lr_column = lr_columns->get_column( &1 ).
      lr_column->set_short_text( &2 ).
      lr_column->set_medium_text( &3 ).
      lr_column->set_long_text( &4 ).
    CATCH cx_salv_not_found INTO lr_salv_error.
    ENDTRY.
  END-OF-DEFINITION.

  LOOP AT component_tab ASSIGNING FIELD-SYMBOL(<comp>).
    ASSIGN COMPONENT <comp>-name OF STRUCTURE <row> TO FIELD-SYMBOL(<fvalue>).
    fname = <comp>-name.
    txt_short = <fvalue>.
    txt_medium = <fvalue>.
    txt_long = <fvalue>.
    ctext fname txt_short txt_medium txt_long .
  ENDLOOP.

  lo_columns ?= lo_salv->get_columns( ).
  l_columns = lo_columns->get( ).

  lo_aggreg = lo_salv->get_aggregations( ).
  lt_fcat = cl_salv_controller_metadata=>get_lvc_fieldcatalog( r_columns      = lo_columns
                                                               r_aggregations =  lo_aggreg ).

  LOOP AT l_columns ASSIGNING <l_column>.
    IF <l_column>-columnname(1) = '_'.
      DELETE lt_fcat WHERE fieldname = <l_column>-columnname.
      CONTINUE.
    ENDIF.
    IF <fcat> IS ASSIGNED.
      UNASSIGN <fcat>.
    ENDIF.
    READ TABLE lt_fcat ASSIGNING <fcat>
      WITH KEY fieldname = <l_column>-columnname.
    IF <fcat> IS ASSIGNED.
      <fcat>-reptext = <l_column>-r_column->get_short_text( ).
    ENDIF.
  ENDLOOP.

  lo_result_data = cl_salv_ex_util=>factory_result_data_table(
       r_data                      = mt_data
       s_layout                    = is_layout
       t_fieldcatalog              = lt_fcat
       t_sort                      = it_sort
       t_filter                    = it_filt ).
  CALL METHOD cl_salv_bs_tt_util=>if_salv_bs_tt_util~transform
    EXPORTING
*     xml_type      = if_salv_bs_xml=>c_type_excel_xml
      xml_type      = if_salv_bs_xml=>c_type_xlsx
      "老系统中没有c_type_xlsx这个类型,只能使用c_type_excel_xml了。
*     xml_version   = if_salv_bs_xml=>version_21 "没感觉到区别和下面
      xml_version   = if_salv_bs_xml=>version_26 "老系统没有26版本
      r_result_data = lo_result_data
      xml_flavour   = if_salv_bs_c_tt=>c_tt_xml_flavour_export
*     gui_type      = if_salv_bs_xml=>c_gui_type_gui
      gui_type      = if_salv_bs_xml=>c_gui_type_wd
    IMPORTING
      xml           = e_xstring.

  IF e_xstring IS NOT INITIAL.
    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        buffer        = e_xstring
      IMPORTING
        output_length = l_size
      TABLES
        binary_tab    = lt_bintab.
    cl_gui_frontend_services=>file_save_dialog(
      EXPORTING
        window_title         = '保存导入模板'
*        default_extension    = 'XLS' "c_type_excel_xml时需要这个。
        default_extension    = 'xlsx'
        default_file_name    = l_filename
*      with_encoding        = with_encoding
*      file_filter          = file_filter
*      initial_directory    = initial_directory
      prompt_on_overwrite  = 'X'
      CHANGING
         filename             = l_filename
         path                 = l_path
         fullpath             = f_path
*      user_action          = user_action
*      file_encoding        = file_encoding
      EXCEPTIONS
        cntl_error           = 1
        error_no_gui         = 2
        not_supported_by_gui = 3
        OTHERS               = 4
           ).
    CHECK f_path IS NOT INITIAL.
    CALL METHOD cl_gui_frontend_services=>gui_download(
      EXPORTING
        bin_filesize = l_size
        filename     = f_path
        filetype     = 'BIN'
      CHANGING
        data_tab     = lt_bintab
      EXCEPTIONS
        OTHERS       = 24 ).
  ENDIF.

ENDFORM.
*//***************************************************************************
*//***************************************************************************
FORM frm_view_templates.

  SELECT DISTINCT srtfd,aedat, pgmid FROM indx
    WHERE usera = 'MAT_MAINTAIN'
    ORDER BY aedat DESCENDING
    INTO TABLE @DATA(lt_list).
*  IF sy-subrc = 0 AND lt_list IS NOT INITIAL.
*  ELSE.
*    MESSAGE '没有模板历史' TYPE 'S' DISPLAY LIKE 'W'.
*  ENDIF.
  "//不用判断,如果没有,也许是需要导入,从其它系统。
  zcl_tabbed=>display_once(
    iv_popup = abap_true
    it_top = VALUE #(
      ( io_tabbed = zcl_tabbed=>new( lt_list )
        iv_alv_except_fields = 'SRTFD'
        iv_alv_with_toolbar = abap_true
        iv_alv_fields_desc = |aedat:模板生成日期,PGMID:模板名称|
        iv_alv_dclick_callback = |template_callback_dclick|
        iv_alv_toolbar = |GENERATE:@DJ@-生成模板,UPLOAD:@48@-上载模板|
        iv_alv_toolbar_callback = |TEMPLATE_CALLBACK_TOOLBAR|
      )
    )
  ).

ENDFORM.
*//***************************************************************************
*//***************************************************************************
FORM template_callback_toolbar USING sender TYPE REF TO cl_gui_alv_grid
                                   e_ucomm TYPE syst_ucomm
                     CHANGING ct_top TYPE zcl_tabbed=>ttyp_tab
                              ct_bottom TYPE zcl_tabbed=>ttyp_tab
                               cs_pop TYPE zcl_tabbed=>typ_tab
                               cv_no_leave TYPE abap_bool. "D20211025 新增参数,
  "为了控制CLOSE LEAVE等在特殊情况下不CLOSE LEAVE<br>
  "2021-10-28 新增,还可以处理ALV自定义上下文菜单功能<br><br><br><br>
  READ TABLE ct_top ASSIGNING FIELD-SYMBOL(<ls_top>) WITH KEY ro_alv = sender.
  CHECK sy-subrc = 0.
  FIELD-SYMBOLS <lt_alv_table> TYPE STANDARD TABLE.
  ASSIGN <ls_top>-io_tabbed->gt_table->* TO <lt_alv_table>.
  CHECK sy-subrc = 0.

  CASE e_ucomm.
    WHEN 'GENERATE'.
      IF lines( <ls_top>-rt_alv_selected_rows ) <> 1.
        MESSAGE |请只选中一行进行模板生成| TYPE 'I' DISPLAY LIKE 'W'.
        RETURN.
      ENDIF.
      DATA ls_indx TYPE indx.
      CLEAR ls_indx.
      READ TABLE <lt_alv_table> ASSIGNING FIELD-SYMBOL(<ls_alv_row>)
      INDEX <ls_top>-rt_alv_selected_rows[ 1 ]-index.
      CHECK sy-subrc = 0.
      MOVE-CORRESPONDING <ls_alv_row> TO ls_indx.
      CHECK ls_indx-srtfd IS NOT INITIAL.
      DATA lt_fields_list LIKE gt_fields_list.
      CLEAR lt_fields_list.
      TRY.
          IMPORT itab = lt_fields_list FROM DATABASE indx(zx) ID ls_indx-srtfd.
        CATCH cx_root INTO DATA(lx_error).
          MESSAGE |获取模板字段失败:{ lx_error->get_text( ) }| TYPE 'I' DISPLAY LIKE 'E'.
          RETURN.
      ENDTRY.

      DATA(lv_counter) = 0.
      CLEAR gt_components.
      go_datadescr ?= cl_abap_datadescr=>describe_by_name( 'STRING' ).
      DO lines( lt_fields_list ) TIMES.
        lv_counter = lv_counter + 1.
        APPEND INITIAL LINE TO gt_components ASSIGNING FIELD-SYMBOL(<ls_comp>).
        <ls_comp>-name = 'COL' && lv_counter.
        <ls_comp>-type = go_datadescr.
      ENDDO.
      go_structdescr = cl_abap_structdescr=>create( gt_components ).
      go_tabledesc = cl_abap_tabledescr=>create( go_structdescr ).
      DATA lt_template TYPE REF TO data.
      CREATE DATA lt_template TYPE HANDLE go_tabledesc.
      FIELD-SYMBOLS <lt_template> TYPE STANDARD TABLE.
      ASSIGN lt_template->* TO <lt_template>.
      APPEND INITIAL LINE TO <lt_template> ASSIGNING FIELD-SYMBOL(<ls_row1>).
      APPEND INITIAL LINE TO <lt_template> ASSIGNING FIELD-SYMBOL(<ls_row2>).
      lv_counter = 0.
      LOOP AT lt_fields_list ASSIGNING FIELD-SYMBOL(<ls_field_list>).
        lv_counter = lv_counter + 1.
        ASSIGN COMPONENT lv_counter OF STRUCTURE <ls_row1> TO FIELD-SYMBOL(<lv_field1>).
        ASSIGN COMPONENT lv_counter OF STRUCTURE <ls_row2> TO FIELD-SYMBOL(<lv_field2>).
        <lv_field1> = <ls_field_list>-fieldname.
        <lv_field2> = <ls_field_list>-fielddesc.
      ENDLOOP.

      DATA lv_file_name TYPE string.
      lv_file_name = ls_indx-pgmid.
      PERFORM download_template USING <lt_template> lv_file_name .
      RETURN.

      DATA(lv_path) = zcl_excel_tools=>set_download_path( |{ ls_indx-pgmid }| ).
      CHECK lv_path IS NOT INITIAL.
      zcl_excel_tools=>download_excel( iv_path = lv_path
                                       it_table = <lt_template>
                                       iv_fields_desc = '' ).
    WHEN 'UPLOAD'.
      DATA(lv_path_upload) = zcl_excel_tools=>get_upload_path( ).
      CHECK lv_path_upload IS NOT INITIAL.
      FIELD-SYMBOLS <lt_excel_template> TYPE STANDARD TABLE.
      DATA(lo_excel) = zcl_excel_tools=>upload_by_fdt( iv_path = lv_path_upload ).
      ASSIGN lo_excel->gt_excel->* TO <lt_excel_template>.
      CHECK sy-subrc = 0.
      CHECK lines( <lt_excel_template> ) > 2.
      READ TABLE <lt_excel_template> ASSIGNING FIELD-SYMBOL(<ls_row1upload>) INDEX 1.
      READ TABLE <lt_excel_template> ASSIGNING FIELD-SYMBOL(<ls_row2upload>) INDEX 2.
      go_tabledesc ?= cl_abap_tabledescr=>describe_by_data( <lt_excel_template> ).
      go_structdescr ?= go_tabledesc->get_table_line_type( ).
      DATA(lt_components) = go_structdescr->get_included_view( ).
      CLEAR gt_fields_list.
      LOOP AT lt_components ASSIGNING FIELD-SYMBOL(<ls_component>).
        ASSIGN COMPONENT <ls_component>-name OF STRUCTURE <ls_row1upload> TO FIELD-SYMBOL(<lv_value1upload>).
        ASSIGN COMPONENT <ls_component>-name OF STRUCTURE <ls_row2upload> TO FIELD-SYMBOL(<lv_value2upload>).
        APPEND INITIAL LINE TO gt_fields_list ASSIGNING <ls_field_list> .
        <ls_field_list>-fieldname = <lv_value2upload>.
        <ls_field_list>-fielddesc = <lv_value1upload>.
      ENDLOOP.
      CHECK lines( gt_fields_list ) > 0.
      "//弹出框,输入模板名称
      DATA ls_name TYPE j_3gbelk.
      CLEAR ls_name.
      zcl_xhl=>get_input_values( EXPORTING iv_structure_name = 'J_3GBELK'
                                           iv_fields = 'J_3GVVCOM1'
                                 CHANGING cs_structure = ls_name ).
      IF ls_name-j_3gvvcom1 IS INITIAL.
        ls_name-j_3gvvcom1 = |物料主数据导入模板-{ sy-datum }-{ sy-uzeit }|.
      ENDIF.
*      DATA ls_indx TYPE indx.
      CLEAR ls_indx.
      TRY.
          ls_indx-srtfd = cl_system_uuid=>create_uuid_c22_static( ).
        CATCH cx_root.
      ENDTRY.
      ls_indx-relid  = 'ZX'.
      ls_indx-usera = 'MAT_MAINTAIN'.
      ls_indx-aedat = sy-datum.
      ls_indx-pgmid = ls_name-j_3gvvcom1.
      EXPORT itab = gt_fields_list TO DATABASE indx(zx) FROM ls_indx ID ls_indx-srtfd.
      COMMIT WORK.
      DATA ls_row TYPE REF TO data.
      CREATE DATA ls_row LIKE LINE OF <lt_alv_table>.
      ASSIGN ls_row->* TO <ls_alv_row>.
      MOVE-CORRESPONDING ls_indx TO <ls_alv_row>.
      INSERT <ls_alv_row> INTO <lt_alv_table> INDEX 1.
      TRY.
          sender->refresh_table_display( ).
        CATCH cx_root.
      ENDTRY.
  ENDCASE.

ENDFORM.
*//***************************************************************************
*//***************************************************************************
FORM template_callback_dclick USING sender TYPE REF TO cl_gui_alv_grid
                           row TYPE int4
                           column TYPE char30
                           cs_current_row TYPE data
            CHANGING ct_top TYPE zcl_tabbed=>ttyp_tab
                    ct_bottom TYPE zcl_tabbed=>ttyp_tab
                    cs_pop TYPE zcl_tabbed=>typ_tab
                     co_tabbed TYPE REF TO zcl_tabbed.

  DATA lt_fields_list LIKE gt_fields_list.
  CLEAR lt_fields_list.
  CLEAR ct_bottom.
  DATA ls_indx TYPE indx.
  MOVE-CORRESPONDING cs_current_row TO ls_indx.
  CHECK ls_indx-srtfd IS NOT INITIAL.
  IMPORT itab = lt_fields_list FROM DATABASE indx(zx) ID ls_indx-srtfd.
  ct_bottom = VALUE #(
    ( io_tabbed = zcl_tabbed=>new( lt_fields_list )
    )
  ).
  co_tabbed->show_tabbed_alvs( ct_bottom ).

ENDFORM.
*//***************************************************************************
*//***************************************************************************
"""""""""""""""""""""""""""""""""""
"BAPI相关变量定义
"""""""""""""""""""""""""""""""""""
DATA:
  headdata             LIKE bapimathead,
  clientdata           LIKE bapi_mara,
  clientdatax          LIKE bapi_marax,
  plantdata            LIKE bapi_marc,
  plantdatax           LIKE bapi_marcx,
  forecastparameters   LIKE bapi_mpop,
  forecastparametersx  LIKE bapi_mpopx,
  planningdata         LIKE bapi_mpgd,
  planningdatax        LIKE bapi_mpgdx,
  storagelocationdata  LIKE bapi_mard,
  storagelocationdatax LIKE bapi_mardx,
  valuationdata        LIKE bapi_mbew,
  valuationdatax       LIKE bapi_mbewx,
  warehousenumberdata  LIKE bapi_mlgn,
  warehousenumberdatax LIKE bapi_mlgnx,
  salesdata            LIKE bapi_mvke,
  salesdatax           LIKE bapi_mvkex,
  storagetypedata      LIKE bapi_mlgt,
  storagetypedatax     LIKE bapi_mlgtx.

DATA:
  materialdescription    TYPE TABLE OF     bapi_makt WITH HEADER LINE,
  unitsofmeasure      TYPE TABLE OF  bapi_marm WITH HEADER LINE,
  unitsofmeasurex        TYPE TABLE OF     bapi_marmx WITH HEADER LINE,
  internationalartnos    TYPE TABLE OF     bapi_mean WITH HEADER LINE,
  materiallongtext    TYPE TABLE OF  bapi_mltx WITH HEADER LINE,
  taxclassifications  TYPE TABLE OF  bapi_mlan WITH HEADER LINE,
  returnmessages      TYPE TABLE OF  bapi_matreturn2 WITH HEADER LINE,
  prtdata                TYPE TABLE OF     bapi_mfhm WITH HEADER LINE,
  prtdatax            TYPE TABLE OF  bapi_mfhmx WITH HEADER LINE.

DATA: extensionin TYPE TABLE OF bapiparex WITH HEADER LINE.
DATA: extensioninx TYPE TABLE OF bapiparexx WITH HEADER LINE.
"""""""""""""""""""""""""""""""""""
"""""""""""""""""""""""""""""""""""
FORM init_variables.
  CLEAR:
  headdata,
  clientdata,
  clientdatax,
  plantdata,
  plantdatax,
  forecastparameters,
  forecastparametersx,
  planningdata,
  planningdatax,
  storagelocationdata,
  storagelocationdatax,
  valuationdata,
  valuationdatax,
  warehousenumberdata,
  warehousenumberdatax,
  salesdata,
  salesdatax,
  storagetypedata,
  storagetypedatax,

  materialdescription,
  materialdescription[],
  unitsofmeasure,
  unitsofmeasure[],
  unitsofmeasurex,
  unitsofmeasurex[],
  internationalartnos,
  internationalartnos[],
  materiallongtext,
  materiallongtext[],
  taxclassifications,
  taxclassifications[],
  returnmessages,
  returnmessages[],
  prtdata,
  prtdata[],
  prtdatax,
  prtdatax[],

  extensionin,
  extensionin[],
  extensioninx,
  extensioninx[]
  .
ENDFORM.
*//***************************************************************************
*//***************************************************************************
FORM frm_prepare_2_bg.

  CLEAR gt_fields.
  go_tabledesc ?= cl_abap_tabledescr=>describe_by_data( <gt_output> ).
  go_structdescr ?= go_tabledesc->get_table_line_type( ).
  CLEAR gt_components.
  DATA(lt_components) = go_structdescr->get_included_view( ).
  LOOP AT lt_components ASSIGNING FIELD-SYMBOL(<ls_comp>).
*    CHECK <ls_comp>-name(1) <> '_'.
    APPEND INITIAL LINE TO gt_fields ASSIGNING FIELD-SYMBOL(<ls_field>).
    <ls_field>-fieldname = <ls_comp>-name.
  ENDLOOP.
  DATA lv_srtfd TYPE indx_srtfd.
  DATA lv_srtfd1 TYPE indx_srtfd.
  TRY.
      lv_srtfd = cl_system_uuid=>create_uuid_c22_static( ).
      lv_srtfd = |{ lv_srtfd CASE = UPPER }|.
    CATCH cx_root.
      MESSAGE 'Oh GOD' TYPE 'X'.
  ENDTRY.
  TRY.
      lv_srtfd1 = cl_system_uuid=>create_uuid_c22_static( ).
      lv_srtfd1 = |{ lv_srtfd1 CASE = UPPER }|.
    CATCH cx_root.
      MESSAGE 'Oh GOD' TYPE 'X'.
  ENDTRY.

  EXPORT itab_structure = gt_fields TO DATABASE indx(zx) ID lv_srtfd1.
  EXPORT itab = <gt_output> TO DATABASE indx(zx) ID lv_srtfd.
  COMMIT WORK AND WAIT.
  DATA(lv_okgo) = abap_false.
  SELECT SINGLE @abap_true FROM indx WHERE srtfd = @lv_srtfd INTO @DATA(lv_result).
  IF sy-subrc <> 0.
    DO 500 TIMES.
      SELECT SINGLE @abap_true FROM indx WHERE srtfd = @lv_srtfd INTO @lv_result.
      IF sy-subrc <> 0.
        WAIT UP TO 1 SECONDS.
      ELSE.
        lv_okgo = abap_true.
        EXIT.
      ENDIF.
    ENDDO.
  ELSE.
    lv_okgo = abap_true.
  ENDIF.
  IF lv_okgo = abap_false.
    MESSAGE |数据准备失败,无法提交后台执行| TYPE 'S' DISPLAY LIKE 'E'.
  ELSE.
    gs_job-intreport = sy-repid.
    gv_background = abap_true.
    gv_test_run = abap_false.
    go_job = zcl_job=>new( ).
    gs_job_return = go_job->create_job( EXPORTING it_sel_table = VALUE #(
                                                      ( selname = 'P_BG'
                                                        kind = 'P'
                                                        sign = 'I'
                                                        option = 'EQ'
                                                        low = abap_true )
                                                      ( selname = 'P_SRTFD'
                                                        kind = 'P'
                                                        sign = 'I'
                                                        option = 'EQ'
                                                        low = lv_srtfd )
                                                      ( selname = 'P_SRTFD1'
                                                        kind = 'P'
                                                        sign = 'I'
                                                        option = 'EQ'
                                                        low = lv_srtfd1 )
                                                    )
                                          CHANGING cs_job_info = gs_job ) .
    IF gs_job_return-type = 'S'.
      MESSAGE |提交后台执行成功,后台job信息| TYPE 'S' .
    ENDIF.
  ENDIF.

ENDFORM.
*//***************************************************************************
*//***************************************************************************
FORM frm_display_job.
  IF gs_job IS NOT INITIAL.
    zcl_tabbed=>display_once(
      iv_popup = abap_true
      iv_top_alvs_mode = zcl_tabbed=>gs_alvs_mode-tab
      it_top = VALUE #(
        ( io_tabbed = zcl_tabbed=>new( gs_job )
          iv_tab_name = '后台任务相关信息'
          iv_alv_dclick_callback = 'job_callback_dclick'
        )
        ( io_tabbed = zcl_tabbed=>new( gs_job_return )
          iv_tab_name = '后台任务创建信息'
        )
      )
     ).
  ENDIF.
ENDFORM.
*//***************************************************************************
*//***************************************************************************
FORM job_callback_dclick USING sender TYPE REF TO cl_gui_alv_grid
                           row TYPE int4
                           column TYPE char30
                           cs_current_row TYPE data
            CHANGING ct_top TYPE zcl_tabbed=>ttyp_tab
                    ct_bottom TYPE zcl_tabbed=>ttyp_tab
                    cs_pop TYPE zcl_tabbed=>typ_tab
                     co_tabbed TYPE REF TO zcl_tabbed.

  DATA ls_job TYPE tbtcjob.
  CLEAR ls_job.
  MOVE-CORRESPONDING cs_current_row TO ls_job.
  CHECK ls_job IS NOT INITIAL.
  go_job->call_sm37( ).

ENDFORM.
*//***************************************************************************
*//***************************************************************************
FORM frm_exec.

  lcl_process=>prepare_field_relation( ).

  CHECK <gt_output> IS ASSIGNED.
  CHECK lines( <gt_output> ) > 2.

  READ TABLE <gt_output> ASSIGNING FIELD-SYMBOL(<row>) INDEX 2.

  DATA lo_struct TYPE REF TO cl_abap_structdescr.
  DATA components_tab TYPE cl_abap_structdescr=>component_table.

  DATA lv_tabname TYPE char30.
  DATA lv_fieldname TYPE char30.
  DATA lv_counter TYPE i VALUE IS INITIAL.

  lo_struct ?= cl_abap_structdescr=>describe_by_data( <row> ).
  components_tab = lo_struct->get_components( ).

  CLEAR:lcl_process=>gs_bapi_ext_relation.
  CLEAR:lcl_process=>gt_bapi_ext_relation.

  LOOP AT components_tab ASSIGNING FIELD-SYMBOL(<comp>).
    IF <comp>-name(1) = '_'.
      CONTINUE.
    ENDIF.

    lv_counter = lv_counter + 1.

    ASSIGN COMPONENT <comp>-name OF STRUCTURE <row> TO FIELD-SYMBOL(<tabfield>).
    CLEAR: lv_tabname, lv_fieldname.

    SPLIT <tabfield> AT '-' INTO lv_tabname lv_fieldname IN CHARACTER MODE.
    READ TABLE lcl_process=>gt_field_relation ASSIGNING FIELD-SYMBOL(<relation>)
    WITH KEY tabname = lv_tabname fieldname = lv_fieldname.
    IF <relation> IS ASSIGNED.
      <relation>-excel_original_text = <comp>-name.
      <relation>-excel_fieldname = '' && lv_counter && ''.
    ENDIF.

    IF lv_fieldname IS NOT INITIAL.

      DATA field1 TYPE char30 VALUE IS INITIAL.
      DATA field2 TYPE char30 VALUE IS INITIAL.
      IF lv_fieldname(1) = 'Z'.
        CLEAR:field1,field2.
        SPLIT lv_tabname AT '_' INTO field1 field2 IN CHARACTER MODE.
        IF field2 IS NOT INITIAL.
          field2 = 'BAPI_TE_' && field2.
          CONDENSE field2 NO-GAPS.

          lcl_process=>gs_bapi_ext_relation-tabname = lv_tabname.
          lcl_process=>gs_bapi_ext_relation-tabname_bapi_ext = field2.
          lcl_process=>gs_bapi_ext_relation-tabname_bapi_extx = field2 && 'X'.

          SELECT SINGLE fieldname INTO field1 FROM dd03l WHERE tabname = field2 AND fieldname = lv_fieldname.
          IF sy-subrc = 0.
            field2 = field2 && 'X'.
            CONDENSE field2 NO-GAPS.
            SELECT SINGLE fieldname INTO field1 FROM dd03l WHERE tabname = field2 AND fieldname = lv_fieldname.
            IF sy-subrc = 0.
              APPEND lcl_process=>gs_bapi_ext_relation TO lcl_process=>gt_bapi_ext_relation.
            ELSE.
              CLEAR: lcl_process=>gs_bapi_ext_relation.
            ENDIF.
          ELSE.
            CLEAR: lcl_process=>gs_bapi_ext_relation.
          ENDIF.
        ENDIF.
      ENDIF.

    ENDIF.

  ENDLOOP.

  SORT lcl_process=>gt_bapi_ext_relation.
  DELETE ADJACENT DUPLICATES FROM lcl_process=>gt_bapi_ext_relation.

  DATA lo_data TYPE REF TO cl_abap_datadescr.
  DATA components_bapi TYPE cl_abap_structdescr=>component_table.
  DATA component_bapi TYPE LINE OF cl_abap_structdescr=>component_table.
  DATA lt_dd03m TYPE TABLE OF dd03m WITH HEADER LINE.
  CLEAR:lt_dd03m,lt_dd03m[].
  LOOP AT lcl_process=>gt_bapi_ext_relation ASSIGNING FIELD-SYMBOL(<bapi_ext>).
    CLEAR: component_bapi,components_bapi.
    SELECT * FROM dd03m INTO TABLE lt_dd03m WHERE tabname = <bapi_ext>-tabname_bapi_ext AND ddlanguage = sy-langu.
    SORT lt_dd03m BY position.
    LOOP AT lt_dd03m.
      component_bapi-name = lt_dd03m-fieldname.
      lo_data ?= cl_abap_datadescr=>describe_by_name( lt_dd03m-tabname && '-' && lt_dd03m-fieldname ).
      component_bapi-type = lo_data.
      APPEND component_bapi TO components_bapi.
      CLEAR component_bapi.
    ENDLOOP.
    lo_struct = cl_abap_structdescr=>create( components_bapi ).
    CREATE DATA <bapi_ext>-bapi_ext_row TYPE HANDLE lo_struct.

    CLEAR: component_bapi,components_bapi.
    SELECT * FROM dd03m INTO TABLE lt_dd03m WHERE tabname = <bapi_ext>-tabname_bapi_extx AND ddlanguage = sy-langu.
    SORT lt_dd03m BY position.
    LOOP AT lt_dd03m.
      component_bapi-name = lt_dd03m-fieldname.
      lo_data ?= cl_abap_datadescr=>describe_by_name( lt_dd03m-tabname && '-' && lt_dd03m-fieldname ).
      component_bapi-type = lo_data.
      APPEND component_bapi TO components_bapi.
      CLEAR component_bapi.
    ENDLOOP.
    lo_struct = cl_abap_structdescr=>create( components_bapi ).
    CREATE DATA <bapi_ext>-bapi_ext_rowx TYPE HANDLE lo_struct.

  ENDLOOP.


  DATA fm_name TYPE rs38l_fnam.
  DATA excel_value_temp TYPE string.
  DATA len TYPE i.

  DATA counter TYPE i VALUE IS INITIAL.
  DATA counter_msg TYPE char40 VALUE IS INITIAL.
  DATA msg TYPE string.

  DATA(check_match) = ''.
  LOOP AT lcl_process=>gt_field_relation ASSIGNING FIELD-SYMBOL(<ls_relation1>) WHERE excel_fieldname IS NOT INITIAL.
    check_match = 'X'.
    EXIT.
  ENDLOOP.

  IF check_match IS INITIAL.
    MESSAGE '模板有问题,请确认后再执行!' TYPE 'I' DISPLAY LIKE 'E'.
    RETURN.
  ENDIF.

  LOOP AT <gt_output> ASSIGNING FIELD-SYMBOL(<ls_output>).
    CHECK sy-tabix > 2.
    ASSIGN COMPONENT '_ICON' OF STRUCTURE <ls_output> TO FIELD-SYMBOL(<temp_icon>).
    ASSIGN COMPONENT '_MSG' OF STRUCTURE <ls_output> TO FIELD-SYMBOL(<temp_msg>).
    IF <temp_icon> = icon_green_light AND <temp_msg> = '导入成功' .
      CONTINUE.
    ENDIF.

    PERFORM init_variables.

    LOOP AT lcl_process=>gt_field_relation ASSIGNING FIELD-SYMBOL(<ls_relation>) WHERE excel_fieldname IS NOT INITIAL..
      ASSIGN COMPONENT <ls_relation>-excel_original_text OF STRUCTURE <ls_output> TO FIELD-SYMBOL(<excel_value>).

      """""""""""""""""""""""""""""""""""""""""""""
      CASE <ls_relation>-tabname.
        WHEN 'BAPIMATHEAD'. "不需要更改参数
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE headdata TO FIELD-SYMBOL(<record_value>).
        WHEN 'BAPI_MARA'. "需要更改参数
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE clientdata TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE clientdatax TO FIELD-SYMBOL(<record_valuex>).
          <record_valuex> = 'X'.
        WHEN 'BAPI_MARC'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE plantdata TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE plantdatax TO <record_valuex>.
          <record_valuex> = 'X'.
        WHEN 'BAPI_MPOP'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE forecastparameters TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE forecastparametersx TO <record_valuex>.
          <record_valuex> = 'X'.
        WHEN 'BAPI_MPGD'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE planningdata TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE planningdatax TO <record_valuex>.
          <record_valuex> = 'X'.
        WHEN 'BAPI_MARD'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE storagelocationdata TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE storagelocationdatax TO <record_valuex>.
          <record_valuex> = 'X'.
        WHEN 'BAPI_MBEW'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE valuationdata TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE valuationdatax TO <record_valuex>.
          <record_valuex> = 'X'.
        WHEN 'BAPI_MLGN'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE warehousenumberdata TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE warehousenumberdatax TO <record_valuex>.
          <record_valuex> = 'X'.
        WHEN 'BAPI_MVKE'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE salesdata TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE salesdatax TO <record_valuex>.
          <record_valuex> = 'X'.
        WHEN 'BAPI_MLGT'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE storagetypedata TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE storagetypedatax TO <record_valuex>.
          <record_valuex> = 'X'.
          "以上是输入参数,结构。

        WHEN 'BAPI_MAKT'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE materialdescription TO <record_value>.
        WHEN 'BAPI_MARM'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE unitsofmeasure TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE unitsofmeasurex TO <record_valuex>.
          <record_valuex> = 'X'.
        WHEN 'BAPI_MEAN'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE internationalartnos TO <record_value>.
        WHEN 'BAPI_MLTX'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE materiallongtext TO <record_value>.
        WHEN 'BAPI_MLAN'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE taxclassifications TO <record_value>.
        WHEN 'BAPI_MFHM'.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE prtdata TO <record_value>.
          ASSIGN COMPONENT <ls_relation>-fieldname OF STRUCTURE prtdatax TO <record_valuex>.
          <record_valuex> = 'X'.
      ENDCASE.
      """""""""""""""""""""""""""""""""""""""""""""

      DATA lo TYPE REF TO cl_abap_datadescr.
      CLEAR lo.
      IF <record_valuex> IS ASSIGNED.
        lo ?= cl_abap_datadescr=>describe_by_data( <record_valuex> ).
      ENDIF.

      IF <ls_relation>-convexit IS NOT INITIAL.
        CONCATENATE 'CONVERSION_EXIT_' <ls_relation>-convexit '_INPUT' INTO fm_name.
        CONDENSE fm_name NO-GAPS.
        excel_value_temp = <excel_value>.
        len = strlen( excel_value_temp ).
        IF len > <ls_relation>-intlen / 2  .
          <record_value> = ''.
          ASSIGN COMPONENT '_ICON' OF STRUCTURE <ls_output> TO FIELD-SYMBOL(<temp>).
          <temp> = icon_red_light.
          ASSIGN COMPONENT '_MSG' OF STRUCTURE <ls_output> TO FIELD-SYMBOL(<temp1>).
          <temp1> = '【该值' && <excel_value> && '长度太长,无法执行转换!' && fm_name && '' .
        ELSE.
          CALL FUNCTION fm_name
            EXPORTING
              input  = <excel_value>
            IMPORTING
              output = <record_value>.
        ENDIF.
        IF lo IS NOT INITIAL.
          IF lo->length > 2.
            <record_valuex> = <record_value>.
          ENDIF.
        ENDIF.
      ELSE.
        TRY.
            <record_value> = <excel_value>.
            IF lo IS NOT INITIAL.
              IF lo->length > 2.
                <record_valuex> = <record_value>.
              ENDIF.
            ENDIF.
          CATCH  cx_sy_conversion_no_number.
            <record_value> = ''.
            ASSIGN COMPONENT '_ICON' OF STRUCTURE <ls_output> TO FIELD-SYMBOL(<temp3>).
            <temp> = icon_red_light.
            ASSIGN COMPONENT '_MSG'  OF STRUCTURE <ls_output> TO FIELD-SYMBOL(<temp4>).
            CONCATENATE '【该值' <excel_value> '无法转换为数字' INTO <temp4> .
        ENDTRY.
      ENDIF.

      "==========================================================================
      " 自定义字段的处理逻辑 开始
      "==========================================================================
      FIELD-SYMBOLS <bapi_ext_row> TYPE any.
      FIELD-SYMBOLS <bapi_ext_rowx> TYPE any.

      LOOP AT lcl_process=>gt_bapi_ext_relation ASSIGNING FIELD-SYMBOL(<bapi_relation>).

        ASSIGN <bapi_relation>-bapi_ext_row->* TO <bapi_ext_row>.

        ASSIGN COMPONENT  <ls_relation>-fieldname OF STRUCTURE <bapi_ext_row> TO FIELD-SYMBOL(<value_ext>).
        IF <value_ext> IS ASSIGNED.
          <value_ext> = <record_value>.
        ENDIF.
        IF <value_ext> IS ASSIGNED.UNASSIGN <value_ext>.ENDIF.

        ASSIGN <bapi_relation>-bapi_ext_rowx->* TO <bapi_ext_rowx>.
        ASSIGN COMPONENT  <ls_relation>-fieldname OF STRUCTURE <bapi_ext_rowx> TO FIELD-SYMBOL(<value_extx>).
        IF <value_extx> IS ASSIGNED.
          lo_data ?= cl_abap_datadescr=>describe_by_data( <value_extx> ).
          IF lo_data->length > 2 . "这个是内部长度,所以CHAR1 在这里是2.
            <value_extx> =  <record_value>.
          ELSE.
            <value_extx> = 'X'.
          ENDIF.
        ENDIF.
        IF <value_extx> IS ASSIGNED.UNASSIGN <value_extx>.ENDIF.

      ENDLOOP.
      "==========================================================================
      "自定义字段的处理逻辑 结束
      "==========================================================================

      IF <record_value> IS ASSIGNED.UNASSIGN <record_value>.ENDIF.
      IF <record_valuex> IS ASSIGNED.UNASSIGN <record_valuex>.ENDIF.

    ENDLOOP.

    IF materialdescription IS NOT INITIAL.
      APPEND: materialdescription.
    ENDIF.
    IF unitsofmeasure IS NOT INITIAL.
      APPEND  unitsofmeasure.
      APPEND unitsofmeasurex.
    ENDIF.

    IF internationalartnos IS NOT INITIAL.
      APPEND internationalartnos.
    ENDIF.
    IF materiallongtext IS NOT INITIAL.
      APPEND materiallongtext.
    ENDIF.

    IF taxclassifications IS NOT INITIAL.
      APPEND taxclassifications.
    ENDIF.
    IF prtdata IS NOT INITIAL.
      APPEND prtdata.
      APPEND prtdatax.
    ENDIF.

    IF lo IS NOT INITIAL.
      CLEAR lo.
    ENDIF.

    LOOP AT lcl_process=>gt_bapi_ext_relation ASSIGNING <bapi_relation>.
      ASSIGN <bapi_relation>-bapi_ext_row->* TO <bapi_ext_row>.
      IF <bapi_ext_row> IS NOT INITIAL.
        extensionin-structure = <bapi_relation>-tabname_bapi_ext.
        extensionin-valuepart1 = <bapi_ext_row>.  "未考虑超过240个字符,后续优化
        APPEND extensionin.
      ENDIF.

      ASSIGN <bapi_relation>-bapi_ext_rowx->* TO <bapi_ext_rowx>.
      IF <bapi_ext_rowx> IS NOT INITIAL.
        extensioninx-structure = <bapi_relation>-tabname_bapi_extx.
        extensioninx-valuepart1 = <bapi_ext_rowx>.
        APPEND extensioninx.
      ENDIF.
    ENDLOOP.

    "按照Excel中的每一行进行处理,每行字段处理完,即调用BAPI提交。
    DATA return TYPE bapiret2 VALUE IS INITIAL.
    CALL FUNCTION 'BAPI_MATERIAL_SAVEDATA'
      EXPORTING
        headdata             = headdata
        clientdata           = clientdata
        clientdatax          = clientdatax
        plantdata            = plantdata
        plantdatax           = plantdatax
        forecastparameters   = forecastparameters
        forecastparametersx  = forecastparametersx
        planningdata         = planningdata
        planningdatax        = planningdatax
        storagelocationdata  = storagelocationdata
        storagelocationdatax = storagelocationdatax
        valuationdata        = valuationdata
        valuationdatax       = valuationdatax
        warehousenumberdata  = warehousenumberdata
        warehousenumberdatax = warehousenumberdatax
        salesdata            = salesdata
        salesdatax           = salesdatax
        storagetypedata      = storagetypedata
        storagetypedatax     = storagetypedatax
      IMPORTING
        return               = return
      TABLES
        materialdescription  = materialdescription
        "unitsofmeasure       = unitsofmeasure
        "unitsofmeasurex      = unitsofmeasurex
        internationalartnos  = internationalartnos
        "materiallongtext     = materiallongtext
        taxclassifications   = taxclassifications
        returnmessages       = returnmessages
        prtdata              = prtdata
        prtdatax             = prtdatax
        extensionin          = extensionin[]
        extensioninx         = extensioninx[].

    DATA(return_ok) = 'X'.

    LOOP AT returnmessages TRANSPORTING NO FIELDS WHERE type CA 'AEX'.
      return_ok = abap_false.
    ENDLOOP.

    ASSIGN COMPONENT '_ICON' OF STRUCTURE <ls_output> TO FIELD-SYMBOL(<temp5>).
    ASSIGN COMPONENT '_MSG'  OF STRUCTURE <ls_output> TO FIELD-SYMBOL(<temp6>).
    IF return_ok = ''.
      CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
      <temp5> = icon_red_light.
      <temp6> = '导入失败'.
    ELSE.
      <temp5> = icon_green_light.
      IF gv_test_run IS NOT INITIAL.
        <temp6> = '测试导入成功'.
        CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
      ELSE.
        CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
          EXPORTING
            wait = 'X'.
        <temp6> = '导入成功'.
      ENDIF.
    ENDIF.
    ASSIGN COMPONENT '_RETURN' OF STRUCTURE <ls_output> TO FIELD-SYMBOL(<temp7>).
    <temp7> = returnmessages[].

    counter = counter + 1.
    counter_msg = counter.
    CONDENSE counter_msg NO-GAPS.
    CONCATENATE '已经处理' counter_msg '' INTO counter_msg.
    CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
      EXPORTING
        text = counter_msg.
    IF p_bg IS NOT INITIAL.
      MESSAGE |{ repeat( val = '*' occ = 80 ) }| TYPE 'S'.
      MESSAGE |{ counter_msg } 当前处理的物料号 { headdata-material }| TYPE 'S'.
    ENDIF.

    DATA lt_enq TYPE TABLE OF seqg3 WITH HEADER LINE.
    CLEAR: lt_enq,lt_enq[].
    DATA garg TYPE seqg3-garg.
    CLEAR garg.
    CONCATENATE sy-mandt headdata-material INTO garg.
    DATA num TYPE sy-tabix.

    CLEAR num.

    CALL FUNCTION 'ENQUE_READ'
      EXPORTING
        gclient = sy-mandt
        guname  = '' " sy-uname
        garg    = garg
      IMPORTING
        number  = num
      TABLES
        enq     = lt_enq[].
    IF num > 0.
      DO 100 TIMES.
        CONCATENATE headdata-material
         '被锁定,正在尝试释放,最多尝试100次,耗时100秒'
         INTO msg.
        CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
          EXPORTING
            text = msg.
        CALL FUNCTION 'BUFFER_REFRESH_ALL'.
        WAIT UP TO 1 SECONDS.
        CALL FUNCTION 'BUFFER_REFRESH_ALL'.
        CLEAR: lt_enq,lt_enq[],num.
        CALL FUNCTION 'ENQUE_READ'
          EXPORTING
            gclient = sy-mandt
            guname  = '' "sy-uname
            garg    = garg
          IMPORTING
            number  = num
          TABLES
            enq     = lt_enq[].
        IF num > 0.
        ELSE.
          EXIT.
        ENDIF.
      ENDDO.
    ENDIF.

  ENDLOOP. "//循环 <GT_OUTPUT>

  TRY.
      CALL METHOD lcl_process=>lo_salv->refresh( ).
    CATCH cx_root INTO DATA(lx_alv_error).
      MESSAGE |{ repeat( val = '*' occ = 80 ) }| TYPE 'S'.
      MESSAGE |ALV相关错误,后台执行可忽略: { lx_alv_error->get_text( ) }| TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.

ENDFORM.

 

posted @ 2021-12-19 18:06  蜡哲图  阅读(155)  评论(0编辑  收藏  举报
目录内容