ABAP 프로그램 만들다 보면 필드카탈로그 일일이 설정하기 귀찮을 때가 있죠..
그럴 때 유용한 클래스 입니다.
일단 클래스로 만들 것이기 때문에 Class Builder로 GoGo
이름은 대충 지어주고 생성 버튼 클릭 ▼
내역 대충 써주고 넘어가죠 ▼
방법을 두개 입력
GET_FCAT_FOR_ITAB / Static Method / Public
GET_ELEMENTS / Static Method / Private
▼
각 방법에 매개변수를 설정하기 GET_FCAT_FOR_ITAB 먼저 클릭하고 매개변수 클릭 ▼
IT_TABLE / Importing / TABLE
RT_FCAT / Exporting / LVC_T_FCAT
다 입력하였으면 방법 눌러서 다시 뒤로 ▼
이번엔 GET_ELEMENTS 매개변수 설정하러 가시죠 ▼
I_COMP_T / Importing / CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE
R_COMP_T / Returning / CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE
다 입력하였으면 방법 눌러서 다시 뒤로 ▼
이제 각 방법의 소스를 작성하러 갑시다~!
소스를 작성할 방법 선택하고 버튼 누르거나 해당 방법 더블클릭
먼저 GET_FCAT_FOR_ITAB 작성하죠 ▼
아래의 코드를 긁어줍시다.
GET_FCAT_FOR_ITAB 소스코드
FIELD-SYMBOLS: <WA> TYPE ANY,
<CP> TYPE ANY.
DATA: LV_SREF TYPE REF TO DATA,
LV_CREF TYPE REF TO DATA.
DATA: LC_STRU_REF TYPE REF TO CL_ABAP_STRUCTDESCR,
LC_CLSS_REF TYPE REF TO CL_ABAP_CLASSDESCR,
LC_ELEM_REF TYPE REF TO CL_ABAP_ELEMDESCR,
LC_TAB_REF TYPE REF TO CL_ABAP_TABLEDESCR,
LT_COMP TYPE CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE,
LT_COMP_ LIKE LT_COMP,
LS_COMP LIKE LINE OF LT_COMP,
LV_SIZE TYPE I,
LV_INDEX TYPE I,
LV_HLPID TYPE STRING,
LV_SNAME TYPE STRING,
LS_FCAT TYPE LVC_S_FCAT,
LS_DFIES TYPE DFIES,
LT_TAB TYPE TABLE OF STRING,
LV_REFSTRUCT TYPE SWCONTDEF-REFSTRUCT,
LV_REFFIELD TYPE SWCONTDEF-REFFIELD,
LS_DD04V TYPE DD04V,
LV_LEN TYPE I.
LC_TAB_REF ?= CL_ABAP_TYPEDESCR=>DESCRIBE_BY_DATA( IT_TABLE ).
LC_STRU_REF ?= LC_TAB_REF->GET_TABLE_LINE_TYPE( ).
*-- Check Reference
LC_CLSS_REF ?= CL_ABAP_TYPEDESCR=>DESCRIBE_BY_OBJECT_REF( LC_STRU_REF ).
IF LC_CLSS_REF->GET_RELATIVE_NAME( ) <> 'CL_ABAP_STRUCTDESCR'.
* RAISE not_a_structure.
ENDIF.
*-- Recursive Search for Include.
LT_COMP_ = LC_STRU_REF->GET_COMPONENTS( ).
* Table Type 제거
LOOP AT LT_COMP_ INTO LS_COMP.
LC_CLSS_REF ?= CL_ABAP_TYPEDESCR=>DESCRIBE_BY_OBJECT_REF( LS_COMP-TYPE ).
IF LC_CLSS_REF->GET_RELATIVE_NAME( ) = 'CL_ABAP_TABLEDESCR'.
DELETE LT_COMP_.
ENDIF.
ENDLOOP.
LT_COMP = GET_ELEMENTS( LT_COMP_ ).
LV_SIZE = LINES( LT_COMP ).
LV_SNAME = LC_STRU_REF->ABSOLUTE_NAME."get_relative_name( ).
*-- get memebers
CREATE DATA LV_SREF TYPE (LV_SNAME).
ASSIGN LV_SREF->* TO <WA>.
LOOP AT LT_COMP INTO LS_COMP.
ASSIGN COMPONENT LS_COMP-NAME OF STRUCTURE <WA> TO <CP>.
DESCRIBE FIELD <CP> HELP-ID LV_HLPID.
** DO lv_size TIMES.
** lv_index = lv_index + 1.
**
** UNASSIGN <cp>.
** ASSIGN COMPONENT lv_index OF STRUCTURE <wa> TO <cp>.
** clear lv_hlpid.
** DESCRIBE FIELD <cp> HELP-ID lv_hlpid.
" XXX-VVV, VVV, SPACE
CLEAR : LT_TAB, LT_TAB[].
SPLIT LV_HLPID AT '-' INTO TABLE LT_TAB.
LV_LEN = LINES( LT_TAB ).
READ TABLE LT_COMP INTO LS_COMP INDEX LV_INDEX.
IF LV_LEN = 2. "struct + field
READ TABLE LT_TAB INTO LV_REFSTRUCT INDEX 1.
READ TABLE LT_TAB INTO LV_REFFIELD INDEX 2.
CALL FUNCTION 'SWP_DDIC_FIELD_INFO_GET'
EXPORTING
REFSTRUCT = LV_REFSTRUCT
REFFIELD = LV_REFFIELD
LANGUAGE = SY-LANGU
IMPORTING
FIELD_ATTRIBUTES = LS_DFIES
EXCEPTIONS
FIELD_INFO_NOT_FOUND = 1
OTHERS = 9.
IF SY-SUBRC = 0.
MOVE-CORRESPONDING LS_DFIES TO LS_FCAT.
* Data Type 에 따라서
* Currency, Quanitity 참조 Field 가 있는지 확인 한다
* 없는경우 삭제 한다
CASE LS_DFIES-DATATYPE.
WHEN 'CURR' OR 'QUAN'.
READ TABLE LT_COMP WITH KEY NAME = LS_DFIES-REFFIELD
TRANSPORTING NO FIELDS.
IF SY-SUBRC = 0.
CASE LS_DFIES-DATATYPE.
WHEN 'CURR' .
LS_FCAT-CFIELDNAME = LS_DFIES-REFFIELD.
WHEN 'QUAN'.
LS_FCAT-QFIELDNAME = LS_DFIES-REFFIELD.
ENDCASE.
ENDIF.
ENDCASE.
LS_FCAT-REF_TABLE = LV_REFSTRUCT.
LS_FCAT-REF_FIELD = LV_REFFIELD.
LS_FCAT-TABNAME = ''.
"[Add]
LS_FCAT-REPTEXT = LS_FCAT-COLTEXT = LS_FCAT-SCRTEXT_L.
LS_FCAT-FIELDNAME = LS_COMP-NAME.
IF LS_FCAT-COL_POS IS INITIAL."ADD
LS_FCAT-COL_POS = LV_INDEX. "ADD
ENDIF. "ADD
APPEND LS_FCAT TO RT_FCAT.
ELSE.
** RAISE no_ddic.
ENDIF.
ELSEIF LV_LEN = 1. "DataElement
READ TABLE LT_TAB INTO LV_REFFIELD INDEX 1.
CALL FUNCTION 'DDIF_DTEL_GET'
EXPORTING
NAME = LV_REFFIELD
LANGU = SY-LANGU
IMPORTING
DD04V_WA = LS_DD04V
EXCEPTIONS
ILLEGAL_INPUT = 1
OTHERS = 2.
IF SY-SUBRC = 0.
MOVE-CORRESPONDING LS_DD04V TO LS_FCAT.
LS_FCAT-REF_TABLE = ''.
LS_FCAT-TABNAME = ''.
"[Add]
LS_FCAT-REPTEXT = LS_FCAT-COLTEXT = LS_FCAT-SCRTEXT_L.
IF LV_REFFIELD <> LS_COMP-NAME.
LS_FCAT-REF_FIELD = LV_REFFIELD.
ENDIF.
LS_FCAT-FIELDNAME = LS_COMP-NAME.
IF LS_FCAT-COL_POS IS INITIAL.
LS_FCAT-COL_POS = LV_INDEX.
ENDIF.
APPEND LS_FCAT TO RT_FCAT.
ELSE.
* RAISE no_ddic.
ENDIF.
ELSEIF LV_LEN = 0. "AND iv_cfield = 'X'. "Custom Field
*
* lc_elem_ref ?= ls_comp-type.
* ls_fcat-fieldname = ls_comp-name.
* ls_fcat-inttype = lc_elem_ref->type_kind.
* ls_fcat-intlen = lc_elem_ref->length.
* ls_fcat-decimals = ls_fcat-decimals_o = lc_elem_ref->decimals.
* ls_fcat-outputlen = lc_elem_ref->output_length.
*
* IF ls_fcat-COL_POS IS INITIAL.
* ls_fcat-COL_POS = lv_index.
* ENDIF.
*
* APPEND ls_fcat TO rt_fcat.
DATA: lv_relative_Name TYPE STRING.
LC_CLSS_REF ?= CL_ABAP_TYPEDESCR=>DESCRIBE_BY_OBJECT_REF( LS_COMP-TYPE ).
lv_relative_Name = LC_CLSS_REF->GET_RELATIVE_NAME( ) .
IF lv_relative_Name = 'CL_ABAP_STRUCTDESCR' . "다음에...
* -- Recursive Search for Include.
* DATA: lt_comp1_ TYPE cl_abap_structdescr=>component_table.
*data: lc_stru_ref_1 TYPE REF TO cl_abap_structdescr,
* lc_clss_ref_1 TYPE REF TO cl_abap_classdescr,
* lc_elem_ref_1 TYPE REF TO cl_abap_elemdescr,
* lc_tab_ref_1 TYPE REF TO cl_abap_tabledescr.
*
* lc_tab_ref_1 ?= cl_abap_typedescr=>describe_by_data( ls_comp-type->COMPONENT ).
* lc_stru_ref_1 ?= lc_tab_ref->get_table_line_type( ).
* lt_comp1_ = ls_comp-type->COMPONENTS.
* CASE ls_comp-type->kind.
* WHEN cl_abap_structdescr=>kind_struct "S
* OR cl_abap_structdescr=>kind_table. "T
* CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
* EXPORTING
* i_structure_name = lv_structure_name
* i_bypassing_buffer = 'X'
* CHANGING
* ct_fieldcat = lt_fieldcat
* EXCEPTIONS
* inconsistent_interface = 1
* program_error = 2.
*
* ENDCASE.
ELSE.
LC_ELEM_REF ?= LS_COMP-TYPE.
LS_FCAT-FIELDNAME = LS_COMP-NAME.
LS_FCAT-INTTYPE = LC_ELEM_REF->TYPE_KIND.
LS_FCAT-INTLEN = LC_ELEM_REF->LENGTH.
LS_FCAT-DECIMALS = LS_FCAT-DECIMALS_O = LC_ELEM_REF->DECIMALS.
LS_FCAT-OUTPUTLEN = LC_ELEM_REF->OUTPUT_LENGTH.
IF LS_FCAT-COL_POS IS INITIAL.
LS_FCAT-COL_POS = LV_INDEX.
ENDIF.
APPEND LS_FCAT TO RT_FCAT.
ENDIF.
ENDIF.
CLEAR: LS_FCAT, LS_COMP, LV_REFFIELD, LV_REFSTRUCT, LS_DD04V, LS_DFIES, LC_ELEM_REF, LT_TAB[].
ENDLOOP.
이번엔 GET_ELEMENTS ▼
GET_ELEMENTS 소스코드
DATA: LC_CLSS_REF TYPE REF TO CL_ABAP_CLASSDESCR,
LT_COMP TYPE CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE,
LS_COMP LIKE LINE OF LT_COMP,
LT_COMP_D LIKE LT_COMP,
LT_COMP_R LIKE LT_COMP,
LS_COMP_D LIKE LS_COMP,
LV_STRU_REF TYPE REF TO CL_ABAP_STRUCTDESCR,
LV_INDEX TYPE SY-INDEX.
LT_COMP[] = I_COMP_T[].
LOOP AT LT_COMP INTO LS_COMP WHERE AS_INCLUDE = 'X'.
LV_INDEX = SY-TABIX.
DELETE LT_COMP.
LV_STRU_REF ?= LS_COMP-TYPE.
LT_COMP_D = LV_STRU_REF->GET_COMPONENTS( )."Recursive Point
IF LS_COMP-SUFFIX IS NOT INITIAL.
LOOP AT LT_COMP_D INTO LS_COMP_D WHERE AS_INCLUDE = SPACE.
CONCATENATE LS_COMP_D-NAME LS_COMP-SUFFIX INTO LS_COMP_D-NAME.
MODIFY LT_COMP_D FROM LS_COMP_D.
ENDLOOP.
ENDIF.
LT_COMP_R = GET_ELEMENTS( LT_COMP_D ).
LOOP AT LT_COMP_R INTO LS_COMP_D.
INSERT LS_COMP_D INTO LT_COMP INDEX LV_INDEX.
LV_INDEX = LV_INDEX + 1.
CLEAR LS_COMP_D.
ENDLOOP.
CLEAR : LS_COMP, LT_COMP_R[].
ENDLOOP.
R_COMP_T = LT_COMP.
저장하고 활성화시켜주면 클래스 작성 끝 ▼
프로그램에 아래와 같이 삽입하면 해당 프로그램의 필드 카탈로그가 인터널 테이블(GT_LIST)의 속성에 맞게 자동 변환 됩니다.
※ GET_FCAT_FOR_ITAB 의 소스코드는 그대로 사용하셔도 되지만 자기 상황에 맞게 수정하시면 됩니다.
끝.
'ABAP' 카테고리의 다른 글
ALV Grid에서 Screen 스크롤이 무한정 내려갈 때 해결 (0) | 2023.07.06 |
---|---|
1000번 화면 F4 Search help (0) | 2023.07.06 |
Background Job Function 주기 코딩 (0) | 2023.06.27 |
User-exit 수정하다가 SQL error 발생(Fixed point arithmetic) (0) | 2023.06.21 |
ALV Grid에서 선택한 데이터 가져오기 (0) | 2021.12.03 |