필드심볼 이야기(http://erp.sarang.net)
작성자 : 한상열
1. 개요
필드심볼 모르면 생노가다!
알면 초간단!
2. 상황 발생
각 계정별로 원하는 기간(월별) 동안의 총 Recivable과
Payable 금액을 보여주는 레포트를 짜고 싶습니다.
테이블을 찾았더니 GLT0 이군요. 첨에는 테이블이 예쁘
게 생겼다고 생각했습니다. 야~ 이거 월별 금액이 각각
의 월필드에 들어가있으니 무지 좋구만~
허걱!
근데 어떻게 각 필드별로 합을 구하쥐?
사용자가 어떤 기간을 줄지 알고?
3. 해결책
멋있는 멍님의 글을 참고해봅시다.
-----------------------------------------------------------------------------------
이 테이블을 자세히 살펴보면...
...
...
HSL01
HSL02
HSL03
HSL04
HSL05
HSL06
HSL07
HSL08
HSL09
HSL10
HSL11
HSL12
HSL13
HSL14
HSL15
HSL16
...
...
이런식으로 필드가 존재합니다...
이 때, 위에서 나열한 필드의 뒤 두 자리가 월을 나타낸다고 했을 때,
현재월까지의 합을 구하는 레포트를 구현한다고 가정을 해봅시다...
만약 Field-Symbol을 사용하지 않을 경우...
지금이 10월이니깐 로직이 이렇게 되겠죠...
변수 = GLT0-HSL01 + GLT0-HSL02 + ......... + GLT0-HSL10. (헥헥~~)
그렇다면 11월일때는 어떡할 것인가 ???
5월일때는 ? 12월일때는 ???
이거 완전한 노가다 입니다...
이때, 우리의 Field-Symbol이 등장합니다... 짜잔~~~
가볍게 코딩을 합니다...
...
FIELD-SYMBOLS <FIELD>.
DATA : CN(2) TYPE N,
FNAME(10),
SUM LIKE GLT0-HSL01.
...
...
DO CN TIMES. "여기서 CN이라는 변수는 해당 월
CC = SY-INDEX.
CONCATENATE 'GLT0-HSL' CC INTO FNAME.
ASSIGN (FNAME) TO <FIELD>.
SUM = SUM + <FIELD>.
CLEAR : FNAME, <FIELD>.
ENDDO.
...
...
이렇게 하면 위에서 했던 노가다를 간단히 몇 줄의 문장으로 기술할 수 있는 것이죠...
<FIELD>라는 FIELD-SYMBOL에는 GTL0-HSL01의 값부터 시작해서...
GTL0-HSL10의 값까지 차례로 들어가면서 더해지게 되는 것이죠...
그리고 보너스로...
이런 구문도 존재한답니다...
...
...
DO.
...
ASSIGN COMPONENT SY-INDEX OF STRUCTURE CUSTOMER TO .
...
ENDDO.
이때, 가령 CUSTOMER라는 INERNAL TABLE이 다음과 같은 필드를 가지는
구조를 참조한다고 할 때...
(KUNNR, ANRED, NAME1, PFACH, STRAS, PSTLZ, ORT01, TELF1, TELFX)
DO... ENDDO... 문장 내에서 필드의 수만큼 LOOP을 돌게 되는거죠...
즉, 하나씩 디버깅을 해보면, 첫번째 루프를 돌때는, <FIELD>에 CUSTOMER-KUNNR의 값이...
그 다음 루프를 돌때는, <FIELD>에 CUSTOMER-ANRED의 값이...
세번째 루프를 돌때는, <FIELD>에 CUSTOMER-NAME1의 값이 들어갑니다...
-----------------------------------------------------------------------------------
4. 결론
노가다 많이 줄였습니다.
**************************************************************************
FIELD만 바뀌고 규칙적인 작업을 할때 각각을 프로그램 LOGIC으로 구성하려면
단순 CODING으로 쓸 데없이 LINE만 길어 질 수 있다.
이때 FIELD-SYMBOL을 사용하면 간단히 해결되면서 프로그램을 분석하기도 한결 수월해 진다.
우선 FIELD-SYMBOL 의 여러가지 변형을 살펴보면
1. ASSIGN f TO <fs>.
단순히 field f의 값을 <fs>가 가리키도록 한다.
2. ASSIGN (f) TO <fs>.
동적 field를 이용한것인데 field f안의 값을 또 field명으로 보고 그 field의 값
을 <fs>가 가리키도록 한다.
3. ASSIGN TABLE FIELD (f) TO <fs>.
2와 같은 경우이나 f 의 값이 table의 field명 일때 그 table field의 값을
<fs>가 가리키도록 한다.
4. ASSIGN LOCAL COPY OF MAIN TABLE FIELD (f) TO <fs>.
3와 같은 경우이나 tables로 선언된 main program의 table field값을
<fs>가 가리키는 것이 아니라 값만 복사 하여 사용하기 때문에 변경할 수 없다.
5. ASSIGN COMPONENT idx OF STRUCTURE rec TO <fs>.
structure의 구성요소 순서를 idx에서 읽어 그 순서에 위치한 구성요소의 값을
<fs>에 할당한다.
6. ASSIGN COMPONENT name OF STRUCTURE rec TO <fs>.
structure의 구성요소명(field명)을 name에서 읽어 그 구성요소의 값을
<fs>에 할당한다.
5번을 제외한 모든 경우는 field명을 사용하는 것이라서 field명에 규칙이 없으면
coding line 줄이는데 효과를 보지 못한다.
따라서 여기서는 field명에 규칙이 없더라도 coding line을 획기 적으로 줄일 수 있는
5번경우를 사용한 예제만 소개하겠다.
예제)
FIELD-SYMBOLS : <FS1>, <FS2>.
DATA:IDX1 LIKE SY-INDEX.
DATA: BEGIN OF ITAB1 OCCURS 0,
CCYYMM(8),
WERKS LIKE MARD-WERKS,
MATNR LIKE MARD-MATNR,
LABST LIKE MARD-LABST,
UMLME LIKE MARD-UMLME,
INSME LIKE MARD-INSME,
EINME LIKE MARD-EINME,
SPEME LIKE MARD-SPEME,
RETME LIKE MARD-RETME,
VMLAB LIKE MARD-VMLAB,
VMUML LIKE MARD-VMUML,
VMINS LIKE MARD-VMINS,
VMEIN LIKE MARD-VMEIN,
VMSPE LIKE MARD-VMSPE,
VMRET LIKE MARD-VMRET,
END OF ITAB1.
DATA: ITAB2 LIKE ITAB1 OCCURS 0 WITH HEADER LINE.
경우1) FIELD-SYMBOL 사용하지 않았을 경우
LOOP AT ITAB1.
READ TABLE ITAB2 WITH KEY CCYYMM = ITAB1-PERIOD
WERKS = ITAB1-WERKS
MATNR = ITAB1-MATNR
BINARY SEARCH.
IF SY-SUBRC <> 0.
WRITE : / 'Not found in ITAB2 : ',
ITAB1-CCYYMM,
ITAB1-WERKS,
ITAB1-MATNR.
ELSE.
IF ITAB1-LABST <> ITAB2-LABST.
WRITE : / SY-INDEX,
ITAB2-CCYYMM,
ITAB2-WERKS,
ITAB2-MATNR,
ITAB1-LABST,
ITAB2-LABST.
ENDIF.
IF ITAB1-UMLME <> ITAB2-UMLME.
WRITE : / SY-INDEX,
ITAB2-CCYYMM,
ITAB2-WERKS,
ITAB2-MATNR,
ITAB1-UMLME,
ITAB2-UMLME.
ENDIF.
.............. 12번 반복 ........
ENDIF.
ENDLOOP.
경우2) FIELD-SYMBOL 사용했을 경우
LOOP AT ITAB1.
READ TABLE ITAB2 WITH KEY CCYYMM = ITAB1-PERIOD
WERKS = ITAB1-WERKS
MATNR = ITAB1-MATNR
BINARY SEARCH.
IF SY-SUBRC <> 0.
WRITE : / 'Not found in ITAB2 : ',
ITAB1-CCYYMM,
ITAB1-WERKS,
ITAB1-MATNR.
ELSE.
IDX1 = 3.
DO 12 TIMES.
IDX1 = IDX1 + 1.
ASSIGN COMPONENT IDX1 OF STRUCTURE ITAB1 TO <FS1>.
ASSIGN COMPONENT IDX1 OF STRUCTURE ITAB2 TO <FS2>.
IF <FS1> <> <FS2>.
WRITE : / SY-INDEX,
ITAB2-CCYYMM,
ITAB2-WERKS,
ITAB2-MATNR,
<FS1>,
<FS2>.
ENDIF.
ENDDO.
ENDIF.
ENDLOOP.
필드심볼을 이용하면 보통사용하는 테이블의 모양을 간단하게 바꿀 수 있다.
<기존에 사용하는 테이블>
연월 | 수량 | 금액 | 단가 |
200501 | 120 | 3500 | 23400 |
200502 | 3000 | 2300 | 3600 |
200503 | 500 | 1000 | 530 |
200504 | 300 | 28 | 400 |
<원하는 테이블>
200501 | 200502 | 200503 | 200504 | |
수량 | 120 | 3000 | 500 | 300 |
단가 | 3500 | 2300 | 1000 | 28 |
금액 | 23400 | 3600 | 530 | 400 |
우리가 원하는것은 해당연월에 수량, 단가, 금액이다.
field symbol을 이용해서 직접 확인해보자.
REPORT ZPPRTESTYW .
DATA: BEGIN OF S,
A VALUE '1', B VALUE '2', C VALUE '3', D VALUE '4',
E VALUE '5', F VALUE '6', G VALUE '7', H VALUE '8',
END OF S.
DATA OFF TYPE I.
FIELD-SYMBOLS <FS>.
ASSIGN S-A TO <FS>.
DO 4 TIMES.
OFF = SY-INDEX - 1.
ASSIGN <FS>+OFF(1) TO <FS>.
WRITE <FS>.
ENDDO.
==> 결과 1,2,4,7
<field symbol을 이용하여 데이터 뿌리기>
fname에 필드명을 count 와 조합하여 만든후 bufs로 assign한다.
LOOP AT it_sum3.
MOVE it_sum3-buname TO it_result-zrsbu.
DO 4 TIMES.
in = it_sum3-lfmon.
cn = cn + 1.
CONCATENATE 'it_result-zrs' in cn INTO fname.
ASSIGN (fname) TO <bufs>.
CASE cn.
WHEN 1.
<bufs> = it_sum3-abssu.
WHEN 2.
<bufs> = it_sum3-sucor.
WHEN 3.
<bufs> = it_sum3-abspr / rd_int.
WHEN 4.
<bufs> = it_sum3-prcor.
ENDCASE.
CLEAR : fname.
ENDDO.
COLLECT it_result.
CLEAR : it_result,it_sum3, cn, in.
ENDLOOP.
[출처] FIELD-SYMBOL 사용예|작성자 미래