본문 바로가기
ABAP/개발Tip

[개발Tip] ALV Field catalog(필드 카탈로그) 만드는 3가지 방법

by name_text 2023. 8. 25.

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 등)

DFIES 와 LVC_S_FCAT 필드 구조

 

# 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.

 

댓글