ALV Field catalog를 만드는 3가지 방법입니다.
#2023.11.06 : CL_SALV_DDIC의 참조테이블/참조필드 정보가 기존 다른 Function/Class와 상이하여 소스 일부 수정
결과적으로는 LVC_T_FCAT 형식의 필드 카탈로그를 생성하여 ALV에 사용하다는 것입니다.
개발자에 따라 주로 사용 하는 방법이 다르다 보니 운영 유지보수를 위해서는 모두 알아두는 것이 좋습니다.
실제 개발시에는 서브루틴으로 만들어서 편리하게 사용할 수 있습니다.
2023.08.28 - [ABAP/소스코드] - [Form] ALV Field catalog(필드 카탈로그) 생성 서브루틴
1. Table/Structure로 필드 카탈로그 생성
Case1. LVC_FIELDCATALOG_MERGE 펑션 (권장)
Case2. CL_SALV_DDIC=>GET_BY_NAME 메소드
2. Internal Table로 필드 카탈로그 생성
Case1. REUSE_ALV_FIELDCATALOG_MERGE 펑션
Case2. CL_SALV_DDIC=>GET_BY_DATA 메소드 (권장)
Case3. CL_SALV_DATA_DESCR=>READ_STRUCTDESCR
3. 필드 카탈로그 직접 생성
서브루틴을 만들어 LVC_T_FACT에 APPEND
3가지 방법 모두 실무에서 많이 사용하며 상황에 맞게 적절히 사용하면 됩니다.
참고로, CL_SALV_DDIC 클래스에서 반환되는 형식(DDFIELDS)이 LCV_T_FCAT과 필드가 100% 매칭되진 않으니 일부 필드는 필드 카탈로그에 맞도록 변환이 필요합니다(예, POSITION -> COL_POS 등)
# 1. Table/Structure로 필드 카탈로그 생성
Case 1. LVC_FIELDCATALOG_MERGE 펑션 이용
Table/Structure에 Data Element가 없는 필드는 DD03T에서 텍스트 보충
DATA LT_FCAT TYPE LVC_T_FCAT.
DATA LT_DD03T TYPE SORTED TABLE OF DD03T WITH UNIQUE KEY FIELDNAME DDLANGUAGE.
DATA LV_STRUCTURE_NAME TYPE DD02L-TABNAME VALUE 'ZCMT8001'.
*S> 필드카탈로그 생성 ---------------------------------------------------------
"Dictionary Table, Structure로 필드카탈로그 생성
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
* I_BUFFER_ACTIVE =
I_STRUCTURE_NAME = LV_STRUCTURE_NAME "Table, Structure
* I_CLIENT_NEVER_DISPLAY = 'X'
* I_BYPASSING_BUFFER =
* I_INTERNAL_TABNAME =
CHANGING
CT_FIELDCAT = LT_FCAT[]
EXCEPTIONS
INCONSISTENT_INTERFACE = 1
PROGRAM_ERROR = 2
OTHERS = 3
.
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE 'I' NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4 DISPLAY LIKE SY-MSGTY.
ELSE.
SELECT
FIELDNAME, DDLANGUAGE, DDTEXT
FROM DD03T
WHERE TABNAME EQ @LV_STRUCTURE_NAME
AND AS4LOCAL EQ 'A'
AND DDLANGUAGE IN ( @SY-LANGU, 'E' )
INTO CORRESPONDING FIELDS OF TABLE @LT_DD03T.
IF SY-SUBRC EQ 0.
LOOP AT LT_FCAT ASSIGNING FIELD-SYMBOL(<LFS>).
IF <LFS>-COLTEXT IS INITIAL AND <LFS>-REPTEXT IS INITIAL AND <LFS>-SCRTEXT_L IS INITIAL AND <LFS>-SCRTEXT_M IS INITIAL AND <LFS>-SCRTEXT_S IS INITIAL.
READ TABLE LT_DD03T INTO DATA(LS_DD03T) WITH TABLE KEY FIELDNAME = <LFS>-FIELDNAME
DDLANGUAGE = SY-LANGU.
IF SY-SUBRC NE 0.
READ TABLE LT_DD03T INTO LS_DD03T WITH TABLE KEY FIELDNAME = <LFS>-FIELDNAME
DDLANGUAGE = 'E'.
ENDIF.
IF SY-SUBRC EQ 0.
<LFS>-COLTEXT = LS_DD03T-DDTEXT.
ENDIF.
ENDIF.
ENDLOOP.
ENDIF.
ENDIF.
"Field catalog의 누락된 항목 보충 (선택사항으로, ALV Display시 알아서 보충됨)
CALL FUNCTION 'LVC_FIELDCAT_COMPLETE'
CHANGING
CT_FIELDCAT = LT_FCAT[].
*E> 필드카탈로그 생성 ---------------------------------------------------------
Case 2. CL_SALV_DDIC=>GET_BY_NAME 메소드 이용
Table/Structure에 Data Element가 없는 필드는 FIELDTEXT로 보충
DATA LT_FCAT TYPE LVC_T_FCAT.
DATA LV_STRUCTURE_NAME TYPE DD02L-TABNAME VALUE 'ZCMT8001'.
*S> 필드카탈로그 생성 ---------------------------------------------------------
"Dictionary Table, Structure로 필드카탈로그 생성
LT_FCAT = CORRESPONDING #( CL_SALV_DDIC=>GET_BY_NAME( LV_STRUCTURE_NAME )
MAPPING KEY = KEYFLAG
COL_POS = POSITION
COLTEXT = FIELDTEXT
REF_TABLE = PRECFIELD
REF_FIELD = LFIELDNAME
CFIELDNAME = REFFIELD
QFIELDNAME = REFFIELD
EXCEPT ROLLNAME ).
LOOP AT LT_FCAT ASSIGNING FIELD-SYMBOL(<LFS>).
IF <LFS>-DATATYPE EQ 'CLNT'.
<LFS>-TECH = 'X'.
ENDIF.
IF <LFS>-COLTEXT IS INITIAL AND <LFS>-REPTEXT IS INITIAL AND <LFS>-SCRTEXT_L IS INITIAL AND <LFS>-SCRTEXT_M IS INITIAL AND <LFS>-SCRTEXT_S IS INITIAL.
CONTINUE.
ELSE.
CLEAR <LFS>-COLTEXT.
ENDIF.
ENDLOOP.
"Field catalog의 누락된 항목 보충 (선택사항으로, ALV Display시 알아서 보충됨)
CALL FUNCTION 'LVC_FIELDCAT_COMPLETE'
CHANGING
CT_FIELDCAT = LT_FCAT[].
*E> 필드카탈로그 생성 ---------------------------------------------------------
# 2. Internal Table로 필드 카탈로그 생성
Case 1. REUSE_ALV_FIELDCATALOG_MERGE 펑션 이용
소스코드 내에서 Internal Table의 정보를 가져오다 보니 소스코드의 열너비가 72자를 넘어가면 덤프가 발생합니다.
워낙 옛날에 만들어진 펑션이다 보니 아직도 많이들 사용하며 저는 권장하지 않습니다.
DATA LT_FCAT TYPE LVC_T_FCAT.
DATA LT_FCAT_OLD TYPE SLIS_T_FIELDCAT_ALV.
DATA: BEGIN OF LT_TMP OCCURS 0,
BUKRS LIKE T001-BUKRS,
MENGE LIKE MSEG-MENGE,
MATNR TYPE MATNR,
CHECK TYPE C,
END OF LT_TMP.
*S> 필드카탈로그 생성 ---------------------------------------------------------
"Internal Table로 필드카탈로그 생성
CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
EXPORTING
I_PROGRAM_NAME = SY-REPID
I_INTERNAL_TABNAME = 'LT_TMP'
* I_STRUCTURE_NAME =
* I_CLIENT_NEVER_DISPLAY = 'X'
I_INCLNAME = SY-REPID
* I_BYPASSING_BUFFER =
* I_BUFFER_ACTIVE =
CHANGING
CT_FIELDCAT = LT_FCAT_OLD[]
EXCEPTIONS
INCONSISTENT_INTERFACE = 1
PROGRAM_ERROR = 2
OTHERS = 3
.
IF SY-SUBRC EQ 0.
CALL FUNCTION 'LVC_TRANSFER_FROM_SLIS'
EXPORTING
IT_FIELDCAT_ALV = LT_FCAT_OLD[]
IMPORTING
ET_FIELDCAT_LVC = LT_FCAT[]
TABLES
IT_DATA = LT_TMP
EXCEPTIONS
IT_DATA_MISSING = 1
OTHERS = 2
.
IF SY-SUBRC <> 0.
* Implement suitable error handling here
ENDIF.
ENDIF.
"Internal Table의 필드가 data element가 아닌 경우 텍스트 보충
LOOP AT LT_FCAT ASSIGNING FIELD-SYMBOL(<LFS>).
CASE <LFS>-FIELDNAME.
WHEN 'CHECK'. <LFS>-COLTEXT = '체크'. "필드에 대한 텍스트 설정
ENDCASE.
ENDLOOP.
"Field catalog의 누락된 항목 보충 (선택사항으로, ALV Display시 알아서 보충됨)
CALL FUNCTION 'LVC_FIELDCAT_COMPLETE'
CHANGING
CT_FIELDCAT = LT_FCAT[].
*E> 필드카탈로그 생성 ---------------------------------------------------------
Case 2. CL_SALV_DDIC=>GET_BY_DATA 메소드 이용
CL_SALV_DDIC=>GET_BY_NAME 과 같이 아주 간단하게 사용할 수 있습니다.
DATA LT_FCAT TYPE LVC_T_FCAT.
TYPES: BEGIN OF T_TMP,
BUKRS LIKE T001-BUKRS,
MENGE LIKE MSEG-MENGE,
MATNR TYPE MATNR,
CHECK TYPE C,
END OF T_TMP.
DATA: LT_TMP TYPE STANDARD TABLE OF T_TMP.
*S> 필드카탈로그 생성 ---------------------------------------------------------
"Internal Table로 필드카탈로그 생성
LOOP AT CL_SALV_DDIC=>GET_BY_DATA( LT_TMP ) INTO DATA(LS_DFIES).
DATA(LS_FIELDCAT) = CORRESPONDING LVC_S_FCAT( LS_DFIES
MAPPING KEY = KEYFLAG ).
LS_FIELDCAT-COL_POS = SY-TABIX.
IF LS_FIELDCAT-DATATYPE EQ 'CLNT'.
LS_FIELDCAT-TECH = 'X'.
ENDIF.
IF LS_DFIES-LFIELDNAME IS NOT INITIAL. "STRUCTURE
LS_FIELDCAT-REF_TABLE = LS_DFIES-PRECFIELD.
LS_FIELDCAT-REF_FIELD = LS_DFIES-LFIELDNAME.
ELSE.
LS_FIELDCAT-REF_TABLE = LS_DFIES-REFTABLE.
LS_FIELDCAT-REF_FIELD = LS_DFIES-REFFIELD.
ENDIF.
IF LS_DFIES-REFTABLE EQ LS_DFIES-PRECFIELD AND LS_DFIES-REFFIELD IS NOT INITIAL.
CASE LS_FIELDCAT-DATATYPE.
WHEN 'CURR'.
LS_FIELDCAT-CFIELDNAME = LS_DFIES-REFFIELD.
WHEN 'QUAN'.
LS_FIELDCAT-QFIELDNAME = LS_DFIES-REFFIELD.
ENDCASE.
ENDIF.
IF LS_FIELDCAT-COLTEXT IS INITIAL AND LS_FIELDCAT-REPTEXT IS INITIAL AND LS_FIELDCAT-SCRTEXT_L IS INITIAL AND LS_FIELDCAT-SCRTEXT_M IS INITIAL AND LS_FIELDCAT-SCRTEXT_S IS INITIAL.
LS_FIELDCAT-COLTEXT = LS_DFIES-FIELDTEXT.
ENDIF.
IF LS_DFIES-LFIELDNAME IS NOT INITIAL.
CLEAR LS_FIELDCAT-ROLLNAME.
ENDIF.
APPEND LS_FIELDCAT TO LT_FCAT.
ENDLOOP.
"Field catalog의 누락된 항목 보충 (선택사항으로, ALV Display시 알아서 보충됨)
CALL FUNCTION 'LVC_FIELDCAT_COMPLETE'
CHANGING
CT_FIELDCAT = LT_FCAT[].
*E> 필드카탈로그 생성 ---------------------------------------------------------
Case 3. CL_SALV_DATA_DESCR=>READ_STRUCTDESCR 메소드 이용
Structure(Work Area)만 사용 가능하여 Internal Table을 이용할 경우 Field-Symbols로 wa로 받은후 사용해야 합니다
DATA LT_FCAT TYPE LVC_T_FCAT.
DATA LR_STRDESCR TYPE REF TO CL_ABAP_STRUCTDESCR.
DATA: LV_FTYPE TYPE C,
LV_COMPS TYPE I.
DATA: LD_DATA TYPE REF TO DATA,
LD_LINE TYPE REF TO DATA.
FIELD-SYMBOLS: <LFT_OUTTAB> TYPE ANY TABLE,
<LFS_OUTTAB> TYPE ANY.
TYPES: BEGIN OF T_TMP,
BUKRS LIKE T001-BUKRS,
MENGE LIKE MSEG-MENGE,
MATNR TYPE MATNR,
CHECK TYPE C,
END OF T_TMP.
DATA: LT_TMP TYPE STANDARD TABLE OF T_TMP.
*S> 필드카탈로그 생성 ---------------------------------------------------------
"Internal Table로 필드카탈로그 생성
DESCRIBE FIELD LT_TMP TYPE LV_FTYPE COMPONENTS LV_COMPS.
IF LV_FTYPE EQ CL_ABAP_TYPEDESCR=>TYPEKIND_TABLE.
CREATE DATA LD_DATA LIKE LT_TMP.
ASSIGN LD_DATA->* TO <LFT_OUTTAB>.
CREATE DATA LD_LINE LIKE LINE OF <LFT_OUTTAB>.
ASSIGN LD_LINE->* TO <LFS_OUTTAB>.
ELSE.
ASSIGN LT_TMP TO <LFS_OUTTAB>.
ENDIF.
LR_STRDESCR ?= CL_ABAP_TYPEDESCR=>DESCRIBE_BY_DATA( <LFS_OUTTAB> ).
LT_FCAT = CORRESPONDING #( CL_SALV_DATA_DESCR=>READ_STRUCTDESCR( LR_STRDESCR )
MAPPING KEY = KEYFLAG
COLTEXT = FIELDTEXT
REF_TABLE = REFTABLE
REF_FIELD = REFFIELD
CFIELDNAME = PRECFIELD
QFIELDNAME = PRECFIELD ).
LOOP AT LT_FCAT ASSIGNING FIELD-SYMBOL(<LFS>).
<LFS>-COL_POS = SY-TABIX.
IF <LFS>-DATATYPE EQ 'CLNT'.
<LFS>-TECH = 'X'.
ENDIF.
CASE <LFS>-DATATYPE.
WHEN 'CURR'.
CLEAR <LFS>-QFIELDNAME.
WHEN 'QUAN'.
CLEAR <LFS>-CFIELDNAME.
ENDCASE.
IF <LFS>-COLTEXT IS INITIAL AND <LFS>-REPTEXT IS INITIAL AND <LFS>-SCRTEXT_L IS INITIAL AND <LFS>-SCRTEXT_M IS INITIAL AND <LFS>-SCRTEXT_S IS INITIAL.
CLEAR <LFS>-COLTEXT.
ENDIF.
IF <LFS>-TABNAME IS NOT INITIAL.
CLEAR <LFS>-ROLLNAME.
ENDIF.
ENDLOOP.
"Field catalog의 누락된 항목 보충 (선택사항으로, ALV Display시 알아서 보충됨)
CALL FUNCTION 'LVC_FIELDCAT_COMPLETE'
CHANGING
CT_FIELDCAT = LT_FCAT[].
*E> 필드카탈로그 생성 ---------------------------------------------------------
# 3. 필드 카탈로그 직접 생성
서브루틴을 만들어 LVC_T_FACT에 APPEND
DATA LT_FCAT TYPE LVC_T_FCAT.
TYPES: BEGIN OF T_TMP,
BUKRS LIKE T001-BUKRS,
MENGE LIKE MSEG-MENGE,
MATNR TYPE MATNR,
MEINS TYPE MEINS,
CHECK TYPE C,
END OF T_TMP.
DATA: LT_TMP TYPE STANDARD TABLE OF T_TMP.
*S> 필드카탈로그 생성 ---------------------------------------------------------
"필드카탈로그 직접 생성
PERFORM CREATE_FIELD_CAT_LVC TABLES LT_FCAT USING :
"COL_POS KEY FIELDNAME COLTEXT DATATYPE OUTPUTLEN CONVEXIT JUST NO_ZERO QFIELDNAME CFIELDNAME DO_SUM
1 'X' 'BUKRS' '회사코드' 'CHAR' 4 '' 'L' ' ' '' '' ' ',
2 ' ' 'MENGE' '수량' 'QUAN' 16 '' 'R' 'X' 'MEINS' '' 'X',
3 ' ' 'MATNR' '자재코드' 'CHAR' 40 'MATN1' 'L' ' ' '' '' ' ',
4 ' ' 'MEINS' '단위' 'UNIT' 3 'CUNIT' 'L' ' ' '' '' ' ',
5 ' ' 'CHECK' '체크' 'CHAR' 1 '' 'C' ' ' '' '' ' '.
*E> 필드카탈로그 생성 ---------------------------------------------------------
ZCL_SALV_TEST=>DISPLAY( LT_FCAT ).
*&---------------------------------------------------------------------*
*& Form CREATE_FIELD_CAT_LVC
*&---------------------------------------------------------------------*
*& 필드 카탈로그를 만들기 위한 서브루틴
*&---------------------------------------------------------------------*
*& --> LT_FCAT
*& COL_POS 열 순서
*& KEY 키 필드여부
*& FIELDNAME 필드명
*& COLTEXT 필드 설명
*& DATATYPE Dictionary 데이타유형
*& OUTPUTLEN 문자의 열 너비
*& CONVEXIT 변환루틴
*& JUST 정렬
*& NO_ZERO 제로값 비표시 여부
*& QFIELDNAME 참조한 단위 필드이름
*& CFIELDNAME 참조한 통화 필드이름
*& DO_SUM 열 값 총합 여부
*&---------------------------------------------------------------------*
FORM CREATE_FIELD_CAT_LVC TABLES P_TABLE
USING COL_POS
KEY
FIELDNAME
COLTEXT
DATATYPE
OUTPUTLEN
CONVEXIT
JUST
NOZERO
MEINS
WAERS
DO_SUM.
DATA LS_FCAT_LVC TYPE LVC_S_FCAT.
LS_FCAT_LVC-COL_POS = COL_POS.
LS_FCAT_LVC-KEY = KEY.
LS_FCAT_LVC-FIELDNAME = FIELDNAME.
LS_FCAT_LVC-COLTEXT = COLTEXT.
LS_FCAT_LVC-DATATYPE = DATATYPE.
LS_FCAT_LVC-OUTPUTLEN = OUTPUTLEN.
LS_FCAT_LVC-CONVEXIT = CONVEXIT.
LS_FCAT_LVC-JUST = JUST.
LS_FCAT_LVC-NO_ZERO = NOZERO.
LS_FCAT_LVC-QFIELDNAME = MEINS.
LS_FCAT_LVC-CFIELDNAME = WAERS.
LS_FCAT_LVC-DO_SUM = DO_SUM.
APPEND LS_FCAT_LVC TO P_TABLE.
ENDFORM.
'ABAP > 개발Tip' 카테고리의 다른 글
[개발Tip] CL_GUI_SIMPLE_TREE 사용 방법 (0) | 2023.10.16 |
---|---|
[개발Tip] Event 호출로 백그라운드 작업 실행(Event Batch) (0) | 2023.09.14 |
[개발Tip] RESTful API 호출 2가지 방법(CL_HTTP_CLIENT, CL_REST_HTTP_CLIENT) (0) | 2023.06.28 |
[개발Tip] REPLACE의 REGEX (정규표현식)를 이용한 특수문자 제거 (0) | 2023.06.22 |
[개발Tip] 비동기 처리를 위한 백그라운드 작업 생성 (0) | 2023.06.22 |
댓글