ABAP Excel处理-内表导出为Excel文件

目录

一、概述

二、内表导出为Excel文件的实现

1. OLE下载内表数据为Excel文件

2. DOI下载内表数据为Excel文件

3. 生成文本形式的Excel(.xls或.csv)

4. 标准方法输出Excel文件流(用作接口或后台)

5. Transformation 生成xml格式的Excel(.XLS)

6.  ABAP2XLSX 和 XLSX Workbench

三、总结


一、概述

        SAP中Excel的处理,在项目需求中算是比较常见,内表数据生成Excel文件是其中一种,实现方式常见的有OLE,DOI和直接操作Excel文件(xml格式文件或者一般文本格式文件);OLE和DOI使用方便,但是缺点是不能脱离gui使用;直接操作Excel文件方式适用性更强,常用在web端接口或者邮件发送,其中代表性的是ABAP2XLSX。

        ABAP中标准下载内表数据为Excel文件的函数中,使用OLE实现的MS_EXCEL_OLE_STANDARD_DAT,使用DOI实现的SAP_CONVERT_TO_XLS_FORMAT/XXL_FULL_API,以及GUI_DOWNLOAD/CL_GUI_FRONTEND_SERVICES=>GUI_DOWNLOAD直接下载以tab为分隔符的文本形式的excel文件(.xls或者.csv文件)。

        实际使用中,上述标准函数均差强人意,各有缺点,因此这里总结一些abap下载内表数据为Excel文件的示例代码,以供参考。

二、内表导出为Excel文件的实现

1. OLE下载内表数据为Excel文件

        参数为内表数据,下载地址全路径和字段Fieldcat(表头描述)

 class-methods EXPORT_EXCEL
    importing
      !ITAB type TABLE
      !FULL_PATH type STRING
      !FIELDCAT type LVC_T_FCAT .
      
    METHOD export_excel.
    
    DATA: excel     TYPE ole2_object,
          workbooks TYPE ole2_object,
          workbook  TYPE ole2_object,
          sheet     TYPE ole2_object,
          cell      TYPE ole2_object,
          border    TYPE ole2_object,
          column    TYPE ole2_object,
          borders   TYPE ole2_object,
          entirecol TYPE ole2_object,
          interior  TYPE ole2_object.

    DATA: lo_data_ref TYPE REF TO data,
          lv_row      TYPE i,
          lv_col      TYPE i.

    DATA: lt_fieldcat TYPE lvc_t_fcat,
          ls_fieldcat TYPE lvc_s_fcat.

    DATA: lr_data         TYPE REF TO data,
          lo_tabdescr     TYPE REF TO cl_abap_structdescr,
          lt_dfies        TYPE ddfields,
          ls_dfies        TYPE dfies,
          ls_fieldcatalog TYPE lvc_s_fcat.

    FIELD-SYMBOLS:   TYPE ANY TABLE,
                     TYPE any,
                    TYPE any.

    DEFINE mcr_cell_value.
      " Set cell value
      CALL METHOD OF excel 'CELLS' = cell
        EXPORTING
          #1 = &1
          #2 = &2.
      SET PROPERTY OF cell 'VALUE'  = &3 .
    END-OF-DEFINITION.

    CREATE DATA lo_data_ref LIKE itab.
    ASSIGN lo_data_ref->* TO .
     = itab.

    " Fieldcatlog
    CREATE DATA lr_data LIKE LINE OF itab.
    lo_tabdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ).
    lt_dfies = cl_salv_data_descr=>read_structdescr( lo_tabdescr ).

    LOOP AT lt_dfies INTO ls_dfies.
      MOVE-CORRESPONDING ls_dfies TO ls_fieldcat.
      READ TABLE fieldcat INTO ls_fieldcatalog WITH KEY fieldname = ls_fieldcat-fieldname.
      IF sy-subrc = 0.
        ls_fieldcat-reptext   = ls_fieldcatalog-reptext.
        ls_fieldcat-coltext   = ls_fieldcatalog-coltext.
        ls_fieldcat-seltext   = ls_fieldcatalog-seltext.
        ls_fieldcat-scrtext_s = ls_fieldcatalog-scrtext_s.
        ls_fieldcat-scrtext_m = ls_fieldcatalog-scrtext_m.
        ls_fieldcat-scrtext_l = ls_fieldcatalog-scrtext_l.
      ENDIF.
      APPEND ls_fieldcat TO lt_fieldcat.
    ENDLOOP.

    " 1. Excel operation
    " Create Excel object
    CREATE OBJECT excel 'EXCEL.APPLICATION'.

    " Set visible 1 visible 0 invisible
    SET PROPERTY OF excel 'VISIBLE' = 1.

    " Set one default sheet for excel
    SET PROPERTY OF excel 'SHEETSINNEWWORKBOOK' = 1.

    " Create workbook
    CALL METHOD OF excel 'WORKBOOKS' = workbooks.
    CALL METHOD OF workbooks 'ADD' = workbook.
*    CALL METHOD OF workbooks 'OPEN' EXPORTING #1 = full_path.

    " Set current sheet
    CALL METHOD OF excel 'SHEETS' =  sheet
      EXPORTING
      #1 = 1.
    SET PROPERTY OF sheet 'NAME' = 'Data'."sheet rename
    CALL METHOD OF excel 'WORKSHEETS' = sheet EXPORTING #1 = 'Data'.
    CALL METHOD OF sheet 'ACTIVATE'.

    " 2. Write data
    " Header
    lv_row = lv_col = 1.
    LOOP AT lt_fieldcat INTO ls_fieldcat.

      mcr_cell_value lv_row lv_col ls_fieldcat-coltext.

      " Set column properties
      CALL METHOD OF excel 'COLUMNS' = column EXPORTING #1 = lv_col. " column number

      " 科学计数法
      IF ls_fieldcat-inttype = 'C' OR ls_fieldcat-inttype = 'P'.
        SET PROPERTY OF column 'NumberFormat' = '@'.
      ENDIF.

      GET PROPERTY OF column 'EntireColumn' = entirecol.
      SET PROPERTY OF entirecol 'Autofit' = 1.

      lv_col = lv_col + 1.
    ENDLOOP.

    " Data
    lv_row = 2.
    LOOP AT  ASSIGNING .

      lv_col = 1.
      LOOP AT lt_fieldcat INTO ls_fieldcat.

        ASSIGN COMPONENT ls_fieldcat-fieldname OF STRUCTURE  TO .
        IF sy-subrc = 0.
          mcr_cell_value lv_row lv_col .
        ENDIF.

        lv_col = lv_col + 1.
      ENDLOOP.

      lv_row = lv_row + 1.
    ENDLOOP.

    " 3. Save
    GET PROPERTY OF excel 'ACTIVEWORKBOOK' = workbook."
    CALL METHOD OF workbook 'SAVEAS' EXPORTING #1 = full_path .
    CALL METHOD OF workbook 'CLOSE'.
    CALL METHOD OF excel 'QUIT'.

    " Free object
    FREE OBJECT sheet.
    FREE OBJECT workbook.
    FREE OBJECT excel.

  ENDMETHOD.   

2. DOI下载内表数据为Excel文件

        参数为内表数据,下载地址全路径和字段Fieldcat(表头描述)

class-methods EXPORT_EXCEL
    importing
      !ITAB type TABLE
      !FULL_PATH type STRING
      !FIELDCAT type LVC_T_FCAT .
      
  METHOD export_excel.

    "DOI Objec
    DATA: lo_container   TYPE REF TO          cl_gui_custom_container,  "container
          lo_control     TYPE REF TO          i_oi_container_control,   "controler
          lo_proxy       TYPE REF TO          i_oi_document_proxy,      "Document object
          lo_spreadsheet TYPE REF TO          i_oi_spreadsheet,         " Sheet
          lo_error       TYPE REF TO          i_oi_error,               "Error
          lo_error_tab   TYPE TABLE OF REF TO i_oi_error.               "Error

    " Doi excel data
    DATA: ranges        TYPE soi_range_list,
          rangeitem     TYPE soi_range_item,
          contents      TYPE soi_generic_table,
          contentsitem  TYPE soi_generic_item,
          lv_range_name TYPE char40.

    " Method para
    DATA:lv_has_activex         TYPE c,
         lv_has                 TYPE i,
         lc_retcode             TYPE soi_ret_string,
         lv_doctype_excel_sheet TYPE char20,
         lv_document_size       TYPE i,
         ls_path                TYPE rlgrap-filename,
         no_flush               TYPE c VALUE 'X'.

    " Logic para
    DATA: lv_is_closed TYPE i,
          lv_top       TYPE i,
          lv_left      TYPE i,
          lv_rows      TYPE i,
          lv_cols      TYPE i,
          lv_rowid     TYPE i,
          lv_colid     TYPE i.

    " Itab field
    DATA: lr_data     TYPE REF TO data,
          lo_data_ref TYPE REF TO data,
          lo_tabdescr TYPE REF TO cl_abap_structdescr,
          lt_dfies    TYPE ddfields,
          ls_dfies    TYPE dfies.

    DATA: lt_field_fcat TYPE lvc_t_fcat,
          ls_field_fcat TYPE lvc_s_fcat.

    " Data
    FIELD-SYMBOLS:  TYPE STANDARD TABLE,
                     TYPE any,
                    TYPE any.

    FIELD-SYMBOLS:  TYPE lvc_s_fcat.

    " Close document when error occurs
    DEFINE close_document.
      CLEAR: lv_is_closed.
      IF lo_proxy IS NOT INITIAL.
* check proxy detroyed adi
        CALL METHOD lo_proxy->is_destroyed
          IMPORTING
            ret_value = lv_is_closed.

* if dun detroyed yet: close -> release proxy
        IF lv_is_closed IS INITIAL.
          CALL METHOD lo_proxy->close_document
            IMPORTING
              error       = lo_error
              retcode     = lc_retcode.
        ENDIF.

        CALL METHOD lo_proxy->release_document
          IMPORTING
            error   = lo_error
            retcode = lc_retcode.
      ELSE.
        lc_retcode = c_oi_errors=>ret_document_not_open.
      ENDIF.

* Detroy control container
      IF lo_control IS NOT INITIAL.
        CALL METHOD lo_control->destroy_control.
      ENDIF.

      CLEAR:
        lo_spreadsheet,
        lo_proxy,
        lo_control.

* free local
      CLEAR: lv_is_closed.
    END-OF-DEFINITION.

    " Macro to catch DOI error
    DEFINE error_doi.
      IF lc_retcode NE c_oi_errors=>ret_ok.
        CALL METHOD lo_error->raise_message
          EXPORTING
            type = 'E'.
        CLEAR: lo_error.
        close_document.
      ENDIF.
    END-OF-DEFINITION.

    " Field for itab
    CREATE DATA lr_data LIKE LINE OF itab.
    lo_tabdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ).
    lt_dfies = cl_salv_data_descr=>read_structdescr( lo_tabdescr ).
    SORT lt_dfies BY fieldname.

    " Data transfer to local
    CREATE DATA lo_data_ref LIKE itab.
    ASSIGN lo_data_ref->* TO .
     = itab.

    " Whether ActiveX Controls Supported
    CALL FUNCTION 'GUI_HAS_ACTIVEX'
      IMPORTING
        return = lv_has_activex.
    IF lv_has_activex IS INITIAL.
      RETURN.
    ENDIF.

    " Get Container Object of Screen
    CALL METHOD c_oi_container_control_creator=>get_container_control
      IMPORTING
        control = lo_control
        retcode = lc_retcode
        error   = lo_error.

    " Initialize Container control
    CALL METHOD lo_control->init_control
      EXPORTING
        parent                   = cl_gui_container=>default_screen
        r3_application_name      = ''
        inplace_enabled          = 'X'
        no_flush                 = 'X'
        register_on_close_event  = 'X'
        register_on_custom_event = 'X'
      IMPORTING
        error                    = lo_error
        retcode                  = lc_retcode.

    error_doi.

    " check exist of document proxy, if exist -> close first
    IF NOT lo_proxy IS INITIAL.
      close_document.
    ENDIF.

    lv_doctype_excel_sheet = 'Excel.Sheet'.
    CALL METHOD lo_control->get_document_proxy
      EXPORTING
        document_type      = lv_doctype_excel_sheet
        register_container = 'X'
      IMPORTING
        document_proxy     = lo_proxy
        error              = lo_error
        retcode            = lc_retcode.

    error_doi.

    " create new excel document
    CALL METHOD lo_proxy->create_document
      EXPORTING
        create_view_data = 'X'
        open_inplace     = 'X'
        no_flush         = 'X'
      IMPORTING
        error            = lo_error
        retcode          = lc_retcode.

    error_doi.

    " Check Spreadsheet Interface of Document Proxy
    CALL METHOD lo_proxy->has_spreadsheet_interface
      IMPORTING
        is_available = lv_has
        error        = lo_error
        retcode      = lc_retcode.

    error_doi.

    " create Spreadsheet object
    CHECK lv_has IS NOT INITIAL.

    CALL METHOD lo_proxy->get_spreadsheet_interface
      IMPORTING
        sheet_interface = lo_spreadsheet
        error           = lo_error
        retcode         = lc_retcode.

    error_doi.

    CALL METHOD lo_spreadsheet->screen_update
      EXPORTING
        updating = ''.

    CALL METHOD lo_spreadsheet->load_lib.

    " Head text set
    lv_range_name = 'Head'.
    lv_top = lv_left = lv_rows = 1.
    lv_cols = lines( fieldcat ).

    CALL METHOD lo_spreadsheet->insert_range_dim
      EXPORTING
        name     = lv_range_name
        top      = lv_top
        left     = lv_left
        rows     = lv_rows
        columns  = lv_cols
        no_flush = no_flush.

    CLEAR: rangeitem,ranges,contentsitem,contents.
    rangeitem-name    = lv_range_name.
    rangeitem-columns = lv_cols.
    rangeitem-rows    = lv_rows.
    APPEND rangeitem TO ranges.

    lv_rowid = 1.
    lv_colid = 1.
    " Head text and cloum attribute
    lt_field_fcat = fieldcat.
    LOOP AT lt_field_fcat ASSIGNING .
      READ TABLE lt_dfies INTO ls_dfies WITH KEY fieldname = -fieldname.
      IF sy-subrc = 0.
        CLEAR ls_field_fcat.
        MOVE-CORRESPONDING ls_dfies TO .
      ENDIF.

      contentsitem-row    = lv_rowid.
      contentsitem-column = lv_colid.
      contentsitem-value  = -coltext.
      CONDENSE contentsitem-value.
      APPEND contentsitem TO contents.
      lv_colid = lv_colid + 1.
    ENDLOOP.

    " Title font
    CALL METHOD lo_spreadsheet->set_font
      EXPORTING
        rangename = lv_range_name
        family    = ''
        size      = 11
        bold      = -1
        italic    = -1
        align     = 0
        no_flush  = no_flush.

    " Title color
    CALL METHOD lo_spreadsheet->set_color
      EXPORTING
        rangename = lv_range_name
        front     = 0
        no_flush  = no_flush
        back      = 15.

    " Set range data title
    CALL METHOD lo_spreadsheet->set_ranges_data
      EXPORTING
        ranges   = ranges
        contents = contents
        no_flush = no_flush.

    " Set excel data
    lv_colid = 1.
    LOOP AT lt_field_fcat ASSIGNING .
      CLEAR: rangeitem,ranges,contentsitem,contents.

      " Insert data using colum
      lv_rowid = 1.
      LOOP AT  ASSIGNING .
        ASSIGN COMPONENT -fieldname OF STRUCTURE  TO .
        IF sy-subrc  =  0.
          contentsitem-row    = lv_rowid.
          contentsitem-column = 1." insert 1 column once,use 1
          contentsitem-value  = .
          CONDENSE contentsitem-value.
          APPEND contentsitem TO contents.
        ENDIF.
        lv_rowid = lv_rowid + 1.
      ENDLOOP.

      " Colum data set
      lv_range_name = 'COLDATA'.
      lv_left  = lv_colid." From cloum ,only set range 1 colum
      lv_top   = 2." Fomr 2, 1 is header
      lv_cols = 1.
      lv_rows = lv_rowid - 1.

      rangeitem-name    = lv_range_name.
      rangeitem-columns = lv_cols.
      rangeitem-rows    = lv_rows.
      APPEND rangeitem TO ranges.

      CALL METHOD lo_spreadsheet->insert_range_dim
        EXPORTING
          name     = lv_range_name
          top      = lv_top
          left     = lv_left
          rows     = lv_rows
          columns  = lv_cols
          no_flush = no_flush.

      " type
      " 0: 文本 1: 货币金额 2: 科学计数法 3: 百分号 4:日期 10: 常规
      CASE -datatype.
        WHEN 'I' OR 'P'.
          CALL METHOD lo_spreadsheet->set_format
            EXPORTING
              rangename = lv_range_name
              currency  = ''
              typ       = 1
              decimals  = ''
              no_flush  = no_flush.
        WHEN 'D'.
          CALL METHOD lo_spreadsheet->set_format
            EXPORTING
              rangename = lv_range_name
              currency  = ''
              typ       = 4
*             decimals  = ''
              no_flush  = no_flush.
        WHEN 'C'.
          CALL METHOD lo_spreadsheet->set_format
            EXPORTING
              rangename = lv_range_name
              currency  = ''
              typ       = 0
*             decimals  = ''
              no_flush  = no_flush.
        WHEN OTHERS.
          CALL METHOD lo_spreadsheet->set_format
            EXPORTING
              rangename = lv_range_name
              currency  = ''
              typ       = 10
*             decimals  = ''
              no_flush  = no_flush.
      ENDCASE.


      " set range data title
      CALL METHOD lo_spreadsheet->set_ranges_data
        EXPORTING
          ranges   = ranges
          contents = contents
          no_flush = no_flush.

      lv_colid = lv_colid + 1.
    ENDLOOP.

    " Whole table set
    lv_range_name = 'WHOLE_TABLE'.
    lv_top = lv_left = 1.
    lv_rows = lines(  ).
    lv_cols = lines( lt_field_fcat ).
    CALL METHOD lo_spreadsheet->insert_range_dim
      EXPORTING
        name     = lv_range_name
        top      = lv_top
        left     = lv_left
        rows     = lv_rows
        columns  = lv_cols
        no_flush = no_flush.

    " columns_autofit = 'X'.
    CALL METHOD lo_spreadsheet->fit_widest
      EXPORTING
        name     = lv_range_name
        no_flush = no_flush.

* frame
* The parameter has 8 bits
*0 Left margin
*1 Top marginT
*2 Bottom margin
*3 Right margin
*4 Horizontal line
*5 Vertical line
*6 Thinness
*7 Thickness
* here 127 = 1111111 6-5-4-3-2-1 mean Thin-ver-hor-right-bot-top-left

* ( final DOI method call, set no_flush = space
    cl_gui_cfw=>flush(
    EXCEPTIONS
      cntl_system_error = 1
      cntl_error = 2
      ).
    CALL METHOD lo_spreadsheet->set_frame
      EXPORTING
        rangename = lv_range_name
        typ       = 127
        color     = 1
        no_flush  = space
      IMPORTING
        error     = lo_error
        retcode   = lc_retcode.

    error_doi.

    CALL METHOD lo_spreadsheet->screen_update
      EXPORTING
        updating = 'X'.

    CALL METHOD c_oi_errors=>flush_errors.

    " Save document
    CONCATENATE 'FILE://' full_path
                INTO ls_path.
    CALL METHOD lo_proxy->save_document_to_url
      EXPORTING
        no_flush      = 'X'
        url           = ls_path
      IMPORTING
        error         = lo_error
        retcode       = lc_retcode
      CHANGING
        document_size = lv_document_size.

    close_document.

  ENDMETHOD.

        如下链接针对alv内表下载,实现标准alv内表下载效果,可作参考做个性化alv内表下载。ALV内表下载为Excel文件(带格式)-Java文档类资源-CSDN下载

3. 生成文本形式的Excel(.xls或.csv)

        字段数据拼接生成text文件,以tab为间隔的.xls文件,以’,‘为分割的.csv文件,这里以.xls文件为例。

        参数为内表数据,下载地址全路径(Excel文件后缀为.xls)和Fieldcat。日期和数值格式可以根据情况做格式特殊处理。

 class-methods EXPORT_EXCEL 
    importing
      !ITAB type TABLE
      !FULL_PATH type STRING
      !FIELDCAT type LVC_T_FCAT .

  METHOD EXPORT_EXCEL_FROM_DATA_TEXT.

    DATA:
      lr_tabdescr TYPE REF TO cl_abap_structdescr,
      lr_data     TYPE REF TO data,
      lt_dfies    TYPE ddfields,
      ls_dfies    TYPE dfies,
      lt_fieldcat TYPE lvc_t_fcat,
      ls_fieldcat TYPE lvc_s_fcat.

    DATA: lv_str_single TYPE string,
          lv_str_line   TYPE string,
          lv_str_file   TYPE string,
          lv_filename   TYPE string,
          lv_xstring    TYPE xstring,
          lv_lengcth    TYPE i,
          lt_bin_data   TYPE TABLE OF solisti1.

    DATA: ls_fieldcat_input TYPE lvc_s_fcat.

    FIELD-SYMBOLS:   TYPE any,
                    TYPE any.

    CREATE DATA lr_data LIKE LINE OF itab.
    ASSIGN lr_data->* TO .

    " 字段清单
    lr_tabdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ).
    lt_dfies = cl_salv_data_descr=>read_structdescr( lr_tabdescr ).
    LOOP AT lt_dfies INTO ls_dfies.
      CLEAR ls_fieldcat.
      MOVE-CORRESPONDING ls_dfies TO ls_fieldcat.
      READ TABLE fieldcat INTO ls_fieldcat_input WITH KEY fieldname = ls_fieldcat-fieldname.
      IF sy-subrc = 0.
        ls_fieldcat-coltext = ls_fieldcat_input-coltext.
      ENDIF.

      IF ls_fieldcat-coltext IS NOT INITIAL.
        lv_str_single = ls_fieldcat-coltext.
      ELSE.
        lv_str_single =  ls_fieldcat-scrtext_l.
      ENDIF.
      lv_str_file   = lv_str_file && cl_abap_char_utilities=>horizontal_tab && lv_str_single.

      APPEND ls_fieldcat TO lt_fieldcat.
    ENDLOOP.

    SHIFT lv_str_file LEFT DELETING LEADING cl_abap_char_utilities=>horizontal_tab.
    lv_str_file = lv_str_file && cl_abap_char_utilities=>cr_lf.

    " 数据拼接
    LOOP AT itab ASSIGNING .
      LOOP AT lt_fieldcat INTO ls_fieldcat.

        ASSIGN COMPONENT ls_fieldcat-fieldname OF STRUCTURE  TO .
        IF sy-subrc = 0.
          lv_str_single = .
          IF ls_fieldcat-inttype = 'I' OR  ls_fieldcat-inttype = 'F' OR  ls_fieldcat-inttype = 'P'.
            SEARCH lv_str_single FOR '-'.
            IF sy-subrc = 0 AND sy-fdpos <> 0.
              SHIFT lv_str_single RIGHT DELETING TRAILING '-'.
              CONDENSE lv_str_single.
              CONCATENATE '-' lv_str_single INTO lv_str_single.
            ELSE.
              CONDENSE lv_str_single.
            ENDIF.
          ENDIF.

          lv_str_line   = lv_str_line && cl_abap_char_utilities=>horizontal_tab && lv_str_single.

        ENDIF.

      ENDLOOP.

      SHIFT lv_str_line LEFT BY 1 PLACES.
      lv_str_file = lv_str_file && lv_str_line && cl_abap_char_utilities=>cr_lf.
      CLEAR lv_str_line.
    ENDLOOP.

    CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
      EXPORTING
        text     = lv_str_file
        mimetype = '"text/html; charset=gb2312"'
*       encoding = '8400'
      IMPORTING
        buffer   = lv_xstring
      EXCEPTIONS
        failed   = 1
        OTHERS   = 2.

    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        buffer          = lv_xstring
        append_to_table = ''
      IMPORTING
        output_length   = lv_lengcth
      TABLES
        binary_tab      = lt_bin_data.

    lv_filename = full_path. " Need XLS文件
    CALL METHOD cl_gui_frontend_services=>gui_download
      EXPORTING
        bin_filesize            = lv_lengcth
        filename                = lv_filename
        filetype                = 'BIN'
*       append                  = SPACE
*       write_field_separator   = SPACE
*       header                  = '00'
*       trunc_trailing_blanks   = SPACE
*       write_lf                = 'X'
*       col_select              = SPACE
*       col_select_mask         = SPACE
*       dat_mode                = SPACE
        confirm_overwrite       = space
*       no_auth_check           = SPACE
*       codepage                = '4103'
*       ignore_cerr             = ABAP_TRUE
*       replacement             = '#'
*       write_bom               = SPACE
*       trunc_trailing_blanks_eol = 'X'
*       wk1_n_format            = SPACE
*       wk1_n_size              = SPACE
*       wk1_t_format            = SPACE
*       wk1_t_size              = SPACE
*       show_transfer_status    = 'X'
*       fieldnames              =
*       write_lf_after_last_line  = 'X'
*       virus_scan_profile      = '/SCET/GUI_DOWNLOAD'
*  IMPORTING
*       filelength              =
      CHANGING
        data_tab                = lt_bin_data
      EXCEPTIONS
        file_write_error        = 1
        no_batch                = 2
        gui_refuse_filetransfer = 3
        invalid_type            = 4
        no_authority            = 5
        unknown_error           = 6
        header_not_allowed      = 7
        separator_not_allowed   = 8
        filesize_not_allowed    = 9
        header_too_long         = 10
        dp_error_create         = 11
        dp_error_send           = 12
        dp_error_write          = 13
        unknown_dp_error        = 14
        access_denied           = 15
        dp_out_of_memory        = 16
        disk_full               = 17
        dp_timeout              = 18
        file_not_found          = 19
        dataprovider_exception  = 20
        control_flush_error     = 21
        not_supported_by_gui    = 22
        error_no_gui            = 23
        OTHERS                  = 24.
    IF sy-subrc <> 0. 
    ENDIF. 
  ENDMETHOD.

4. 标准方法输出Excel文件流(用作接口或后台)

        该方式直接生成Excel文件的十六进制文件流,可以用在FPM内表数据下载,后台发送邮件时作为附件,以及其它需要获取Excel文件的接口。

        第一种使用SALV相关类,主要类分别为cl_salv_export_tool_xls和cl_salv_bs_tt_util,两种实现方式,参考代码分别如下:

class-methods EXPORT_EXCEL 
    importing
      !ITAB type TABLE
      !FULL_PATH type STRING
      !FIELDCAT type LVC_T_FCAT.

  METHOD EXPORT_EXCEL.

    DATA: lr_result_data TYPE REF TO data,
          lr_data_line   TYPE REF TO data.

    DATA: lo_excel_export_service    TYPE REF TO cl_salv_export_tool_xls,
          lo_salv_export_column_conf TYPE REF TO if_salv_export_column_conf,
          lo_configuration           TYPE REF TO if_salv_export_configuration.

    DATA: lv_content   TYPE cl_salv_export_tool_xls=>y_file_content,
          lv_mime_type TYPE cl_salv_export_tool_xls=>y_mime_type,
          lv_filename  TYPE cl_salv_export_tool_xls=>y_filename, "#EC NEEDED
          lt_infos     TYPE cl_salv_export_tool_xls=>yt_msg, "#EC NEEDED
          lt_warnings  TYPE cl_salv_export_tool_xls=>yt_msg. "#EC NEEDED

    DATA: lo_table_rtti    TYPE REF TO cl_abap_tabledescr,
          lt_dfies         TYPE ddfields,
          ls_dfies         TYPE dfies,
          lo_field_catalog TYPE REF TO cl_abap_structdescr.

    DATA: lv_fieldname    TYPE string,
          ls_fieldcat     TYPE lvc_s_fcat,
          lv_headtext     TYPE string,
          lv_xstring      TYPE xstring,
          lv_bin_filesize TYPE i,
          lt_data_tab     TYPE TABLE OF solisti1.

    FIELD-SYMBOLS:  TYPE STANDARD TABLE.

    CREATE DATA lr_result_data LIKE itab.
    ASSIGN lr_result_data->* TO .
     = itab.

    lo_excel_export_service = cl_salv_export_tool_xls=>create_for_excel( lr_result_data ).

    lo_configuration = lo_excel_export_service->configuration( ).

    CREATE DATA lr_data_line LIKE LINE OF .
    lo_field_catalog ?= cl_abap_tabledescr=>describe_by_data_ref( lr_data_line ).
    lt_dfies = cl_salv_data_descr=>read_structdescr( lo_field_catalog ).
    LOOP AT lt_dfies INTO ls_dfies.

      " Text
      CLEAR ls_fieldcat.
      READ TABLE fieldcat INTO ls_fieldcat WITH KEY fieldname = ls_dfies-fieldname.

      IF ls_fieldcat-coltext IS NOT INITIAL.
        lv_headtext = ls_fieldcat-coltext.
      ELSE.
        lv_headtext = ls_dfies-scrtext_l.
      ENDIF.

      lv_fieldname = ls_dfies-fieldname.
      lo_salv_export_column_conf = lo_configuration->add_column(
      header_text = lv_headtext
      field_name = lv_fieldname
      display_type = if_salv_export_column_conf=>display_types-text_view
      ).

*    LO_SALV_EXPORT_COLUMN_CONF->SET_CELL_DESIGN(
*    EXPORTING
*      CELL_DESIGN = '61'
*      CELL_DESIGN_SRC_FIELD = LW_COMP_TAB-NAME
*    ).

    ENDLOOP.

    lo_excel_export_service->check_configuration(
      IMPORTING
        t_messages_info    = lt_infos
        t_messages_warning = lt_warnings
    ).

    TRY.
        lo_excel_export_service->read_result(
          IMPORTING
            content            = lv_content
            mime_type          = lv_mime_type
            filename           = lv_filename
            t_messages_info    = lt_infos
            t_messages_warning = lt_warnings
        ).
      CATCH cx_salv_export_error.                       "#EC NO_HANDLER
    ENDTRY.

    lv_xstring = lv_content.
    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        buffer          = lv_xstring
        append_to_table = ''
      IMPORTING
        output_length   = lv_bin_filesize
      TABLES
        binary_tab      = lt_data_tab.

    lv_filename = full_path..
    CALL METHOD cl_gui_frontend_services=>gui_download
      EXPORTING
        bin_filesize            = lv_bin_filesize
        filename                = lv_filename
        filetype                = 'BIN'
*       append                  = SPACE
*       write_field_separator   = SPACE
*       header                  = '00'
*       trunc_trailing_blanks   = SPACE
*       write_lf                = 'X'
*       col_select              = SPACE
*       col_select_mask         = SPACE
*       dat_mode                = SPACE
*       confirm_overwrite       = SPACE
*       no_auth_check           = SPACE
        codepage                = '4103'
*       ignore_cerr             = ABAP_TRUE
*       replacement             = '#'
*       write_bom               = SPACE
*       trunc_trailing_blanks_eol = 'X'
*       wk1_n_format            = SPACE
*       wk1_n_size              = SPACE
*       wk1_t_format            = SPACE
*       wk1_t_size              = SPACE
*       show_transfer_status    = 'X'
*       fieldnames              =
*       write_lf_after_last_line  = 'X'
*       virus_scan_profile      = '/SCET/GUI_DOWNLOAD'
*  IMPORTING
*       filelength              =
      CHANGING
        data_tab                = lt_data_tab
      EXCEPTIONS
        file_write_error        = 1
        no_batch                = 2
        gui_refuse_filetransfer = 3
        invalid_type            = 4
        no_authority            = 5
        unknown_error           = 6
        header_not_allowed      = 7
        separator_not_allowed   = 8
        filesize_not_allowed    = 9
        header_too_long         = 10
        dp_error_create         = 11
        dp_error_send           = 12
        dp_error_write          = 13
        unknown_dp_error        = 14
        access_denied           = 15
        dp_out_of_memory        = 16
        disk_full               = 17
        dp_timeout              = 18
        file_not_found          = 19
        dataprovider_exception  = 20
        control_flush_error     = 21
        not_supported_by_gui    = 22
        error_no_gui            = 23
        OTHERS                  = 24.
    IF sy-subrc <> 0.
    ENDIF.

  ENDMETHOD.
class-methods EXPORT_EXCEL 
    importing
      !ITAB type TABLE
      !FULL_PATH type STRING
      !FIELDCAT type LVC_T_FCAT .

  METHOD EXPORT_EXCEL.

    DATA: lo_data_ref TYPE REF TO data,
          lv_xstring  TYPE xstring,
          ls_fcat     TYPE lvc_s_fcat.

    DATA: lv_bin_filesize TYPE i,
          lv_filename     TYPE string,
          lt_data_tab     TYPE TABLE OF solisti1.

    FIELD-SYMBOLS:  TYPE ANY TABLE,
                    TYPE lvc_s_fcat.

    CREATE DATA lo_data_ref LIKE itab.

    CLEAR lv_xstring.
    ASSIGN lo_data_ref->* TO .
     = itab.

    TRY.
        cl_salv_table=>factory(
          IMPORTING r_salv_table = DATA(lo_table)
          CHANGING  t_table      =  ).

        DATA(lt_fcat) =
          cl_salv_controller_metadata=>get_lvc_fieldcatalog(
            r_columns      = lo_table->get_columns( )
            r_aggregations = lo_table->get_aggregations( ) ).

        LOOP AT lt_fcat ASSIGNING .
          READ TABLE fieldcat INTO ls_fcat WITH KEY fieldname = -fieldname.
          IF sy-subrc = 0.
            -reptext     = ls_fcat-reptext.
            -coltext     = ls_fcat-coltext.
            -seltext     = ls_fcat-seltext.
            -scrtext_s   = ls_fcat-scrtext_s.
            -scrtext_m   = ls_fcat-scrtext_m.
            -scrtext_l   = ls_fcat-scrtext_l.
          ENDIF.
        ENDLOOP.

        DATA(lo_result) =
          cl_salv_ex_util=>factory_result_data_table(
            r_data         = lo_data_ref
            t_fieldcatalog = lt_fcat ).

        cl_salv_bs_tt_util=>if_salv_bs_tt_util~transform(
          EXPORTING
            xml_type      = if_salv_bs_xml=>c_type_xlsx
            xml_version   = cl_salv_bs_a_xml_base=>get_version( )
            r_result_data = lo_result
            xml_flavour   = if_salv_bs_c_tt=>c_tt_xml_flavour_export
            gui_type      = if_salv_bs_xml=>c_gui_type_gui
          IMPORTING
            xml           = lv_xstring ).
      CATCH cx_root.
        CLEAR lv_xstring.
    ENDTRY.

    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        buffer          = lv_xstring
        append_to_table = ''
      IMPORTING
        output_length   = lv_bin_filesize
      TABLES
        binary_tab      = lt_data_tab.

    lv_filename = full_path..
    CALL METHOD cl_gui_frontend_services=>gui_download
      EXPORTING
        bin_filesize            = lv_bin_filesize
        filename                = lv_filename
        filetype                = 'BIN'
*       append                  = SPACE
*       write_field_separator   = SPACE
*       header                  = '00'
*       trunc_trailing_blanks   = SPACE
*       write_lf                = 'X'
*       col_select              = SPACE
*       col_select_mask         = SPACE
*       dat_mode                = SPACE
*       confirm_overwrite       = SPACE
*       no_auth_check           = SPACE
        codepage                = '4103'
*       ignore_cerr             = ABAP_TRUE
*       replacement             = '#'
*       write_bom               = SPACE
*       trunc_trailing_blanks_eol = 'X'
*       wk1_n_format            = SPACE
*       wk1_n_size              = SPACE
*       wk1_t_format            = SPACE
*       wk1_t_size              = SPACE
*       show_transfer_status    = 'X'
*       fieldnames              =
*       write_lf_after_last_line  = 'X'
*       virus_scan_profile      = '/SCET/GUI_DOWNLOAD'
*  IMPORTING
*       filelength              =
      CHANGING
        data_tab                = lt_data_tab
      EXCEPTIONS
        file_write_error        = 1
        no_batch                = 2
        gui_refuse_filetransfer = 3
        invalid_type            = 4
        no_authority            = 5
        unknown_error           = 6
        header_not_allowed      = 7
        separator_not_allowed   = 8
        filesize_not_allowed    = 9
        header_too_long         = 10
        dp_error_create         = 11
        dp_error_send           = 12
        dp_error_write          = 13
        unknown_dp_error        = 14
        access_denied           = 15
        dp_out_of_memory        = 16
        disk_full               = 17
        dp_timeout              = 18
        file_not_found          = 19
        dataprovider_exception  = 20
        control_flush_error     = 21
        not_supported_by_gui    = 22
        error_no_gui            = 23
        OTHERS                  = 24.
    IF sy-subrc <> 0.
    ENDIF.
  ENDMETHOD.

        第二种主要使用类cl_fdt_xl_spreadsheet, 参考代码如下:

  class-methods EXPORT_EXCEL 
    importing
      !ITAB type TABLE
      !FULL_PATH type STRING
      !FIELDCAT type LVC_T_FCAT .
      
  METHOD EXPORT_EXCEL_FROM_DATA_OTHER.

    DATA: lref_string TYPE REF TO cl_abap_datadescr,
          lref_data   TYPE REF TO data,
          lt_column   TYPE if_fdt_doc_spreadsheet=>t_column,
          ls_column   TYPE LINE OF if_fdt_doc_spreadsheet=>t_column.

    DATA:
      lr_tabdescr TYPE REF TO cl_abap_structdescr,
      lr_data     TYPE REF TO data,
      lt_dfies    TYPE ddfields,
      ls_dfies    TYPE dfies,
      lt_fieldcat TYPE lvc_t_fcat,
      ls_fieldcat TYPE lvc_s_fcat.

    DATA: lv_filename TYPE string,
          lv_xstring  TYPE xstring,
          lv_lengcth  TYPE i,
          lv_index    TYPE i,
          lt_bin_data TYPE TABLE OF solisti1.

    DATA: ls_fieldcat_input TYPE lvc_s_fcat.

* Field symbols declaration
    FIELD-SYMBOLS:  TYPE STANDARD TABLE,
                        TYPE any,
                       TYPE any.

    CREATE DATA lr_data LIKE LINE OF itab.
    ASSIGN lr_data->* TO .

* Create data object
    CREATE DATA lref_data LIKE itab.

* Assign download contents to field symbol
    ASSIGN lref_data->* TO .
     = itab.

    " 字段清单
    lr_tabdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ).
    lt_dfies = cl_salv_data_descr=>read_structdescr( lr_tabdescr ).
    LOOP AT lt_dfies INTO ls_dfies.
      lv_index = sy-tabix.

      CLEAR ls_fieldcat.
      READ TABLE fieldcat INTO ls_fieldcat WITH KEY fieldname = ls_dfies-fieldname.

      ASSIGN COMPONENT ls_dfies-fieldname OF STRUCTURE  TO .
      IF sy-subrc = 0.
        lref_string ?= cl_abap_datadescr=>describe_by_data(  ).

*     Prepare structure for header text
        ls_column-id           = lv_index.
        ls_column-name         = ls_dfies-fieldname.

        IF ls_fieldcat-coltext IS NOT INITIAL.
          ls_column-display_name = ls_fieldcat-coltext.
        ELSE.
          ls_column-display_name = ls_dfies-scrtext_l.
        ENDIF.

*        ls_column-is_result    = abap_true.
        ls_column-type         = lref_string.
*     Append structure prepared to internal table
        APPEND ls_column TO lt_column.
      ENDIF.

    ENDLOOP.

* Call class method to convert data to be downloaded to .xlsx compatible xstring
    cl_fdt_xl_spreadsheet=>if_fdt_doc_spreadsheet~create_document(
          EXPORTING
            itab         = lref_data
            iv_call_type = 1
            columns      = lt_column
          RECEIVING
            xdocument    = lv_xstring ).

    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        buffer          = lv_xstring
        append_to_table = ''
      IMPORTING
        output_length   = lv_lengcth
      TABLES
        binary_tab      = lt_bin_data.

    lv_filename = full_path.
    CALL METHOD cl_gui_frontend_services=>gui_download
      EXPORTING
        bin_filesize            = lv_lengcth
        filename                = lv_filename
        filetype                = 'BIN'
*       append                  = SPACE
*       write_field_separator   = SPACE
*       header                  = '00'
*       trunc_trailing_blanks   = SPACE
*       write_lf                = 'X'
*       col_select              = SPACE
*       col_select_mask         = SPACE
*       dat_mode                = SPACE
        confirm_overwrite       = space
*       no_auth_check           = SPACE
*       codepage                = '4103'
*       ignore_cerr             = ABAP_TRUE
*       replacement             = '#'
*       write_bom               = SPACE
*       trunc_trailing_blanks_eol = 'X'
*       wk1_n_format            = SPACE
*       wk1_n_size              = SPACE
*       wk1_t_format            = SPACE
*       wk1_t_size              = SPACE
*       show_transfer_status    = 'X'
*       fieldnames              =
*       write_lf_after_last_line  = 'X'
*       virus_scan_profile      = '/SCET/GUI_DOWNLOAD'
*  IMPORTING
*       filelength              =
      CHANGING
        data_tab                = lt_bin_data
      EXCEPTIONS
        file_write_error        = 1
        no_batch                = 2
        gui_refuse_filetransfer = 3
        invalid_type            = 4
        no_authority            = 5
        unknown_error           = 6
        header_not_allowed      = 7
        separator_not_allowed   = 8
        filesize_not_allowed    = 9
        header_too_long         = 10
        dp_error_create         = 11
        dp_error_send           = 12
        dp_error_write          = 13
        unknown_dp_error        = 14
        access_denied           = 15
        dp_out_of_memory        = 16
        disk_full               = 17
        dp_timeout              = 18
        file_not_found          = 19
        dataprovider_exception  = 20
        control_flush_error     = 21
        not_supported_by_gui    = 22
        error_no_gui            = 23
        OTHERS                  = 24.
    IF sy-subrc <> 0.
    ENDIF.
  ENDMETHOD.

5. Transformation 生成xml格式的Excel(.XLS)

        将Excel模版文件另存为xml格式的Excel文件

        新建transformation(xslt),并将上述保存的xml文件内容复制到下图红框处

ABAP Excel处理-内表导出为Excel文件_第1张图片

        将xml文件中数据部分重新绑定数据源为transformation传入内表,生成对应xml文件,然后下载后缀为.xls的Excel文件。

        如下附加对应transformation语法处理。

循环处理内表(TABLE为传入内表)

 ...... 

数据据绑定(如果在循环内,父节点已声明路径,仅用字段绑定,已使用variable声明的同理)



分支

            
              
              ......
              
              
              ......
              
            

变量声明及使用

 

使用大括号表示使用值

ss:ExpandedRowCount="{//APPROVE/ALLROWS}"

abap 方法调用:

          

6.  ABAP2XLSX 和 XLSX Workbench

        ABAP2XLSX 参考地址:abap2xlsx - ABAP Development - Community Wiki

        Git包中有很多demo以供参考,算是目前功能最全的使用abap处理Excel的git源码,代码原理基于XLSX文件的结构,如下图XLSX文件是包含一些xml文件的压缩包。

ABAP Excel处理-内表导出为Excel文件_第2张图片

        因此ABAP2XLSX 处理Excel文件时由于版本的不同,可能会出现一些小bug,找到问题,调整对应xml文件的生成即可。

        XLSX Workbench 参考地址:XLSX Workbench for SAP(ABAP) – tool for exporting data to Excel | SAP Blogs

        图形化界面操作,较为友好。

三、总结

        内表数据生成excel文件的需求中,如果不要求格式,直接下载内表为Excel表格,可以考虑使用标准类,相对更方便,使用也比较友好,既可以在gui端使用也可以在FPM等web端使用。如果带有较为复杂的格式,gui端建议使用DOI,提前上传模版到OAOR,然后填充数据,而且对比起OLE更加友好。如果是web端需求或者格式要求更复杂,建议使用ABAP2XLSX。

你可能感兴趣的:(功能,ABAP,速食,abap)