abap读取csv文件到内表
在 ABAP 中,可以使用字符串函数和逻辑处理来分割 CSV 文件。
由于某些字段值可能包含逗号,按照分割符分割出来的数据列就会出现对不齐的现象,也就是某些数据被拆分成了两列或者多列,你需要在处理时考虑这种情况。
上传的csv文件内容:
ID,姓名,年龄,地址
1,张三,25,"北京,中国"
2,李四,30,"上海,中国"
3,王五,28,"广州,中国"
一、选择屏幕-参数设定
首先进入se38
创建一个程序,创建一个程序名为ztest_split_csv01
程序。
设定好上传文件的参数。
*& Report ZTEST_SPLIT_CSV01
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ztest_split_csv01.
*--------------------------------------------------------------------*
* 选择屏幕
*--------------------------------------------------------------------*
PARAMETERS:p_path TYPE localfile.
* F4值帮助
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path.
CALL FUNCTION 'F4_FILENAME'
* EXPORTING
* PROGRAM_NAME = SYST-CPROG
* DYNPRO_NUMBER = SYST-DYNNR
* FIELD_NAME = ' '
IMPORTING
file_name = p_path.
二、获取csv文件数据 (按行)
自定义的csv文件,编码格式是utf-8
,但是使用gui_upload
函数读取文件数据,会出现中文乱码,因此需要给形参codepage
指定编码格式。
2.1 获取codepage
三种方式获取codepage
:
-
使用语言编码维护表
DATA:lv_codepage TYPE abap_encoding. SELECT SINGLE lv_codepage INTO codepage FROM tcp00a WHERE cpattr = 'UTF-8'.
-
使用
SCP_CODEPAGE_BY_EXTERNAL_NAME
函数DATA:lv_codepage TYPE abap_encoding. CALL FUNCTION 'SCP_CODEPAGE_BY_EXTERNAL_NAME' EXPORTING external_name = 'UTF-8' * KIND = 'H' IMPORTING SAP_CODEPAGE = lv_codepage * EXCEPTIONS * NOT_FOUND = 1 * OTHERS = 2 .
-
使用
cl_abap_codepage=>sap_codepage
类方法DATA:lv_codepage TYPE abap_encoding. lv_codepage = cl_abap_codepage=>sap_codepage( 'UTF-8' ).
2.2 gui_upload
* 定义类型
DATA: lt_csv_lines TYPE STANDARD TABLE OF string, "保存读取的数据行
lv_csv_data TYPE string,
lv_filename TYPE string,
lv_codepage TYPE abap_encoding. "编码
lv_filename = p_path.
*--------------------------------------------------------------------*
* 主程序
*--------------------------------------------------------------------*
START-OF-SELECTION.
"获取数据行
PERFORM get_csv_lines.
FORM get_csv_lines .
" 1. 获取utf-8编码格式
"SELECT SINGLE lv_codepage INTO codepage FROM tcp00a WHERE cpattr = 'UTF-8'.
lv_codepage = cl_abap_codepage=>sap_codepage( 'UTF-8' ).
" 2. 获取数据行
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
filename = lv_filename
* FILETYPE = 'ASC'
* HAS_FIELD_SEPARATOR = ' '
* HEADER_LENGTH = 0
* READ_BY_LINE = 'X'
* DAT_MODE = ' '
codepage = lv_codepage
* IGNORE_CERR = ABAP_TRUE
* REPLACEMENT = '#'
* CHECK_BOM = ' '
* VIRUS_SCAN_PROFILE =
* NO_AUTH_CHECK = ' '
* IMPORTING
* FILELENGTH =
* HEADER =
TABLES
data_tab = lt_csv_lines
* CHANGING
* ISSCANPERFORMED = ' '
* EXCEPTIONS
* FILE_OPEN_ERROR = 1
* FILE_READ_ERROR = 2
* NO_BATCH = 3
* GUI_REFUSE_FILETRANSFER = 4
* INVALID_TYPE = 5
* NO_AUTHORITY = 6
* UNKNOWN_ERROR = 7
* BAD_DATA_FORMAT = 8
* HEADER_NOT_ALLOWED = 9
* SEPARATOR_NOT_ALLOWED = 10
* HEADER_TOO_LONG = 11
* UNKNOWN_DP_ERROR = 12
* ACCESS_DENIED = 13
* DP_OUT_OF_MEMORY = 14
* DISK_FULL = 15
* DP_TIMEOUT = 16
* OTHERS = 17
.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ENDFORM.
三、转换csv数据行 (csv_to_structure)
- 1、声明一个
cl_rsda_csv_converter
对象; - 2、调用
cl_rsda_csv_converter=>create
创建一个实例lo_csv
; - 3、通过实例对象
lo_csv
调用实例方法csv_to_structure
,将csv文本数据行转换成定义的数据类型(结构体)。
"分割行数据中的值
PERFORM converter_csv_data.
* 子程序
FORM converter_csv_data .
"实例csv转换器
DATA:lo_csv TYPE REF TO cl_rsda_csv_converter.
CALL METHOD cl_rsda_csv_converter=>create
* EXPORTING
* i_delimiter = C_DEFAULT_DELIMITER
* i_separator = C_DEFAULT_SEPARATOR
* i_escape =
* i_line_separator = CL_ABAP_CHAR_UTILITIES=>NEWLINE
RECEIVING
r_r_conv = lo_csv.
LOOP AT lt_csv_lines INTO lv_csv_data.
"跳过第一次循环
AT FIRST.
CONTINUE.
ENDAT.
"将csv转abap数据结构
CALL METHOD lo_csv->csv_to_structure
EXPORTING
i_data = lv_csv_data
IMPORTING
e_s_data = wa_user.
"分割好的数据结构插入内表
APPEND wa_user TO it_user.
WRITE: / wa_user-id, wa_user-name, wa_user-age, wa_user-address.
CLEAR wa_user.
ENDLOOP.
ENDFORM.
四、完整的demo
该程序执行的结果:
完整代码如下:
*&---------------------------------------------------------------------*
*& Report ZTEST_SPLIT_CSV01
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ztest_split_csv01.
* 定义类型
DATA: lt_csv_lines TYPE STANDARD TABLE OF string, "保存读取的数据行
lv_csv_data TYPE string,
lv_filename TYPE string,
lv_codepage TYPE abap_encoding. "编码
TYPES:BEGIN OF ty_user,
id TYPE i,
name TYPE string,
age TYPE i,
address TYPE string,
END OF ty_user.
DATA:it_user TYPE STANDARD TABLE OF ty_user,
wa_user TYPE ty_user.
*--------------------------------------------------------------------*
* 选择屏幕
*--------------------------------------------------------------------*
PARAMETERS:p_path TYPE localfile.
* F4值帮助
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path.
CALL FUNCTION 'F4_FILENAME'
* EXPORTING
* PROGRAM_NAME = SYST-CPROG
* DYNPRO_NUMBER = SYST-DYNNR
* FIELD_NAME = ' '
IMPORTING
file_name = p_path.
lv_filename = p_path.
*--------------------------------------------------------------------*
* 主程序
*--------------------------------------------------------------------*
START-OF-SELECTION.
"获取数据行
PERFORM get_csv_lines.
"分割行数据中的值
PERFORM converter_csv_data.
*&---------------------------------------------------------------------*
*& Form get_csv_lines
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM get_csv_lines.
" 1. 获取utf-8编码格式
* SELECT SINGLE cpcodepage INTO lv_codepage FROM tcp00a WHERE cpattr = 'UTF-8'.
lv_codepage = cl_abap_codepage=>sap_codepage( 'UTF-8' ).
" 2. 获取数据行
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
filename = lv_filename
* FILETYPE = 'ASC'
* HAS_FIELD_SEPARATOR = ' '
* HEADER_LENGTH = 0
* READ_BY_LINE = 'X'
* DAT_MODE = ' '
codepage = lv_codepage
* IGNORE_CERR = ABAP_TRUE
* REPLACEMENT = '#'
* CHECK_BOM = ' '
* VIRUS_SCAN_PROFILE =
* NO_AUTH_CHECK = ' '
* IMPORTING
* FILELENGTH =
* HEADER =
TABLES
data_tab = lt_csv_lines
* CHANGING
* ISSCANPERFORMED = ' '
* EXCEPTIONS
* FILE_OPEN_ERROR = 1
* FILE_READ_ERROR = 2
* NO_BATCH = 3
* GUI_REFUSE_FILETRANSFER = 4
* INVALID_TYPE = 5
* NO_AUTHORITY = 6
* UNKNOWN_ERROR = 7
* BAD_DATA_FORMAT = 8
* HEADER_NOT_ALLOWED = 9
* SEPARATOR_NOT_ALLOWED = 10
* HEADER_TOO_LONG = 11
* UNKNOWN_DP_ERROR = 12
* ACCESS_DENIED = 13
* DP_OUT_OF_MEMORY = 14
* DISK_FULL = 15
* DP_TIMEOUT = 16
* OTHERS = 17
.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form converter_csv_data
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM converter_csv_data .
"实例csv转换器
DATA:lo_csv TYPE REF TO cl_rsda_csv_converter.
CALL METHOD cl_rsda_csv_converter=>create
* EXPORTING
* i_delimiter = C_DEFAULT_DELIMITER
* i_separator = C_DEFAULT_SEPARATOR
* i_escape =
* i_line_separator = CL_ABAP_CHAR_UTILITIES=>NEWLINE
RECEIVING
r_r_conv = lo_csv.
LOOP AT lt_csv_lines INTO lv_csv_data.
"跳过第一次循环
AT FIRST.
CONTINUE.
ENDAT.
"将csv转abap数据结构
CALL METHOD lo_csv->csv_to_structure
EXPORTING
i_data = lv_csv_data
IMPORTING
e_s_data = wa_user.
APPEND wa_user TO it_user.
WRITE: / wa_user-id, wa_user-name, wa_user-age, wa_user-address.
CLEAR wa_user.
ENDLOOP.
ENDFORM.