使用 CL_FDT_XL_SPREADSHEET 是在ABAP中处理 .xlsx 格式文件的一种标准方法,这个类基于XML技术,能够在服务器端直接解析 Excel 文件,无需前端 Excel 组件。
下面是一个完整的代码示例,演示如何从本地选择 .xlsx 文件,读取其内容,并转换到你指定的内表格式。代码实现了通用性,能够将数据根据目标内表的格式进行导入。Excel 文档的字段结构按顺序,需要与内表的结构相同。
本例假设需要导入会计科目主数据。
abao
report zfif001.
types: begin of ty_output,
company_code type bukrs, " 公司代码
account_number type saknr, " account number
chart_of_accounts type ktopl, " chart of account
glaccount_type type glaccount_coa_data-glaccount_type, " g/l account type
ktoks type glaccount_coa_data-ktoks, " account group
txt20 type glaccount_name_data-txt20,
txt50 type glaccount_name_data-txt50,
bilkt type glaccount_coa_data-bilkt, " 集团科目号
gr_acc_desc type string, " 集团科目描述
waers type glaccount_ccode_data-waers, " currency
xsalh type glaccount_ccode_data-xsalh, " only local currency
mwskz type glaccount_ccode_data-mwskz, " tax type
xmwno type glaccount_ccode_data-xmwno, " 允许含/不含税过账
mitkz type glaccount_ccode_data-mitkz, " 统驭科目类型
xopvw type glaccount_ccode_data-xopvw, " 未清项目管理
zuawa type glaccount_ccode_data-zuawa, " 排序码
katyp type GLACCOUNT_CAREA_DATA-katyp, " 成本要素类型
fstag type glaccount_ccode_data-fstag, " 字段状态码
xintb type glaccount_ccode_data-xintb, " 只能自动过账
xmitk type glaccount_ccode_data-xmitk, " 统驭科目是否可允许输入
end of ty_output.
selection-screen begin of block b1 with frame title text-t00.
parameters: p_file type rlgrap-filename.
selection-screen end of block b1.
*selection-screen function key 1.
at selection-screen on value-request for p_file.
perform frm_get_filepath.
start-of-selection.
perform frm_excel_to_itab.
**********************************************************************
* 获取上载的文件路径
**********************************************************************
form frm_get_filepath .
data: lv_action type i,
lt_filetable type filetable,
lv_rc type i.
call method cl_gui_frontend_services=>file_open_dialog
exporting
window_title = '选择上载的文件名'
default_extension = '.xlsx'
file_filter = 'Excel文件(*.xlsx)|*.xlsx'
multiselection = ''
changing
file_table = lt_filetable
rc = lv_rc
exceptions
others = 1.
if lv_action ne 0.
message text-m01 type 'S' display like 'E'.
exit.
endif.
read table lt_filetable assigning field-symbol(<ls_file>) index 1.
p_file = <ls_file>-filename.
endform.
**********************************************************************
* Excel文件导入到内表
**********************************************************************
form frm_excel_to_itab.
* 文件选择相关变量
data: lv_filename type string, " 文件完整路径
lv_filelength type i.
* Excel处理相关变量
data: lt_raw_data type standard table of raw255, " 二进制数据表
lv_xstring type xstring, " XSTRING数据
lo_excel type ref to cl_fdt_xl_spreadsheet, " Excel对象
lt_worksheetnames type table of string, " 工作表名称表
lt_data type ref to data, " 动态内表引用
lx_exception type ref to cx_fdt_excel_core. " 异常对象
* 动态处理相关变量
field-symbols: <dyn_table> type standard table,
<dyn_wa> type any,
<dyn_field> type any,
<comp> type any.
* 定义动态内表的结构,用于按列号访问字段
data: lo_struct type ref to cl_abap_structdescr,
lt_comp type cl_abap_structdescr=>component_table.
data: lt_output type standard table of ty_output. " 目标内表
data: ls_output like line of lt_output.
**----------------------------------------------------------------------
** 1. 上传文件
**----------------------------------------------------------------------
lv_filename = p_file.
call method cl_gui_frontend_services=>gui_upload
exporting
filename = lv_filename
filetype = 'BIN' " 对于.xlsx文件,必须使用BIN模式
importing
filelength = lv_filelength
changing
data_tab = lt_raw_data
exceptions
others = 1.
if sy-subrc <> 0.
message '文件上传失败, 请检查文件是否为打开状态' type 'E'.
endif.
*----------------------------------------------------------------------
* 2. 将二进制表转换为XSTRING
*----------------------------------------------------------------------
call function 'SCMS_BINARY_TO_XSTRING'
exporting
input_length = lv_filelength
importing
buffer = lv_xstring
tables
binary_tab = lt_raw_data
exceptions
failed = 1
others = 2.
if sy-subrc <> 0.
message '数据转换失败' type 'E'.
endif.
*----------------------------------------------------------------------
* 3. 实例化 CL_FDT_XL_SPREADSHEET 类
*----------------------------------------------------------------------
try.
lo_excel = new #( document_name = lv_filename
xdocument = lv_xstring ).
catch cx_fdt_excel_core into lx_exception.
message lx_exception->get_text( ) type 'E'.
endtry.
*----------------------------------------------------------------------
* 4. 获取工作表名称
*----------------------------------------------------------------------
lo_excel->if_fdt_doc_spreadsheet~get_worksheet_names(
importing
worksheet_names = lt_worksheetnames ).
if lt_worksheetnames is initial.
message 'Excel文件中没有工作表' type 'E'.
endif.
*----------------------------------------------------------------------
* 5. 读取工作表数据到动态内表
*----------------------------------------------------------------------
try.
lt_data = lo_excel->if_fdt_doc_spreadsheet~get_itab_from_worksheet(
lt_worksheetnames[ 1 ] ).
catch cx_fdt_excel_core into lx_exception.
message lx_exception->get_text( ) type 'E'.
endtry.
*----------------------------------------------------------------------
* 6. 转换为指定格式内表
*----------------------------------------------------------------------
* 将动态引用分配给字段符号
assign lt_data->* to <dyn_table>.
* 获取目标内表的结构描述
clear ls_output.
lo_struct ?= cl_abap_typedescr=>describe_by_data( ls_output ).
lt_comp = lo_struct->get_components( ).
* 循环处理动态内表中的每一行(从第二行开始)
loop at <dyn_table> assigning <dyn_wa> from 2 .
clear ls_output.
" 内循环:将动态行的每个字段映射到 ls_output 的对应字段
do lines( lt_comp ) times.
data(lv_index) = sy-index. " 当前列号(从1开始)
" 获取动态行的当前列的值
assign component lv_index of structure <dyn_wa> to <dyn_field>.
if sy-subrc <> 0.
continue.
endif.
" 获取目标结构 ls_output 的第 lv_index 个字段
read table lt_comp into data(ls_comp) index lv_index.
if sy-subrc = 0.
assign component ls_comp-name of structure ls_output to <comp>.
if sy-subrc = 0.
<comp> = <dyn_field>. " 将Excel单元格的值赋给目标字段
endif.
endif.
enddo.
append ls_output to lt_output. " 将转换后的行追加到目标内表
endloop.
cl_demo_output=>display( lt_output ).
endform.
使用说明
文件格式限制:该类只支持 .xlsx 格式,不支持旧的 .xls 。
SAP官方立场:这个类最初是为 BRFplus 设计的,虽然可以用于读取 Excel,但SAP官方并不推荐在自定义程序中作为首选方案,未来版本可能会有变更 。
性能考量:对于非常大的数据集(如超过15万行),该类性能可能不佳,甚至报错 。
替代方案:如果需要更强大、更稳定的 Excel 处理功能,可以考虑开源的 abap2xlsx 框架 。