SAP 리포트 결과를 Excel로 떨어뜨리는 작업, 자주 만나는 요구사항입니다. GUI_DOWNLOAD 같은 표준 펑션이면 단순 CSV·TXT 출력은 빠르게 끝나지만, 색상·서식·테두리·열 너비 자동 조정 까지 함께 적용된 Excel 파일을 만들고 싶다면 OLE Automation이 답입니다.
특히 데이터 양이 많을 때 한 셀씩 Cells(r, c).Value = ... 식으로 채우면 성능이 매우 떨어집니다. 대신 클립보드(OS clipboard)를 우회 통로로 사용 해서 한 번에 붙여넣는 패턴이 정석이고, 그 다음 서식만 OLE로 입혀주면 됩니다.
이 글은 SAP 데이터를 Excel로 떨어뜨리는 클립보드 export + OLE 서식 적용 패턴을 정리한 메모입니다.
핵심 원리
OLE Excel 다운로드의 표준 흐름은 다음과 같습니다.
| 단계 | 처리 내용 | 핵심 API |
|---|---|---|
| 1 | SAP 데이터 조회 | SELECT + 내부 테이블 |
| 2 | TAB 구분 문자열 라인으로 변환 | cl_abap_char_utilities=>horizontal_tab |
| 3 | 클립보드로 export | cl_gui_frontend_services=>clipboard_export |
| 4 | Excel 시작 + 시트 준비 | CREATE OBJECT 'Excel.Application' |
| 5 | 셀 선택 + 붙여넣기 | Cells(r, c).SELECT + PASTE |
| 6 | 서식 적용 (글꼴·색상·테두리) | Range + Font + Borders + Interior |
| 7 | 열 너비 자동 조정 + Visible | Columns.AutoFit + VISIBLE = 1 |
| 8 | 저장 + 종료 | SaveAs + Close + Quit |
핵심 아이디어는 데이터를 셀에 하나씩 넣지 않고, TAB 구분 텍스트로 만들어서 클립보드에 한 번에 올리고 PASTE 한다 는 것입니다. Excel은 TAB을 셀 구분자로 인식하므로, 한 줄의 텍스트가 자동으로 여러 셀에 흩어집니다.
기본 선언부:
DATA: lv_application TYPE ole2_object,
lv_workbook TYPE ole2_object,
w_cell1 TYPE ole2_object,
w_columns TYPE ole2_object,
borders TYPE ole2_object,
range TYPE ole2_object,
w_font TYPE ole2_object.
1단계 — SAP 데이터 조회
다운로드 대상 데이터를 일반적인 SELECT로 조회합니다. 예제는 SAP 표준 비행기 운항 마스터(SFLIGHT) 기준.
SELECT carrid,
connid,
fldate,
price,
currency,
planetype
INTO TABLE @DATA(lt_sflight)
FROM sflight
WHERE carrid = 'LH'.
2단계 — TAB 구분 문자열 라인으로 변환
각 행을 TAB(cl_abap_char_utilities=>horizontal_tab)으로 구분된 한 줄 문자열 로 만들어 문자열 테이블에 적재합니다. 첫 줄은 컬럼 헤더.
TYPES: t_c(1500) TYPE c,
t_data TYPE TABLE OF t_c.
DATA: gt_excel TYPE t_data,
gs_excel TYPE LINE OF t_data,
deli TYPE c.
deli = cl_abap_char_utilities=>horizontal_tab.
LOOP AT lt_sflight INTO DATA(ls_sflight).
" 첫 행에만 헤더 라인 적재
AT FIRST.
gs_excel = |항공사 코드 { deli } 항공편 연결 번호 { deli } 항공편 일자 { deli }|
&& | 항공 요금 { deli } 항공사의 현지통화 { deli } 항공기 유형 { deli }|.
APPEND gs_excel TO gt_excel.
CLEAR gs_excel.
ENDAT.
gs_excel = |{ ls_sflight-carrid } { deli } { ls_sflight-connid } { deli } { ls_sflight-fldate } { deli }|
&& |{ ls_sflight-price } { deli } { ls_sflight-currency } { deli } { ls_sflight-planetype }|.
APPEND gs_excel TO gt_excel.
CLEAR gs_excel.
ENDLOOP.
핵심 포인트:
deli문자(TAB)는 SAP 에디터에서는#으로 표시되지만 실제 클립보드에는 TAB 문자로 들어감- 한 라인의 길이 한계가 있으니
t_c(1500)처럼 충분한 폭으로 선언
3단계 — 클립보드 export
cl_gui_frontend_services=>clipboard_export 로 위 문자열 테이블을 클립보드에 올립니다. 이 호출이 있어야 다음 단계의 PASTE 가 의미를 가집니다.
DATA: lv_rc TYPE i.
CALL METHOD cl_gui_frontend_services=>clipboard_export
EXPORTING
no_auth_check = space
IMPORTING
data = gt_excel
CHANGING
rc = lv_rc
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
not_supported_by_gui = 3
no_authority = 4
OTHERS = 5.
호출이 끝나면 사용자가 Excel에서 Ctrl + V 만 눌러도 데이터가 붙여넣어지는 상태입니다.
4단계 — Excel 시작과 시트 준비
OLE로 Excel을 띄우고 새 통합 문서·시트를 준비합니다. 이때 VISIBLE = 1 을 마지막에 설정하는 게 핵심 — 가공 도중에 표시하면 사용자가 작업 중인 화면이 깜빡거리며 보입니다.
CREATE OBJECT lv_application 'EXCEL.APPLICATION'.
CALL METHOD OF lv_application 'WORKBOOKS' = lv_workbook.
CALL METHOD OF lv_workbook 'ADD' = lv_workbook.
" 가공이 끝난 마지막에 화면 표시할 예정이므로 여기선 주석
" SET PROPERTY OF lv_application 'VISIBLE' = 1.
" 현재 활성 시트 가져와서 이름 변경
GET PROPERTY OF lv_application 'ACTIVESHEET' = lv_workbook.
SET PROPERTY OF lv_workbook 'NAME' = 'SFLIGHT'.
5단계 — 셀 위치 지정 + 클립보드 PASTE
붙여넣기 시작 위치 셀을 선택하고(SELECT) Workbook 레벨에서 PASTE 메서드를 호출합니다.
" 2행 2열을 시작점으로 선택
CALL METHOD OF lv_workbook 'CELLS' = w_cell1
EXPORTING
#1 = 2
#2 = 2.
CALL METHOD OF w_cell1 'SELECT'.
" 클립보드 내용을 붙여넣기
CALL METHOD OF lv_workbook 'PASTE'.
" 추가: 1행 1열에 식별용 값 넣기 (예: 작성자 / 리포트 식별자)
CALL METHOD OF lv_workbook 'CELLS' = w_cell1
EXPORTING
#1 = 1
#2 = 1.
SET PROPERTY OF w_cell1 'VALUE' = 'TEST'.
특정 열의 너비를 미리 정해두고 싶으면 ColumnWidth 프로퍼티를 사용:
DATA: lv_index TYPE i.
DO 7 TIMES.
lv_index = lv_index + 1.
IF lv_index >= 2.
CALL METHOD OF lv_workbook 'CELLS' = w_cell1
EXPORTING
#1 = 2
#2 = lv_index.
SET PROPERTY OF w_cell1 'ColumnWidth' = 22.
ENDIF.
ENDDO.
6단계 — Range 서식 + 테두리 적용
붙여넣은 데이터 영역에 행 단위로 서식을 적용합니다. 헤더 + 데이터를 합쳐서 행마다 B{i}:G{i} 범위를 잡고, 글꼴 / 배경색 / 테두리를 일괄 적용.
DATA(i) = 1.
LOOP AT gt_excel INTO gs_excel.
i = i + 1.
DATA(first) = |B{ i }|. " 컬럼 시작
DATA(finish) = |G{ i }|. " 컬럼 끝
" 가운데 정렬
CALL METHOD OF lv_workbook 'Range' = w_cell1
EXPORTING
#1 = first
#2 = finish.
SET PROPERTY OF w_cell1 'HorizontalAlignment' = 3. " 3 = Center
" 글꼴
CALL METHOD OF w_cell1 'FONT' = w_font.
SET PROPERTY OF w_font 'NAME' = 'Arial Black'.
SET PROPERTY OF w_font 'SIZE' = 16.
" 셀 배경색
GET PROPERTY OF w_cell1 'Interior' = w_font.
SET PROPERTY OF w_font 'ColorIndex' = 6. " 6 = 노란색
" 테두리 (왼쪽=7, 오른쪽=8, 위=9, 아래=10, 내부 가운데=11)
CALL METHOD OF lv_workbook 'Range' = range
EXPORTING
#1 = first
#2 = finish.
CALL METHOD OF range 'Borders' = borders no flush EXPORTING #1 = 7.
SET PROPERTY OF borders 'LineStyle' = 1.
CALL METHOD OF range 'Borders' = borders no flush EXPORTING #1 = 8.
SET PROPERTY OF borders 'LineStyle' = 1.
CALL METHOD OF range 'Borders' = borders no flush EXPORTING #1 = 9.
SET PROPERTY OF borders 'LineStyle' = 1.
CALL METHOD OF range 'Borders' = borders no flush EXPORTING #1 = 10.
SET PROPERTY OF borders 'LineStyle' = 1.
CALL METHOD OF range 'Borders' = borders no flush EXPORTING #1 = 11.
SET PROPERTY OF borders 'LineStyle' = 1.
" 열 너비 자동 맞춤
CALL METHOD OF lv_workbook 'Columns' = w_columns.
CALL METHOD OF w_columns 'AutoFit' no flush.
ENDLOOP.
테두리 인덱스 의미 정리.
| Index | 테두리 위치 |
|---|---|
7 |
왼쪽 테두리 (xlEdgeLeft) |
8 |
위쪽 테두리 (xlEdgeTop) |
9 |
아래쪽 테두리 (xlEdgeBottom) |
10 |
오른쪽 테두리 (xlEdgeRight) |
11 |
내부 세로 테두리 (xlInsideVertical) |
no flush 옵션은 OLE 호출을 즉시 실행하지 않고 묶어서 한 번에 처리하라는 의미. 반복 호출 성능에 큰 차이가 납니다.
7단계 — 가공 완료 후 Excel 화면 표시
모든 가공이 끝난 뒤에 VISIBLE = 1 을 설정합니다. 사용자는 깔끔하게 완성된 Excel만 보게 됩니다.
SET PROPERTY OF lv_application 'VISIBLE' = 1.
8단계 — 파일 저장과 종료
마지막으로 SaveAs 로 파일을 저장하고 Close · Quit 호출 후 객체를 정리합니다.
DATA: lv_filename TYPE string.
lv_filename = 'C:\TEMP\sflight_export.xlsx'.
" 파일 저장
CALL METHOD OF lv_workbook 'SaveAs'
EXPORTING
#1 = lv_filename.
" 워크북 닫기 (저장 여부: 0 = 안 함, 1 = 함)
CALL METHOD OF lv_workbook 'Close'
EXPORTING
#1 = 0.
" 엑셀 종료
CALL METHOD OF lv_application 'Quit'.
" 객체 정리
FREE: lv_workbook,
lv_application.
저장 경로는 보통 cl_gui_frontend_services=>file_save_dialog 로 사용자가 직접 위치를 고르게 하는 패턴이 흔합니다.
흔히 빠뜨리는 함정
VISIBLE을 처음에 켜기
VISIBLE = 1 을 코드 처음에 설정하면 사용자는 빈 Excel이 열리고 → 데이터 붙여지고 → 색상 바뀌고 → 테두리 그려지는 과정을 모두 보게 됩니다. 화면이 깜빡거리고 성능도 떨어집니다. 반드시 가공이 끝난 후 마지막에 VISIBLE = 1 호출.
clipboard_export 누락
PASTE 호출 직전에 clipboard_export 가 없으면 SAP 자체 데이터가 아니라 OS 클립보드의 이전 내용이 붙여집니다. 의외로 흔한 실수.
TAB이 아닌 다른 구분자 사용
쉼표·세미콜론 등을 구분자로 쓰면 Excel이 한 셀에 통째로 넣어버립니다. 셀 분리는 반드시 TAB(cl_abap_char_utilities=>horizontal_tab) 사용.
no flush 옵션 미사용 → 성능 저하
수백/수천 행에 테두리·서식을 반복 적용할 때 OLE 호출이 매번 GUI로 왕복하면 매우 느립니다. no flush 옵션을 활용해서 호출을 묶어 처리.
FREE OBJECT 누락 → Excel 프로세스 잔존
OLE 객체를 해제하지 않으면 Excel.exe가 백그라운드에 살아남아 작업 관리자에서 직접 종료해야 합니다. 사용 끝난 객체는 FREE OBJECT 로 명시적으로 해제.
Workbook.SaveAs 경로에 폴더만 지정
SaveAs 의 첫 인자는 파일명 포함 풀 경로 여야 합니다. 폴더만 주면 폴더명 자체를 파일명으로 저장하려다 권한 오류 발생.
요약
| 단계 | 목적 | 핵심 호출 |
|---|---|---|
| 1 | SAP 데이터 조회 | SELECT |
| 2 | TAB 구분 문자열 변환 | horizontal_tab + string template |
| 3 | 클립보드로 export | cl_gui_frontend_services=>clipboard_export |
| 4 | Excel 시작 + 시트 준비 | CREATE OBJECT + WORKBOOKS.ADD |
| 5 | 셀 선택 + PASTE | Cells.SELECT + Workbook.PASTE |
| 6 | 서식 + 테두리 | Range + Font + Borders(7~11) + Interior |
| 7 | 자동 너비 + 화면 표시 | Columns.AutoFit + VISIBLE = 1 |
| 8 | 저장 + 종료 | SaveAs + Close + Quit + FREE OBJECT |
OLE Excel 다운로드의 핵심은 셀에 직접 쓰지 말고 클립보드로 한 번에 붙여넣기 한 다음, 서식은 OLE로 나중에 입히는 패턴입니다. 이 구조를 잡아두면 행 수가 수천 단위로 늘어나도 성능이 크게 떨어지지 않고, 사용자에게 보이는 화면도 끊김 없이 깔끔하게 보여줄 수 있습니다.
Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다. OLE Automation은 클라이언트 PC에 Excel이 설치되어 있어야 동작하며, 서버 사이드 배치에는 부적합합니다. SAP 버전·Excel 버전·Windows 환경에 따라 동작이 다를 수 있으므로 운영 환경 적용 전 개발 시스템에서 확인하시기 바랍니다.