본문 바로가기
ALV · 화면 · 리포트

[SAP ABAP] CL_GUI_TEXTEDIT 텍스트 그리드 — 여러 줄 텍스트 입력·저장·조회 (READ_TEXT·SAVE_TEXT)

by Song.sh 2026. 5. 29.

SAP 화면에서 사용자가 여러 줄의 자유 텍스트를 입력·편집할 수 있는 메모장 같은 컨트롤이 필요할 때가 있습니다. 기안 내용, 비고, 처리 의견처럼 길이가 정해지지 않은 텍스트를 받는 화면이 대표적입니다. 이때 쓰는 것이 CL_GUI_TEXTEDIT — 흔히 "텍스트 그리드" 또는 "텍스트 에디터" 라고 부르는 컨트롤입니다.

 

ALV 그리드가 표 형태의 정형 데이터를 보여준다면, TextEdit 은 줄바꿈·잘라내기·붙여넣기가 되는 편집 가능한 텍스트 영역입니다. 여기에 SAPscript 텍스트 저장소(READ_TEXT/SAVE_TEXT) 를 연동하면 입력한 텍스트를 영구 저장하고 다시 불러올 수 있습니다.

 

이 글에서는 TextEdit 컨트롤 생성 → 텍스트 표시/가져오기 → 편집/조회 모드 제어 → SAPscript 저장소 연동(저장·조회) 까지 정리합니다. 핵심은 세 가지 텍스트 형태(화면 stream ↔ SAPscript ITF ↔ 저장소) 사이의 변환 입니다.

핵심 — 텍스트의 3가지 형태와 변환

TextEdit 으로 입력한 텍스트를 저장하려면 형태를 두 번 변환해야 합니다.

형태 타입 용도
Stream TLINE-TDLINE 테이블 TextEdit 화면에 표시되는 텍스트 줄
ITF TLINE 테이블 SAPscript 내부 포맷 (포맷 코드 + 텍스트)
저장소 STXH / STXL (THEAD 키) DB 영구 저장 (READ_TEXT/SAVE_TEXT 로 접근)

변환 흐름은 다음과 같습니다.

[저장]
TextEdit 화면 ──get_text_as_stream──▶ Stream
Stream ──CONVERT_STREAM_TO_ITF_TEXT──▶ ITF
ITF ──SAVE_TEXT(+THEAD 키)──▶ 저장소(STXH/STXL)

[조회]
저장소 ──READ_TEXT(THEAD 키)──▶ ITF
ITF ──CONVERT_ITF_TO_STREAM_TEXT──▶ Stream
Stream ──set_text_as_stream──▶ TextEdit 화면

저장과 조회는 정확히 대칭 구조입니다. 화면용 stream 과 저장용 ITF 사이를 변환 함수가 이어줍니다.


1단계 — DATA 선언 + 화면 준비

TextEdit 컨테이너·에디터 참조와, 텍스트를 담을 stream/ITF 테이블, 저장소 키(THEAD) 를 선언합니다.

DATA: ok_code TYPE sy-ucomm.

DATA: g_textcontainer TYPE REF TO cl_gui_custom_container,  " 텍스트 컨테이너
      g_editor        TYPE REF TO cl_gui_textedit,          " 텍스트 그리드
      g_header        LIKE thead,                           " 저장소 키(헤더)
      gt_text         TYPE TABLE OF tline-tdline,           " 화면 stream
      gt_itftext      TYPE TABLE OF tline.                  " SAPscript ITF

* 생성/편집 vs 조회 모드 선택
PARAMETERS: r_edit  RADIOBUTTON GROUP gr1 DEFAULT 'X',      " 편집
            r_disp  RADIOBUTTON GROUP gr1.                  " 조회

화면(Screen 100) 에는 Custom Control 을 하나 그리고 이름을 C_TEXT_100_01 로 지정합니다. Flow Logic 의 PBO 에 컨테이너/에디터 생성 모듈과 텍스트 표시 모듈을, PAI 에 저장 처리 모듈을 연결합니다.


2단계 — PBO: 컨테이너 + TextEdit 생성 + 모드 제어

PBO 에서 컨테이너와 TextEdit 을 생성합니다. 생성 시 줄바꿈 방식(wordwrap_mode) 과 최대 글자 수(max_number_chars) 를 지정합니다.

MODULE set_text_100_01 OUTPUT.

  IF g_textcontainer IS INITIAL.

* 텍스트 컨테이너 생성 (SE51 Custom Control 'C_TEXT_100_01')
    g_textcontainer = NEW #( container_name = 'C_TEXT_100_01' ).

* 텍스트 그리드 생성
    g_editor = NEW #(
      parent            = g_textcontainer
      wordwrap_mode     = cl_gui_textedit=>wordwrap_at_fixed_position  " 고정 위치 줄바꿈
      wordwrap_position = 80                                            " 80번째 칸에서 줄바꿈
      max_number_chars  = 1000 ).                                       " 최대 1000자

* 편집 모드 vs 조회 모드
    IF r_edit = 'X'.
      g_editor->set_readonly_mode(  readonly_mode  = 0 ).   " 0 = 편집 가능
      g_editor->set_statusbar_mode( statusbar_mode = 1 ).   " 상태바 표시
      g_editor->set_toolbar_mode(   toolbar_mode   = 1 ).   " 툴바 표시
    ELSE.
      g_editor->set_readonly_mode(  readonly_mode  = 1 ).   " 1 = 읽기 전용
      g_editor->set_toolbar_mode(   toolbar_mode   = 0 ).
      g_editor->set_statusbar_mode( statusbar_mode = 0 ).
    ENDIF.

  ENDIF.

ENDMODULE.

wordwrap_mode 의 줄바꿈 옵션은 다음과 같습니다.

상수 동작
wordwrap_off 0 자동 줄바꿈 없음 (가로 스크롤)
wordwrap_at_windowborder 1 창 너비에 맞춰 자동 줄바꿈
wordwrap_at_fixed_position 2 wordwrap_position 칸에서 줄바꿈

모드 제어 메소드의 값은 직관과 반대로 헷갈리기 쉬우니 주의합니다.

메소드 0 1
set_readonly_mode 편집 가능 읽기 전용
set_toolbar_mode 숨김 표시
set_statusbar_mode 숨김 표시

set_readonly_mode 만 0 이 "활성(편집 가능)" 이라 다른 두 메소드와 의미 방향이 반대입니다.


3단계 — 텍스트 표시: set_text_as_stream

내부 테이블(stream) 의 텍스트를 화면에 뿌립니다.

MODULE set_text_editor OUTPUT.
  g_editor->set_text_as_stream( text = gt_text ).
ENDMODULE.

set_text_as_streamTLINE-TDLINE 타입의 줄 테이블을 받아 TextEdit 화면에 표시합니다. 조회 모드라면 5단계에서 읽어온 텍스트가 여기서 화면에 나타납니다.


4단계 — 저장: 화면 → stream → ITF → 저장소

PAI 에서 SAVE 명령 시, 화면의 텍스트를 가져와(stream) ITF 로 변환하고 SAPscript 저장소에 저장합니다.

MODULE user_command_0100 INPUT.

  CASE ok_code.
    WHEN 'BACK' OR 'EXIT' OR 'CANC'.
      LEAVE TO SCREEN 0.

    WHEN 'SAVE'.

* 1) 화면 텍스트 가져오기 (화면 → stream)
      g_editor->get_text_as_stream( IMPORTING text = gt_text ).
      CHECK gt_text IS NOT INITIAL.

* 2) stream → ITF 변환
      CALL FUNCTION 'CONVERT_STREAM_TO_ITF_TEXT'
        TABLES
          text_stream = gt_text
          itf_text    = gt_itftext.

* 3) 저장소 키(THEAD) 세팅
      g_header-tdname   = 'DEMO_KEY_001'.   " 텍스트 이름(키)
      g_header-tdobject = 'ZXX_TEXT'.       " 텍스트 오브젝트 (SE75 커스텀)
      g_header-tdid     = 'ZX01'.           " 텍스트 ID
      g_header-tdspras  = '3'.              " 언어 (3 = 한국어)

* 4) 저장
      CALL FUNCTION 'SAVE_TEXT'
        EXPORTING
          header          = g_header
          insert          = ' '
          savemode_direct = 'X'
        TABLES
          lines           = gt_itftext
        EXCEPTIONS
          id       = 1
          language = 2
          name     = 3
          object   = 4
          OTHERS   = 5.

  ENDCASE.

ENDMODULE.

THEAD 의 4가지 키 — tdname(텍스트 이름)·tdobject(텍스트 오브젝트)·tdid(텍스트 ID)·tdspras(언어) — 가 저장소에서 텍스트를 식별하는 복합 키입니다. savemode_direct = 'X' 는 즉시 DB 저장(COMMIT 대기 없이) 을 의미합니다.


5단계 — 조회: 저장소 → ITF → stream → 화면

조회 모드(r_disp) 로 실행하면 START-OF-SELECTION 에서 저장된 텍스트를 읽어 stream 으로 변환합니다.

START-OF-SELECTION.

  IF r_disp = 'X'.

    CLEAR g_header.
    g_header-tdobject = 'ZXX_TEXT'.
    g_header-tdid     = 'ZX01'.

* 1) 저장소에서 ITF 읽기
    CALL FUNCTION 'READ_TEXT'
      EXPORTING
        client   = sy-mandt
        id       = g_header-tdid
        language = '3'
        name     = 'DEMO_KEY_001'        " 텍스트 이름(키)
        object   = g_header-tdobject
      TABLES
        lines    = gt_itftext
      EXCEPTIONS
        id        = 1
        language  = 2
        name      = 3
        not_found = 4
        object    = 5
        OTHERS    = 8.

    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.

* 2) ITF → stream 변환 (화면 표시용)
    CALL FUNCTION 'CONVERT_ITF_TO_STREAM_TEXT'
      TABLES
        itf_text    = gt_itftext
        text_stream = gt_text.

  ENDIF.

  CALL SCREEN 100.

READ_TEXT 의 키(id·language·name·object) 는 저장할 때 쓴 SAVE_TEXT 의 키와 정확히 같아야 같은 텍스트를 찾아옵니다.


자주 빠뜨리는 함정

저장/조회 키 불일치

SAVE_TEXTREAD_TEXT 의 4가지 키(name·object·id·language) 중 하나라도 다르면 텍스트를 못 찾습니다. 텍스트 그리드가 화면에 여러 개일 때는 특히 name 을 그리드마다 다르게 줘서 구분해야 합니다.

텍스트 오브젝트/ID 미등록

tdobject·tdidSE75 에 미리 등록된 값이어야 합니다. 커스텀 텍스트 오브젝트(ZXX_TEXT 등) 를 쓰려면 SE75 에서 먼저 만들어야 SAVE_TEXT 가 동작합니다.

stream ↔ ITF 변환 누락

TextEdit 은 stream(TDLINE) 을 다루고 저장소는 ITF(TLINE) 를 다룹니다. 변환 함수(CONVERT_STREAM_TO_ITF_TEXT / CONVERT_ITF_TO_STREAM_TEXT) 를 빼먹으면 타입이 안 맞아 저장/표시가 깨집니다.

readonly_mode 값 혼동

set_readonly_mode 는 0 이 "편집 가능", 1 이 "읽기 전용" 입니다. 반면 set_toolbar_mode·set_statusbar_mode 는 1 이 "표시" 입니다. 방향이 달라 헷갈리기 쉽습니다.

컨테이너 생성 가드

PBO 의 IF g_textcontainer IS INITIAL 가드 없이 매번 생성하면 컨트롤이 중복 생성됩니다.

Background 실행 시 덤프

TextEdit 도 SAP GUI 전용입니다. 배치 잡에서는 컨트롤 생성 시점에 덤프가 납니다.


전체 코드 — 복사용 통합본

아래 통합본은 SE38 에 붙여 활성화 가능. SE51 에서 Screen 100 에 Custom Control 'C_TEXT_100_01' 을 그리고, Flow Logic 에 status_0100 · set_text_100_01 · set_text_editor (PBO) · user_command_0100 (PAI) 를 연결합니다. 텍스트 오브젝트/ID 는 SE75 에 등록된 값으로 교체하세요.

*&---------------------------------------------------------------------*
*& Report ZRXX_TEXTEDIT_GRID (예시)
*&---------------------------------------------------------------------*
*& CL_GUI_TEXTEDIT 텍스트 그리드 — 입력 / 저장 / 조회
*&---------------------------------------------------------------------*
REPORT zrxx_textedit_grid.

DATA: ok_code TYPE sy-ucomm.

DATA: g_textcontainer TYPE REF TO cl_gui_custom_container,
      g_editor        TYPE REF TO cl_gui_textedit,
      g_header        LIKE thead,
      gt_text         TYPE TABLE OF tline-tdline,
      gt_itftext      TYPE TABLE OF tline.

PARAMETERS: r_edit RADIOBUTTON GROUP gr1 DEFAULT 'X',   " 편집/저장
            r_disp RADIOBUTTON GROUP gr1.               " 조회

* ── 조회 모드: 저장된 텍스트 읽기 ──
START-OF-SELECTION.

  IF r_disp = 'X'.
    CLEAR g_header.
    g_header-tdobject = 'ZXX_TEXT'.
    g_header-tdid     = 'ZX01'.

    CALL FUNCTION 'READ_TEXT'
      EXPORTING
        client   = sy-mandt
        id       = g_header-tdid
        language = '3'
        name     = 'DEMO_KEY_001'
        object   = g_header-tdobject
      TABLES
        lines    = gt_itftext
      EXCEPTIONS
        id = 1 language = 2 name = 3 not_found = 4
        object = 5 reference_check = 6
        wrong_access_to_archive = 7 OTHERS = 8.

    IF sy-subrc = 0.
      CALL FUNCTION 'CONVERT_ITF_TO_STREAM_TEXT'
        TABLES
          itf_text    = gt_itftext
          text_stream = gt_text.
    ENDIF.
  ENDIF.

  CALL SCREEN 100.

* ── PBO: GUI Status ──
MODULE status_0100 OUTPUT.
  SET PF-STATUS 'S100'.
ENDMODULE.

* ── PBO: ★ 컨테이너 + TextEdit 생성 + 모드 제어 ──
MODULE set_text_100_01 OUTPUT.
  IF g_textcontainer IS INITIAL.
    g_textcontainer = NEW #( container_name = 'C_TEXT_100_01' ).

    g_editor = NEW #(
      parent            = g_textcontainer
      wordwrap_mode     = cl_gui_textedit=>wordwrap_at_fixed_position
      wordwrap_position = 80
      max_number_chars  = 1000 ).

    IF r_edit = 'X'.
      g_editor->set_readonly_mode(  readonly_mode  = 0 ).
      g_editor->set_statusbar_mode( statusbar_mode = 1 ).
      g_editor->set_toolbar_mode(   toolbar_mode   = 1 ).
    ELSE.
      g_editor->set_readonly_mode(  readonly_mode  = 1 ).
      g_editor->set_toolbar_mode(   toolbar_mode   = 0 ).
      g_editor->set_statusbar_mode( statusbar_mode = 0 ).
    ENDIF.
  ENDIF.
ENDMODULE.

* ── PBO: ★ 텍스트 화면 표시 ──
MODULE set_text_editor OUTPUT.
  g_editor->set_text_as_stream( text = gt_text ).
ENDMODULE.

* ── PAI: 저장 처리 ──
MODULE user_command_0100 INPUT.
  CASE ok_code.
    WHEN 'BACK' OR 'EXIT' OR 'CANC'.
      LEAVE TO SCREEN 0.

    WHEN 'SAVE'.
* 화면 → stream
      g_editor->get_text_as_stream( IMPORTING text = gt_text ).
      CHECK gt_text IS NOT INITIAL.

* stream → ITF
      CALL FUNCTION 'CONVERT_STREAM_TO_ITF_TEXT'
        TABLES
          text_stream = gt_text
          itf_text    = gt_itftext.

* THEAD 키 세팅
      g_header-tdname   = 'DEMO_KEY_001'.
      g_header-tdobject = 'ZXX_TEXT'.
      g_header-tdid     = 'ZX01'.
      g_header-tdspras  = '3'.

* 저장
      CALL FUNCTION 'SAVE_TEXT'
        EXPORTING
          header          = g_header
          insert          = ' '
          savemode_direct = 'X'
        TABLES
          lines           = gt_itftext
        EXCEPTIONS
          id = 1 language = 2 name = 3 object = 4 OTHERS = 5.

  ENDCASE.
ENDMODULE.

요약

동작 핵심 호출 변환
생성 NEW cl_gui_textedit( wordwrap_mode... ) 컨테이너 → 에디터
표시 set_text_as_stream stream → 화면
저장 get_text_as_streamSAVE_TEXT 화면 → stream → ITF → 저장소
조회 READ_TEXTset_text_as_stream 저장소 → ITF → stream → 화면
모드 set_readonly_mode / set_toolbar_mode 편집(0) / 조회(1) 전환

TextEdit 그리드의 본질은 "화면용 stream 과 저장용 ITF 사이를 변환 함수로 잇고, THEAD 키로 SAPscript 저장소에 영구 보관". set_text_as_stream/get_text_as_stream 으로 화면과 내부 테이블을 오가고, CONVERT_* 함수로 형태를 바꾼 뒤 READ_TEXT/SAVE_TEXT 로 저장·조회합니다. 저장/조회 키만 정확히 맞추면 기안 내용·비고 같은 자유 텍스트 입력 화면을 안정적으로 만들 수 있습니다.


Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다.

CL_GUI_TEXTEDITset_text_as_stream·get_text_as_stream·모드 제어 메소드와 wordwrap 상수(at_fixed_position=2 등), READ_TEXT/SAVE_TEXT 시그니처는 NetWeaver 표준 정의(ECC 6.0 / S/4HANA on-premise 기준) 입니다. 적용 환경 버전에 따라 일부 차이가 있을 수 있으니 실제 적용 시 SE24 의 클래스 정의를 확인하시기 바랍니다. 텍스트 오브젝트·ID·키 값은 모두 가상 예시값이며, 실제 적용 시 SE75 에 등록된 값으로 교체해야 합니다.