(ABAP 코드) 엑셀 업로드 - CLASS 사용 (라인무한)
*&---------------------------------------------------------------------*
*& Report ZEXCEL_UPLOAD_T
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZEXCEL_UPLOAD_T.
"==================================================================================================================
" Class
CLASS LCL_EXCEL_UPLOADER DEFINITION.
PUBLIC SECTION.
DATA: HEADER_ROWS_COUNT TYPE I. " 헤더의 Row 갯수
DATA: MAX_ROWS TYPE I. " 최대 Rows - Constructor에서 9999로 셋팅 됨.
DATA: FILENAME TYPE LOCALFILE. " 파일 이름
METHODS:
CONSTRUCTOR.
METHODS:
UPLOAD CHANGING CT_DATA TYPE ANY TABLE. " 엑셀 파일 저장할 테이블
PRIVATE SECTION.
DATA: LV_TOT_COMPONENTS TYPE I. " 엑셀로 변환 될 테이블의 Column 갯수를 저장.
METHODS:
DO_UPLOAD
IMPORTING
LV_BEGIN TYPE I " 시작 라인
LV_END TYPE I " 마지막 라인
EXPORTING
RV_EMPTY TYPE FLAG " 엑셀 파일 읽기 종료 플래그
CHANGING
CT_DATA TYPE STANDARD TABLE. " 엑셀 파일 저장할 테이블
ENDCLASS.
CLASS LCL_EXCEL_UPLOADER IMPLEMENTATION.
METHOD CONSTRUCTOR.
MAX_ROWS = 9999. " 9999 <- ALSM_EXCEL_TO_INTERNAL_TABLE 함수가 최대로 읽을 수 있는 라인 갯수.
" Object 생성 시에 9999로 세팅되며, 추후에 MAX_ROWS 갯수를 바꿀 수 있다.
ENDMETHOD.
METHOD UPLOAD.
DATA: LO_STRUCT TYPE REF TO CL_ABAP_STRUCTDESCR,
LO_TABLE TYPE REF TO CL_ABAP_TABLEDESCR,
LT_COMP TYPE CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE.
" RTTS를 사용하여 CT_DATA의 구조 파악.
LO_TABLE ?= CL_ABAP_STRUCTDESCR=>DESCRIBE_BY_DATA( CT_DATA ) .
LO_STRUCT ?= LO_TABLE->GET_TABLE_LINE_TYPE( ).
" CT_DATA의 필드들을 가져옴( 필드마다 행에 저장 됨 ).
LT_COMP = LO_STRUCT->GET_COMPONENTS( ).
" 필드의 갯수를 저장.
LV_TOT_COMPONENTS = LINES( LT_COMP ).
"
DATA: LV_EMPTY TYPE FLAG, " 엑셀 파일 읽기 종료 플래그
LV_BEGIN TYPE I, " 엑셀 시작 라인
LV_END TYPE I. " 엑세 종료 라인.
LV_BEGIN = HEADER_ROWS_COUNT + 1. " 엑셀 해더의 Row 갯수 + 1 -> 헤더 다음부터 읽는다는 소리.
LV_END = MAX_ROWS. " 9999 <- ALSM_EXCEL_TO_INTERNAL_TABLE 함수가 최대로 읽을 수 있는 라인 갯수.
" 엑셀 파일 읽기 종료 플래그가 셋팅 될 때 까지 읽음.
WHILE LV_EMPTY IS INITIAL.
DO_UPLOAD(
EXPORTING
LV_BEGIN = LV_BEGIN
LV_END = LV_END
IMPORTING
RV_EMPTY = LV_EMPTY
CHANGING
CT_DATA = CT_DATA
).
LV_BEGIN = LV_END + 1. " 마지막 읽은 라인 + 1 -> 마지막 읽은 라인 다음 라인부터 읽음
LV_END = LV_BEGIN + MAX_ROWS. " 읽기 시작하는 ROW의 라인 + 9999 -> 9999라인만 읽겠다는 소리
ENDWHILE.
ENDMETHOD.
METHOD DO_UPLOAD.
DATA: LI_EXCELDATA TYPE STANDARD TABLE OF ALSMEX_TABLINE. " 엑셀 데이터 저장 Table
DATA: LS_EXCELDATA LIKE LINE OF LI_EXCELDATA. " 엑셀 데이터 저장 Struct
DATA: LV_TOT_ROWS TYPE I. " CT_DATA에 정상적으로 삽입 된 데이터 수
DATA: LV_PACKET TYPE I. " 읽을 데이터의 총 라인 수
FIELD-SYMBOLS: <FS_WA> TYPE ANY,
<FS_VAL> TYPE ANY.
" 엑셀 데이터 읽음
CALL FUNCTION 'ALSM_EXCEL_TO_INTERNAL_TABLE'
EXPORTING
filename = FILENAME
i_begin_col = 1
i_begin_row = LV_BEGIN
i_end_col = LV_TOT_COMPONENTS
i_end_row = LV_END
TABLES
intern = LI_EXCELDATA
EXCEPTIONS
INCONSISTENT_PARAMETERS = 1
UPLOAD_OLE = 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.
RV_EMPTY = 'X'.
EXIT.
ENDIF.
" 읽은 데이터가 없을 경우,
IF LI_EXCELDATA IS INITIAL.
RV_EMPTY = 'X'.
EXIT.
ENDIF.
LOOP AT LI_EXCELDATA INTO LS_EXCELDATA.
" 새로운 Row 추가
AT NEW ROW.
APPEND INITIAL LINE TO CT_DATA ASSIGNING <FS_WA>.
ENDAT.
" Field 데이터 추가
ASSIGN COMPONENT LS_EXCELDATA-COL OF STRUCTURE <FS_WA> TO <FS_VAL>.
IF SY-SUBRC EQ 0.
<FS_VAL> = LS_EXCELDATA-VALUE.
ENDIF.
" Row의 마지막 값일 경우, Row 갯수 추가
AT END OF ROW.
IF <FS_WA> IS NOT INITIAL.
LV_TOT_ROWS = LV_TOT_ROWS + 1.
ENDIF.
ENDAT.
ENDLOOP.
" 데이터의 읽은 총 개수 (LV_END - LV_BEGIN)가 데이터를 읽고 처리한 갯수(LV_TOT_ROWS) 보다 클 경우,
" 앞으로 더이상 읽을 데이터가 없다는 의미 이미로 RV_EMPTY 에 X 세팅.
LV_PACKET = LV_END - LV_BEGIN.
IF LV_TOT_ROWS LT LV_PACKET.
RV_EMPTY = 'X'.
ENDIF.
ENDMETHOD.
ENDCLASS.
"=============================================================================================================================
" 실제로직
TYPES: BEGIN OF TS_DATA,
F1 TYPE CHAR10,
F2 TYPE CHAR10,
F3 TYPE CHAR10,
END OF TS_DATA,
TT_DATA TYPE STANDARD TABLE OF TS_DATA.
DATA: GT_DATA TYPE TT_DATA.
DATA: LO_UPLOADER TYPE REF TO LCL_EXCEL_UPLOADER.
PARAMETERS: P_FNAME TYPE RLGRAP-FILENAME.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR P_FNAME.
PERFORM GET_FILEPATH.
START-OF-SELECTION.
CREATE OBJECT LO_UPLOADER. " Uploader 클래스 생성
LO_UPLOADER->MAX_ROWS = 10. " 최대 읽을 갯수 세팅
LO_UPLOADER->FILENAME = P_FNAME. " 파일이름 세팅
LO_UPLOADER->HEADER_ROWS_COUNT = 1. " 엑셀파일의 헤더라인 갯수 세팅
LO_UPLOADER->UPLOAD( CHANGING CT_DATA = GT_DATA ). " 업로드.
BREAK-POINT.
*&---------------------------------------------------------------------*
*& Form GET_FILEPATH
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM get_filepath .
DATA: ls_filetab TYPE file_table,
lt_filetab TYPE filetable,
lv_rc TYPE i.
CALL METHOD cl_gui_frontend_services=>file_open_dialog
CHANGING
file_table = lt_filetab
rc = lv_rc
EXCEPTIONS
file_open_dialog_failed = 1
cntl_error = 2
error_no_gui = 3
not_supported_by_gui = 4
OTHERS = 5.
IF sy-subrc NE 0.
BREAK-POINT.
ENDIF.
READ TABLE lt_filetab INTO ls_filetab INDEX 1.
IF sy-subrc EQ 0.
CLEAR: P_FNAME.
P_FNAME = ls_filetab-filename.
ELSE.
BREAK-POINT.
ENDIF.
ENDFORM.