쌓고 쌓다
[ABAP] 동적 ALV Field Catalog 본문
동적으로 ALV 필드 카탈로그를 구성하여 보자.
품목 개수에 맞춰 ALV 필드 개수가 맞춰지는 예제이다.

조회된 결과에서 품목 개수가 최대 5개라면 품목1, 품목2, ..., 품목5처럼
5개의 필드가 표시되고

품목이 하나라면 품목1 하나의 필드가 표시되도록 해보자.
1. 데이터 SELECT

구매오더번호, 품목코드1, 품목코드2, 품목코드3, ...
위의 형태로 ALV에 구성하고자한다면
구매오더번호, 품목번호, 품목코드
이렇게 3개의 필드를 갖는 데이터를 조회해야한다.

(1) : 필드 카탈로그 설정
(2) : 필드 카탈로그 기반 Internal Table 생성 및 데이터 넣기
2. SET_PO_DYNAMIC_FCAT

먼저 ALV에 표시할때 반드시 나올 필드인 고정 필드 카탈로그를 넣어준다.

구매오더번호를 그룹으로 묶어서 각 그룹의 사이즈를 이용해서
품목1, 품목2, ... 품목N개 표시할 최대 품목 총 개수를 구한다.

최대 품목 개수 N을 구한만큼 필드 카탈로그에 추가한다.
이때 필드명(FIELDNAME)은 품목1, 품목2, ... 형식으로한다.
나중에 구매오더번호 한개씩 돌며
그 구매오더번호에 포함된 품목을 돌며
순서대로 품목1, 품목2, ... 품목N에 값을 넣어주면 된다.
SET_PO_DYNAMIC_FCAT 전체 코드
FORM SET_PO_DYNAMIC_FCAT .
DATA : LS_FCAT TYPE LVC_S_FCAT.
CLEAR GT_PO_FCAT.
* 고정 필드카탈로그
LS_FCAT-FIELDNAME = 'EBELN'.
LS_FCAT-COLTEXT = '구매 문서 번호'.
LS_FCAT-KEY = 'X'.
LS_FCAT-HOTSPOT = 'X'.
APPEND LS_FCAT TO GT_PO_FCAT.
CLEAR LS_FCAT.
LS_FCAT-FIELDNAME = 'COUNT'.
LS_FCAT-COLTEXT = '품목 개수'.
LS_FCAT-JUST = 'C'.
APPEND LS_FCAT TO GT_PO_FCAT.
DATA : LV_MAXCNT TYPE I. " 최대 품목 개수 (동적으로 추가할 컬럼 개수)
LOOP AT GT_PO ASSIGNING FIELD-SYMBOL(<FS_PO>)
GROUP BY ( EBELN = <FS_PO>-EBELN " 그룹화할 기준
SIZE = GROUP SIZE " 그룹에 포함된 요소들 개수
INDEX = GROUP INDEX ) " GT_PO 기준으로 순서대로 위에서 아래로 그룹을 묶었을때 몇번째 그룹인가에 대한 값
DESCENDING " 그룹 인덱스(1번째 그룹, 2번째 그룹)를 기준으로 탐색할때 오름차순, 내림차순으로 순서를 지정할 수 있음
ASSIGNING FIELD-SYMBOL(<FS_GROUP>). " <FS_GROUP> : 그룹화된 결과
* <FS_PO>-COUNT = <FS_GROUP>-SIZE. 위의 WorkArea 필드에 접근하면 덤프가 발생한다. 아래의 루프문에서 WorkArea 접근해야한다.
IF <FS_GROUP>-SIZE > LV_MAXCNT. " 최대 품목 개수 갱신
LV_MAXCNT = <FS_GROUP>-SIZE. " SIZE : 그룹의 사이즈
ENDIF.
LOOP AT GROUP <FS_GROUP> ASSIGNING FIELD-SYMBOL(<FS_ROW>). " 그룹별 ROW 접근
<FS_ROW>-COUNT = <FS_GROUP>-SIZE. " PO의 품목 총 개수 넣어줌
ENDLOOP.
ENDLOOP.
* 동적 필드 카탈로그
DO LV_MAXCNT TIMES. " 최대 품목 수 만큼 필드 카탈로그 추가해주기
CLEAR LS_FCAT.
LS_FCAT-FIELDNAME = 'EBELP' && SY-INDEX. " EBELP1, EBELP2, EBELP3, ...
LS_FCAT-COLTEXT = '품목 번호'.
LS_FCAT-CONVEXIT = 'ALPHA'.
LS_FCAT-JUST = 'C'.
APPEND LS_FCAT TO GT_PO_FCAT.
CLEAR LS_FCAT.
LS_FCAT-FIELDNAME = 'MATNR' && SY-INDEX. " MATNR1, MATNR2, MATNR3, ...
LS_FCAT-COLTEXT = '자재코드'.
LS_FCAT-REF_TABLE = 'EKPO'.
LS_FCAT-REF_FIELD = 'MATNR'.
LS_FCAT-JUST = 'C'.
APPEND LS_FCAT TO GT_PO_FCAT.
ENDDO.
ENDFORM.
3. CREATE_DYNAMIC_TABLE

'CL_ALV_TABLE_CREATE=>CREATE_DYNAMIC_TABLE'
위의 메소드는 필드카탈로그를 읽어
그 필드 카탈로그를 사용할 수 있는 Internal Table을 생성해 가리키는 레퍼런스를 반환해준다.


동적으로 생성된 필드카탈로그에 맞춰 생성된 Internal Table의 WorkArea Structure를
만들기위한 과정이다.
ASSIGN LT_LIST_R->* TO <GT_LIST>
: 위의 메소드로 받아온 GT_LIST_R 레퍼런스를 가지고
Internal Table 필드심볼 <GT_LIST>에 할당한다.
<GT_LIST>에는 동적으로 구성된 필드에 맞춰
Internal Table을 갖게 된다.
CREATE DATTA LS_DATA LIKE LINE OF <GT_LIST>
: <GT_LIST>의 WORKAREA 타입의 레퍼런스 변수
LS_DATA 를 생성한다.
ASSIGN LS_DATA->* TO <FS_LIST>
: LS_DATA 레퍼런스 변수가 가리키는 공간의 데이터를
필드심볼 <FS_LIST>에 할당한다.
최종적으로 <FS_LIST>에는
동적으로 생성된 Internal Table의 WorkArea 형태의 필드심볼이 된다.
이제 이 WorkArea를가지고 ALV에 뿌려줄 행 데이터를 구성하면 된다.

이제 구매오더, 품목번호, 품목코드가 들어있는 GT_PO를 가지고
ALV의 행 데이터를 구성하면 된다.
새로운 구매오더번호일때는 품목번호를 1로 초기화
ASSIGN COMPONENT 구문으로 스트럭처의 특정 필드 필드심볼을 받아
값을 할당해주면 된다.
마지막 구매오더번호일때는 ALV에 뿌려줄 Internal Table에 APPEND해주면 된다.
CREATE_DYNAMIC_TABLE 전체 코드
FORM CREATE_DYNAMIC_TABLE .
DATA : LT_LIST_R TYPE REF TO DATA. " 모든 종류의 데이터 객체 주소를 담을 수 있다.
* 필드카탈로그를 읽어 그에 맞는 Internal Table을 만들어준다.
CALL METHOD CL_ALV_TABLE_CREATE=>CREATE_DYNAMIC_TABLE
EXPORTING
IT_FIELDCATALOG = GT_PO_FCAT
IMPORTING
EP_TABLE = LT_LIST_R. " 레퍼런스를 반환해준다.
UNASSIGN <GT_LIST>. " <GT_LIST> 필드심볼 연결 끊기
ASSIGN LT_LIST_R->* TO <GT_LIST>. " GT_LIST_R이 가리키는 데이터를 <GT_LIST>에 할당
FIELD-SYMBOLS : <FS_LIST> TYPE DATA, " 어떤 타입으로도 변환 가능한 TYPE DATA
<FS_VALUE> TYPE DATA.
DATA : LV_FNAME TYPE FIELDNAME,
LV_INDEX TYPE I.
* <FS_LIST>에 <GT_LIST>와 동일한 스트럭쳐를 할당하는 과정 필요
DATA : LS_DATA TYPE REF TO DATA. " 참조 변수 선언
CREATE DATA LS_DATA LIKE LINE OF <GT_LIST>. " 참조 변수 생성 <GT_LIST>의 WorkArea 객체를 참조할 수 있는 변수를 생성
" => LS_DATA는 Structure 타입이 된다.
ASSIGN LS_DATA->* TO <FS_LIST>. " LS_DATA가 가리키는 주소값을 <FS_LIST>에 할당
LOOP AT GT_PO INTO DATA(LS_PO). " 구매오더별, 구매오더품목별 접근
AT NEW EBELN. " 새로운 구매오더번호
LV_INDEX = 1.
ENDAT.
ASSIGN COMPONENT 'EBELN' OF STRUCTURE <FS_LIST> TO <FS_VALUE>.
<FS_VALUE> = LS_PO-EBELN.
LV_FNAME = 'EBELP' && LV_INDEX. " 품목 번호에 맞춰 EBELP1, EBELP2, ... 필드에 값 할당
ASSIGN COMPONENT LV_FNAME OF STRUCTURE <FS_LIST> TO <FS_VALUE>.
<FS_VALUE> = LS_PO-EBELP.
LV_FNAME = 'MATNR' && LV_INDEX.
ASSIGN COMPONENT LV_FNAME OF STRUCTURE <FS_LIST> TO <FS_VALUE>.
<FS_VALUE> = LS_PO-MATNR.
AT END OF EBELN.
LV_FNAME = 'COUNT'.
ASSIGN COMPONENT LV_FNAME OF STRUCTURE <FS_LIST> TO <FS_VALUE>.
<FS_VALUE> = LV_INDEX.
APPEND <FS_LIST> TO <GT_LIST>.
CLEAR <FS_LIST>.
ENDAT.
LV_INDEX = LV_INDEX + 1.
ENDLOOP.
ENDFORM.
'SAP > ABAP' 카테고리의 다른 글
| [ABAP] Fixed Value(Value Range) 값 JOIN으로 가져오기 (DD07T) (0) | 2025.10.14 |
|---|---|
| [ABAP] Selection Texts의 DDIC Reference (6) | 2025.10.10 |
| [ABAP] 엑셀 업로드와 BDC 프로그램 (0) | 2025.09.15 |
| [ABAP] LEFT OUTER JOIN할때 IS INITIAL 사용시 주의사항 (1) | 2025.09.14 |
| [ABAP] SmartForms Loop 사용법과 집계 구하는법 (4) | 2025.09.03 |