
TOP 선언
" ===== 트리 관련 전역 선언 =====
" 노드 키 (filter_detail에서 루트 판단)
DATA: gv_all_node TYPE lvc_nkey,
gv_sel_node TYPE lvc_nkey.
" 데이터 테이블
DATA : BEGIN OF gs_data,
END OF gs_data,
gt_data LIKE TABLE OF gs_data, " 트리용 마스터
gt_make_tree LIKE TABLE OF gs_data. " 트리 내부 outtab
" CDS 기반 그리드용
DATA: gs_item TYPE zcds_e3_cm_0001_i,
gt_item LIKE TABLE OF gs_item.
" 컨테이너 / 트리 / 그리드 객체
DATA: gcl_dock_container TYPE REF TO cl_gui_docking_container,
gcl_splitter TYPE REF TO cl_gui_splitter_container,
gcl_top_con TYPE REF TO cl_gui_container, " TOP OF PAGE
gcl_tree_con TYPE REF TO cl_gui_container, " 트리
gcl_right_con TYPE REF TO cl_gui_container, " 그리드
gcl_chart_con TYPE REF TO cl_gui_container, " 차트
gcl_tree TYPE REF TO cl_gui_alv_tree,
gcl_grid TYPE REF TO cl_gui_alv_grid,
gcl_doc_top TYPE REF TO cl_dd_document.
" 필드카탈로그 / 레이아웃
DATA: gt_fcat_tree TYPE lvc_t_fcat, " 트리 숫자 컬럼용
gt_fcat TYPE lvc_t_fcat, " 그리드용
gs_fcat TYPE lvc_s_fcat,
gs_layout TYPE lvc_s_layo,
gs_variant TYPE disvariant,
gs_stable TYPE lvc_s_stbl.
" 이벤트
DATA: gt_event TYPE cntl_simple_events,
gs_event LIKE LINE OF gt_event.
PBO

*&---------------------------------------------------------------------*
*& Form create_dock_con
*&---------------------------------------------------------------------*
FORM create_dock_con.
CREATE OBJECT gcl_dock_container
EXPORTING
side = cl_gui_docking_container=>dock_at_left
extension = 5000.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form create_splitter
*& 상하(TOP/하단) → 좌우(트리/그리드) → 우측 상하(그리드/차트)
*&---------------------------------------------------------------------*
FORM create_splitter.
DATA: lcl_bottom_con TYPE REF TO cl_gui_container,
lcl_lr_splitter TYPE REF TO cl_gui_splitter_container,
lcl_right_splitter TYPE REF TO cl_gui_splitter_container.
" [1단계] 상하 분할 (상단 20% TOP / 하단 80% 컨텐츠)
CREATE OBJECT gcl_splitter
EXPORTING
parent = gcl_dock_container
rows = 2
columns = 1.
gcl_splitter->get_container( EXPORTING row=1 column=1 RECEIVING container=gcl_top_con ).
gcl_splitter->get_container( EXPORTING row=2 column=1 RECEIVING container=lcl_bottom_con ).
gcl_splitter->set_row_height( id=1 height=20 ).
gcl_splitter->set_row_height( id=2 height=80 ).
" [2단계] 하단 좌우 분할 (트리 35% / 그리드 65%)
CREATE OBJECT lcl_lr_splitter
EXPORTING
parent = lcl_bottom_con
rows = 1
columns = 2.
lcl_lr_splitter->get_container( EXPORTING row=1 column=1 RECEIVING container=gcl_tree_con ).
lcl_lr_splitter->get_container( EXPORTING row=1 column=2 RECEIVING container=gcl_right_con ).
lcl_lr_splitter->set_column_width( id=1 width=35 ).
lcl_lr_splitter->set_column_width( id=2 width=65 ).
" [3단계] 우측 상하 분할 (그리드 50% / 차트 50%)
CREATE OBJECT lcl_right_splitter
EXPORTING
parent = gcl_right_con
rows = 2
columns = 1.
lcl_right_splitter->get_container( EXPORTING row=1 column=1 RECEIVING container=gcl_right_con ).
lcl_right_splitter->get_container( EXPORTING row=2 column=1 RECEIVING container=gcl_chart_con ).
lcl_right_splitter->set_row_height( id=1 height=50 ).
lcl_right_splitter->set_row_height( id=2 height=50 ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form create_top_doc
*& cl_dd_document 객체 생성 (set_top_page에서 사용)
*&---------------------------------------------------------------------*
FORM create_top_doc.
CREATE OBJECT gcl_doc_top
EXPORTING
style = 'ALV_TO_HTML'
background_color = 1
no_margins = space.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form set_tree_header
*& 트리 좌측 숫자 컬럼 필드카탈로그
*&---------------------------------------------------------------------*
FORM set_tree_header.
PERFORM set_fcat_tree USING:
'APRICE' '취득원가' 'ZTE3CM0002' 'APRICE' '8',
'ACCUM' '감가누계' 'ZTE3CM0002' 'ACCUM' '8',
'BOOK' '장부가액' 'ZTE3CM0002' 'APRICE' '8',
'WAERS' '통화' 'ZTE3CM0002' 'WAERS' '8'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form set_fcat_tree
*&---------------------------------------------------------------------*
FORM set_fcat_tree USING pv_field
pv_text
pv_ref_table
pv_ref_field
pv_len.
gs_fcat-fieldname = pv_field.
gs_fcat-coltext = pv_text.
gs_fcat-ref_table = pv_ref_table.
gs_fcat-ref_field = pv_ref_field.
gs_fcat-outputlen = pv_len.
CASE pv_field.
WHEN 'APRICE' OR 'ACCUM' OR 'BOOK'.
gs_fcat-cfieldname = 'WAERS'. " 통화키 연결
gs_fcat-do_sum = 'X'. " 합계 자동계산
ENDCASE.
APPEND gs_fcat TO gt_fcat_tree.
CLEAR gs_fcat.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form create_tree
*& ALV Tree 객체 생성 + 이벤트 등록
*&---------------------------------------------------------------------*
FORM create_tree.
DATA: l_hierarchy_header TYPE treev_hhdr.
l_hierarchy_header-heading = '자산명'.
l_hierarchy_header-width = 25.
l_hierarchy_header-width_pix = space.
CREATE OBJECT gcl_tree
EXPORTING
parent = gcl_tree_con
node_selection_mode = cl_gui_column_tree=>node_sel_mode_single
item_selection = space
no_html_header = 'X'
no_toolbar = space.
" 더블클릭 이벤트 등록
gcl_tree->get_registered_events( IMPORTING events = gt_event ).
gs_event-eventid = cl_gui_column_tree=>eventid_node_double_click.
gs_event-appl_event = 'X'.
APPEND gs_event TO gt_event.
gcl_tree->set_registered_events( EXPORTING events = gt_event ).
SET HANDLER lcl_event_handler=>handle_node_click FOR gcl_tree.
gs_variant-report = sy-repid.
gcl_tree->set_table_for_first_display(
EXPORTING
i_save = 'A'
is_variant = gs_variant
is_hierarchy_header = l_hierarchy_header
CHANGING
it_outtab = gt_make_tree " 트리 내부 데이터 (add_node가 여기 채워넣음)
it_fieldcatalog = gt_fcat_tree ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form make_hierarchy
*& [Lv.0] 전체 루트
*& [Lv.1] 자산분류 폴더 (anlkl 기준 합계)
*& [Lv.2] 개별 자산 리프
*&---------------------------------------------------------------------*
FORM make_hierarchy.
DATA: lt_data_tmp LIKE TABLE OF gs_data,
lt_sum LIKE TABLE OF gs_data,
ls_sum LIKE gs_data,
ls_root LIKE gs_data,
lv_all_key TYPE lvc_nkey,
lv_cls_key TYPE lvc_nkey,
lv_node_key TYPE lvc_nkey.
lt_data_tmp = gt_data.
REFRESH: gt_make_tree, lt_sum.
"----------------------------------------------------------------
" STEP 1. anlkl별 합계 집계 (COLLECT → O(n) 루프 1번)
" COLLECT은 anlkl 같은 행끼리 aprice/accum 자동 합산
"----------------------------------------------------------------
LOOP AT lt_data_tmp INTO gs_data.
CLEAR ls_sum.
ls_sum-anlkl = gs_data-anlkl.
ls_sum-aprice = gs_data-aprice.
ls_sum-accum = gs_data-accum.
ls_sum-book = gs_data-aprice - gs_data-accum.
ls_sum-waers = 'KRW'.
COLLECT ls_sum INTO lt_sum.
ENDLOOP.
SORT lt_sum BY anlkl.
SORT lt_data_tmp BY anlkl anln1.
"----------------------------------------------------------------
" STEP 2. [Lv.0] 루트 노드 — 전체
" ls_root는 반드시 CLEAR 후 넘겨야 COLLECT 잔여값 방지
"----------------------------------------------------------------
CLEAR ls_root.
PERFORM add_node USING ls_root '전체' space lv_all_key.
gv_all_node = lv_all_key. " 전역 저장 → filter_detail에서 루트 판단에 사용
"----------------------------------------------------------------
" STEP 3. [Lv.1] 분류 폴더 + [Lv.2] 개별 자산 리프
"----------------------------------------------------------------
LOOP AT lt_sum INTO ls_sum.
" [Lv.1] 자산분류 폴더 노드 (부모: lv_all_key)
PERFORM add_node USING ls_sum ls_sum-anlkl lv_all_key lv_cls_key.
" [Lv.2] 개별 자산 리프 노드 (부모: lv_cls_key)
LOOP AT lt_data_tmp INTO gs_data WHERE anlkl = ls_sum-anlkl.
PERFORM add_node USING gs_data gs_data-anlnt lv_cls_key lv_node_key.
ENDLOOP.
ENDLOOP.
"----------------------------------------------------------------
" STEP 4. 트리 렌더링
"----------------------------------------------------------------
gcl_tree->expand_node( i_node_key = gv_all_node ).
gcl_tree->update_calculations( ).
gcl_tree->frontend_update( ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form add_node
*& ps_data : 노드에 담길 실제 데이터 (오른쪽 숫자 컬럼)
*& pv_text : 왼쪽 계층 컬럼에 표시될 텍스트
*& pv_relat_key : 부모 노드 키 (space면 최상위 루트)
*& pv_node_key : 생성된 노드의 고유 키 반환 (자식 연결 시 부모로 사용)
*&---------------------------------------------------------------------*
FORM add_node USING ps_data LIKE gs_data
pv_text
pv_relat_key TYPE lvc_nkey
pv_node_key TYPE lvc_nkey.
DATA lv_node_text TYPE lvc_value.
lv_node_text = pv_text.
gcl_tree->add_node(
EXPORTING
i_relat_node_key = pv_relat_key
i_relationship = cl_gui_column_tree=>relat_last_child
i_node_text = lv_node_text
is_outtab_line = ps_data
IMPORTING
e_new_node_key = pv_node_key ).
ENDFORM.
EVENT
*&---------------------------------------------------------------------*
*& Include ZRE3FI0008_C01
*&---------------------------------------------------------------------*
CLASS lcl_event_handler DEFINITION FINAL.
PUBLIC SECTION.
CLASS-METHODS:
handle_node_click
FOR EVENT node_double_click OF cl_gui_alv_tree
IMPORTING node_key.
ENDCLASS.
*&---------------------------------------------------------------------*
*& Class (Implementation) lcl_event_handler
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
CLASS lcl_event_handler IMPLEMENTATION.
METHOD handle_node_click.
PERFORM filter_detail USING node_key.
ENDMETHOD.
ENDCLASS.
*&---------------------------------------------------------------------*
*& Form filter_detail
*& 트리 노드 클릭 시 우측 Grid 필터링
*& - 전체 노드: 전체 조회
*& - Lv.1 폴더: anlkl 조건
*& - Lv.2 리프: anln1 조건
*&---------------------------------------------------------------------*
FORM filter_detail USING pv_node_key TYPE lvc_nkey.
DATA: ls_node LIKE gs_data,
lr_anln1 TYPE RANGE OF zte3cm0002-anln1,
lr_anlkl TYPE RANGE OF zte3cm0002-anlkl.
" 클릭한 노드의 outtab 데이터 읽기
gcl_tree->get_outtab_line(
EXPORTING i_node_key = pv_node_key
IMPORTING e_outtab_line = ls_node ).
" 노드 종류 판단 → RANGE 조건 세팅
IF pv_node_key NE gv_all_node. " 전체가 아니면
IF ls_node-anln1 IS NOT INITIAL. " Lv.2 리프 클릭
lr_anln1 = VALUE #( ( sign='I' option='EQ' low=ls_node-anln1 ) ).
ELSEIF ls_node-anlkl IS NOT INITIAL. " Lv.1 폴더 클릭
lr_anlkl = VALUE #( ( sign='I' option='EQ' low=ls_node-anlkl ) ).
ENDIF.
ENDIF.
" CDS에서 조건에 맞는 월별 감가상각 조회
REFRESH gt_item.
SELECT bukrs, anln1, anlnt, waers,
m01, m02, m03, m04, m05, m06,
m07, m08, m09, m10, m11, m12
FROM zcds_e3_cm_0001_i
WHERE bukrs = @pa_bukrs
AND ( gjahr = @pa_gjahr OR gjahr IS NULL )
AND anln1 IN @lr_anln1
AND anlkl IN @lr_anlkl
INTO CORRESPONDING FIELDS OF TABLE @gt_item.
gcl_grid->refresh_table_display(
EXPORTING is_stable = gs_stable i_soft_refresh = space ).
ENDFORM.

PBO 에 EVENT 등록
FORM create_tree .
DATA: l_hierarchy_header TYPE treev_hhdr.
l_hierarchy_header-heading = '자산명'.
l_hierarchy_header-width = 25.
l_hierarchy_header-width_pix = space.
CREATE OBJECT gcl_tree
EXPORTING
parent = gcl_tree_con
node_selection_mode = cl_gui_column_tree=>node_sel_mode_single
item_selection = space
no_html_header = 'X'
no_toolbar = space
EXCEPTIONS
OTHERS = 1.
" 이벤트 등록
CALL METHOD gcl_tree->get_registered_events
IMPORTING
events = gt_event.
gs_event-eventid = cl_gui_column_tree=>eventid_node_double_click.
gs_event-appl_event = 'X'.
APPEND gs_event TO gt_event.
CALL METHOD gcl_tree->set_registered_events
EXPORTING
events = gt_event.
SET HANDLER lcl_event_handler=>handle_node_click FOR gcl_tree.
gs_variant-report = sy-repid.
CALL METHOD gcl_tree->set_table_for_first_display
EXPORTING
i_save = 'A'
is_variant = gs_variant
is_hierarchy_header = l_hierarchy_header
CHANGING
it_outtab = gt_make_tree
it_fieldcatalog = gt_fcat_tree.
ENDFORM.
LAYOUT
FORM set_tree_header .
PERFORM set_fcat_tree USING:
'APRICE' '취득원가' 'ZTE3CM0002' 'APRICE' '8',
'ACCUM' '감가누계' 'ZTE3CM0002' 'ACCUM' '8',
'BOOK' '장부가액' 'ZTE3CM0002' 'APRICE' '8',
'WAERS' '통화' 'ZTE3CM0002' 'WAERS' '8'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form set_fcat_tree
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> P_
*& --> P_
*& --> P_
*& --> P_
*& --> P_
*&---------------------------------------------------------------------*
FORM set_fcat_tree USING pv_field
pv_text
pv_ref_table
pv_ref_field
pv_len.
gs_fcat-fieldname = pv_field.
gs_fcat-coltext = pv_text.
gs_fcat-ref_table = pv_ref_table.
gs_fcat-ref_field = pv_ref_field.
gs_fcat-outputlen = pv_len.
CASE pv_field.
WHEN 'APRICE' OR 'ACCUM' OR 'BOOK'.
gs_fcat-cfieldname = 'WAERS'.
gs_fcat-do_sum = 'X'.
ENDCASE.
APPEND gs_fcat TO gt_fcat_tree.
CLEAR gs_fcat.
ENDFORM.'ABAP' 카테고리의 다른 글
| [ABAP] SPLITTER 정리 (0) | 2026.05.30 |
|---|---|
| CALL FUNCTION 'RP_LAST_DAY_OF_MONTHS' 말일 계산 FUNCTION (0) | 2026.05.16 |
| [ABAP] CALL FUNCTION 'LVC_FIELDCATALOG_MERGE' (0) | 2026.04.19 |
| [ABAP] FCAT 필드 값 바꾸기 (0) | 2026.04.19 |
| CL_GUI_TIMER - 타이머 이벤트 (0) | 2026.04.12 |