ALV 화면에서 특정 셀만 색상을 바꾸거나, 특정 셀만 편집 가능하게 하고 싶은 경우가 자주 있습니다. 결재 상태에 따라 특정 컬럼만 빨갛게 표시한다거나, 승인된 행은 편집 불가로 잠그는 식의 화면입니다. 단순히 필드카탈로그(fieldcat) 의 EDIT = 'X' 만 켜면 컬럼 전체가 편집되거나 모든 행 같은 색이 적용돼서 원하는 결과를 얻을 수 없습니다.
SAP 는 셀 단위 제어를 위해 두 가지 인터널 테이블 — LVC_T_SCOL(색상) 과 LVC_T_STYL(스타일) 을 제공합니다. 데이터 행 인터널 테이블의 각 row 안에 이 두 테이블을 자식 컬럼으로 추가하고, 셀별로 값을 채워주면 ALV 가 자동으로 적용합니다.
행마다 반복적으로 들어가는 색상·스타일 추가 로직을 깔끔하게 처리하려면 ABAP 매크로(DEFINE ~ END-OF-DEFINITION) 가 효율적입니다.
이 글은 ALV 셀별 편집·색상 제어의 원리, 매크로 패턴, 자주 만나는 함정을 정리한 메모입니다.
핵심 — 셀별 색·편집은 별도 인터널 테이블로 제어
ALV 그리드는 데이터 행 인터널 테이블의 컬럼으로 색상·스타일 메타데이터를 받습니다. 즉, 데이터 구조에 두 개의 추가 컬럼을 만들어 둡니다.
| 컬럼 | 타입 | 역할 |
|---|---|---|
COLOR(임의 이름) |
LVC_T_SCOL (인터널 테이블) |
해당 행의 셀별 색상 — 행 안에 여러 셀 색을 동시에 보관 |
CELLTAB(임의 이름) |
LVC_T_STYL (인터널 테이블) |
해당 행의 셀별 편집 가능 여부 (enabled / disabled) |
연결은 두 단계입니다.
1. 데이터 구조에 COLOR · CELLTAB 컬럼 추가
2. ALV Layout 의 STYLEFNAME · CTAB_FNAME 에 컬럼 이름 등록
3. 각 행 출력 직전에 매크로로 셀별 정보 채움
이 글에서는 매크로 두 개로 단순화합니다.
| 매크로 | 용도 |
|---|---|
add_cell_color |
행의 특정 컬럼에 색상 적용 |
set_cell_edit |
행의 특정 컬럼을 편집 가능/불가로 토글 |
1단계 — 인터널 테이블 확장 (COLOR · CELLTAB 컬럼 추가)
ALV 에서 사용할 데이터 인터널 테이블에 색상과 스타일을 보관할 컬럼을 추가합니다. 이름은 자유롭게 정할 수 있지만 일반적으로 COLOR · CELLTAB 으로 명명합니다.
TYPES: BEGIN OF ty_data,
matnr TYPE matnr, " 자재
maktx TYPE maktx, " 자재명
appsta TYPE c LENGTH 1, " 승인 상태 (A/B/C)
menge TYPE mara-ntgew, " 수량
color TYPE lvc_t_scol, " ★ 셀별 색상 (행 단위)
celltab TYPE lvc_t_styl, " ★ 셀별 스타일
END OF ty_data.
DATA: gt_data TYPE STANDARD TABLE OF ty_data,
gs_data TYPE ty_data.
LVC_T_SCOL 과 LVC_T_STYL 은 표준 SAP 타입이므로 별도 정의 없이 바로 사용 가능합니다.
2단계 — 매크로 정의 (DEFINE ~ END-OF-DEFINITION)
같은 패턴을 모든 행에 반복하지 않도록 매크로 두 개를 정의합니다. ABAP 매크로는 컴파일 시점에 인라인 치환되는 메커니즘이라, 호출 시점에 변수와 인자가 그대로 펼쳐집니다.
* ★ 매크로 1) 셀 색상 추가
* 호출: add_cell_color '필드명' 색상번호 강도 역상 워크에어리어
DEFINE add_cell_color.
CLEAR ls_color.
ls_color-fname = &1. " 적용할 컬럼명 (필드카탈로그 이름)
ls_color-color-col = &2. " 색상 코드 (1~7)
ls_color-color-int = &3. " 강도 (0=일반, 1=강조)
ls_color-color-inv = &4. " 역상 (0=일반, 1=반전)
APPEND ls_color TO &5-color.
END-OF-DEFINITION.
* ★ 매크로 2) 셀 편집 가능 여부
* 호출: set_cell_edit '필드명' 스타일상수 워크에어리어
DEFINE set_cell_edit.
CLEAR ls_style.
ls_style-fieldname = &1.
ls_style-style = &2. " mc_style_enabled / mc_style_disabled
APPEND ls_style TO &3-celltab.
END-OF-DEFINITION.
매크로에 사용된 변수(ls_color · ls_style) 는 매크로 호출 측에서 미리 선언돼 있어야 합니다.
DATA: ls_color TYPE lvc_s_scol,
ls_style TYPE lvc_s_styl.
색상 코드 (Cn) 의미
COL 필드에 들어가는 1~7 의 의미입니다.
| COL | 색상 | 대표 용도 |
|---|---|---|
| 0 | 기본 (테마 색) | 색상 초기화 — 색 제거 |
| 1 | 진한 회청색 (Navy) | 헤더 강조 |
| 2 | 회색-노랑 | 소제목·구분 영역 |
| 3 | 노랑 | 주의·경고 (예: 미입력 필드) |
| 4 | 파랑 (밝은 파랑) | 정보 강조 |
| 5 | 초록 | 정상·성공 (예: 승인 완료) |
| 6 | 빨강 | 오류·반려 (예: 거절·실패) |
| 7 | 주황·분홍 | 진행 중·검토 단계 |
INT(강도) 가 1 이면 같은 색이 강조 톤으로 나오고, INV(역상) 가 1 이면 배경과 글자가 반전됩니다.
편집 가능 여부 상수
| 상수 | 의미 |
|---|---|
cl_gui_alv_grid=>mc_style_enabled |
편집 가능 (입력 가능) |
cl_gui_alv_grid=>mc_style_disabled |
편집 불가 (조회 전용) |
3단계 — Field Catalog · Layout 설정
ALV 가 행 안의 COLOR · CELLTAB 컬럼을 인식하려면 Layout 에 컬럼 이름을 등록해야 합니다.
DATA: ls_layout TYPE lvc_s_layo.
ls_layout-ctab_fname = 'COLOR'. " 색상 컬럼 이름
ls_layout-stylefname = 'CELLTAB'. " 스타일 컬럼 이름
ls_layout-zebra = abap_true.
ls_layout-sel_mode = 'A'. " 다중 선택
전체 컬럼이 아니라 특정 컬럼만 편집 대상으로 만들고 싶다면 필드카탈로그(lvc_t_fcat) 의 EDIT 도 켭니다.
LOOP AT lt_fcat ASSIGNING FIELD-SYMBOL(<fcat>).
CASE <fcat>-fieldname.
WHEN 'APPSTA' OR 'MENGE'.
<fcat>-edit = abap_true. " 이 두 컬럼만 편집 가능
ENDCASE.
ENDLOOP.
EDIT = 'X' 만 켜면 컬럼 전체 행이 편집 가능해지지만, 거기에 CELLTAB 으로 개별 셀을 disabled 로 표시하면 그 셀만 잠겨 보입니다.
4단계 — 행마다 매크로 호출 (실무 패턴)
데이터 출력 직전 LOOP 안에서 행마다 조건에 맞춰 매크로를 호출합니다.
LOOP AT gt_data ASSIGNING FIELD-SYMBOL(<row>).
CLEAR: <row>-color, <row>-celltab. " 매번 초기화
CASE <row>-appsta.
WHEN 'A'. " 승인 완료
add_cell_color 'APPSTA' 5 1 0 <row>. " 초록 강조
set_cell_edit 'APPSTA' cl_gui_alv_grid=>mc_style_disabled <row>.
set_cell_edit 'MENGE' cl_gui_alv_grid=>mc_style_disabled <row>.
WHEN 'B'. " 진행 중
add_cell_color 'APPSTA' 7 1 0 <row>. " 주황 강조
set_cell_edit 'APPSTA' cl_gui_alv_grid=>mc_style_enabled <row>.
set_cell_edit 'MENGE' cl_gui_alv_grid=>mc_style_enabled <row>.
WHEN 'C'. " 반려
add_cell_color 'APPSTA' 6 1 0 <row>. " 빨강 강조
add_cell_color 'MENGE' 6 0 0 <row>. " 수량도 빨갛게
set_cell_edit 'APPSTA' cl_gui_alv_grid=>mc_style_enabled <row>.
set_cell_edit 'MENGE' cl_gui_alv_grid=>mc_style_disabled <row>.
ENDCASE.
" 수량이 0 이면 노랑 강조 (상태와 무관)
IF <row>-menge = 0.
add_cell_color 'MENGE' 3 1 0 <row>.
ENDIF.
ENDLOOP.
매크로 한 줄로 셀 단위 색·편집 제어가 끝나므로 가독성이 크게 좋아집니다. 같은 로직을 직접 펴서 작성하면 같은 작업에 4~5줄씩 반복돼 코드가 복잡해집니다.
흔히 빠뜨리는 함정
CTAB_FNAME · STYLEFNAME 누락
Layout 에 컬럼 이름을 안 등록하면 데이터에 색상·스타일을 채워도 ALV 가 인식하지 못합니다. ls_layout-ctab_fname = 'COLOR' 과 ls_layout-stylefname = 'CELLTAB' 두 줄을 빼먹지 않습니다.
행마다 CLEAR 누락
LOOP 안에서 매크로 호출 전에 CLEAR <row>-color · CLEAR <row>-celltab 를 안 하면 이전 행 정보가 누적되어 의도와 다른 결과가 나옵니다.
EDIT = 'X' 안 켜고 CELLTAB 만 사용
CELLTAB 으로 일부 셀만 enabled 로 표시해도, 필드카탈로그의 EDIT 이 안 켜져 있으면 컬럼 자체가 잠겨 있어서 결국 편집이 안 됩니다. 컬럼 단위 EDIT 을 켜고, 셀별로 CELLTAB 으로 잠그는 패턴이 맞습니다.
매크로 인자 따옴표 누락
ABAP 매크로의 첫 인자(&1)에 컬럼명을 넘길 때 'APPSTA' 처럼 따옴표를 빼면 변수로 인식되어 컴파일 에러가 납니다. 반드시 문자 리터럴로 넘깁니다.
매크로 변수 미선언
매크로 안에서 사용한 ls_color · ls_style 는 매크로 호출 측에서 미리 DATA 로 선언돼 있어야 합니다. 매크로는 컴파일 시점에 그대로 펼쳐지므로 매크로 자체가 변수 선언을 가지지 않습니다.
ALV 새로고침 누락
데이터를 변경한 후 화면에 즉시 반영되게 하려면 cl_gui_alv_grid=>refresh_table_display 또는 REUSE_ALV_GRID_DISPLAY 의 I_DEFAULT 처리를 호출합니다.
같은 셀에 여러 색 중복 호출
같은 행·같은 컬럼에 add_cell_color 을 두 번 호출하면 두 엔트리가 모두 color 인터널 테이블에 들어갑니다. 마지막 값이 우선되지만 깔끔하지 않으므로, 새 색을 적용하기 전에 DELETE <row>-color WHERE fname = '필드명' 으로 기존 엔트리를 제거하거나 LOOP 시작 시 CLEAR 합니다.
매크로 디버깅 어려움
매크로는 디버거에서 단계별로 들어갈 수 없어서 문제 추적이 어렵습니다. 복잡한 로직이라면 FORM 또는 METHODS 가 더 안전합니다. 매크로는 짧고 반복적인 패턴에만 사용합니다.
색·스타일 컬럼명 충돌
데이터 테이블에 우연히 COLOR 라는 실제 데이터 컬럼이 있다면 충돌합니다. 다른 이름(T_COLOR · CELL_COLOR 등) 으로 명명합니다.
전체 코드 — 복사용 통합본
매크로 두 개 + Layout 설정 + LOOP 호출 흐름을 한 프로그램에 담았습니다. SE38 에 그대로 붙여 실행 가능합니다.
REPORT z_alv_macro_demo.
* ★ 1) 데이터 구조 — COLOR · CELLTAB 컬럼 포함
TYPES: BEGIN OF ty_data,
matnr TYPE matnr,
maktx TYPE maktx,
appsta TYPE c LENGTH 1,
menge TYPE p LENGTH 10 DECIMALS 3,
color TYPE lvc_t_scol,
celltab TYPE lvc_t_styl,
END OF ty_data.
DATA: gt_data TYPE STANDARD TABLE OF ty_data,
gt_fcat TYPE lvc_t_fcat,
gs_layout TYPE lvc_s_layo,
ls_color TYPE lvc_s_scol, " 매크로용
ls_style TYPE lvc_s_styl. " 매크로용
* ★ 2) 매크로 정의
DEFINE add_cell_color.
CLEAR ls_color.
ls_color-fname = &1.
ls_color-color-col = &2.
ls_color-color-int = &3.
ls_color-color-inv = &4.
APPEND ls_color TO &5-color.
END-OF-DEFINITION.
DEFINE set_cell_edit.
CLEAR ls_style.
ls_style-fieldname = &1.
ls_style-style = &2.
APPEND ls_style TO &3-celltab.
END-OF-DEFINITION.
START-OF-SELECTION.
* ★ 3) 테스트 데이터
gt_data = VALUE #(
( matnr = 'M-001' maktx = '자재 A' appsta = 'A' menge = 100 )
( matnr = 'M-002' maktx = '자재 B' appsta = 'B' menge = 50 )
( matnr = 'M-003' maktx = '자재 C' appsta = 'C' menge = 0 )
( matnr = 'M-004' maktx = '자재 D' appsta = 'B' menge = 0 )
).
* ★ 4) 행마다 셀별 색·편집 적용
LOOP AT gt_data ASSIGNING FIELD-SYMBOL(<row>).
CLEAR: <row>-color, <row>-celltab.
CASE <row>-appsta.
WHEN 'A'. " 승인 완료 → 초록 + 잠금
add_cell_color 'APPSTA' 5 1 0 <row>.
set_cell_edit 'APPSTA' cl_gui_alv_grid=>mc_style_disabled <row>.
set_cell_edit 'MENGE' cl_gui_alv_grid=>mc_style_disabled <row>.
WHEN 'B'. " 진행 중 → 주황 + 편집 가능
add_cell_color 'APPSTA' 7 1 0 <row>.
set_cell_edit 'APPSTA' cl_gui_alv_grid=>mc_style_enabled <row>.
set_cell_edit 'MENGE' cl_gui_alv_grid=>mc_style_enabled <row>.
WHEN 'C'. " 반려 → 빨강 + 수량 잠금
add_cell_color 'APPSTA' 6 1 0 <row>.
add_cell_color 'MENGE' 6 0 0 <row>.
set_cell_edit 'APPSTA' cl_gui_alv_grid=>mc_style_enabled <row>.
set_cell_edit 'MENGE' cl_gui_alv_grid=>mc_style_disabled <row>.
ENDCASE.
" 추가 규칙: 수량이 0 이면 노랑 강조
IF <row>-menge = 0.
add_cell_color 'MENGE' 3 1 0 <row>.
ENDIF.
ENDLOOP.
* ★ 5) Field Catalog (편집 가능 컬럼 지정)
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = 'TY_DATA'
CHANGING
ct_fieldcat = gt_fcat
EXCEPTIONS
OTHERS = 1.
LOOP AT gt_fcat ASSIGNING FIELD-SYMBOL(<fcat>).
CASE <fcat>-fieldname.
WHEN 'APPSTA' OR 'MENGE'.
<fcat>-edit = abap_true.
WHEN 'COLOR' OR 'CELLTAB'.
<fcat>-no_out = abap_true. " ★ 메타 컬럼은 화면에서 숨김
ENDCASE.
ENDLOOP.
* ★ 6) Layout — CTAB_FNAME · STYLEFNAME 등록
gs_layout-ctab_fname = 'COLOR'.
gs_layout-stylefname = 'CELLTAB'.
gs_layout-zebra = abap_true.
* ★ 7) ALV 출력
cl_salv_table=>factory(
IMPORTING r_salv_table = DATA(lo_alv)
CHANGING t_table = gt_data
).
" SALV 도 동일 원리로 색/스타일 적용 가능. 위 코드는 REUSE 또는 OO ALV 공통
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
is_layout_lvc = gs_layout
it_fieldcat_lvc = gt_fcat
TABLES
t_outtab = gt_data.
요약
| 단계 | 작업 | 핵심 |
|---|---|---|
| 1 | 인터널 테이블 확장 | COLOR TYPE LVC_T_SCOL · CELLTAB TYPE LVC_T_STYL |
| 2 | 매크로 정의 | add_cell_color · set_cell_edit |
| 3 | Layout · Field Catalog | CTAB_FNAME · STYLEFNAME + 컬럼별 EDIT |
| 4 | LOOP 호출 | 행마다 CLEAR color · celltab 후 매크로 호출 |
| 5 | 색상 코드 | 1 회청 · 3 노랑 · 5 초록 · 6 빨강 · 7 주황 + INT(강도) / INV(역상) |
ALV 셀별 색상·편집 제어는 LVC_T_SCOL 과 LVC_T_STYL 두 인터널 테이블을 데이터 행에 자식 컬럼으로 추가하면 표준 ALV 가 자동으로 적용해 줍니다. 행마다 반복되는 색·편집 로직은 DEFINE 매크로로 한 줄짜리 호출로 줄여 가독성을 크게 높일 수 있습니다. Layout 의 CTAB_FNAME · STYLEFNAME 등록과 LOOP 시작 시 CLEAR 두 가지만 빼먹지 않으면 안정적으로 동작합니다.
Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다.
LVC_T_SCOL · LVC_T_STYL · LVC_S_LAYO 타입과 cl_gui_alv_grid=>mc_style_enabled · mc_style_disabled 상수는 SAP NetWeaver 표준 기능으로 시스템 버전 의존 없이 동작합니다. ABAP 매크로(DEFINE ~ END-OF-DEFINITION) 는 컴파일 시점에 인라인 치환되는 메커니즘이라 디버거에서 단계 추적이 어려운 점이 있어, 복잡한 로직은 폼 루틴(FORM) 또는 메소드(METHODS) 로 분리하는 것이 유지보수 관점에서 더 안전합니다. 색상 코드(COL 0~7) 의 실제 표시는 SAP GUI 테마 설정에 따라 약간씩 다를 수 있으니, 운영 환경의 실제 화면에서 가독성을 한 번 확인하시기 바랍니다.