ABAP-OOALV实现

相关类

  • CL_GUI_ALV_GRID

  • CL_GUI_CUSTOM_CONTAINER

  • CL_GUI_DOCKING_CONTAINER

  • CL_GUI_SPLITTER_CONTAINER


控制区域、容器、Grid 关系

先在屏幕上绘制一个用户自定义控件区域,然后该用户以自定义控件区域为基础来创建 CL_GUI_CUSTOM_CONTAINER 容器实例,最后以此容器实例来创建 CL_GUI_ALV_GRID 实例


CL_GUI_ALV_GRID 重要方法

SET_TABLE_FOR_FIRST_DISPLAY

  • ALV 展示方法

  • 参数:

    • IS_VARIANT

      • 确定用于显示输出表的布局。如果使用此参数,则必须至少填充类型结构的“REPORT”字段。
    • I_SAVE
      • 决定用户是否可以保存变式:

        'X' 只能保存全局变式; 

        'U' 只能保存特定变式; 

        'A' 都可以保存; 

        SPACE 不可以将布局保存为变式

    • I_DEFAULT
      • 此参数确定是否允许用户定义默认布局:

        "X":允许默认布局(默认设置)

        空格:不允许默认布局

      • 如果允许默认布局,并且存在这样的布局,并且 IS_VARIANT 中未指定其他布局,则在调用此方法时会自动加载默认布局。
    • IS_LAYOUT

      • 确定网格控件的属性。布局结构与用于保存筛选器、排序和列属性的布局无关。

      • 字段:

        • CWIDTH_OPT:最优化宽度 SPACE, 'X'

        • GRID_TITLE:标题,在网格和工具条之间 最长 70 个字符

        • NO_TOOLBAR:隐藏工具条 SPACE, 'X'

        • NO_VGRIDLN:隐藏垂直线 SPACE, 'X'

        • SEL_MODE:选择模式 SPACE, 'A', 'B', 'C', 'D'

        • CTAB_FNAME:带有复杂单元格颜色编码的字段名称 最长 30 个字符

        • INFO_FNAME:带有简单行彩色代码的字段名称 最长 30 个字符

        • ZEBRA:可选行颜色,如果设置了,出现了间隔色带 SPACE, 'X'

        • STYLEFNAME:字段格式

    • IT_OUTTAB

      • 要显示的数据的输出表
    • IT_FIELDCATALOG
      • 确定输出表的结构和要显示的数据的格式

      • 字段:

        • COL_POS:输出列 列的位置,第几列,例如 1,2,…

        • FIELDNAME:字段名称

        • CURRENCY/CFIELDNAME:货币单位/参考的当前单位的字段名称

        • QUANTITY/QFIELDNAME:计量单位/参考计量单位的字段名称

        • DO_SUM:总计列值 'X',合计

        • FIX_COLUMN:固定列

        • EMPHASIZE:列的颜色

        • NO_OUT:列没有输出'X' ,隐藏此列

        • OUTPUTLEN:列的字符宽度

        • DATATYPE:ABAP 字典中的数据类型

        • INTTYPE:ABAP 数据类型(C,D,N,...)

        • HOTSPOT:单击敏感'X',下面出现下划线,响应单击

        • SCRTEXT_L/M/S:字段标签长/中/短

        • REF_TABLE/REF_FIELD:参考表/参考字段

        • EDIT:是否可编辑

    • IT_SORT

      • 具有最初要排序的列的排序属性的表

    • IT_FILTER

      • 具有最初要为其设置筛选器的列的筛选器属性的表

REFRESH_TABLE_DISPLAY

 

  • IS_STABLE:刷新的稳定性,就是滚动条保持不动
  • I_SOFT_REFRESH:软刷新,如果设置了这个参数,临时给 ALV 创建的合计、排序、数据过滤都将保持不变。这个是非常有意义的,例如:当你没有修改数据内表里的数据,但因布局修改了想刷新 ALV 时可使用

 

  • SET_FRONTED_FIELDCATALOG:如果 fieldcat 格式有修改,需要刷新格式设置,则调用这个方法

EVENTS

TOOLBAR 事件

  • 定义事件类

    • CLASS lcl_event_receiver DEFINITION.
        PUBLIC SECTION.
          CLASS-METHODS:
            handle_toolbar FOR EVENT toolbar OF cl_gui_alv_grid "自定义工具栏
                           IMPORTING e_object e_interactive.
      ENDCLASS.
  • 实现 handle_toolbar 方法

    • CLASS lcl_event_receiver IMPLEMENTATION.
        METHOD handle_toolbar.
          DATA: ls_toolbar  TYPE stb_button.
          MOVE '' TO ls_toolbar-function.
          MOVE '' TO ls_toolbar-icon.
          MOVE '3' TO ls_toolbar-butn_type.
          APPEND ls_toolbar TO e_object->mt_toolbar.
      
          CLEAR ls_toolbar.
          MOVE 'SELA' TO ls_toolbar-function.
          MOVE icon_select_all TO ls_toolbar-icon.
          MOVE '全选' TO ls_toolbar-quickinfo.
          MOVE ''(112) TO ls_toolbar-text.
          APPEND ls_toolbar TO e_object->mt_toolbar.
      
          CLEAR ls_toolbar.
          MOVE 'DSEL' TO ls_toolbar-function.
          MOVE icon_deselect_all TO ls_toolbar-icon.
          MOVE '取消全选' TO ls_toolbar-quickinfo.
          MOVE ''(112) TO ls_toolbar-text.
          APPEND ls_toolbar TO e_object->mt_toolbar.
          CLEAR ls_toolbar.
      
          MOVE 'B_LIST' TO ls_toolbar-function.
          MOVE 1 TO ls_toolbar-butn_type.
          MOVE icon_calculation TO ls_toolbar-icon.
          MOVE '自定义下拉菜单按钮'(202) TO ls_toolbar-quickinfo.
          MOVE '下拉菜单按钮' TO ls_toolbar-text.
          "MOVE '' TO ls_toolbar-disabled.
          APPEND ls_toolbar TO e_object->mt_toolbar.
        ENDMETHOD.                    "handle_toolbar
      ENDCLASS.

MENU_BUTTON 事件

  • 定义事件类

    • CLASS lcl_event_receiver DEFINITION.
        PUBLIC SECTION.
          CLASS-METHODS:
            handle_menu_button        "自定义菜单
              FOR EVENT menu_button OF cl_gui_alv_grid
              IMPORTING e_object e_ucomm.
      ENDCLASS.
  • 实现 handle_menu_button 方法

    • CLASS lcl_event_receiver IMPLEMENTATION.
        METHOD handle_menu_button .  "自定义菜单实现方法
          IF e_ucomm = 'B_LIST'."给下拉菜单按钮增加选项,可以多次调用该方法以增加多行
            CALL METHOD e_object->add_function
              EXPORTING
                icon  = ICON_OKAY
                fcode = 'B_SUM' "字菜单按钮的FunCode
                text  = '显示ALV总行数'.
            CALL METHOD e_object->add_function
              EXPORTING
                icon  = ICON_CANCEL
                fcode = 'C_SUM' "字菜单按钮的FunCode
                text  = '测试'.
          ENDIF.
        ENDMETHOD.                    "handle_menu_button
      ENDCLASS.

USER_COMMAND 事件

  • 定义方法

    • CLASS lcl_event_receiver DEFINITION.
        PUBLIC SECTION.
          CLASS-METHODS:
            handle_user_command       "自定义按钮事件
              FOR EVENT user_command OF cl_gui_alv_grid IMPORTING e_ucomm.
      ENDCLASS.
  • 实现 handle_user_command 方法

    • CLASS lcl_event_receiver IMPLEMENTATION.
        METHOD handle_user_command.  "自定义按钮实现方法
          DATA: sum TYPE i .
          CASE e_ucomm.
            WHEN 'SELA'.
              LOOP AT it_9001 INTO wa_9001.
                wa_9001-check = 'X'.
                MODIFY it_9001 INDEX sy-tabix FROM wa_9001 TRANSPORTING check.
              ENDLOOP.
              CALL METHOD oo_grid->refresh_table_display"这句话一定要写,否则界面没刷新,不生效
                EXPORTING
                  is_stable = wa_stbl.
            WHEN 'DSEL'.
              LOOP AT it_9001 INTO wa_9001.
                wa_9001-check = ''.
                MODIFY it_9001 INDEX sy-tabix FROM wa_9001 TRANSPORTING check.
              ENDLOOP.
              CALL METHOD oo_grid->refresh_table_display
                EXPORTING
                  is_stable = wa_stbl.
            WHEN 'B_SUM'.
              DESCRIBE TABLE it_9001[] LINES sum.
              MESSAGE i001(00) WITH '当前ALV表格中的数据总行数为:' sum.
             WHEN 'C_SUM'.
              MESSAGE i001(00) WITH '测试为:' sum.
          ENDCASE.
        ENDMETHOD.
      ENDCLASS.

HOTSPOT(单点)事件

  • 定义方法

    • CLASS lcl_event_receiver DEFINITION.
        PUBLIC SECTION.
          CLASS-METHODS:
            handle_hotspot_click1     "单击事件
                          FOR EVENT hotspot_click OF cl_gui_alv_grid 
                          IMPORTING e_row_id e_column_id.
      ENDCLASS.
  • 实现 handle_hotspot_click1 方法

    • CLASS lcl_event_receiver IMPLEMENTATION.
        METHOD handle_data_changed.  "数据变化实现方法
          PERFORM handle_data_changed USING er_data_changed.
        ENDMETHOD.
      
        METHOD handle_hotspot_click1. "单击事件实现方法
          READ TABLE it_9001 INTO wa_9001 INDEX e_row_id-index.
          CASE e_column_id-fieldname.
            WHEN 'VBELN_VF'.
              SET PARAMETER ID 'VF' FIELD wa_9001-vbeln_vf.
              CALL TRANSACTION 'VF03' AND SKIP FIRST SCREEN.
            WHEN 'VBELN_SO'.
              SET PARAMETER ID 'AUN' FIELD wa_9001-vbeln_so.
              CALL TRANSACTION 'VA03' AND SKIP FIRST SCREEN.
          ENDCASE.
        ENDMETHOD.                  "HANDLE_HOTSPOT_CLICK1
      ENDCLASS.

DATA_CHANGE 事件

  • 定义方法

    • CLASS lcl_event_receiver DEFINITION.
        PUBLIC SECTION.
          CLASS-METHODS:
            handle_data_changed       "数据改变触发
                          FOR EVENT data_changed OF cl_gui_alv_grid
                          IMPORTING er_data_changed.
      ENDCLASS.
  • 实现方法

    • CLASS lcl_event_receiver IMPLEMENTATION.
        METHOD handle_data_changed.  "数据变化实现方法
            "PERFORM handle_data_changed USING er_data_changed.
          DATA: x_change TYPE lvc_s_modi.
          LOOP AT data_changed->mt_good_cells INTO x_change.
          "结算数量发生变化
            IF x_change-fieldname  = 'FKLMG_JS'.
              READ TABLE it_9001 INTO wa_9001 INDEX x_change-row_id.
              wa_9001-fklmg_js = x_change-value.
              wa_9001-kbetr_tmp = wa_9001-kbetr_js * wa_9001-fklmg_js / wa_9001-kpein / '1.13'.
              MODIFY it_9001 FROM wa_9001 INDEX x_change-row_id.
            ENDIF.
            "行备注内容发生变化
            IF x_change-fieldname  = 'ZREMARK'.
              READ TABLE it_9001 INTO wa_9001 INDEX x_change-row_id.
              wa_9001-zremark = x_change-value.
              MODIFY it_9001 FROM wa_9001 INDEX x_change-row_id.
            ENDIF.
            CALL METHOD oo_grid->refresh_table_display
              EXCEPTIONS
                finished = 1
                OTHERS   = 2.
          ENDLOOP.
        ENDMETHOD.
      ENDCLASS.

F4 搜索帮助事件

  • 如果希望 ALV 中某字段具有搜索帮助,第一种办法当然是对表中某字段的引用,设置 ref_table、ref_field,将自动触发该字段所带的搜索帮助。

  • 第二种办法就是利用自定义代码来实现 ALV 的搜索帮助,显然它的功能更强大、更灵活。针对在 OO ALV 中实现搜索帮助,其主要步骤有:

    • 定义方法

      • CLASS lcl_event_receiver DEFINITION.
          PUBLIC SECTION.
            CLASS-METHODS:
              handle_onf4 FOR EVENT onf4 OF cl_gui_alv_grid
                                      IMPORTING e_fieldname es_row_no er_event_data.
        ENDCLASS.
        CLASS lcl_event_receiver IMPLEMENTATION.
          METHOD handle_onf4.
            DATA:ls_modi TYPE lvc_s_modi,
                 lt_ret_tab TYPE TABLE OF ddshretval WITH HEADER LINE.
         
            FIELD-SYMBOLS <modtab> TYPE lvc_t_modi.
            IF e_fieldname = 'FIELD_NAME'. "我们自定义搜索的字段名
              READ TABLE gt_alv_data INDEX es_row_no-row_id.
              CHECK sy-subrc = 0.
        **  这里可以添加代码以对lt_hitlist内表进行填充
              CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
                EXPORTING
                  retfield        = 'HIT_FIELD'
                  value_org       = 'S'
                TABLES
                  value_tab       = lt_hitlist
                  return_tab      = lt_ret_tab
                EXCEPTIONS
                  parameter_error = 1
                  no_values_found = 2
                  OTHERS          = 3.
              IF sy-subrc = 0.
        **  Update the value in ALV cell
                READ TABLE lt_ret_tab INDEX 1.
                IF sy-subrc = 0. " User didn't cancel
                  ls_modi-row_id = es_row_no-row_id.
                  ls_modi-fieldname = e_fieldname.
                  ls_modi-value = lt_ret_tab-fieldval.
                  ASSIGN er_event_data->m_data->* TO <modtab>.
                  APPEND ls_modi TO <modtab>.
                ENDIF.
              ENDIF.
        **  Inform ALV Grid that event 'onf4' has been processed
              er_event_data->m_event_handled = 'X'.
            ENDIF.
          ENDMETHOD.
        ENDCLASS.
    • 在 Method 的最后,记得加上 er_event_data->m_event_handled = 'X'. 通知系统搜索事件处理完毕,这样就不会调用系统标准的 Search Help。

    • 需要自定义搜索帮助的字段,设置其 field catalog 时:

      • ls_fieldcat-f4availabl = 'X'.
    • 在创建 ALV 对象之后,要对需要自定义搜索帮助的字段进行注册。lvc_s_f4 中的字段 getbefore 和 changeafter 应该代表是否触发 data_changed 事件。

      • DATA: lt_f4 TYPE lvc_t_f4 WITH HEADER LINE.
        CLEAR lt_f4.
        lt_f4-fieldname = 'FIELD_NAME'.
        lt_f4-register = 'X'.
        lt_f4-chngeafter = 'X'. 
        APPEND lt_f4.
        CALL METHOD mygrid->register_f4_for_fields
          EXPORTING
            it_f4 = lt_f4[].
        CREATE OBJECT go_evt_receiver.
        SET HANDLER go_evt_receiver->handle_onf4 FOR go_alv_grid.

TOP OF PAGE事件

  • 如果希望 ALV 中带有表头,需要先将OO ALV拆分成两个部分

    •     
      DATA: go_split_left        TYPE REF TO cl_gui_splitter_container,
            go_header_left       TYPE REF TO cl_gui_container,
            go_alvcontainer_left TYPE REF TO cl_gui_container,
            gref_doc_left        TYPE REF TO cl_dd_document,
            gref_viewer_left     TYPE REF TO cl_gui_html_viewer.
      
      *&---------------------------------------------------------------------*
      *& Form disp_alv
      *&---------------------------------------------------------------------*
      *& text
      *&---------------------------------------------------------------------*
      *& -->  p1        text
      *& <--  p2        text
      *&---------------------------------------------------------------------*
      FORM disp_alv .
        DATA:lo_event TYPE REF TO lcl_event_receiver.
        FIELD-SYMBOLS: <lfs_tab> TYPE STANDARD TABLE.
        ASSIGN gt_data TO <lfs_tab>.
        CHECK <lfs_tab> IS ASSIGNED.
      
        CREATE OBJECT go_docking
          EXPORTING
            repid                       = sy-repid
            dynnr                       = sy-dynnr
            side                        = cl_gui_docking_container=>dock_at_bottom "dock_at_top
            extension                   = 500
          EXCEPTIONS
            cntl_error                  = 1
            cntl_system_error           = 2
            create_error                = 3
            lifetime_error              = 4
            lifetime_dynpro_dynpro_link = 5
            OTHERS                      = 6.
        IF sy-subrc <> 0.
          MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                     WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
        ENDIF.
        "容器拆分成两行一列
        CREATE OBJECT go_split_left
          EXPORTING
            parent            = go_docking
            rows              = 2
            columns           = 1
          EXCEPTIONS
            cntl_error        = 1
            cntl_system_error = 2
            OTHERS            = 3.
        IF sy-subrc <> 0.
          MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      
        ENDIF.
      
      
        CALL METHOD go_split_left->get_container
          EXPORTING
            row       = 1
            column    = 1
          RECEIVING
            container = go_header_left. "放置top of pag的容器
      
        "设置TOP-OF-PAGE的高度
        CALL METHOD go_split_left->set_row_height
          EXPORTING
            id     = 1
            height = 12.
      
        CALL METHOD go_split_left->get_container
          EXPORTING
            row       = 2
            column    = 1
          RECEIVING
            container = go_alvcontainer_left. " 放置alv的容器
      
        CREATE OBJECT go_grid
          EXPORTING
            i_parent          = go_alvcontainer_left
          EXCEPTIONS
            error_cntl_create = 1
            error_cntl_init   = 2
            error_cntl_link   = 3
            error_dp_create   = 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.
        ENDIF.
      
        CREATE OBJECT lo_event.
        SET HANDLER lo_event->top_of_page
                    "alv_event_receiver=>handle_double_click
                 FOR go_grid.
        SET HANDLER lo_event->handle_double_click FOR go_grid.
        CREATE OBJECT gref_doc_left.
        CALL METHOD gref_doc_left->initialize_document.
      
        CALL METHOD go_grid->list_processing_events
          EXPORTING
            i_event_name = 'TOP_OF_PAGE'
            i_dyndoc_id  = gref_doc_left.
        CALL METHOD go_grid->set_table_for_first_display
          EXPORTING
            i_save                        = 'A'
            is_layout                     = gs_layout
            it_toolbar_excluding          = gt_exclude
            is_variant                    = gs_variant
          CHANGING
            it_outtab                     = <lfs_tab>
            it_fieldcatalog               = gt_fieldcat
          EXCEPTIONS
            invalid_parameter_combination = 1
            program_error                 = 2
            too_many_lines                = 3
            OTHERS                        = 4.
      ENDFORM.

       

  • TOP OF PAGE方法:

    • 定义方法

      •   
        *&---------------------------------------------------------------------*
        *&事件类定义
        *&---------------------------------------------------------------------*
        
        CLASS lcl_event_receiver DEFINITION.
          PUBLIC SECTION.
            METHODS:
              top_of_page FOR EVENT top_of_page OF cl_gui_alv_grid
                IMPORTING e_dyndoc_id.
        ENDCLASS.
        
        *&---------------------------------------------------------------------*
        *&事件类实现
        *&---------------------------------------------------------------------*
        CLASS lcl_event_receiver IMPLEMENTATION.
          METHOD top_of_page.
        *   Top-of-page event
            PERFORM event_top_of_page USING e_dyndoc_id.
          ENDMETHOD.
        ENDCLASS.
        
        *&---------------------------------------------------------------------*
        *& text
        *&---------------------------------------------------------------------*
        *&      --> O_DYNDOC_ID
        *&---------------------------------------------------------------------*
        FORM event_top_of_page USING p_eref_doc TYPE REF TO cl_dd_document.
        
          DATA:lv_text      TYPE string,
               dl_text(255) TYPE c,
               lv_p         TYPE i.  "Text
        
          lv_text = '<HTML><CENTER><H2>现金流量表</H2></CENTER><HTML>'.
          CALL METHOD p_eref_doc->html_insert
            EXPORTING
              contents = lv_text
            CHANGING
              position = lv_p.
        
          CLEAR:dl_text.
          dl_text = '编制单位:'.
        
          SELECT SINGLE butxt,waers
            FROM t001
           WHERE bukrs = @p_bukrs
            INTO ( @DATA(lv_butxt),@DATA(lv_waers) ).
          dl_text = dl_text && lv_butxt.
        
          CALL METHOD p_eref_doc->add_text
            EXPORTING
              text         = dl_text
              sap_emphasis = cl_dd_area=>heading
              sap_color    = cl_dd_area=>list_heading_int.
        
          CALL METHOD p_eref_doc->new_line.
          CLEAR:dl_text.
          dl_text = '单位:'.
          dl_text = dl_text && lv_waers.
        
          CALL METHOD p_eref_doc->add_text
            EXPORTING
              text         = dl_text
              sap_emphasis = cl_dd_area=>heading
              sap_color    = cl_dd_area=>list_heading_int.
        
          IF gref_viewer_left IS INITIAL.
            CREATE OBJECT gref_viewer_left
              EXPORTING
                parent = go_header_left.
          ENDIF.
        
          CALL FUNCTION 'REUSE_ALV_GRID_COMMENTARY_SET'
            EXPORTING
              document = gref_doc_left
              bottom   = space.
        
          CALL METHOD gref_doc_left->merge_document.
        
          gref_doc_left->html_control = gref_viewer_left.
          CALL METHOD gref_doc_left->display_document
            EXPORTING
              reuse_control = 'X'
              parent        = go_header_left.
        ENDFORM.

 

EVENTS 注册

"屏幕输出前
MODULE status_9001 OUTPUT.

  "设置GUI状态
  SET PF-STATUS '9001_PF'.
  "设置界面标题
  SET TITLEBAR '9001_BAR'.

  IF oo_container IS INITIAL.
*   建立一个容器控件作为ALV的容器
    CREATE OBJECT oo_container
      EXPORTING
        container_name = oo_cont_on_9001.
*   建立一个ALV的实例
    CREATE OBJECT oo_grid
      EXPORTING
        i_parent = oo_container.

*   显示表格
    CALL METHOD oo_grid->set_table_for_first_display
      EXPORTING
        is_layout       = oo_layout
      CHANGING
        it_outtab       = it_9001[]
        it_fieldcatalog = oo_field.

*   注册ALV的事件
    DATA: lt_f4 TYPE lvc_t_f4 WITH HEADER LINE.
    CLEAR lt_f4.
    lt_f4-fieldname = 'FIELD_NAME'.
    lt_f4-register = 'X'.
    lt_f4-chngeafter = 'X'. 
    APPEND lt_f4.
    CALL METHOD oo_grid->register_f4_for_fields
      EXPORTING
        it_f4 = lt_f4[].
    
    CREATE OBJECT event_receiver.

    SET HANDLER event_receiver->handle_toolbar FOR oo_grid.       "注册工具栏
    SET HANDLER event_receiver->handle_menu_button FOR oo_grid.   "注册工具栏菜单
    SET HANDLER event_receiver->handle_user_command FOR oo_grid.  "注册用户自定义命令
    SET HANDLER event_receiver->handle_data_changed FOR oo_grid.  "单元格数据更改时触发
    SET HANDLER event_receiver->handle_hotspot_click1 FOR oo_grid."单击事件
    SET HANDLER event_receiver->handle_onf4 FOR go_alv_grid.      "搜索帮助事件


    "调用此方法才能激活工具栏上增加的自定义按钮
    CALL METHOD oo_grid->set_toolbar_interactive.

    CALL METHOD oo_grid->register_edit_event "单元格数据更改时触发条件
      EXPORTING
*       I_EVENT_ID = CL_GUI_ALV_GRID=>MC_EVT_ENTER. "回车时触发
        i_event_id = cl_gui_alv_grid=>mc_evt_modified. "单元格失去焦点触发
  ENDIF.
  CALL METHOD oo_grid->refresh_table_display.
ENDMODULE.

实现可编辑

实现列可编辑

  • 只要将 catalog 中的字段 edit 设置成‘X',整列就变成能输入的了,LVC_S_FCAT-EDIT

    • REPORT ztest_alv_lvc_edit.
      
      TYPES:BEGIN OF gty_ekko,
              ebeln TYPE ekko-ebeln,
              verkf TYPE ekko-verkf,
            END OF gty_ekko.
      DATA:git_ekko TYPE STANDARD TABLE OF gty_ekko.
      DATA:git_fcat   TYPE lvc_t_fcat,
           gwa_fcat   LIKE LINE OF git_fcat,
           gwa_layout TYPE lvc_s_layo.
      DATA:l_pos TYPE i VALUE 1.
      
      START-OF-SELECTION.
      
        SELECT ebeln
               verkf
          INTO TABLE git_ekko
          FROM ekko
         UP TO 10 ROWS.
      
        CLEAR: l_pos.
        l_pos = l_pos + 1.
        gwa_fcat-coltext   = 'PO'.
        gwa_fcat-scrtext_l = 'PO'.
        gwa_fcat-scrtext_m = 'PO'.
        gwa_fcat-scrtext_s = 'PO'.
        gwa_fcat-fieldname = 'EBELN'.
        gwa_fcat-col_pos = l_pos.
        gwa_fcat-outputlen = '10'.
        APPEND gwa_fcat TO git_fcat.
        l_pos = l_pos + 1.
        gwa_fcat-coltext   = 'PO item'.
        gwa_fcat-scrtext_l = 'PO item'.
        gwa_fcat-scrtext_m = 'PO item'.
        gwa_fcat-scrtext_s = 'PO item'.
        gwa_fcat-fieldname = 'VERKF'.
        gwa_fcat-col_pos = l_pos.
        gwa_fcat-edit = 'X'.  "设置列为可编辑状态
        gwa_fcat-outputlen = '20'.
        APPEND gwa_fcat TO git_fcat.
      
        gwa_layout-zebra = 'X'.
        gwa_layout-sel_mode = 'A'.
        gwa_layout-cwidth_opt = 'X'.
      
        CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
          EXPORTING
            i_callback_program = sy-repid
            is_layout_lvc      = gwa_layout
            it_fieldcat_lvc    = git_fcat
          TABLES
            t_outtab           = git_ekko[]
          EXCEPTIONS
            program_error      = 1
            OTHERS             = 2.
        IF sy-subrc = 0.
      *    BREAK-POINT.
        ENDIF.

实现单元格可编辑

  • 单元格可编辑状态设置的主要思想:首先通过 EIDT 参数设置列为可编辑状态;其次对输出内表进行循环将不需要编辑的行设置为不可编辑状态,如此单元格的可编辑属性设置完毕。下面粘贴简要代码。

    • TYPE-POOLS: SLIS.
      *- Fieldcatalog
      DATA: IT_FIELDCAT TYPE LVC_T_FCAT.
      DATA: X_FIELDCAT TYPE LVC_S_FCAT.
      DATA: X_LAYOUT TYPE LVC_S_LAYO.
      
      "第1步:用操作具体单元的是否可编辑的内表和工作区
      
      DATA: LS_EDIT TYPE LVC_S_STYL,
            LT_EDIT TYPE LVC_T_STYL.
      "第2步:在内表定义添加字段,用于控制具体行的具体单元是否可编辑
      DATA: BEGIN OF IT_VBAP OCCURS 0,
        VBELN LIKE VBAP-VBELN,
        POSNR LIKE VBAP-POSNR,
        STYLE TYPE LVC_T_STYL, "FOR DISABLE
      END OF IT_VBAP.
      DATA: LS_OUTTAB LIKE LINE OF IT_VBAP.
      SELECT VBELN  POSNR
        UP TO 100 ROWS
        INTO CORRESPONDING FIELDS OF TABLE IT_VBAP
      FROM VBAP.
      
      DATA:L_POS TYPE I VALUE 1.
      CLEAR: L_POS.
      L_POS = L_POS + 1.
      X_FIELDCAT-SELTEXT = 'VBELN'.
      X_FIELDCAT-FIELDNAME = 'VBELN'.
      X_FIELDCAT-TABNAME = 'ITAB'.
      X_FIELDCAT-COL_POS = L_POS.
      X_FIELDCAT-EDIT = 'X'.
      X_FIELDCAT-OUTPUTLEN = '10'.
      x_fieldcat-ref_field = 'VBELN'.
      x_fieldcat-ref_table = 'VBAK'.
      APPEND X_FIELDCAT TO IT_FIELDCAT.
      
      CLEAR X_FIELDCAT.
      L_POS = L_POS + 1.
      X_FIELDCAT-SELTEXT = 'POSNR'.
      X_FIELDCAT-FIELDNAME = 'POSNR'.
      X_FIELDCAT-TABNAME = 'ITAB'.
      X_FIELDCAT-COL_POS = L_POS.
      X_FIELDCAT-EDIT = 'X'.
      X_FIELDCAT-OUTPUTLEN = '5'.
      APPEND X_FIELDCAT TO IT_FIELDCAT.
      CLEAR X_FIELDCAT.
      L_POS = L_POS + 1.
      
      "第3步:设置第六行两个单元都不能输入
      SY-TABIX = 6.
      LS_EDIT-FIELDNAME = 'VBELN'.
      LS_EDIT-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
      LS_EDIT-STYLE2 = SPACE.
      LS_EDIT-STYLE3 = SPACE.
      LS_EDIT-STYLE4 = SPACE.
      LS_EDIT-MAXLEN = 10.
      INSERT LS_EDIT INTO TABLE LT_EDIT.
      
      LS_EDIT-FIELDNAME = 'POSNR'.
      LS_EDIT-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
      LS_EDIT-STYLE2 = SPACE.
      LS_EDIT-STYLE3 = SPACE.
      LS_EDIT-STYLE4 = SPACE.
      LS_EDIT-MAXLEN = 6.
      INSERT LS_EDIT INTO TABLE LT_EDIT.
      
      INSERT LINES OF LT_EDIT INTO TABLE LS_OUTTAB-STYLE.
      
      "第4步:将控制数据写到内表
      MODIFY IT_VBAP INDEX SY-TABIX FROM LS_OUTTAB TRANSPORTING STYLE .
      "设置第10行只有项目不能输入
      clear LS_OUTTAB.
      refresh LT_EDIT.
      LS_EDIT-FIELDNAME = 'POSNR'.
      LS_EDIT-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
      LS_EDIT-STYLE2 = SPACE.
      LS_EDIT-STYLE3 = SPACE.
      LS_EDIT-STYLE4 = SPACE.
      LS_EDIT-MAXLEN = 6.
      INSERT LS_EDIT INTO TABLE LT_EDIT.
      INSERT LINES OF LT_EDIT INTO TABLE LS_OUTTAB-STYLE.
      SY-TABIX = 10.
      
      "将控制数据写到内表
      MODIFY IT_VBAP INDEX SY-TABIX FROM LS_OUTTAB TRANSPORTING STYLE .
      
      "第5步:设置控制字段
      X_LAYOUT-STYLEFNAME = 'STYLE'.
      
      CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
        EXPORTING
          I_CALLBACK_PROGRAM = SY-REPID
          IS_LAYOUT_LVC      = X_LAYOUT
          IT_FIELDCAT_LVC    = IT_FIELDCAT
        TABLES
          T_OUTTAB           = IT_VBAP[]
        EXCEPTIONS
          PROGRAM_ERROR      = 1
          OTHERS             = 2.
      IF SY-SUBRC NE 0.
        MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
        WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
      ENDIF.

ALV 的颜色设定(单元格,行,列的颜色设定)

在 ABAP 开发过程中,有的时候,我们需要在 ALV 网格上绘上一些颜色.可以给特定的行,某个特定的列,某个特定的单元格绘制颜色.

如果某列被设置为关键列,这列的颜色将被自动绘制,而不需要我们额外的指定.,ALV 的颜色是四位的如 C710,第一位是固定死的 C,第二位是颜色代码,可能值为 1-7,代表颜色如下:

1:Gray-blue —>headers

2:Light gray —>List bodies

3:yellow —>totals

4:Blue-green—>Key columns

5:green —>Positive threshold value

6:red —>Negative threshold value

7:orange —>Control levels

后两位是 1 和 0 的组合,10 则代表颜色用在背景,01 代表颜色用在前景。

列颜色设定

  • 列的颜色很简单,在构成 ALV 字段的 FIELDCAT 内表中有一个字段是 EMPHASIZE,将一个 char 型 4 位的颜色代码分配到 FIELDCAT 内表这个字段即可。

    • LW_FCAT-EMPHASIZE = 'C710'. "设置字段的颜色 

行颜色设定

  • 为某行设置颜色,是有点复杂的,我们需要在要显示的数据内表中增加一个字段,这个字段不需要在字段目录中存在.同样,这个字段也是 4 位的 CHAR 型,符合颜色编码的定义.,然后在布局设定中指定该列为颜色列,gs_layout-info_fname = ‘COLOR’.或(info_fieldname)

    • FORM p_data .
        LOOP AT gt_mara.
          IF gt_mara-matnr = '100-100'.
            gt_mara-color = 'C310'.
          ENDIF.
          MODIFY gt_mara.
        ENDLOOP.
      ENDFORM.
        
      gs_layout-info_fname = 'COLOR'

单元格颜色设定

  • 设置单元格和设置行的颜色,本质上没有什么大的区别,但是定位单元格需要 2 个参数.我们需要在数据内表中插入一个表类型的字段,这样我们的数据内表就变成了 DEEP 结构了,不过 ALV 是可以处理的.不需要担心.

  • 插入的这个表类型的类型为”LVC_T_SCOL”.里面有 3 个参数:

  • FNAME 告诉我们你需要设置的是哪个字段,如果为空,然后直接在 COLOR 中设置颜色,就是整行设置为这个颜色.如果具体到某个单元格,必须指定是哪个字段.

  • COLOR 字段是用来设置颜色的.

  • NOKEYCOL 字段比较关键了.设置为关键列的一些字段,我们的颜色设置可能被覆盖.通过这个字段的设置,可以避免被关键列的颜色被覆盖.

  • 同样,ALV 在布局中有个字段”CTAB_FNAME”告诉我们,数据内表中,哪个字段是用来设置单元格的颜色的,类似于设置行颜色的 INTO_FNAME.

    • FORM p_data .
        LOOP AT gt_mara.
          IF gt_mara-matnr = '100-100'.
            gt_mara-color = 'C310'."设置行的颜色
          ENDIF.
          IF gt_mara-matnr = '100-401'.
            CLEAR gs_cellcolor.
            gs_cellcolor-fname = 'MTART'.
            gs_cellcolor-color-col = '6'.
            APPEND gs_cellcolor TO gt_mara-cellclor."设置单元格的颜色
            gs_cellcolor-fname = 'ERSDA'.
            gs_cellcolor-color-col = '7'.
            APPEND gs_cellcolor TO gt_mara-cellclor.
          ENDIF.
          MODIFY gt_mara.
        ENDLOOP.
      ENDFORM.
      gs_layout-ctab_fname = 'COLOR'.

下拉框设置

  • 设置下拉框数据

    • DATA: gs_dropdowm TYPE lvc_s_drop,
            gt_dropdowm TYPE lvc_t_drop.
      gs_dropdowm-handle = '2'.
      gs_dropdowm-value  = 'drop-value1'.
      APPEND gs_dropdowm TO gt_dropdowm.
      
      CLEAR: gs_dropdowm.
      gs_dropdowm-handle = '2'.
      gs_dropdowm-value  = 'drop-value2'.
      APPEND gs_dropdowm TO gt_dropdowm.
  • 设置 FieldCatelog 属性

    • gs_fieldcat-drdn_hndl = 2.
  • 调用 ALV 显示方法之前设置下拉框

    • CALL METHOD g_grid01->set_drop_down_table
        EXPORTING
          it_drop_down = gt_dropdowm. "添加下拉框方法到ALV中顯示
      
      " 调用ALV 显示方法
      CALL METHOD g_grid01->set_table_for_first_display
        EXPORTING
      *   i_structure_name              = 'SPFLI' " 参照表结构字段显示
          is_layout                     = ls_layout " 布局
        CHANGING
          it_fieldcatalog               = gt_fieldcat " 显示字段
          it_outtab                     = gt_data[]
        EXCEPTIONS
          invalid_parameter_combination = 1
          program_error                 = 2
          too_many_lines                = 3
          others                        = 4.

CL_GUI_DOCKING_CONTAINER

  • 使用 CL_GUI_DOCKING_CONTAINER 不需要提前在屏幕中绘制自定义控制区域

    • DATA: GS_DOCK TYPE REF TO CL_GUI_DOCKING_CONTAINER. "屏幕容器对象
      FORM FRM_SET_GRID .
      
        "实例化屏幕容器
        CREATE OBJECT GS_DOCK
          EXPORTING
      *     PARENT                      =
            REPID                       = SY-REPID      "当前程序
            DYNNR                       = '0100'        "屏幕编号
            SIDE                        = CL_GUI_DOCKING_CONTAINER=>DOCK_AT_LEFT  "容器吸附左侧
            EXTENSION                   = 1300           "ALV的宽度
      *     STYLE                       =
      *     LIFETIME                    = lifetime_default
      *     CAPTION                     =
            METRIC                      = 0
      *     RATIO                       = 100           "ALV的比率,优先级高于上面的EXTENSION
      *     NO_AUTODEF_PROGID_DYNNR     =
      *     NAME                        =
          EXCEPTIONS
            CNTL_ERROR                  = 1
            CNTL_SYSTEM_ERROR           = 2
            CREATE_ERROR                = 3
            LIFETIME_ERROR              = 4
            LIFETIME_DYNPRO_DYNPRO_LINK = 5
            OTHERS                      = 6.
        IF SY-SUBRC <> 0.
      *   MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
      *              WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
        ENDIF.
      
      
      *
      *  CREATE OBJECT GS_CON
      *    EXPORTING
      **     PARENT                      =
      *      CONTAINER_NAME              = 'GC_CON'
      **     STYLE                       =
      **     LIFETIME                    = lifetime_default
      **      REPID                       = SY-REPID
      **      DYNNR                       = '0100'
      **     NO_AUTODEF_PROGID_DYNNR     =
      *    EXCEPTIONS
      *      CNTL_ERROR                  = 1
      *      CNTL_SYSTEM_ERROR           = 2
      *      CREATE_ERROR                = 3
      *      LIFETIME_ERROR              = 4
      *      LIFETIME_DYNPRO_DYNPRO_LINK = 5
      *      OTHERS                      = 6.
      *  IF SY-SUBRC <> 0.
      ** MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
      **            WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
      *  ENDIF.
      
      
        "实例化alv展示对象
        CREATE OBJECT GS_ALV
          EXPORTING
      *     I_SHELLSTYLE      = 0
      *     I_LIFETIME        =
            I_PARENT          = GS_DOCK
      *     I_APPL_EVENTS     = space
      *     I_PARENTDBG       =
      *     I_APPLOGPARENT    =
      *     I_GRAPHICSPARENT  =
      *     I_NAME            =
      *     I_FCAT_COMPLETE   = SPACE
          EXCEPTIONS
            ERROR_CNTL_CREATE = 1
            ERROR_CNTL_INIT   = 2
            ERROR_CNTL_LINK   = 3
            ERROR_DP_CREATE   = 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.
        ENDIF.
      ENDFORM.

CL_GUI_SPLITTER_CONTAINER

  • 拆分 CL_GUI_CONTAINER 可以通过使用 CL_GUI_SPLITTER_CONTAINER 对象的 GET_CONTAINER 方法获取多个容器对象来实现。 

    • DATA: G_SPLITTER_CONTAINER_1 TYPE REF TO CL_GUI_SPLITTER_CONTAINER.
      DATA: MYCONTAINER_1 TYPE REF TO CL_GUI_CONTAINER.
      DATA: MYCONTAINER_2 TYPE REF TO CL_GUI_CONTAINER.
        CREATE OBJECT G_SPLITTER_CONTAINER_1
          EXPORTING
            PARENT  = CL_GUI_CONTAINER=>SCREEN0
            ROWS    = 2         "该方法中传入实参ROWS和COLUMNS的值决定你每行跟每列的容器数目
            COLUMNS = 1.
        
        CALL METHOD G_SPLITTER_CONTAINER_1->GET_CONTAINER
          EXPORTING
            ROW       = 1       "该方法中传入实参ROW和COLUMNS决定容器在屏幕中所处的相对位置
            COLUMN    = 1
          RECEIVING
            CONTAINER = MYCONTAINER_1.
        
        CALL METHOD G_SPLITTER_CONTAINER_1->GET_CONTAINER
          EXPORTING
            ROW      = 2
            COLUMN   = 1
          RECEIVING
            CONTAINER = MYCONTAINER_2.
  • 在容器中放 ALV 控件就实现了分屏显示多个 ALV 控件

    • DATA: G_GUI_ALV_1 TYPE REF TO CL_GUI_ALV_GRID.
      DATA: G_GUI_ALV_2 TYPE REF TO CL_GUI_ALV_GRID.
      CREATE OBJECT G_GUI_ALV_1
        EXPORTING
          I_PARENT = MYCONTAINER_1.
        
      CREATE OBJECT G_GUI_ALV_2
        EXPORTING
          I_PARENT = MYCONTAINER_2.
      *—–省略给ALV展示所需参数赋值……
      
      CALL METHOD G_GUI_ALV_1->SET_TABLE_FOR_FIRST_DISPLAY
        EXPORTING
          IS_LAYOUT            = GTH_LAYOUT_UP
        CHANGING
          IT_OUTTAB            = GT_MAT
          IT_FIELDCATALOG      = GTD_FIELDCAT_UP.

CALL METHOD lo_grid->get_filtered_entries--获取被ALV界面上过滤的行,比如全选的时候不选中被过滤的行

FORM frm_select USING field.

  DATA: lo_grid      TYPE REF TO cl_gui_alv_grid,
        filt_table   TYPE lvc_t_fidx,
        l_filt_table TYPE int4.
  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid = lo_grid.

  CALL METHOD lo_grid->get_filtered_entries
    IMPORTING
      et_filtered_entries = filt_table. "被过滤的内表数据行

  LOOP AT gt_alv ASSIGNING <fs_alv>.

    READ TABLE filt_table TRANSPORTING NO FIELDS
                          WITH KEY table_line = sy-tabix.
    IF sy-subrc NE 0.
      <fs_alv>-sel = field.
    ENDIF.
  ENDLOOP.
ENDFORM.

 


ALV标题多表头实现

最终结果:

 创建类ZCL_GUI_ALV_GRID,继承CL_GUI_ALV_GRID类

并添加以下几个方法:

Z_SET_MERGE_HORIZ(横向合并)

  METHOD z_set_merge_horiz.
* ROW - Zeile deren Spalten zusammengef�hrt werden sollen
* tab_col_merge - Spalten, die zusammengef�hrt werden sollen
    FIELD-SYMBOLS <fs_cols> TYPE lvc_s_co01.
    FIELD-SYMBOLS <fs_data> TYPE lvc_s_data.
    DATA outputlen TYPE i.

    SORT tab_col_merge.
* Die Spalten, die zusammengef�hrt werden sollen
    LOOP AT tab_col_merge ASSIGNING <fs_cols>.
* ein paar Pr�fungen
      IF <fs_cols>-col_id LE 0.
        CONTINUE.
      ENDIF.
      IF <fs_cols>-outputlen LE <fs_cols>-col_id.
        CONTINUE.
      ENDIF.
      outputlen = <fs_cols>-outputlen - <fs_cols>-col_id.
      LOOP AT mt_data ASSIGNING <fs_data>
           WHERE row_pos = row  AND
                 ( col_pos BETWEEN <fs_cols>-col_id AND
                                   <fs_cols>-outputlen ).
* Setze wie weit soll gemerged werden Von Spalte in L�nge
* und zwar wird bei der 1 Spalte angefangen
        IF <fs_data>-col_pos = <fs_cols>-col_id.
          <fs_data>-mergehoriz = outputlen.
          <fs_data>-value = value.
* bei allen anderen, die zusammangeh�ren
* muss der Wert raus, da er aus der 1. Spalte kommt
* und das mergekennzeichen muss auch weg !
        ELSE.
          CLEAR <fs_data>-mergehoriz.
          CLEAR <fs_data>-value.
        ENDIF.
      ENDLOOP.

    ENDLOOP.
  ENDMETHOD.

Z_SET_MERGE_VERT(竖向合并)

  METHOD z_set_merge_vert.
* ROW - Zeile deren Spalten zusammengef�hrt werden sollen
* tab_col_merge - Spalten, die zusammengef�hrt werden sollen
    FIELD-SYMBOLS <fs_cols> TYPE lvc_s_co01.
    FIELD-SYMBOLS <fs_data> TYPE lvc_s_data.
    DATA outputlen TYPE i.

    SORT tab_col_merge.
* Die Spalten, die zusammengef�hrt werden sollen
    LOOP AT tab_col_merge ASSIGNING <fs_cols>.
* ein paar Pr�fungen
      IF <fs_cols>-col_id    LE 0.                CONTINUE. ENDIF.
      IF <fs_cols>-outputlen LE <fs_cols>-col_id. CONTINUE. ENDIF.
      outputlen = <fs_cols>-outputlen - <fs_cols>-col_id.
      LOOP AT mt_data ASSIGNING <fs_data>
           WHERE row_pos = row  AND
                 ( col_pos BETWEEN <fs_cols>-col_id AND
                                   <fs_cols>-outputlen ).
* Setze wie weit soll gemerged werden Von Spalte in L�nge
* und zwar wird bei der 1 Spalte angefangen
        IF <fs_data>-col_pos = <fs_cols>-col_id.
          <fs_data>-mergevert = outputlen.
          <fs_data>-value = value.
* bei allen anderen, die zusammangeh�ren
* muss der Wert raus, da er aus der 1. Spalte kommt
* und das mergekennzeichen muss auch weg !
        ELSE.
          CLEAR <fs_data>-mergevert.
          CLEAR <fs_data>-value.
        ENDIF.
      ENDLOOP.

    ENDLOOP.

  ENDMETHOD.

Z_DISPLAY

  METHOD z_display.
    DATA lv_stable TYPE lvc_s_stbl.
    DATA lv_soft   TYPE c.

**** Prepare refresh
*  lv_stable-row = 'X'.
*  lv_stable-col = 'X'.
*  lv_soft       = 'X'.
*
**** Refresh table because Z_SET_CELL_STYLE adds style-values
**** Refresh initializes mt_data
*  CALL METHOD refresh_table_display
*    EXPORTING
*      is_stable      = lv_stable
*      i_soft_refresh = lv_soft
*    EXCEPTIONS
*      OTHERS         = 1.

* Jetzt noch  �bertragen der ge�nderten Daten
    CALL METHOD me->set_data_table
      CHANGING
        data_table = mt_data[].

    CALL METHOD set_auto_redraw
      EXPORTING
        enable = 1.
  ENDMETHOD.

Z_SET_CELL_STYLE

  METHOD z_set_cell_style.

    FIELD-SYMBOLS <fs_data> TYPE lvc_s_data.
    IF row IS INITIAL.
      IF col IS INITIAL.
* Beides leer -> nichts zu tun.
        EXIT.
      ELSE.
* Nur Spalte setze komplette Spalte
        LOOP AT mt_data ASSIGNING <fs_data>
        WHERE col_pos = col.
          <fs_data>-style  = <fs_data>-style + style.
          <fs_data>-style2 = <fs_data>-style2 + style2.
        ENDLOOP.
      ENDIF.
    ELSE.
      IF col IS INITIAL.
* Nur Zeile eingegeben -> komplette Zeile setzen
        LOOP AT mt_data ASSIGNING <fs_data>
        WHERE row_pos = row.
          <fs_data>-style  = <fs_data>-style + style.
          <fs_data>-style2 = <fs_data>-style2 + style2.
        ENDLOOP.
      ELSE.
        READ TABLE mt_data ASSIGNING <fs_data>
        WITH KEY row_pos = row
        col_pos = col.
        IF sy-subrc EQ 0.
          <fs_data>-style  = <fs_data>-style + style.
          <fs_data>-style2 = <fs_data>-style2 + style2.
        ELSE.
          EXIT.
        ENDIF.
      ENDIF.
    ENDIF.
  ENDMETHOD.

Z_SET_FIXED_COL_ROW

  METHOD z_set_fixed_col_row.
    me->set_fixed_cols( col ).
    me->set_fixed_rows( row ).
  ENDMETHOD.

Z_INIT_CELL_STYLES

  METHOD z_init_cell_styles.
    FIELD-SYMBOLS <fs_data> TYPE lvc_s_data.
* Nur Spalte setze komplette Spalte
    LOOP AT mt_data ASSIGNING <fs_data>.
      <fs_data>-style = 0.
    ENDLOOP.
  ENDMETHOD.

代码DEMO

*&---------------------------------------------------------------------*
*& Report ZSDR007
*&---------------------------------------------------------------------*
*&描述:销售周例会报表
*&类型:报表
*&创建人:ZJ
*&日期:2024-01-02
*&---------------------------------------------------------------------*
REPORT zsdr007.
*&---------------------------------------------------------------------*
*&INCLUDE
*&---------------------------------------------------------------------*
INCLUDE <cl_alv_control>.
INCLUDE <icon>.
INCLUDE zsdr007_c01.
INCLUDE zsdr007_top.
INCLUDE zsdr007_s01.
INCLUDE zsdr007_f01.
INCLUDE zsdr007_o01.
INCLUDE zsdr007_i01.

*&---------------------------------------------------------------------*
*&INITIALIZATION
*&---------------------------------------------------------------------*
INITIALIZATION.
  PERFORM frm_init."初始化事件
*&---------------------------------------------------------------------*
*&AT SELECTION-SCREEN
*&---------------------------------------------------------------------*
AT SELECTION-SCREEN.
  PERFORM frm_pai."PAI事件
*&---------------------------------------------------------------------*
*&AT SELECTION-SCREEN ON VALUE-REQUEST
*&---------------------------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file3.
****文件上传路径搜索帮助
  PERFORM f4_p_file.
*&---------------------------------------------------------------------*
*&START-OF-SELECTION
*&---------------------------------------------------------------------*
START-OF-SELECTION.
  PERFORM frm_check_data."选择屏幕数据检查
  PERFORM frm_get_data."数据获取
*&---------------------------------------------------------------------*
*&END-OF-SELECTION
*&---------------------------------------------------------------------*
END-OF-SELECTION.
  IF sy-dynnr NE 9003.
    CALL SCREEN 100.
  ENDIF.
*&---------------------------------------------------------------------*
*& 包含               ZSDR007_C01
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&事件类定义
*&---------------------------------------------------------------------*

CLASS lcl_event_receiver DEFINITION.
  PUBLIC SECTION.
ENDCLASS.

*&---------------------------------------------------------------------*
*&事件类实现
*&---------------------------------------------------------------------*
CLASS lcl_event_receiver IMPLEMENTATION.
ENDCLASS.
*&---------------------------------------------------------------------*
*& 包含               ZSDR007_TOP
*&---------------------------------------------------------------------*
TABLES:zsdt006,sscrfields.
*&---------------------------------------------------------------------*
*&全局类型
*&---------------------------------------------------------------------*
TYPES:BEGIN OF gty_zsdt004,
        vkorg      TYPE zsdt004-vkorg,
        spart      TYPE zsdt004-spart,
        kunnr_va   TYPE zsdt004-kunnr_va,
        wadat_ist  TYPE zsdt004-wadat_ist,
        erdat_va   TYPE zsdt004-erdat_va,
        aedat      TYPE zsdt004-aedat,
        wbstk      TYPE zsdt004-wbstk,
        kzwi4_vf   TYPE zsdt004-kzwi4_vf,
        kzwi4_va_s TYPE zsdt004-kzwi4_va_s,
      END OF gty_zsdt004,

      BEGIN OF gty_bsid_sym,
        bukrs TYPE bsid-bukrs,
        kunnr TYPE bsid-kunnr,
        spart TYPE vbrp-spart,
        netwr TYPE vbrp-netwr,
        zfbdt TYPE bsid-zfbdt,
        zbd1t TYPE bsid-zbd1t,
      END OF gty_bsid_sym,

      BEGIN OF gty_bsid_bydqys,
        bukrs TYPE bsid-bukrs,
        kunnr TYPE bsid-kunnr,
        spart TYPE vbrp-spart,
        netwr TYPE vbrp-netwr,
      END OF gty_bsid_bydqys,

      BEGIN OF gty_bsad_hkje,
        bukrs TYPE bsad-bukrs,
        kunnr TYPE bsad-kunnr,
        spart TYPE vbrp-spart,
        netwr TYPE vbrp-netwr,
        budat TYPE bsad-budat,
      END OF gty_bsad_hkje,

      BEGIN OF gty_data,
        field01 TYPE string,
        field02 TYPE string,
        field03 TYPE string,
        field04 TYPE string,
        field05 TYPE string,
        field06 TYPE string,
        field07 TYPE string,
        field08 TYPE string,
        field09 TYPE string,
        field10 TYPE string,
        field11 TYPE string,
        field12 TYPE string,
        field13 TYPE string,
        field14 TYPE string,
        field15 TYPE string,
        field16 TYPE string,
        field17 TYPE string,
        field18 TYPE string,
        field19 TYPE string,
        field20 TYPE string,
        field21 TYPE string,
        field22 TYPE string,
        field23 TYPE string,
        field24 TYPE string,
        field25 TYPE string,
        field26 TYPE string,
        field27 TYPE string,
        field28 TYPE string,
        field29 TYPE string,
        field30 TYPE string,
      END OF gty_data,

      BEGIN OF gty_excle,
        zsyb  TYPE zsdt006-zsyb,
        bztxt TYPE t171t-bztxt,
        kunnr TYPE kna1-kunnr,
        name1 TYPE kna1-name1,
        bezei TYPE tvgrt-bezei,
        gjahr TYPE zsdt006-gjahr,
        m01   TYPE zsdt006-m01,
        m02   TYPE zsdt006-m02,
        m03   TYPE zsdt006-m03,
        m04   TYPE zsdt006-m04,
        m05   TYPE zsdt006-m05,
        m06   TYPE zsdt006-m06,
        m07   TYPE zsdt006-m07,
        m08   TYPE zsdt006-m08,
        m09   TYPE zsdt006-m09,
        m10   TYPE zsdt006-m10,
        m11   TYPE zsdt006-m11,
        m12   TYPE zsdt006-m12,
      END OF gty_excle,

      BEGIN OF gty_cols_rows,
        begin_col TYPE i,
        begin_row TYPE i,
        end_col   TYPE i,
        end_row   TYPE i,
      END OF gty_cols_rows.

*&---------------------------------------------------------------------*
*&全局表
*&---------------------------------------------------------------------*
DATA:gt_9001        TYPE TABLE OF gty_data,
     gt_zsdt006     TYPE TABLE OF zsdt006,
     gt_byxsyj      TYPE TABLE OF gty_zsdt004,
     gt_symddje     TYPE TABLE OF gty_zsdt004,
     gt_xddje       TYPE TABLE OF gty_zsdt004,
     gt_qxddje      TYPE TABLE OF gty_zsdt004,
     gt_excel       TYPE TABLE OF gty_excle,
     gt_upload      TYPE TABLE OF alsmex_tabline,
     gt_9003        TYPE TABLE OF zsdt006,
     gt_9002        TYPE TABLE OF zsdt006,
     gt_bsid_sym    TYPE TABLE OF gty_bsid_sym,
     gt_bsid_bydqys TYPE TABLE OF gty_bsid_bydqys,
     gt_bsad_hkje   TYPE TABLE OF gty_bsad_hkje.

RANGES:gr_kunnr FOR zsdt006-kunnr.
*&---------------------------------------------------------------------*
*&全局变量
*&---------------------------------------------------------------------*
DATA:gv_ok_code     TYPE sy-ucomm,
     ok_code        TYPE sy-ucomm,
     gv_col         TYPE i,
     gv_dynnr       TYPE sy-dynnr,
     gv_date_first  TYPE sy-datum,
     gv_date_last   TYPE sy-datum,
     gv_date_first2 TYPE sy-datum,
     gv_date_last2  TYPE sy-datum,
     gs_cols_rows   TYPE gty_cols_rows.
*&---------------------------------------------------------------------*
*&ALV全局变量
*&---------------------------------------------------------------------*
DATA:go_grid      TYPE REF TO zcl_gui_alv_grid,
     go_docking   TYPE REF TO cl_gui_docking_container,
     gs_layout    TYPE lvc_s_layo,
     gt_fieldcat  TYPE lvc_t_fcat,
     gs_fieldcat  TYPE lvc_s_fcat,
     gt_exclude   TYPE ui_functions,
     gs_style     TYPE lvc_s_styl, "样式
     gs_col_merge TYPE lvc_s_co01, "列布局
     gt_col_merge TYPE lvc_t_co01. "列布局

*&---------------------------------------------------------------------*
*&宏
*&---------------------------------------------------------------------*
DEFINE fieldcat_add.
  CLEAR gs_fieldcat.
  gv_col = gv_col + 1.
  gs_fieldcat-col_pos    = gv_col. "列的显示位置
  gs_fieldcat-fieldname  = &1.      "表字段
  gs_fieldcat-reptext    = &2.      "列标题
  gs_fieldcat-outputlen  = &3.      "输出长度
  gs_fieldcat-no_zero    = &4.      "为输出隐藏零
  gs_fieldcat-decimals   = &5.      "小数位数
  gs_fieldcat-just       = &6.      "输出格式(L:靠左,C:居中,R:靠右)
  gs_fieldcat-hotspot    = &7.      "是否单点
  gs_fieldcat-ref_table  = &8.      "参考表
  gs_fieldcat-ref_field  = &9.      "参考字段
*  gs_fieldcat-convexit   = &10.     "转换例程
*  gs_fieldcat-edit       = &11.     "这一列设为可编辑状态
  APPEND gs_fieldcat TO gt_fieldcat.
END-OF-DEFINITION.
*&---------------------------------------------------------------------*
*& 包含               ZSDR007_S01
*&---------------------------------------------------------------------*
****销售周例会报表
SELECTION-SCREEN BEGIN OF SCREEN 9001 AS SUBSCREEN.
  SELECTION-SCREEN BEGIN OF BLOCK bk1 WITH FRAME TITLE TEXT-001.
    SELECT-OPTIONS:s_syb1 FOR zsdt006-zsyb."事业部
    PARAMETERS:p_gjahr1 TYPE zsdt006-gjahr, "年份
               p_mon1   TYPE month. "月份
    SELECT-OPTIONS:s_kunnr1 FOR zsdt006-kunnr,"客户
                   s_vkgrp1 FOR zsdt006-vkgrp."业务员
  SELECTION-SCREEN END OF BLOCK bk1.
SELECTION-SCREEN END OF SCREEN 9001.

****客户月度目标查询
SELECTION-SCREEN BEGIN OF SCREEN 9002 AS SUBSCREEN .
  SELECTION-SCREEN BEGIN OF BLOCK bk2 WITH FRAME TITLE TEXT-002.
    SELECT-OPTIONS:s_syb2 FOR zsdt006-zsyb."事业部
    PARAMETERS:p_gjahr2 TYPE zsdt006-gjahr. "年份
    SELECT-OPTIONS:s_kunnr2 FOR zsdt006-kunnr,"客户
                   s_vkgrp2 FOR zsdt006-vkgrp."业务员
  SELECTION-SCREEN END OF BLOCK bk2.
SELECTION-SCREEN END OF SCREEN 9002.

****导入客户月度目标
SELECTION-SCREEN BEGIN OF SCREEN 9003 AS SUBSCREEN .
  SELECTION-SCREEN BEGIN OF BLOCK bk3 WITH FRAME TITLE TEXT-003.
    PARAMETERS:p_file3 TYPE rlgrap-filename.
  SELECTION-SCREEN END OF BLOCK bk3.
SELECTION-SCREEN END OF SCREEN 9003.

****下载按钮
SELECTION-SCREEN FUNCTION KEY 1.
****页签
SELECTION-SCREEN:BEGIN OF TABBED BLOCK mytab FOR 25 LINES,
TAB (20) p_tab1 USER-COMMAND tab1,
TAB (20) p_tab2 USER-COMMAND tab2,
TAB (20) p_tab3 USER-COMMAND tab3,
END OF BLOCK mytab.
*&---------------------------------------------------------------------*
*& 包含               ZSDR007_F01
*&---------------------------------------------------------------------*

*&---------------------------------------------------------------------*
*& Form get_data
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_data .
  CASE mytab-dynnr.
    WHEN 9001.
      PERFORM frm_get_data_xszlh."销售周例会报表数据获取
      PERFORM frm_process_data_xszlh."销售周例会报表数据处理
    WHEN 9002.
      PERFORM frm_get_data_khydmb."客户月度目标查询
    WHEN 9003.
      PERFORM frm_import_data_khydmb."客户月度目标数据导入
  ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_build_fcat
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_build_fcat.

  CLEAR:gv_col,gs_fieldcat,gt_fieldcat.

  gv_col = 1.
  DATA:lv_count(2) TYPE n.
  "设置字段属性
  DATA: lv_stru TYPE dd02l-tabname.

  CASE mytab-dynnr.
    WHEN 9001.
      DO 30 TIMES.
        lv_count = sy-index.

        "栏位显示顺序
        gs_fieldcat-col_pos = lv_count.

        "内表栏位
        gs_fieldcat-fieldname = 'FIELD' && lv_count.

        "客户去除前导零
        IF gs_fieldcat-fieldname = 'FIELD02'.
          gs_fieldcat-convexit = 'ALPHA'.
        ENDIF.

        APPEND gs_fieldcat TO gt_fieldcat.
        CLEAR gs_fieldcat.
      ENDDO.
    WHEN 9002.
      lv_stru = 'ZSDT006'.
      CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
        EXPORTING
          i_structure_name       = lv_stru
        CHANGING
          ct_fieldcat            = gt_fieldcat
        EXCEPTIONS
          inconsistent_interface = 1
          program_error          = 2
          OTHERS                 = 3.

  ENDCASE.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_layout
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_set_layout .
  CLEAR: gs_layout.
  gs_layout-zebra = 'X'.
  gs_layout-cwidth_opt = 'X'.
  gs_layout-sel_mode = 'A'.

  IF mytab-dynnr = 9001.
    "内表字段名称
    gs_layout-stylefname = 'CELL'.
    "隐藏列标题
    gs_layout-no_headers = 'X'.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form exclude_tb_functions
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> GT_EXCLUDE
*&      --> PERFORM
*&      --> DISP_ALV
*&---------------------------------------------------------------------*

FORM exclude_tb_functions  TABLES pt_exclude TYPE ui_functions .
  DATA: ls_exclude TYPE ui_func.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_maximum .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_minimum .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_subtot .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_sum .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_average .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_mb_sum .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_mb_subtot .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_sort_asc.
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_sort_dsc .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_find .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_filter .
*  APPEND ls_exclude TO pt_exclude.
  ls_exclude = cl_gui_alv_grid=>mc_fc_print .
  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_print_prev .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_mb_export .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_graph .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_mb_view .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_detail .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_help .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_fc_info .
*  APPEND ls_exclude TO pt_exclude.
*  ls_exclude = cl_gui_alv_grid=>mc_mb_variant.
*  APPEND ls_exclude TO pt_exclude.
  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_append_row.
  APPEND ls_exclude TO pt_exclude.
  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_copy_row.
  APPEND ls_exclude TO pt_exclude.
  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_cut.
  APPEND ls_exclude TO pt_exclude.
  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_delete_row.
  APPEND ls_exclude TO pt_exclude.
  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_insert_row.
  APPEND ls_exclude TO pt_exclude.
  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_move_row.
  APPEND ls_exclude TO pt_exclude.
  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_paste.
  APPEND ls_exclude TO pt_exclude.
  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_paste_new_row.
  APPEND ls_exclude TO pt_exclude.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form disp_alv
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM disp_alv .
  DATA:lo_event TYPE REF TO lcl_event_receiver.
  FIELD-SYMBOLS: <lfs_tab> TYPE STANDARD TABLE.

  CASE mytab-dynnr.
    WHEN 9001.
      ASSIGN gt_9001 TO <lfs_tab>.
    WHEN 9002.
      ASSIGN gt_9002 TO <lfs_tab>.
  ENDCASE.

  CHECK <lfs_tab> IS ASSIGNED.
  IF <lfs_tab> IS INITIAL.
    MESSAGE '没有选择条件对应的数据,请检查' TYPE 'S' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

  CREATE OBJECT go_docking
    EXPORTING
      repid                       = sy-repid
      dynnr                       = sy-dynnr
      side                        = cl_gui_docking_container=>dock_at_bottom "dock_at_top
      extension                   = 500
    EXCEPTIONS
      cntl_error                  = 1
      cntl_system_error           = 2
      create_error                = 3
      lifetime_error              = 4
      lifetime_dynpro_dynpro_link = 5
      OTHERS                      = 6.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

  CREATE OBJECT go_grid
    EXPORTING
      i_parent          = go_docking
    EXCEPTIONS
      error_cntl_create = 1
      error_cntl_init   = 2
      error_cntl_link   = 3
      error_dp_create   = 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.
  ENDIF.

  "解决多表头ALV行数据有限制的问题
  CALL METHOD go_grid->set_ready_for_input
    EXPORTING
      i_ready_for_input = 1.

  CALL METHOD go_grid->set_table_for_first_display
    EXPORTING
      i_save                        = 'A'
      is_layout                     = gs_layout
      it_toolbar_excluding          = gt_exclude
    CHANGING
      it_outtab                     = <lfs_tab>
      it_fieldcatalog               = gt_fieldcat
    EXCEPTIONS
      invalid_parameter_combination = 1
      program_error                 = 2
      too_many_lines                = 3
      OTHERS                        = 4.
  CREATE OBJECT lo_event.

  IF mytab-dynnr = 9001.
    "合并标题
    PERFORM frm_merge_data.
    "设置样式
    PERFORM frm_set_style.
    "显示数据
    go_grid->z_display( ).
  ENDIF.


*  SET HANDLER cl_event_receiver=>handle_hotspot_click
*              "alv_event_receiver=>handle_double_click
*           FOR ALL INSTANCES.
ENDFORM.

FORM frm_refresh_alv USING po_grid TYPE REF TO zcl_gui_alv_grid.
  DATA:ls_stable TYPE lvc_s_stbl.

  ls_stable-row = 'X'." 基于行的稳定刷新
  ls_stable-col = 'X'." 基于列稳定刷新

  "重新设置布局
  CALL METHOD po_grid->set_frontend_layout
    EXPORTING
      is_layout = gs_layout.

  CALL METHOD po_grid->refresh_table_display
    EXPORTING
      is_stable = ls_stable
    EXCEPTIONS
      finished  = 1
      OTHERS    = 2.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_init
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_init .
  DATA: lv_functxt TYPE smp_dyntxt.

  "图标初始化
  lv_functxt-icon_id   = icon_export. "图标,可以通过ICON查找
  lv_functxt-icon_text = TEXT-004."描述
  sscrfields-functxt_01 = lv_functxt.

  p_tab1 = TEXT-001.
  p_tab2 = TEXT-002.
  p_tab3 = TEXT-003.

  CLEAR gv_dynnr.
  mytab-prog = sy-repid.

  IMPORT gv_dynnr FROM MEMORY ID 'SCREEN'."传入上次执行的屏幕号
  FREE MEMORY ID 'SCREEN'.
  IF gv_dynnr = space.
    mytab-dynnr = 9001.
    mytab-activetab = 'TAB1'.
  ELSE.
    CASE gv_dynnr.
      WHEN 9001.
        mytab-dynnr = 9001.
        mytab-activetab = 'TAB1'.
      WHEN 9002.
        mytab-dynnr = 9002.
        mytab-activetab = 'TAB2'.
      WHEN 9003.
        mytab-dynnr = 9003.
        mytab-activetab = 'TAB3'.
    ENDCASE.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_pai
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_pai .
  CASE sy-dynnr.
    WHEN 1000.
      CASE sy-ucomm.
        WHEN 'TAB1'.
          mytab-dynnr = 9001.
          mytab-activetab = 'P_TAB1'.
          gv_dynnr     = 9001.
          EXPORT gv_dynnr TO MEMORY ID 'SCREEN'.     "录入ABAP内存屏幕号
        WHEN 'TAB2'.
          mytab-dynnr = 9002.
          mytab-activetab = 'P_TAB2'.
          gv_dynnr     = 9002.
          EXPORT gv_dynnr TO MEMORY ID 'SCREEN'.
        WHEN 'TAB3'.
          mytab-dynnr = 9003.
          mytab-activetab = 'P_TAB3'.
          gv_dynnr     = 9003.
          EXPORT gv_dynnr TO MEMORY ID 'SCREEN'.
        WHEN 'FC01'.
          PERFORM frm_export_excle."模板导出
      ENDCASE.
  ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_check_data
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_check_data .
  CASE mytab-dynnr.
    WHEN 9001.
      IF p_gjahr1 IS INITIAL OR
         p_mon1 IS INITIAL.
        MESSAGE '年份/月份不能为空' TYPE 'S' DISPLAY LIKE 'E'.
        LEAVE LIST-PROCESSING.
      ENDIF.
    WHEN 9002.
      IF p_gjahr2 IS INITIAL.
        MESSAGE '年份不能为空' TYPE 'S' DISPLAY LIKE 'E'.
        LEAVE LIST-PROCESSING.
      ENDIF.
    WHEN 9003.
      IF p_file3 IS INITIAL.
        MESSAGE '文件路径不能为空' TYPE 'S' DISPLAY LIKE 'E'.
        LEAVE LIST-PROCESSING.
      ENDIF.
    WHEN OTHERS.
  ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_data_xszlh
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_data_xszlh .
  CLEAR:gt_zsdt006,gt_byxsyj,gt_xddje,gt_symddje,gt_qxddje,
        gv_date_first,gv_date_last,gt_bsid_sym,gv_date_first2,
        gv_date_last2.

  "当月第一天
  gv_date_first = |{ p_gjahr1 }{ p_mon1 }01|.

  "当月最后一天
  CALL FUNCTION 'LAST_DAY_OF_MONTHS'
    EXPORTING
      day_in            = gv_date_first
    IMPORTING
      last_day_of_month = gv_date_last
    EXCEPTIONS
      day_in_no_date    = 1
      OTHERS            = 2.

  "获取自建表客户数据
  SELECT *
    FROM zsdt006
    INTO TABLE @gt_zsdt006
   WHERE gjahr EQ @p_gjahr1
     AND zsyb IN @s_syb1
     AND kunnr IN @s_kunnr1
     AND vkgrp IN @s_vkgrp1.

  LOOP AT gt_zsdt006 INTO DATA(ls_zsdt006) WHERE kunnr NE '新客户'.

    gr_kunnr-sign = 'I'.
    gr_kunnr-option = 'EQ'.
    gr_kunnr-low = ls_zsdt006-kunnr.
    COLLECT gr_kunnr.
    CLEAR:ls_zsdt006,gr_kunnr.
  ENDLOOP.


  "获取本月销售业绩
  SELECT vkorg,spart,kunnr_va,
         wadat_ist,kzwi4_vf
    FROM zsdt004
    INTO CORRESPONDING FIELDS OF TABLE @gt_byxsyj
   WHERE wbstk = 'C' AND
         wadat_ist GE @gv_date_first AND
         wadat_ist LE @gv_date_last AND
         ( vkorg EQ '8000' AND ( spart EQ '10' OR spart EQ '20' ) ) OR "家私推杆
         ( vkorg EQ '8000' AND ( spart EQ '30' OR spart EQ '70' ) ) OR "智能升降桌
         ( vkorg EQ '8000' AND spart EQ '80' ) OR "新兴业务部
         ( vkorg EQ '8010' ) OR "家私铁架
         ( vkorg EQ '8020' ). "凯程

  "获取新订单金额
  SELECT vkorg,spart,kunnr_va,
         erdat_va,kzwi4_va_s
    FROM zsdt004
    INTO CORRESPONDING FIELDS OF TABLE @gt_xddje
   WHERE erdat_va GE @gv_date_first AND
         erdat_va LE @gv_date_last AND
         ( vkorg EQ '8000' AND ( spart EQ '10' OR spart EQ '20' ) ) OR "家私推杆
         ( vkorg EQ '8000' AND ( spart EQ '30' OR spart EQ '70' ) ) OR "智能升降桌
         ( vkorg EQ '8000' AND spart EQ '80' ) OR "新兴业务部
         ( vkorg EQ '8010' ) OR "家私铁架
         ( vkorg EQ '8020' ). "凯程

  "获取取消订单金额
  SELECT vkorg,spart,kunnr_va,
         erdat_va,kzwi4_va_s * -1 AS kzwi4_va_s
    FROM zsdt004
    INTO CORRESPONDING FIELDS OF TABLE @gt_qxddje
   WHERE abgru NE '' AND
         aedat GE @gv_date_first AND
         aedat LE @gv_date_last AND
         ( vkorg EQ '8000' AND ( spart EQ '10' OR spart EQ '20' ) ) OR "家私推杆
         ( vkorg EQ '8000' AND ( spart EQ '30' OR spart EQ '70' ) ) OR "智能升降桌
         ( vkorg EQ '8000' AND spart EQ '80' ) OR "新兴业务部
         ( vkorg EQ '8010' ) OR "家私铁架
         ( vkorg EQ '8020' ). "凯程

  "上个月第一天
  PERFORM frm_get_date_calc USING gv_date_first '0' '1' '-'
                         CHANGING gv_date_first2.
  "上个月最后一天
  PERFORM frm_get_date_month USING gv_date_first2
                          CHANGING gv_date_last2.

  "获取上月末订单金额
  SELECT vkorg,spart,kunnr_va,
         erdat_va,kzwi4_vf
    FROM zsdt004
    INTO CORRESPONDING FIELDS OF TABLE @gt_symddje
   WHERE wbstk NE 'C' AND
         erdat_va LE @gv_date_last2 AND
         ( vkorg EQ '8000' AND ( spart EQ '10' OR spart EQ '20' ) ) OR "家私推杆
         ( vkorg EQ '8000' AND ( spart EQ '30' OR spart EQ '70' ) ) OR "智能升降桌
         ( vkorg EQ '8000' AND spart EQ '80' ) OR "新兴业务部
         ( vkorg EQ '8010' ) OR "家私铁架
         ( vkorg EQ '8020' )."凯程

  "上月末应收款余额 & 累计逾期余额(上月末)
  SELECT a~bukrs,a~kunnr,b~spart,
         CASE c~fkart
           WHEN 'ZF2'
           THEN b~netwr + b~mwsbp
           WHEN 'ZS2'
           THEN b~netwr + b~mwsbp
           WHEN 'ZL2'
           THEN b~netwr + b~mwsbp
           WHEN 'ZRE'
           THEN - ( b~netwr + b~mwsbp )
           WHEN 'ZS1'
           THEN - ( b~netwr + b~mwsbp )
           WHEN 'ZG1'
           THEN - ( b~netwr + b~mwsbp )
         END AS netwr,a~zfbdt,a~zbd1t
   FROM bsid AS a
  INNER JOIN vbrp AS b
     ON a~bukrs EQ b~vkorg_auft
    AND a~zuonr EQ b~vbeln
   LEFT JOIN vbrk AS c
     ON a~vbeln EQ c~vbeln
  WHERE a~budat LE @gv_date_last2
    AND c~fkart IN ( 'ZF2','ZS2','ZL2','ZRE','ZS1','ZG1' )
    AND ( a~bukrs EQ '8000' AND ( b~spart EQ '10' OR b~spart EQ '20' ) ) OR "家私推杆
        ( a~bukrs EQ '8000' AND ( b~spart EQ '30' OR b~spart EQ '70' ) ) OR "智能升降桌
        ( a~bukrs EQ '8000' AND b~spart EQ '80' ) OR "新兴业务部
        ( a~bukrs EQ '8010' ) OR "家私铁架
        ( a~bukrs EQ '8020' )"凯程
   INTO TABLE @gt_bsid_sym.
  SORT gt_bsid_sym BY bukrs spart kunnr.

  "本月到期应收
  SELECT a~bukrs,a~kunnr,b~spart,
         CASE c~fkart
           WHEN 'ZF2'
           THEN b~netwr + b~mwsbp
           WHEN 'ZS2'
           THEN b~netwr + b~mwsbp
           WHEN 'ZL2'
           THEN b~netwr + b~mwsbp
           WHEN 'ZRE'
           THEN - ( b~netwr + b~mwsbp )
           WHEN 'ZS1'
           THEN - ( b~netwr + b~mwsbp )
           WHEN 'ZG1'
           THEN - ( b~netwr + b~mwsbp )
         END AS netwr
   FROM bsid AS a
  INNER JOIN vbrp AS b
     ON a~bukrs EQ b~vkorg_auft
    AND a~zuonr EQ b~vbeln
   LEFT JOIN vbrk AS c
     ON a~vbeln EQ c~vbeln
  WHERE a~gjahr EQ @p_gjahr1
    AND a~monat EQ @p_mon1
    AND c~fkart IN ( 'ZF2','ZS2','ZL2','ZRE','ZS1','ZG1' )
    AND ( a~bukrs EQ '8000' AND ( b~spart EQ '10' OR b~spart EQ '20' ) ) OR "家私推杆
        ( a~bukrs EQ '8000' AND ( b~spart EQ '30' OR b~spart EQ '70' ) ) OR "智能升降桌
        ( a~bukrs EQ '8000' AND b~spart EQ '80' ) OR "新兴业务部
        ( a~bukrs EQ '8010' ) OR "家私铁架
        ( a~bukrs EQ '8020' )"凯程
   INTO TABLE @gt_bsid_bydqys.
  SORT gt_bsid_bydqys BY bukrs spart kunnr.


  "回款金额
  SELECT a~bukrs,a~kunnr,b~spart,
         CASE c~fkart
           WHEN 'ZF2'
           THEN b~netwr + b~mwsbp
           WHEN 'ZS2'
           THEN b~netwr + b~mwsbp
           WHEN 'ZL2'
           THEN b~netwr + b~mwsbp
           WHEN 'ZRE'
           THEN - ( b~netwr + b~mwsbp )
           WHEN 'ZS1'
           THEN - ( b~netwr + b~mwsbp )
           WHEN 'ZG1'
           THEN - ( b~netwr + b~mwsbp )
         END AS netwr,a~budat
   FROM bsad AS a
  INNER JOIN vbrp AS b
     ON a~bukrs EQ b~vkorg_auft
    AND a~zuonr EQ b~vbeln
   LEFT JOIN vbrk AS c
     ON a~vbeln EQ c~vbeln
  WHERE a~gjahr EQ @p_gjahr1
    AND a~monat EQ @p_mon1
    AND c~fkart IN ( 'ZF2','ZS2','ZL2','ZRE','ZS1','ZG1' )
    AND ( a~bukrs EQ '8000' AND ( b~spart EQ '10' OR b~spart EQ '20' ) ) OR "家私推杆
        ( a~bukrs EQ '8000' AND ( b~spart EQ '30' OR b~spart EQ '70' ) ) OR "智能升降桌
        ( a~bukrs EQ '8000' AND b~spart EQ '80' ) OR "新兴业务部
        ( a~bukrs EQ '8010' ) OR "家私铁架
        ( a~bukrs EQ '8020' )"凯程
   INTO TABLE @gt_bsad_hkje.
  SORT gt_bsad_hkje BY bukrs spart kunnr.


ENDFORM.

*&---------------------------------------------------------------------*
*& Form frm_get_data_khydmb
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_data_khydmb .

  "数据读取
  SELECT *
    FROM zsdt006
    INTO TABLE gt_9002
   WHERE zsyb IN s_syb2
     AND gjahr EQ p_gjahr2
     AND kunnr IN s_kunnr2
     AND vkgrp IN s_vkgrp2.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_import_data_khydmb
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_import_data_khydmb.
  PERFORM frm_upload_excel."EXCEL数据上传
  PERFORM frm_process_excel."EXCEL数据处理
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_process_data_xszlh
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_process_data_xszlh .
  CLEAR:gt_9001.
  DATA:ls_data       TYPE gty_data,
       lv_field      TYPE string,
       lv_field2     TYPE string,
       lv_num        TYPE n LENGTH 2,
       lv_date_first TYPE sy-datum,
       lv_dqfhje     TYPE zsdt004-kzwi4_vf,
       lv_ysjd       TYPE p LENGTH 13 DECIMALS 2,
       lv_yqbl       TYPE p LENGTH 13 DECIMALS 2,
       lv_hkbl       TYPE p LENGTH 13 DECIMALS 2.

  "拼接fieldname
  lv_field = |M{ p_mon1 }|.

  "第一周的第一天
  lv_date_first = |{ p_gjahr1 }{ p_mon1 }01|.

  "空行数据,用于标题合并
  DO 2 TIMES.
    APPEND INITIAL LINE TO gt_9001.
  ENDDO.
  "设置标题
  PERFORM frm_set_title.
*---  取域ZD_SYB的描述
  SELECT ddtext,
         domvalue_l
    FROM dd07t
    INTO TABLE @DATA(lt_dd07t)
   WHERE domname = 'ZD_SYB'
     AND ddlanguage = @sy-langu.
  SORT lt_dd07t BY domvalue_l.
  "数据处理
  LOOP AT gt_zsdt006 INTO DATA(ls_zsdt006).
    "事业部
    ls_data-field01 = ls_zsdt006-zsyb.
    "客户代码
    ls_data-field02 = ls_zsdt006-kunnr.
    "客户名称
    ls_data-field03 = ls_zsdt006-name1.
    "业务员
    ls_data-field04 = ls_zsdt006-bezei.
    "根据fieldname 获取结构相应月度目标
    ASSIGN COMPONENT lv_field OF STRUCTURE ls_zsdt006 TO FIELD-SYMBOL(<fv_value>).
    ls_data-field05 = <fv_value>."月度目标

    "销售业绩处理
    PERFORM frm_process_xsyj USING ls_zsdt006
                          CHANGING ls_data.
    CLEAR:lv_dqfhje,lv_ysjd.
    "当期发货金额
    lv_dqfhje = ls_data-field06 + ls_data-field07 + ls_data-field08 + ls_data-field09.

    "预算进度
    IF ls_data-field05 NE 0.
      lv_ysjd = lv_dqfhje / ls_data-field05 * 100.
      ls_data-field10 = lv_ysjd && '%'.
    ENDIF.

    "上月末订单金额处理
    PERFORM frm_process_symddje USING ls_zsdt006
                             CHANGING ls_data.

    "新订单金额处理
    PERFORM frm_process_xddje USING ls_zsdt006
                           CHANGING ls_data.

    "取消订单金额处理
    PERFORM frm_process_qxddje USING ls_zsdt006
                            CHANGING ls_data.

    "在手订单金额 = 上月末订单金额 + 新订单金额 + 取消订单金额( FILED11 - FEILD019 )
    DO 9 TIMES.
      lv_num = 10 + sy-index.
      lv_field2 = |FIELD{ lv_num }|.
      ASSIGN COMPONENT lv_field2 OF STRUCTURE ls_data TO <fv_value>.
      "在手订单金额
      ls_data-field20 = <fv_value> + ls_data-field20.
    ENDDO.

    "上月末应收款余额 & 逾期金额( 上月末 )
    PERFORM frm_process_symskye USING ls_zsdt006
                             CHANGING ls_data.

    "逾期比例
    CLEAR:lv_yqbl.
    IF ls_data-field21 NE 0.
      lv_yqbl = ls_data-field22 / ls_data-field21 * 100.
      ls_data-field23 = lv_yqbl && '%'.
    ENDIF.

    "本月到期应收
    PERFORM frm_process_bydqys USING ls_zsdt006
                            CHANGING ls_data.

    "回款金额
    PERFORM frm_process_hkje USING ls_zsdt006
                          CHANGING ls_data.

    "回款比例 = (第一周+第二周+第三周+第四周回款)/本月到期应收
    CLEAR:lv_hkbl.
    IF ls_data-field24 NE 0.
      lv_hkbl = ( ls_data-field25 + ls_data-field26 + ls_data-field27 + ls_data-field28 ) / ls_data-field24 * 100.
      ls_data-field29 = lv_hkbl && '%'.
    ENDIF.

    "应收余额 = 上月末应收款+本月到期应收款-回款金额合计
    ls_data-field30 = ls_data-field21 + ls_data-field24 - ( ls_data-field25 + ls_data-field26 + ls_data-field27 + ls_data-field28 ).


    READ TABLE lt_dd07t INTO DATA(ls_dd07t)
                        WITH KEY domvalue_l = ls_zsdt006-zsyb
                        BINARY SEARCH.
    IF sy-subrc EQ 0.
      "事业部描述
      ls_data-field01 = ls_dd07t-ddtext.
    ENDIF.
    APPEND ls_data TO gt_9001.
    CLEAR:ls_data.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_xsyj
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LS_ZSDT006
*&---------------------------------------------------------------------*
FORM frm_process_xsyj USING ps_zsdt006 TYPE zsdt006
                   CHANGING ps_data TYPE gty_data.

  LOOP AT gt_byxsyj INTO DATA(ls_byxsyj).
    CASE ps_zsdt006-zsyb.
      WHEN 'A'."家私推杆事业部
        IF ls_byxsyj-vkorg EQ '8000' AND
           ( ls_byxsyj-spart EQ '10' OR
             ls_byxsyj-spart EQ '20' ).
          "家私推杆销售业绩字段处理
          PERFORM frm_set_xsyj USING ps_zsdt006 ls_byxsyj
                            CHANGING ps_data.
        ENDIF.
      WHEN 'B'."智能升降桌
        IF ls_byxsyj-vkorg EQ '8000' AND
           ( ls_byxsyj-spart EQ '30' OR
             ls_byxsyj-spart EQ '70' ).
          "智能升降桌销售业绩字段处理
          PERFORM frm_set_xsyj USING ps_zsdt006 ls_byxsyj
                            CHANGING ps_data.
        ENDIF.
      WHEN 'C'."新兴业务部
        IF ls_byxsyj-vkorg EQ '8000' AND
           ( ls_byxsyj-spart EQ '80' ).
          "新兴业务部销售业绩字段处理
          PERFORM frm_set_xsyj USING ps_zsdt006 ls_byxsyj
                            CHANGING ps_data.
        ENDIF.
      WHEN 'D'."家私铁架
        IF ls_byxsyj-vkorg EQ '8010'.
          "家私铁架销售业绩字段处理
          PERFORM frm_set_xsyj USING ps_zsdt006 ls_byxsyj
                            CHANGING ps_data.
        ENDIF.
      WHEN 'E'."凯程
        IF ls_byxsyj-vkorg EQ '8020'.
          "凯程销售业绩字段处理
          PERFORM frm_set_xsyj USING ps_zsdt006 ls_byxsyj
                            CHANGING ps_data.
        ENDIF.
    ENDCASE.
  ENDLOOP.


ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_xsyj_jstg
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> PS_ZSDT006
*&      --> PV_DATE_FIRST
*&---------------------------------------------------------------------*
FORM frm_set_xsyj USING ps_zsdt006 TYPE zsdt006
                         ps_byxsyj TYPE gty_zsdt004
                CHANGING ps_data TYPE gty_data.

  DATA:lv_date_first TYPE sy-datum,
       lv_date_last  TYPE sy-datum,
       lv_num        TYPE n LENGTH 2 VALUE '05',
       lv_field      TYPE string.

  DO 4 TIMES.
    IF sy-index EQ 1.
      "首次进来 开始日期 = 1号
      lv_date_first = gv_date_first.
    ELSE.
      "开始日期 = 上周结束日期 + 1
      lv_date_first = lv_date_last + 1.
    ENDIF.

    IF sy-index NE 4.
      "获取+6后日期
      PERFORM frm_get_date_calc USING lv_date_first '6' '0' '+'
                             CHANGING lv_date_last.
    ELSE.
      "最后一次获取当月最后一天日期
      lv_date_last = gv_date_last.
    ENDIF.

    "拼接字段名
    lv_num = lv_num + sy-index.
    lv_field = |FIELD{ lv_num }|.

    "获取对应销售业绩字段指针
    ASSIGN COMPONENT lv_field OF STRUCTURE ps_data TO FIELD-SYMBOL(<fv_xsyj>).

    IF ps_byxsyj-wadat_ist GE lv_date_first AND
       ps_byxsyj-wadat_ist LE lv_date_last.

      "老客户销售业绩
      IF ps_zsdt006-kunnr NE '新客户' AND
         ps_byxsyj-kunnr_va EQ ps_zsdt006-kunnr.
        <fv_xsyj> = <fv_xsyj> + ps_byxsyj-kzwi4_vf.
      ENDIF.

      "新客户销售业绩
      IF ps_zsdt006-kunnr EQ '新客户' AND
         ps_byxsyj-kunnr_va NOT IN gr_kunnr.
        <fv_xsyj> = <fv_xsyj> + ps_byxsyj-kzwi4_vf.
      ENDIF.
    ENDIF.

  ENDDO.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_date_calc
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LV_DATE_FIRST
*&      <-- LV_DATE_LAST
*&---------------------------------------------------------------------*
FORM frm_get_date_calc USING pv_date_first TYPE sy-datum
                             pv_date TYPE t5a4a-dlydy
                             pv_month TYPE t5a4a-dlymo
                             pv_split TYPE t5a4a-split
                    CHANGING pv_date_last TYPE sy-datum.

  CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
    EXPORTING
      date      = pv_date_first   "日期
      days      = pv_date            "天数
      months    = pv_month            "月数
      signum    = pv_split
      years     = 0             "年数
    IMPORTING
      calc_date = pv_date_last.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_date_month
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LV_DATE_FIRST
*&      <-- LV_DATE_LAST
*&---------------------------------------------------------------------*
FORM frm_get_date_month  USING    pv_date_first TYPE sy-datum
                         CHANGING pv_date_last TYPE sy-datum.

  CALL FUNCTION 'LAST_DAY_OF_MONTHS'
    EXPORTING
      day_in            = pv_date_first "输入日期
    IMPORTING
      last_day_of_month = pv_date_last "返回最后一天日期
    EXCEPTIONS
      day_in_no_date    = 1
      OTHERS            = 2.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_process_symddje
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LS_ZSDT006
*&      <-- LS_DATA
*&---------------------------------------------------------------------*
FORM frm_process_symddje USING ps_zsdt006 TYPE zsdt006
                      CHANGING ps_data TYPE gty_data.

  LOOP AT gt_symddje INTO DATA(ls_symddje).
    CASE ps_zsdt006-zsyb.
      WHEN 'A'."家私推杆事业部
        IF ls_symddje-vkorg EQ '8000' AND
           ( ls_symddje-spart EQ '10' OR
             ls_symddje-spart EQ '20' ).
          "家私推杆上月末订单金额字段处理
          PERFORM frm_set_symddje USING ps_zsdt006 ls_symddje
                               CHANGING ps_data.
        ENDIF.
      WHEN 'B'."智能升降桌
        IF ls_symddje-vkorg EQ '8000' AND
           ( ls_symddje-spart EQ '30' OR
             ls_symddje-spart EQ '70' ).
          "智能升降桌上月末订单金额字段处理
          PERFORM frm_set_symddje USING ps_zsdt006 ls_symddje
                            CHANGING ps_data.
        ENDIF.
      WHEN 'C'."新兴业务部
        IF ls_symddje-vkorg EQ '8000' AND
           ( ls_symddje-spart EQ '80' ).
          "新兴业务部上月末订单金额字段处理
          PERFORM frm_set_symddje USING ps_zsdt006 ls_symddje
                            CHANGING ps_data.
        ENDIF.
      WHEN 'D'."家私铁架
        IF ls_symddje-vkorg EQ '8010'.
          "家私铁架上月末订单金额字段处理
          PERFORM frm_set_symddje USING ps_zsdt006 ls_symddje
                               CHANGING ps_data.
        ENDIF.
      WHEN 'E'."凯程
        IF ls_symddje-vkorg EQ '8020'.
          "凯程上月末订单金额字段处理
          PERFORM frm_set_symddje USING ps_zsdt006 ls_symddje
                               CHANGING ps_data.
        ENDIF.
    ENDCASE.
    CLEAR:ls_symddje.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_symddje
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> PS_ZSDT006
*&      --> LS_SYMDDJE
*&      <-- PS_DATA
*&---------------------------------------------------------------------*
FORM frm_set_symddje USING ps_zsdt006 TYPE zsdt006
                            ps_symddje TYPE gty_zsdt004
                   CHANGING ps_data TYPE gty_data.

  "老客户上月末订单金额
  IF ps_zsdt006-kunnr NE '新客户' AND
     ps_symddje-kunnr_va EQ ps_zsdt006-kunnr.
    ps_data-field11 = ps_data-field11 + ps_symddje-kzwi4_vf.
  ENDIF.

  "新客户上月末订单金额
  IF ps_zsdt006-kunnr EQ '新客户' AND
     ps_symddje-kunnr_va NOT IN gr_kunnr.
    ps_data-field11 = ps_data-field11 + ps_symddje-kzwi4_vf.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_process_xddje
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LS_ZSDT006
*&      <-- LS_DATA
*&---------------------------------------------------------------------*
FORM frm_process_xddje USING ps_zsdt006 TYPE zsdt006
                    CHANGING ps_data TYPE gty_data.

  LOOP AT gt_xddje INTO DATA(ls_xddje).
    CASE ps_zsdt006-zsyb.
      WHEN 'A'."家私推杆事业部
        IF ls_xddje-vkorg EQ '8000' AND
           ( ls_xddje-spart EQ '10' OR
             ls_xddje-spart EQ '20' ).
          "家私推杆新订单金额字段处理
          PERFORM frm_set_xddje USING ps_zsdt006 ls_xddje
                               CHANGING ps_data.
        ENDIF.
      WHEN 'B'."智能升降桌
        IF ls_xddje-vkorg EQ '8000' AND
           ( ls_xddje-spart EQ '30' OR
             ls_xddje-spart EQ '70' ).
          "智能升降桌新订单金额字段处理
          PERFORM frm_set_xddje USING ps_zsdt006 ls_xddje
                            CHANGING ps_data.
        ENDIF.
      WHEN 'C'."新兴业务部
        IF ls_xddje-vkorg EQ '8000' AND
           ( ls_xddje-spart EQ '80' ).
          "新兴业务部新订单金额字段处理
          PERFORM frm_set_xddje USING ps_zsdt006 ls_xddje
                            CHANGING ps_data.
        ENDIF.
      WHEN 'D'."家私铁架
        IF ls_xddje-vkorg EQ '8010'.
          "家私铁架新订单金额字段处理
          PERFORM frm_set_xddje USING ps_zsdt006 ls_xddje
                               CHANGING ps_data.
        ENDIF.
      WHEN 'E'."凯程
        IF ls_xddje-vkorg EQ '8020'.
          "凯程新订单金额字段处理
          PERFORM frm_set_xddje USING ps_zsdt006 ls_xddje
                               CHANGING ps_data.
        ENDIF.
    ENDCASE.
    CLEAR:ls_xddje.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_xddje
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> PS_ZSDT006
*&      --> LS_XDDJE
*&      <-- PS_DATA
*&---------------------------------------------------------------------*
FORM frm_set_xddje USING ps_zsdt006 TYPE zsdt006
                          ps_xddje TYPE gty_zsdt004
                 CHANGING ps_data TYPE gty_data.

  DATA:lv_date_first TYPE sy-datum,
       lv_date_last  TYPE sy-datum,
       lv_num        TYPE n LENGTH 2 VALUE '11',
       lv_field      TYPE string.

  DO 4 TIMES.
    IF sy-index EQ 1.
      "首次进来 开始日期 = 1号
      lv_date_first = gv_date_first.
    ELSE.
      "开始日期 = 上周结束日期 + 1
      lv_date_first = lv_date_last + 1.
    ENDIF.

    IF sy-index NE 4.
      "获取+6后日期
      PERFORM frm_get_date_calc USING lv_date_first '6' '0' '+'
                             CHANGING lv_date_last.
    ELSE.
      "最后一次获取当月最后一天日期
      lv_date_last = gv_date_last.
    ENDIF.

    "拼接字段名
    lv_num = lv_num + sy-index.
    lv_field = |FIELD{ lv_num }|.

    "获取对应销售业绩字段指针
    ASSIGN COMPONENT lv_field OF STRUCTURE ps_data TO FIELD-SYMBOL(<fv_xddje>).

    IF ps_xddje-wadat_ist GE lv_date_first AND
       ps_xddje-wadat_ist LE lv_date_last.

      "老客户新订单金额
      IF ps_zsdt006-kunnr NE '新客户' AND
         ps_xddje-kunnr_va EQ ps_zsdt006-kunnr.
        <fv_xddje> = <fv_xddje> + ps_xddje-kzwi4_va_s.
      ENDIF.

      "新客户新订单金额
      IF ps_zsdt006-kunnr EQ '新客户' AND
         ps_xddje-kunnr_va NOT IN gr_kunnr.
        <fv_xddje> = <fv_xddje> + ps_xddje-kzwi4_va_s.
      ENDIF.
    ENDIF.

  ENDDO.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_process_qxddje
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LS_ZSDT006
*&      <-- LS_DATA
*&---------------------------------------------------------------------*
FORM frm_process_qxddje USING ps_zsdt006 TYPE zsdt006
                     CHANGING ps_data TYPE gty_data.

  LOOP AT gt_qxddje INTO DATA(ls_qxddje).
    CASE ps_zsdt006-zsyb.
      WHEN 'A'."家私推杆事业部
        IF ls_qxddje-vkorg EQ '8000' AND
           ( ls_qxddje-spart EQ '10' OR
             ls_qxddje-spart EQ '20' ).
          "家私推杆新订单金额字段处理
          PERFORM frm_set_qxddje USING ps_zsdt006 ls_qxddje
                              CHANGING ps_data.
        ENDIF.
      WHEN 'B'."智能升降桌
        IF ls_qxddje-vkorg EQ '8000' AND
           ( ls_qxddje-spart EQ '30' OR
             ls_qxddje-spart EQ '70' ).
          "智能升降桌新订单金额字段处理
          PERFORM frm_set_qxddje USING ps_zsdt006 ls_qxddje
                              CHANGING ps_data.
        ENDIF.
      WHEN 'C'."新兴业务部
        IF ls_qxddje-vkorg EQ '8000' AND
           ( ls_qxddje-spart EQ '80' ).
          "新兴业务部新订单金额字段处理
          PERFORM frm_set_qxddje USING ps_zsdt006 ls_qxddje
                              CHANGING ps_data.
        ENDIF.
      WHEN 'D'."家私铁架
        IF ls_qxddje-vkorg EQ '8010'.
          "家私铁架新订单金额字段处理
          PERFORM frm_set_qxddje USING ps_zsdt006 ls_qxddje
                              CHANGING ps_data.
        ENDIF.
      WHEN 'E'."凯程
        IF ls_qxddje-vkorg EQ '8020'.
          "凯程新订单金额字段处理
          PERFORM frm_set_qxddje USING ps_zsdt006 ls_qxddje
                              CHANGING ps_data.
        ENDIF.
    ENDCASE.
    CLEAR:ls_qxddje.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_qxddje
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> PS_ZSDT006
*&      --> LS_QXDDJE
*&      <-- PS_DATA
*&---------------------------------------------------------------------*
FORM frm_set_qxddje USING ps_zsdt006 TYPE zsdt006
                          ps_qxddje TYPE gty_zsdt004
                 CHANGING ps_data TYPE gty_data.

  DATA:lv_date_first TYPE sy-datum,
       lv_date_last  TYPE sy-datum,
       lv_num        TYPE n LENGTH 2 VALUE '15',
       lv_field      TYPE string.

  DO 4 TIMES.
    IF sy-index EQ 1.
      "首次进来 开始日期 = 1号
      lv_date_first = gv_date_first.
    ELSE.
      "开始日期 = 上周结束日期 + 1
      lv_date_first = lv_date_last + 1.
    ENDIF.

    IF sy-index NE 4.
      "获取+6后日期
      PERFORM frm_get_date_calc USING lv_date_first '6' '0' '+'
                             CHANGING lv_date_last.
    ELSE.
      "最后一次获取当月最后一天日期
      lv_date_last = gv_date_last.
    ENDIF.

    "拼接字段名
    lv_num = lv_num + sy-index.
    lv_field = |FIELD{ lv_num }|.

    "获取对应销售业绩字段指针
    ASSIGN COMPONENT lv_field OF STRUCTURE ps_data TO FIELD-SYMBOL(<fv_qxddje>).

    IF ps_qxddje-wadat_ist GE lv_date_first AND
       ps_qxddje-wadat_ist LE lv_date_last.

      "老客户取消订单金额
      IF ps_zsdt006-kunnr NE '新客户' AND
         ps_qxddje-kunnr_va EQ ps_zsdt006-kunnr.
        <fv_qxddje> = <fv_qxddje> + ps_qxddje-kzwi4_va_s.
      ENDIF.

      "新客户取消订单金额
      IF ps_zsdt006-kunnr EQ '新客户' AND
         ps_qxddje-kunnr_va NOT IN gr_kunnr.
        <fv_qxddje> = <fv_qxddje> + ps_qxddje-kzwi4_va_s.
      ENDIF.
    ENDIF.

  ENDDO.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_merge_data
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_merge_data .
  "标题列合并
  PERFORM frm_set_merge_col: USING 1 1 4 '事业部',
                             USING 2 1 5 '客户代码',
                             USING 3 1 6 '客户名称',
                             USING 4 1 7 '业务员',
                             USING 5 2 7 '月度目标',
                             USING 10 2 12 '预算进度',
                             USING 11 2 13 '上月末订单金额',
                             USING 20 2 22 '在手订单金额',
                             USING 21 2 23 '上月末应收款余额',
                             USING 22 2 24 '逾期金额',
                             USING 23 2 25 '逾期比例',
                             USING 24 2 26 '本月到期应收总额',
                             USING 29 2 31 '回款比例',
                             USING 30 2 32 '应收余额'.

  "标题行合并
  PERFORM frm_set_merge_row USING: 5 1 10 '销售业绩',
                                   6 2 9 '发货金额',
                                   11 1 20 '接单情况',
                                   12 2 15 '新订单金额',
                                   16 2 19 '取消订单金额',
                                   16 2 19 '取消订单金额',
                                   21 1 30 '回款情况',
                                   25 2 28 '回款金额'.

  "固定标题
  go_grid->z_set_fixed_col_row( EXPORTING col = 0 row = 4 ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_merge
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> P_1
*&      --> P_2
*&      --> P_
*&---------------------------------------------------------------------*
FORM frm_set_merge_col USING pv_col_id TYPE lvc_s_co01-col_id
                             pv_row TYPE i
                             pv_outputlen TYPE lvc_s_co01-outputlen
                             pv_value TYPE string.


  "合并客户标题
  gs_col_merge-col_id    = pv_col_id.
  gs_col_merge-outputlen = pv_outputlen.
  APPEND gs_col_merge TO gt_col_merge.
  CLEAR gs_col_merge.

  CALL METHOD go_grid->z_set_merge_vert
    EXPORTING
      row           = pv_row
      value         = pv_value
    CHANGING
      tab_col_merge = gt_col_merge.

  CLEAR gt_col_merge.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_merge
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> P_1
*&      --> P_2
*&      --> P_
*&---------------------------------------------------------------------*
FORM frm_set_merge_row USING pv_col_id TYPE lvc_s_co01-col_id
                             pv_row TYPE i
                             pv_outputlen TYPE lvc_s_co01-outputlen
                             pv_value TYPE string.


  "合并客户标题
  gs_col_merge-col_id    = pv_col_id.
  gs_col_merge-outputlen = pv_outputlen.
  APPEND gs_col_merge TO gt_col_merge.
  CLEAR gs_col_merge.

  CALL METHOD go_grid->z_set_merge_horiz
    EXPORTING
      row           = pv_row
      value         = pv_value
    CHANGING
      tab_col_merge = gt_col_merge.

  CLEAR gt_col_merge.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_style
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_set_style .
  CLEAR:gs_style.
  "标题设置粗体和居中
  gs_style-style = alv_style_font_bold + alv_style_align_center_center.

  PERFORM frm_process_style USING: 1 1, "事业部
                                   1 2,"客户代码
                                   1 3,"客户名称
                                   1 4,"业务员
                                   1 5,"销售业绩
                                   2 5,"月度目标
                                   2 6,"发货金额
                                   3 6,"1-7
                                   3 7,"8-14
                                   3 8,"15-21
                                   3 9,"22-30/31
                                   4 6,"第一周
                                   4 7,"第二周
                                   4 8,"第三周
                                   4 9, "第四周
                                   2 10,"预算进度
                                   1 11,"接单情况
                                   2 11,"上月末订单金额
                                   2 12,"新订单金额
                                   3 12,"1-7
                                   4 12,"第一周
                                   3 13,"8-14
                                   4 13,"第二周
                                   3 14,"15-21
                                   4 14,"第三周
                                   3 15,"22-30/31
                                   4 15,"第四周
                                   2 16,"取消订单金额
                                   3 16,"1-7
                                   4 16,"第一周
                                   3 17,"8-14
                                   4 17,"第二周
                                   3 18,"15-21
                                   4 18,"第三周
                                   3 19,"22-30/31
                                   4 19,"第四周
                                   2 20,"在手订单金额
                                   1 21,"回款情况
                                   2 21,"上月末应收款余额
                                   2 22,"逾期金额
                                   2 23,"逾期比例
                                   2 24,"本月到期应收总额
                                   2 25,"汇款金额
                                   3 25,"1-7
                                   4 25,"第一周
                                   3 26,"8-14
                                   4 26,"第二周
                                   3 27,"15-21
                                   4 27,"第三周
                                   3 28,"22-30/31
                                   4 28,"第四周
                                   2 29,"回款比例
                                   2 30."应收余额


  "事业部客户抬头字段
  gs_style-style = alv_style_color_heading.
  PERFORM frm_process_style USING:space 1,
                                  space 2,
                                  space 3,
                                  space 4.

  "销售业绩
  gs_style-style = alv_style_color_background.
  PERFORM frm_process_style USING:space 5,
                                  space 6,
                                  space 7,
                                  space 8,
                                  space 9,
                                  space 10.

  "接单情况
  gs_style-style = alv_style_color_background.
  PERFORM frm_process_style USING:space 5,
                                  space 6,
                                  space 7,
                                  space 8,
                                  space 9,
                                  space 10.

  "接单情况
  gs_style-style = alv_style_color_group.
  PERFORM frm_process_style USING:space 11,
                                  space 12,
                                  space 13,
                                  space 14,
                                  space 15,
                                  space 16,
                                  space 17,
                                  space 18,
                                  space 19,
                                  space 20.

  "接单情况
  gs_style-style = alv_style_color_total.
  PERFORM frm_process_style USING:space 21,
                                  space 22,
                                  space 23,
                                  space 24,
                                  space 25,
                                  space 26,
                                  space 27,
                                  space 28,
                                  space 29,
                                  space 30.


ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_title
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_set_title .
  DATA:ls_data TYPE gty_data.

  ls_data-field06 = '1-7'.
  ls_data-field07 = '8-14'.
  ls_data-field08 = '15-21'.
  ls_data-field09 = '22-' && gv_date_last+6(2).
  ls_data-field12 = '1-7'.
  ls_data-field13 = '8-14'.
  ls_data-field14 = '15-21'.
  ls_data-field15 = '22-' && gv_date_last+6(2).
  ls_data-field16 = '1-7'.
  ls_data-field17 = '8-14'.
  ls_data-field18 = '15-21'.
  ls_data-field19 = '22-' && gv_date_last+6(2).
  ls_data-field25 = '1-7'.
  ls_data-field26 = '8-14'.
  ls_data-field27 = '15-21'.
  ls_data-field28 = '22-' && gv_date_last+6(2).
  APPEND ls_data TO gt_9001.
  CLEAR:ls_data.

  ls_data-field06 = '第一周'.
  ls_data-field07 = '第二周'.
  ls_data-field08 = '第三周'.
  ls_data-field09 = '第四周'.
  ls_data-field12 = '第一周'.
  ls_data-field13 = '第二周'.
  ls_data-field14 = '第三周'.
  ls_data-field15 = '第四周'.
  ls_data-field16 = '第一周'.
  ls_data-field17 = '第二周'.
  ls_data-field18 = '第三周'.
  ls_data-field19 = '第四周'.
  ls_data-field25 = '第一周'.
  ls_data-field26 = '第二周'.
  ls_data-field27 = '第三周'.
  ls_data-field28 = '第四周'.
  APPEND ls_data TO gt_9001.
  CLEAR:ls_data.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_process_style
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> P_1
*&      --> P_1
*&---------------------------------------------------------------------*
FORM frm_process_style USING pv_row TYPE i
                             pv_col TYPE i.
  CALL METHOD go_grid->z_set_cell_style
    EXPORTING
      row   = pv_row
      col   = pv_col
      style = gs_style-style.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_export_excle
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_export_excle .
  DATA:lv_init_path TYPE string,
       lv_title     TYPE string,
       lv_path      TYPE string,
       lv_fpath     TYPE string,
       lv_file      TYPE rlgrap-filename.

  DATA:ls_wdatb LIKE wwwdatatab,
       lv_subrc TYPE sy-subrc,
       lv_msg   TYPE string.

  DATA:lv_objid TYPE w3objid,
       lv_fname TYPE string.

  lv_objid = 'ZSDR007'.
  lv_fname = '客户月度目标导入模板'.


  "获取桌面路径
  CALL METHOD cl_gui_frontend_services=>get_desktop_directory
    CHANGING
      desktop_directory    = lv_init_path
    EXCEPTIONS
      cntl_error           = 1
      error_no_gui         = 2
      not_supported_by_gui = 3
      OTHERS               = 4.
  IF sy-subrc <> 0.
    EXIT.
  ENDIF.

  "保存文件
  CALL METHOD cl_gui_frontend_services=>file_save_dialog
    EXPORTING
      window_title         = lv_title
      default_extension    = 'xlsx'
      default_file_name    = lv_fname
      initial_directory    = lv_init_path
      file_filter          = 'EXCEL文件(*.xlsx)||全部文件(*.*)||'
      prompt_on_overwrite  = 'X'
    CHANGING
      filename             = lv_fname
      path                 = lv_path
      fullpath             = lv_fpath
    EXCEPTIONS
      cntl_error           = 1
      error_no_gui         = 2
      not_supported_by_gui = 3
      OTHERS               = 4.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ELSE.
    CLEAR:lv_file.
    lv_file = lv_fpath.
    IF lv_file IS NOT INITIAL.
      "判断文件模板是否存在
      SELECT SINGLE
             relid
             objid
        FROM wwwdata
        INTO CORRESPONDING FIELDS OF ls_wdatb
       WHERE srtf2 = 0
         AND relid = 'MI'
         AND objid = lv_objid.

      IF ls_wdatb IS INITIAL.
        MESSAGE TEXT-e03 TYPE 'E'.
      ELSE.

        CALL FUNCTION 'DOWNLOAD_WEB_OBJECT'
          EXPORTING
            key         = ls_wdatb
            destination = lv_file
          IMPORTING
            rc          = lv_subrc.
        IF lv_subrc <> 0.
          MESSAGE TEXT-e02 TYPE 'E'.
        ELSE.
          CLEAR:lv_msg.
          CONCATENATE '模板下载到本地文件' lv_file INTO lv_msg.
          MESSAGE lv_msg TYPE 'S'.
        ENDIF.
      ENDIF.
    ELSE.
      MESSAGE TEXT-e01 TYPE 'E' .
    ENDIF.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form f4_p_file
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM f4_p_file .
  DATA:lt_tab TYPE filetable,
       lv_qty TYPE i, "返回的文件数量
       ls_wa  TYPE string.

  CALL METHOD cl_gui_frontend_services=>file_open_dialog
    EXPORTING
      window_title     = '选择文件' "窗口标题
      default_filename = '' "默认文件名
      multiselection   = '' "是否多选,X=一次性可多选,空=单选
      file_filter      = 'Excel表格| *.xls;*.xlsx;*.xlsm'
    CHANGING
      file_table       = lt_tab  "返回的文件结果
      rc               = lv_qty.  "返回的文件个数

  LOOP AT lt_tab INTO ls_wa.
    p_file3 = ls_wa."文件选择框内 = 返回的所选文件路径
  ENDLOOP.
  CALL METHOD cl_gui_cfw=>flush.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_upload_excel
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_upload_excel .

  CLEAR:gs_cols_rows.
  gs_cols_rows-begin_col = '1'.
  gs_cols_rows-begin_row = '3'.
  gs_cols_rows-end_row = '99999'.
  gs_cols_rows-end_col = '18'.

  CALL FUNCTION 'ALSM_EXCEL_TO_INTERNAL_TABLE'
    EXPORTING
      filename                = p_file3
      i_begin_col             = gs_cols_rows-begin_col
      i_begin_row             = gs_cols_rows-begin_row
      i_end_col               = gs_cols_rows-end_col
      i_end_row               = gs_cols_rows-end_row
    TABLES
      intern                  = gt_upload
    EXCEPTIONS
      inconsistent_parameters = 1
      upload_ole              = 2
      OTHERS                  = 3.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_process_excel
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_process_excel .

  DATA:ls_zsdt006 TYPE zsdt006,
       ls_excel   TYPE gty_excle,
       gv_struc   TYPE string,
       gv_table   TYPE string.

  FIELD-SYMBOLS: <fv_field>.

  LOOP AT gt_upload INTO DATA(ls_upload).

    ASSIGN COMPONENT ls_upload-col OF STRUCTURE ls_excel TO FIELD-SYMBOL(<fv_data>).
    IF <fv_data> IS ASSIGNED.
      <fv_data> = ls_upload-value.
    ENDIF.

    CASE ls_upload-col.
      WHEN 3.
        "客户编码补充前导零
        <fv_data> = |{ <fv_data> ALPHA = IN }|.
    ENDCASE.
    AT END OF row.
      APPEND ls_excel TO gt_excel.
      CLEAR:ls_excel.
    ENDAT.
    CLEAR:ls_upload.
  ENDLOOP.

  PERFORM frm_check_excel."EXCEL数据检查及补充
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_check_excel
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_check_excel .

  RANGES:lr_syb FOR zsdt006-zsyb.
  DATA:lv_index TYPE sy-index,
       ls_9003  TYPE zsdt006.

  "查询所有阈值
  SELECT DISTINCT
         'I' AS sign,
         'EQ' AS option,
         domvalue_l AS low
    FROM dd07v
    INTO TABLE @lr_syb
   WHERE domname = 'ZD_SYB'
     AND ddlanguage = @sy-langu.

  "查询客户编码
  WITH +i AS ( SELECT DISTINCT kunnr
                 FROM @gt_excel AS k
                WHERE kunnr NE '新客户' )
SELECT i~kunnr
  FROM +i AS i
 INNER JOIN kna1 AS a
    ON i~kunnr EQ a~kunnr
  INTO TABLE @DATA(lt_kna1).
  SORT lt_kna1 BY kunnr.

  "查询地区,客户名称,业务员
  WITH +i AS ( SELECT DISTINCT kunnr
                 FROM @gt_excel AS k
                WHERE kunnr NE '新客户' )
SELECT i~kunnr,b~bztxt,c~name1,a~vkgrp,d~bezei
  FROM +i AS i
  LEFT JOIN knvv AS a
    ON i~kunnr EQ a~kunnr
  LEFT JOIN t171t AS b
    ON a~bzirk EQ b~bzirk
  LEFT JOIN kna1 AS c
    ON i~kunnr EQ c~kunnr
  LEFT JOIN tvgrt AS d
    ON a~vkgrp EQ d~vkgrp
 WHERE c~spras EQ @sy-langu
   AND d~spras EQ @sy-langu
  INTO TABLE @DATA(lt_knvv).
  SORT lt_kna1 BY kunnr.

  LOOP AT gt_excel INTO DATA(ls_excel).

    lv_index = lv_index + 1.

    "校验事业部是否在域内
    IF ls_excel-zsyb NOT IN lr_syb.
      MESSAGE '' && lv_index && '行:事业部不存在,请确认' TYPE 'S' DISPLAY LIKE 'E'.
      LEAVE LIST-PROCESSING.
    ENDIF.

    "校验客户编码是否存在
    IF ls_excel-kunnr NE '新客户'.
      READ TABLE lt_kna1 TRANSPORTING NO FIELDS
                         WITH KEY kunnr = ls_excel-kunnr
                         BINARY SEARCH.
      IF sy-subrc NE 0.
        MESSAGE '' && lv_index && '行:客户编码不存在,请确认' TYPE 'S' DISPLAY LIKE 'E'.
        LEAVE LIST-PROCESSING.
      ENDIF.
    ENDIF.

    ls_9003 = CORRESPONDING #( ls_excel ).

    "地区,客户名称.业务员
    READ TABLE lt_knvv INTO DATA(ls_knvv)
                       WITH KEY kunnr = ls_excel-kunnr
                       BINARY SEARCH.
    IF sy-subrc EQ 0.
      "地区
      ls_9003-bztxt = ls_knvv-bztxt.
      "客户名称
      ls_9003-name1 = ls_knvv-name1.
      "销售组
      ls_9003-vkgrp = ls_knvv-vkgrp.
      "业务员
      ls_9003-bezei = ls_knvv-bezei.
    ENDIF.

    APPEND ls_9003 TO gt_9003.
    CLEAR:ls_excel,ls_9003.
  ENDLOOP.

  MODIFY zsdt006 FROM TABLE gt_9003.
  IF sy-subrc EQ 0.
    COMMIT WORK AND WAIT.
    MESSAGE '数据导入成功' TYPE 'S'.
    LEAVE LIST-PROCESSING.
  ELSE.
    ROLLBACK WORK.
    MESSAGE '数据导入失败' TYPE 'S' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_process_symskye
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LS_ZSDT006
*&      <-- LS_DATA
*&---------------------------------------------------------------------*
FORM frm_process_symskye USING ps_zsdt006 TYPE zsdt006
                       CHANGING ps_data TYPE gty_data.
  LOOP AT gt_bsid_sym INTO DATA(ls_bsid_sym).
    CASE ps_zsdt006-zsyb.
      WHEN 'A'."家私推杆事业部
        IF ls_bsid_sym-bukrs EQ '8000' AND
           ( ls_bsid_sym-spart EQ '10' OR
             ls_bsid_sym-spart EQ '20' ).
          "家私推杆上月末应收款余额字段处理
          PERFORM frm_set_symysk USING ps_zsdt006 ls_bsid_sym
                              CHANGING ps_data.
        ENDIF.
      WHEN 'B'."智能升降桌
        IF ls_bsid_sym-bukrs EQ '8000' AND
           ( ls_bsid_sym-spart EQ '30' OR
             ls_bsid_sym-spart EQ '70' ).
          "智能升降桌上月末应收款余额字段处理
          PERFORM frm_set_symysk USING ps_zsdt006 ls_bsid_sym
                              CHANGING ps_data.
        ENDIF.
      WHEN 'C'."新兴业务部
        IF ls_bsid_sym-bukrs EQ '8000' AND
           ( ls_bsid_sym-spart EQ '80' ).
          "新兴业务部上月末应收款余额字段处理
          PERFORM frm_set_symysk USING ps_zsdt006 ls_bsid_sym
                              CHANGING ps_data.
        ENDIF.
      WHEN 'D'."家私铁架
        IF ls_bsid_sym-bukrs EQ '8010'.
          "家私铁架上月末应收款余额字段处理
          PERFORM frm_set_symysk USING ps_zsdt006 ls_bsid_sym
                              CHANGING ps_data.
        ENDIF.
      WHEN 'E'."凯程
        IF ls_bsid_sym-bukrs EQ '8020'.
          "凯程上月末应收款余额字段处理
          PERFORM frm_set_symysk USING ps_zsdt006 ls_bsid_sym
                              CHANGING ps_data.
        ENDIF.
    ENDCASE.
    CLEAR:ls_bsid_sym.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_symysk
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> PS_ZSDT006
*&      --> LS_BSID_SYM
*&      <-- PS_DATA
*&---------------------------------------------------------------------*
FORM frm_set_symysk USING ps_zsdt006 TYPE zsdt006
                           ps_bsid_sym TYPE gty_bsid_sym
                  CHANGING ps_data TYPE gty_data.

  DATA:lv_date TYPE sy-datum.

  "获取逾期日期
  lv_date = ps_bsid_sym-zfbdt + ps_bsid_sym-zbd1t.

  "老客户上月末应收款余额 & 逾期金额
  IF ps_zsdt006-kunnr NE '新客户' AND
     ps_bsid_sym-kunnr EQ ps_zsdt006-kunnr.
    "应收款
    ps_data-field21 = ps_data-field21 + ps_bsid_sym-netwr.

    IF lv_date LE gv_date_last2.
      "逾期
      ps_data-field22 = ps_data-field22 + ps_bsid_sym-netwr.
    ENDIF.
  ENDIF.

  "新客户上月末应收款余额 & 逾期金额
  IF ps_zsdt006-kunnr EQ '新客户' AND
     ps_bsid_sym-kunnr NOT IN gr_kunnr.
    "应收款
    ps_data-field21 = ps_data-field21 + ps_bsid_sym-netwr.

    IF lv_date LE gv_date_last2.
      "逾期
      ps_data-field22 = ps_data-field22 + ps_bsid_sym-netwr.
    ENDIF.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_process_bydqys
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LS_ZSDT006
*&      <-- LS_DATA
*&---------------------------------------------------------------------*
FORM frm_process_bydqys USING ps_zsdt006 TYPE zsdt006
                      CHANGING ps_data TYPE gty_data.

  LOOP AT gt_bsid_bydqys INTO DATA(ls_bsid_bydqys).
    CASE ps_zsdt006-zsyb.
      WHEN 'A'."家私推杆事业部
        IF ls_bsid_bydqys-bukrs EQ '8000' AND
           ( ls_bsid_bydqys-spart EQ '10' OR
             ls_bsid_bydqys-spart EQ '20' ).
          "家私推杆本月到期应收字段处理
          PERFORM frm_set_bydqys USING ps_zsdt006 ls_bsid_bydqys
                              CHANGING ps_data.
        ENDIF.
      WHEN 'B'."智能升降桌
        IF ls_bsid_bydqys-bukrs EQ '8000' AND
           ( ls_bsid_bydqys-spart EQ '30' OR
             ls_bsid_bydqys-spart EQ '70' ).
          "智能升降桌本月到期应收字段处理
          PERFORM frm_set_bydqys USING ps_zsdt006 ls_bsid_bydqys
                              CHANGING ps_data.
        ENDIF.
      WHEN 'C'."新兴业务部
        IF ls_bsid_bydqys-bukrs EQ '8000' AND
           ( ls_bsid_bydqys-spart EQ '80' ).
          "新兴业务部本月到期应收字段处理
          PERFORM frm_set_bydqys USING ps_zsdt006 ls_bsid_bydqys
                              CHANGING ps_data.
        ENDIF.
      WHEN 'D'."家私铁架
        IF ls_bsid_bydqys-bukrs EQ '8010'.
          "家私铁架本月到期应收字段处理
          PERFORM frm_set_bydqys USING ps_zsdt006 ls_bsid_bydqys
                              CHANGING ps_data.
        ENDIF.
      WHEN 'E'."凯程
        IF ls_bsid_bydqys-bukrs EQ '8020'.
          "凯程本月到期应收字段处理
          PERFORM frm_set_bydqys USING ps_zsdt006 ls_bsid_bydqys
                              CHANGING ps_data.
        ENDIF.
    ENDCASE.
    CLEAR:ls_bsid_bydqys.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_bydqys
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> PS_ZSDT006
*&      --> LS_BSID_BYDQYS
*&      <-- PS_DATA
*&---------------------------------------------------------------------*
FORM frm_set_bydqys USING ps_zsdt006 TYPE zsdt006
                           ps_bsid_bydqys TYPE gty_bsid_bydqys
                  CHANGING ps_data TYPE gty_data.

  "老客户本月到期应收
  IF ps_zsdt006-kunnr NE '新客户' AND
     ps_bsid_bydqys-kunnr EQ ps_zsdt006-kunnr.
    ps_data-field24 = ps_data-field24 + ps_bsid_bydqys-netwr.
  ENDIF.

  "新客户本月到期应收
  IF ps_zsdt006-kunnr EQ '新客户' AND
     ps_bsid_bydqys-kunnr NOT IN gr_kunnr.
    ps_data-field24 = ps_data-field24 + ps_bsid_bydqys-netwr.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_process_hkje
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> LS_ZSDT006
*&      <-- LS_DATA
*&---------------------------------------------------------------------*
FORM frm_process_hkje USING ps_zsdt006 TYPE zsdt006
                      CHANGING ps_data TYPE gty_data.

  LOOP AT gt_bsad_hkje INTO DATA(ls_bsad_hkje).
    CASE ps_zsdt006-zsyb.
      WHEN 'A'."家私推杆事业部
        IF ls_bsad_hkje-bukrs EQ '8000' AND
           ( ls_bsad_hkje-spart EQ '10' OR
             ls_bsad_hkje-spart EQ '20' ).
          "家私推杆回款金额字段处理
          PERFORM frm_set_hkje USING ps_zsdt006 ls_bsad_hkje
                            CHANGING ps_data.
        ENDIF.
      WHEN 'B'."智能升降桌
        IF ls_bsad_hkje-bukrs EQ '8000' AND
           ( ls_bsad_hkje-spart EQ '30' OR
             ls_bsad_hkje-spart EQ '70' ).
          "智能升降桌回款金额字段处理
          PERFORM frm_set_hkje USING ps_zsdt006 ls_bsad_hkje
                            CHANGING ps_data.
        ENDIF.
      WHEN 'C'."新兴业务部
        IF ls_bsad_hkje-bukrs EQ '8000' AND
           ( ls_bsad_hkje-spart EQ '80' ).
          "新兴业务部回款金额字段处理
          PERFORM frm_set_hkje USING ps_zsdt006 ls_bsad_hkje
                              CHANGING ps_data.
        ENDIF.
      WHEN 'D'."家私铁架
        IF ls_bsad_hkje-bukrs EQ '8010'.
          "家私铁架回款金额字段处理
          PERFORM frm_set_hkje USING ps_zsdt006 ls_bsad_hkje
                            CHANGING ps_data.
        ENDIF.
      WHEN 'E'."凯程
        IF ls_bsad_hkje-bukrs EQ '8020'.
          "凯程回款金额字段处理
          PERFORM frm_set_hkje USING ps_zsdt006 ls_bsad_hkje
                            CHANGING ps_data.
        ENDIF.
    ENDCASE.
    CLEAR:ls_bsad_hkje.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_hkje
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> PS_ZSDT006
*&      --> LS_BSAD_HKJE
*&      <-- PS_DATA
*&---------------------------------------------------------------------*
FORM frm_set_hkje  USING ps_zsdt006 TYPE zsdt006
                         ps_bsad_hkje TYPE gty_bsad_hkje
                 CHANGING ps_data TYPE gty_data.

  DATA:lv_date_first TYPE sy-datum,
       lv_date_last  TYPE sy-datum,
       lv_num        TYPE n LENGTH 2 VALUE '24',
       lv_field      TYPE string.

  DO 4 TIMES.
    IF sy-index EQ 1.
      "首次进来 开始日期 = 1号
      lv_date_first = gv_date_first.
    ELSE.
      "开始日期 = 上周结束日期 + 1
      lv_date_first = lv_date_last + 1.
    ENDIF.

    IF sy-index NE 4.
      "获取+6后日期
      PERFORM frm_get_date_calc USING lv_date_first '6' '0' '+'
                             CHANGING lv_date_last.
    ELSE.
      "最后一次获取当月最后一天日期
      lv_date_last = gv_date_last.
    ENDIF.

    "拼接字段名
    lv_num = lv_num + sy-index.
    lv_field = |FIELD{ lv_num }|.

    "获取对应回款金额字段指针
    ASSIGN COMPONENT lv_field OF STRUCTURE ps_data TO FIELD-SYMBOL(<fv_hkje>).

    IF ps_bsad_hkje-budat GE lv_date_first AND
       ps_bsad_hkje-budat LE lv_date_last.

      "老客户取消订单金额
      IF ps_zsdt006-kunnr NE '新客户' AND
         ps_bsad_hkje-kunnr EQ ps_zsdt006-kunnr.
        <fv_hkje> = <fv_hkje> + ps_bsad_hkje-netwr.
      ENDIF.

      "新客户取消订单金额
      IF ps_zsdt006-kunnr EQ '新客户' AND
         ps_bsad_hkje-kunnr NOT IN gr_kunnr.
        <fv_hkje> = <fv_hkje> + ps_bsad_hkje-netwr.
      ENDIF.
    ENDIF.

  ENDDO.
ENDFORM.
*&---------------------------------------------------------------------*
*& 包含               ZSDR007_O01
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
  SET PF-STATUS '0100'.
  CASE mytab-dynnr.
    WHEN 9001.
      SET TITLEBAR '0100' WITH '销售周例会报表'.
    WHEN 9002.
      SET TITLEBAR '0100' WITH '客户月度目标查询'.
  ENDCASE.

ENDMODULE.
*&---------------------------------------------------------------------*
*& Module INIT_ALV OUTPUT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
MODULE init_alv OUTPUT.
  IF go_docking IS NOT BOUND.
    "创建ALV结构
    PERFORM frm_build_fcat.
    "设置ALV输出格式及变式
    PERFORM frm_set_layout.
    PERFORM exclude_tb_functions  TABLES gt_exclude.
    "显示ALV数据
    PERFORM disp_alv.
  ELSE.
    PERFORM frm_refresh_alv USING go_grid.
  ENDIF.
ENDMODULE.
*&---------------------------------------------------------------------*
*& 包含               ZSDR007_I01
*&---------------------------------------------------------------------*

*&---------------------------------------------------------------------*
*&      Module  EXIT  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE exit INPUT.
  CLEAR:gv_ok_code.
  gv_ok_code = ok_code.
  CLEAR:ok_code.
  CASE gv_ok_code.
    WHEN 'BACK' OR 'EXIT' OR 'CANCLE'.
      LEAVE TO SCREEN 0.
  ENDCASE.
ENDMODULE.

屏幕:

 状态栏:

 

 

 

 

posted @ 2022-08-04 10:57  阿胖的阿多  阅读(2383)  评论(8编辑  收藏  举报