SAP/ABAP 코드

(ABAP 코드) 엑셀 업로드 - CLASS 사용 (라인무한)

haramang 2022. 2. 8. 10:57

*&---------------------------------------------------------------------*
*& Report ZEXCEL_UPLOAD_T
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZEXCEL_UPLOAD_T.

"==================================================================================================================
" Class

CLASS LCL_EXCEL_UPLOADER DEFINITION.
  PUBLIC SECTION.
    DATAHEADER_ROWS_COUNT TYPE I.              " 헤더의 Row 갯수
    DATAMAX_ROWS TYPE I.                       " 최대 Rows - Constructor에서 9999로 셋팅 됨.
    DATAFILENAME TYPE LOCALFILE.               " 파일 이름

    METHODS:
      CONSTRUCTOR.
    METHODS:
      UPLOAD CHANGING CT_DATA TYPE ANY TABLE.    " 엑셀 파일 저장할 테이블


  PRIVATE SECTION.
    DATALV_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.
    DATALO_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_DATACT_DATA .
   LO_STRUCT ?= LO_TABLE->GET_TABLE_LINE_TYPE).

   " CT_DATA의 필드들을 가져옴( 필드마다 행에 저장 됨 ).
   LT_COMP LO_STRUCT->GET_COMPONENTS).

   " 필드의 갯수를 저장.
   LV_TOT_COMPONENTS LINESLT_COMP ).

   "
   DATALV_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.

    DATALI_EXCELDATA TYPE STANDARD TABLE OF ALSMEX_TABLINE.  " 엑셀 데이터 저장 Table
    DATALS_EXCELDATA LIKE LINE OF LI_EXCELDATA.              " 엑셀 데이터 저장 Struct
    DATALV_TOT_ROWS TYPE I.                                  " CT_DATA에 정상적으로 삽입 된 데이터 수
    DATALV_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.




"=============================================================================================================================
" 실제로직
  TYPESBEGIN OF TS_DATA,
           F1 TYPE CHAR10,
           F2 TYPE CHAR10,
           F3 TYPE CHAR10,
         END OF TS_DATA,
         TT_DATA TYPE STANDARD TABLE OF TS_DATA.


   DATAGT_DATA TYPE TT_DATA.
   DATALO_UPLOADER TYPE REF TO LCL_EXCEL_UPLOADER.


   PARAMETERSP_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->UPLOADCHANGING CT_DATA GT_DATA ).  " 업로드.

  BREAK-POINT.




*&---------------------------------------------------------------------*
*& Form GET_FILEPATH
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM get_filepath .

 DATAls_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.
    CLEARP_FNAME.
    P_FNAME ls_filetab-filename.
  ELSE.
    BREAK-POINT.
  ENDIF.

ENDFORM.