目录
一、概述
二、内表导出为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文件的示例代码,以供参考。
参数为内表数据,下载地址全路径和字段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.
参数为内表数据,下载地址全路径和字段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下载
字段数据拼接生成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.
该方式直接生成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.
将Excel模版文件另存为xml格式的Excel文件
新建transformation(xslt),并将上述保存的xml文件内容复制到下图红框处
将xml文件中数据部分重新绑定数据源为transformation传入内表,生成对应xml文件,然后下载后缀为.xls的Excel文件。
如下附加对应transformation语法处理。
循环处理内表(TABLE为传入内表)
......
数据据绑定(如果在循环内,父节点已声明路径,仅用字段绑定,已使用variable声明的同理)
分支
......
......
变量声明及使用
使用大括号表示使用值
ss:ExpandedRowCount="{//APPROVE/ALLROWS}"
abap 方法调用:
ABAP2XLSX 参考地址:abap2xlsx - ABAP Development - Community Wiki
Git包中有很多demo以供参考,算是目前功能最全的使用abap处理Excel的git源码,代码原理基于XLSX文件的结构,如下图XLSX文件是包含一些xml文件的压缩包。
因此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。