本程序的几点说明:
1、只支持剪贴板和TXT文件的上载,不支持Excel上载
2、有的参数是可能有好几个值的,可以用|分隔
3、双击多值参数可以弹出窗口显示明细列表
4、执行结果以红绿灯显示,双击执行信息列可以查看详细执行过程
5、根据ALV的Fieldcat字段,使用MASK的方式选择导入数据,更灵活
*&---------------------------------------------------------------------*
*& 批导用户.
*& 本地上载数据类程序的模板程序
*& Baitianzhen
*&---------------------------------------------------------------------*
REPORT zupload_user NO STANDARD PAGE HEADING.
TABLES: sscrfields,bapiadtel,bapiparam,bapiagr,bapiprof.
DATA: gt_fldct TYPE lvc_t_fcat,
gs_slayt TYPE lvc_s_layo.
DATA: BEGIN OF gs_user,
uname TYPE usr01-bname, "用户名
bcode TYPE xuncode, "密码
ustyp TYPE usr02-ustyp, "用户类型
gltgb TYPE usr02-gltgb, "有效至
tzone TYPE usr02-tzone, "时区
lname TYPE adrp-name_last, "姓
fname TYPE adrp-name_first, "名
dprtm TYPE adcp-department, "部门
tlnum TYPE adcp-tel_number, "电话号码
email TYPE adr6-smtp_addr, "电子邮件
langu TYPE usr01-langu, "登录语言
dcpfm TYPE usr01-dcpfm, "数值格式
datfm TYPE usr01-dcpfm, "日期格式
timfm TYPE usr01-timefm, "时间格式
spdev TYPE usr01-spld, "假脱机
paras TYPE string, "参数值(:|分隔)
agrns TYPE string, "角色(|分隔)
profs TYPE string, "参数文件(|分隔)
resul TYPE char4, "结果
rtmsg TYPE string, "执行信息
ttele TYPE TABLE OF bapiadtel, "电话
tpara TYPE TABLE OF bapiparam, "拆分后的参数内表
tagrn TYPE TABLE OF bapiagr, "角色
tprof TYPE TABLE OF bapiprof, "参数文件
retab TYPE TABLE OF bapiret2, "BAPI执行输出消息
END OF gs_user.
DATA: gt_user LIKE TABLE OF gs_user.
DATA: gv_mask TYPE string.
SELECTION-SCREEN FUNCTION KEY 1.
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE btxt1.
PARAMETERS p_frclp RADIOBUTTON GROUP typ USER-COMMAND sele DEFAULT 'X'.
PARAMETERS p_frtxt RADIOBUTTON GROUP typ.
PARAMETERS p_file TYPE string OBLIGATORY DEFAULT 'c:\ZROLEUPS.txt' MODIF ID a.
SELECTION-SCREEN END OF BLOCK b1.
SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE btxt2.
PARAMETERS p_dele AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK b2.
INITIALIZATION.
gv_mask = 'XXXXXXXXXXXXXXXXXX'.
PERFORM fill_fcat TABLES gt_fldct
USING: 'UNAME' 'USR01' 'BNAME ' '账号'(f01),
'BCODE' ' ' ' ' '密码'(f02),
'USTYP' 'USR02' 'USTYP ' '用户类型'(f03),
'GLTGB' 'USR02' 'GLTGB ' '有效至'(f04),
'TZONE' 'USR02' 'TZONE ' '时区'(f05),
'LNAME' 'ADRP ' 'NAME_LAST ' '姓'(f06),
'FNAME' 'ADRP ' 'NAME_FIRST' '名'(f07),
'DPRTM' 'ADCP ' 'DEPARTMENT' '部门'(f08),
'TLNUM' 'ADCP ' 'TEL_NUMBER' '电话'(f09),
'EMAIL' 'ADR6 ' 'SMTP_ADDR ' '电子邮件'(f20),
'LANGU' 'USR01' 'LANGU ' '登录语言'(f10),
'DCPFM' 'USR01' 'DCPFM ' '数值格式'(f11),
'DATFM' 'USR01' 'DCPFM ' '日期格式'(f12),
'TIMFM' 'USR01' 'TIMEFM ' '时间格式'(f13),
'SPDEV' 'USR01' 'SPLD ' '假脱机'(f14),
'PARAS' 'RSREF' 'STRING ' '参数值(|:分隔)'(f15),
'AGRNS' 'RSREF' 'STRING ' '角色(|分隔)'(f16),
'PROFS' 'RSREF' 'STRING ' '参数文件(|分隔)'(f17),
'RESUL' 'RSMPE' 'ICON_ID ' '结果'(f18),
'RTMSG' 'RSREF' 'STRING ' '执行信息'(f19).
AT SELECTION-SCREEN OUTPUT.
btxt1 = '数据来源'(t01).
btxt2 = '选项'(t02).
sscrfields-functxt_01 = '导出模板结构'(t04).
%_p_frclp_%_app_%-text = '数据来自剪贴板(不要复制标题)'(t05).
%_p_frtxt_%_app_%-text = '数据来自文本文件'(t06).
%_p_file_%_app_%-text = '文本文件(不要标题行)'(t07).
%_p_dele_%_app_%-text = '如用户已存在则先删除再重建'(t08).
LOOP AT SCREEN.
CASE 'X'.
WHEN p_frclp.
IF screen-group1 CA 'A'.
screen-active = '0'.
ENDIF.
ENDCASE.
MODIFY SCREEN.
ENDLOOP.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
CALL FUNCTION 'WS_FILENAME_GET'
EXPORTING
mask = ',文本文件(*.TXT),*.TXT,所有文件(*.*),*.*.'
mode = 'O'
IMPORTING
filename = p_file
EXCEPTIONS
OTHERS = 5.
AT SELECTION-SCREEN.
IF sscrfields-ucomm = 'FC01'.
PERFORM export_tmpl_fcat TABLES gt_fldct USING gv_mask.
ENDIF.
START-OF-SELECTION.
* PERFORM savelog(zreplog) USING sy-repid '' IF FOUND.
PERFORM getdata.
PERFORM outdata.
*&---------------------------------------------------------------------*
*& 上载数据并补充完整
*&---------------------------------------------------------------------*
FORM getdata.
DATA: lt_tstr TYPE TABLE OF string WITH HEADER LINE,
lv_str1 TYPE string,
lv_str2 TYPE string.
PERFORM upload_data_fcat TABLES gt_user gt_fldct
USING gv_mask p_frclp p_file.
LOOP AT gt_user INTO gs_user.
IF gs_user-tlnum NE ''.
bapiadtel-telephone = gs_user-tlnum.
bapiadtel-r_3_user = 1.
APPEND bapiadtel TO gs_user-ttele.
ENDIF.
IF gs_user-paras NE ''.
CLEAR lt_tstr[].
SPLIT gs_user-paras AT '|' INTO TABLE lt_tstr.
LOOP AT lt_tstr.
SPLIT lt_tstr AT ':' INTO bapiparam-parid bapiparam-parva.
SELECT SINGLE partext INTO bapiparam-partxt
FROM tparat
WHERE paramid = bapiparam-parid AND
sprache = sy-langu.
APPEND bapiparam TO gs_user-tpara.
CLEAR bapiparam.
ENDLOOP.
ENDIF.
IF gs_user-agrns NE ''.
CLEAR lt_tstr[].
SPLIT gs_user-agrns AT '|' INTO TABLE lt_tstr.
LOOP AT lt_tstr.
bapiagr-agr_name = lt_tstr.
SELECT SINGLE text INTO bapiagr-agr_text
FROM agr_texts
WHERE agr_name = bapiagr-agr_name AND
spras = sy-langu AND
line = ''.
COLLECT bapiagr INTO gs_user-tagrn.
CLEAR bapiagr.
ENDLOOP.
ENDIF.
IF gs_user-profs NE ''.
CLEAR lt_tstr[].
SPLIT gs_user-profs AT '|' INTO TABLE lt_tstr.
LOOP AT lt_tstr.
bapiprof-bapiprof = lt_tstr.
SELECT SINGLE ptext INTO bapiprof-bapiptext
FROM usr11
WHERE langu = sy-langu AND
profn = bapiprof-bapiprof AND
aktps = 'A'.
COLLECT bapiprof INTO gs_user-tprof.
CLEAR bapiprof.
ENDLOOP.
ENDIF.
MODIFY gt_user FROM gs_user.
ENDLOOP.
ENDFORM. "getdata
*&---------------------------------------------------------------------*
*& ALV输出
*&---------------------------------------------------------------------*
FORM outdata.
gs_slayt-zebra = 'X'.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
it_fieldcat_lvc = gt_fldct
is_layout_lvc = gs_slayt
i_callback_program = sy-repid
i_callback_user_command = 'USER_COMMAND'
i_callback_pf_status_set = 'SET_STATUS'
TABLES
t_outtab = gt_user
EXCEPTIONS
program_error = 1
OTHERS = 2.
ENDFORM. "outdata
*&--------------------------------------------------------------------*
*& ALV PF_STATUS_SET
*&--------------------------------------------------------------------*
FORM set_status USING rt_extab TYPE slis_t_extab.
SET PF-STATUS 'STD_FULL' EXCLUDING rt_extab.
ENDFORM. "set_status
*&--------------------------------------------------------------------*
*& ALV COMMAND
*&--------------------------------------------------------------------*
FORM user_command USING pv_ucomm TYPE sy-ucomm
cs_field TYPE slis_selfield.
CASE pv_ucomm.
WHEN '&IC1'.
READ TABLE gt_user INTO gs_user INDEX cs_field-tabindex.
CASE cs_field-fieldname.
WHEN 'PARAS'.
PERFORM show_list TABLES gs_user-tpara USING 'BAPIPARAM'.
WHEN 'AGRNS'.
PERFORM show_list TABLES gs_user-tagrn USING 'BAPIAGR'.
WHEN 'PROFS'.
PERFORM show_list TABLES gs_user-tprof USING 'BAPIPROF'.
WHEN 'RTMSG'.
CALL FUNCTION 'SUSR_DISPLAY_LOG'
EXPORTING
display_in_popup = 'X'
TABLES
it_log_bapiret2 = gs_user-retab
EXCEPTIONS
parameter_error = 1
OTHERS = 2.
ENDCASE.
WHEN 'POST'.
PERFORM create_user.
cs_field-row_stable = 'X'.
cs_field-col_stable = 'X'.
cs_field-refresh = 'X'.
ENDCASE.
ENDFORM. "user_command
*&---------------------------------------------------------------------*
*& ALV FiledCat赋值
*&---------------------------------------------------------------------*
FORM fill_fcat TABLES t_fldcat
USING pv_field pv_reftab pv_reffld pv_text.
DATA: ls_fldcat TYPE lvc_s_fcat.
ls_fldcat-fieldname = pv_field. "字段名
ls_fldcat-scrtext_l = pv_text. "长描述
ls_fldcat-coltext = pv_text. "列描述
ls_fldcat-ref_table = pv_reftab. "参考表名
ls_fldcat-ref_field = pv_reffld. "参考字段名
ls_fldcat-col_opt = 'A'. "自动优化列宽
APPEND ls_fldcat TO t_fldcat.
CLEAR ls_fldcat.
ENDFORM. "fill_fcat
*&---------------------------------------------------------------------*
*& 显示明细
*&---------------------------------------------------------------------*
FORM show_list TABLES t_tab USING pv_struname.
DATA: ls_slayt TYPE lvc_s_layo.
CHECK t_tab[] IS NOT INITIAL.
ls_slayt-cwidth_opt = 'X'.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
i_structure_name = pv_struname
is_layout_lvc = ls_slayt
i_screen_start_column = 40
i_screen_start_line = 4
i_screen_end_column = 130
i_screen_end_line = 16
TABLES
t_outtab = t_tab
EXCEPTIONS
program_error = 1.
ENDFORM. "show_list
*&---------------------------------------------------------------------*
*& create_user
*&---------------------------------------------------------------------*
FORM create_user.
DATA: ls_logond TYPE bapilogond, "登录数据
ls_defaul TYPE bapidefaul, "缺省值
ls_addr3 TYPE bapiaddr3, "地址
lt_retn TYPE bapiret2_t WITH HEADER LINE.
LOOP AT gt_user INTO gs_user WHERE resul = ''.
CLEAR: lt_retn,lt_retn[],gs_user-rtmsg.
ls_logond-ustyp = gs_user-ustyp.
ls_logond-gltgb = gs_user-gltgb.
ls_logond-tzone = gs_user-tzone.
ls_defaul-spld = gs_user-spdev.
IF gs_user-spdev NE ''.
ls_defaul-spdb = 'G'.
ENDIF.
ls_defaul-datfm = gs_user-datfm.
ls_defaul-dcpfm = gs_user-dcpfm.
ls_defaul-langu = gs_user-langu.
ls_defaul-timefm = gs_user-timfm.
ls_addr3-lastname = gs_user-lname.
ls_addr3-firstname = gs_user-fname.
ls_addr3-department = gs_user-dprtm.
ls_addr3-e_mail = gs_user-email.
IF p_dele = 'X'.
PERFORM mess_retn TABLES gs_user-retab
USING '删除用户:' gs_user-uname ''.
CALL FUNCTION 'BAPI_USER_DELETE'
EXPORTING
username = gs_user-uname
TABLES
return = lt_retn.
APPEND LINES OF lt_retn TO gs_user-retab.
COMMIT WORK AND WAIT.
ENDIF.
CLEAR lt_retn[].
PERFORM mess_retn TABLES gs_user-retab
USING '创建用户' gs_user-uname ''.
CALL FUNCTION 'BAPI_USER_CREATE1'
EXPORTING
username = gs_user-uname
password = gs_user-bcode
logondata = ls_logond
defaults = ls_defaul
address = ls_addr3
TABLES
parameter = gs_user-tpara
addtel = gs_user-ttele
return = lt_retn.
APPEND LINES OF lt_retn TO gs_user-retab.
LOOP AT lt_retn WHERE type CA 'AEX'.
gs_user-rtmsg = gs_user-rtmsg && '/' && lt_retn-message.
ENDLOOP.
IF sy-subrc = 0.
SHIFT gs_user-rtmsg LEFT.
gs_user-resul = '@0A@'.
ROLLBACK WORK.
ELSE.
gs_user-rtmsg = '创建成功'.
gs_user-resul = '@08@'.
COMMIT WORK AND WAIT.
***角色
IF gs_user-tagrn[] IS NOT INITIAL.
CLEAR lt_retn[].
PERFORM mess_retn TABLES gs_user-retab
USING '用户' gs_user-uname '分配角色'.
CALL FUNCTION 'BAPI_USER_ACTGROUPS_ASSIGN'
EXPORTING
username = gs_user-uname
TABLES
activitygroups = gs_user-tagrn
return = lt_retn.
APPEND LINES OF lt_retn TO gs_user-retab.
READ TABLE lt_retn WITH KEY id = '01' number = '048'.
IF sy-subrc = 0.
COMMIT WORK AND WAIT.
gs_user-rtmsg = gs_user-rtmsg && ' 分配角色成功'.
ELSE.
ROLLBACK WORK.
gs_user-resul = '@09@'.
gs_user-rtmsg = gs_user-rtmsg && ' 分配角色失败'.
ENDIF.
ENDIF.
***参数文件
IF gs_user-tprof[] IS NOT INITIAL.
CLEAR lt_retn[].
PERFORM mess_retn TABLES gs_user-retab
USING '用户' gs_user-uname '分配参数文件'.
CALL FUNCTION 'BAPI_USER_PROFILES_ASSIGN'
EXPORTING
username = gs_user-uname
TABLES
profiles = gs_user-tprof
return = lt_retn.
APPEND LINES OF lt_retn TO gs_user-retab.
READ TABLE lt_retn WITH KEY id = '01' number = '046'.
IF sy-subrc = 0.
COMMIT WORK AND WAIT.
gs_user-rtmsg = gs_user-rtmsg && ' 分配参数文件成功'.
ELSE.
ROLLBACK WORK.
gs_user-resul = '@09@'.
gs_user-rtmsg = gs_user-rtmsg && ' 分配参数文件失败'.
ENDIF.
ENDIF.
ENDIF.
MODIFY gt_user FROM gs_user.
ENDLOOP.
IF sy-subrc = 0.
MESSAGE s000(oo) WITH '执行完毕'.
ELSE.
MESSAGE s000(oo) WITH '无可执行数据'.
ENDIF.
ENDFORM. "create_user
*---------------------------------------------------------------------*
* 导出模板格式到剪贴板
*---------------------------------------------------------------------*
FORM export_tmpl_fcat TABLES t_fldct STRUCTURE lvc_s_fcat
USING pv_upmask.
DATA: lv_subrc TYPE sy-subrc.
DATA: lv_upmsk TYPE char1024.
DATA: lv_index TYPE sy-index.
DATA: ls_dfies TYPE dfies.
DATA: lt_clip TYPE TABLE OF char2048 WITH HEADER LINE.
DATA: lv_hztab VALUE cl_abap_char_utilities=>horizontal_tab.
lv_upmsk = pv_upmask.
LOOP AT t_fldct.
lv_index = sy-tabix - 1.
CHECK lv_upmsk+lv_index(1) = 'X' OR lv_upmsk = ''.
IF t_fldct-coltext = ''.
CALL FUNCTION 'C_DD_READ_FIELD'
EXPORTING
i_tabname = t_fldct-ref_table
i_fieldname = t_fldct-ref_field
IMPORTING
e_dfies = ls_dfies
EXCEPTIONS
OTHERS = 4.
IF sy-subrc NE 0.
ls_dfies-fieldtext = t_fldct-fieldname.
ENDIF.
ELSE.
ls_dfies-fieldtext = t_fldct-coltext.
ENDIF.
CONCATENATE lt_clip lv_hztab ls_dfies-fieldtext INTO lt_clip.
ENDLOOP.
SHIFT lt_clip.
APPEND lt_clip.
CALL METHOD cl_gui_frontend_services=>clipboard_export
IMPORTING
data = lt_clip[]
CHANGING
rc = lv_subrc
EXCEPTIONS
OTHERS = 4.
IF sy-subrc = 0.
MESSAGE s000(oo) WITH '已复制表头,请打开Excel粘贴'.
ELSE.
MESSAGE e000(oo) WITH '复制到剪贴板失败'.
ENDIF.
ENDFORM. "export_tmpl_fcat
*---------------------------------------------------------------------*
* 指定FieldCat列的剪贴板数据上传到内表,支持剪贴板和TXT文件
*---------------------------------------------------------------------*
FORM upload_data_fcat TABLES t_outtab t_fldct
USING pv_upmask pv_clip pv_file.
DATA: lt_clip TYPE TABLE OF char2048,
ls_clip TYPE char2048,
lv_file TYPE string,
ls_fcat TYPE lvc_s_fcat,
lv_mask TYPE char1024,
lt_fld TYPE TABLE OF char2048,
ls_fld TYPE char2048.
DATA: lr_croot TYPE REF TO cx_root,
ls_usr01 TYPE usr01,
lv_cxmsg TYPE string,
lv_ftype TYPE c,
lv_index TYPE sy-index,
lv_tabix TYPE sy-tabix,
lv_filed TYPE fieldname,
lv_hztab VALUE cl_abap_char_utilities=>horizontal_tab.
FIELD-SYMBOLS: <lv_fld> TYPE any,
<ls_out> TYPE any.
IF pv_clip = 'X'.
CALL METHOD cl_gui_frontend_services=>clipboard_import
IMPORTING
data = lt_clip
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
not_supported_by_gui = 3
OTHERS = 4.
IF sy-subrc NE 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CALL METHOD cl_gui_cfw=>flush.
ELSE.
lv_file = pv_file.
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
filename = lv_file
filetype = 'ASC'
TABLES
data_tab = lt_clip
EXCEPTIONS
OTHERS = 1.
IF sy-subrc = 1.
MESSAGE e000(oo) WITH '文件打开错误'.
ENDIF.
ENDIF.
SELECT SINGLE * INTO ls_usr01 FROM usr01 WHERE bname = sy-uname.
lv_mask = pv_upmask.
ASSIGN t_outtab TO <ls_out>.
LOOP AT lt_clip INTO ls_clip.
CLEAR: lt_fld.
SPLIT ls_clip AT lv_hztab INTO TABLE lt_fld.
lv_tabix = 1.
LOOP AT lt_fld INTO ls_fld.
CLEAR lv_filed.
LOOP AT t_fldct INTO ls_fcat FROM lv_tabix.
lv_tabix = sy-tabix + 1.
lv_index = sy-tabix - 1.
IF lv_mask = '' OR lv_mask+lv_index(1) = 'X'.
lv_filed = ls_fcat-fieldname.
EXIT.
ENDIF.
ENDLOOP.
IF lv_filed IS INITIAL.
EXIT.
ENDIF.
ASSIGN COMPONENT lv_filed OF STRUCTURE <ls_out> TO <lv_fld>.
CHECK sy-subrc = 0.
TRY.
DESCRIBE FIELD <lv_fld> TYPE lv_ftype.
CASE lv_ftype.
WHEN 'I' OR 'P' OR 'F' OR 'a' OR 'e' OR 'b' OR 's'.
IF ls_usr01-dcpfm = 'X'.
TRANSLATE ls_fld USING ', '.
ELSE.
TRANSLATE ls_fld USING '. '.
TRANSLATE ls_fld USING ',.'.
ENDIF.
CONDENSE ls_fld NO-GAPS.
<lv_fld> = ls_fld.
WHEN 'D'.
IF ls_fld CN ' 0123456789'.
CALL FUNCTION 'DATE_STRING_CONVERT'
EXPORTING
date_format = ls_usr01-datfm
date_string = ls_fld
IMPORTING
result_date = <lv_fld>.
ELSEIF ls_fld = ''.
CLEAR <lv_fld>.
ELSE.
<lv_fld> = ls_fld.
ENDIF.
IF <lv_fld> IS NOT INITIAL.
CALL FUNCTION 'DATE_CHECK_PLAUSIBILITY'
EXPORTING
date = <lv_fld>
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE e000(oo) WITH '日期格式非法:' ls_fld.
ENDIF.
ENDIF.
WHEN 'T'.
IF ls_fld CN ' 0123456789'.
CONCATENATE ls_fld(2) ls_fld+3(2) ls_fld+6(2) INTO <lv_fld>.
ELSEIF ls_fld = ''.
CLEAR <lv_fld>.
ELSE.
<lv_fld> = ls_fld.
ENDIF.
CALL FUNCTION 'TIME_CHECK_PLAUSIBILITY'
EXPORTING
time = <lv_fld>
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE e000(oo) WITH '时间格式非法:' ls_fld.
ENDIF.
WHEN OTHERS.
<lv_fld> = ls_fld.
ENDCASE.
CATCH cx_root INTO lr_croot.
lv_cxmsg = lr_croot->get_text( ).
ENDTRY.
ENDLOOP.
APPEND <ls_out> TO t_outtab.
CLEAR <ls_out>.
ENDLOOP.
IF lv_cxmsg IS NOT INITIAL.
MESSAGE s000(oo) WITH '数据转换有错误发生,已经忽略'(m10) DISPLAY LIKE 'W'.
ENDIF.
ENDFORM. "upload_data_fcat
*&---------------------------------------------------------------------*
*& 给RETURN表添加事件描述
*&---------------------------------------------------------------------*
FORM mess_retn TABLES t_retn STRUCTURE bapiret2
USING msg1 msg2 msg3.
DATA: ls_retn TYPE bapiret2,
uzeitmp LIKE sy-uzeit.
GET TIME FIELD uzeitmp.
ls_retn-type = 'H'.
ls_retn-id = 'OO'.
ls_retn-number = '000'.
ls_retn-message_v1 = msg1.
ls_retn-message_v2 = msg2.
ls_retn-message_v3 = msg3.
ls_retn-message_v4 = uzeitmp+0(2) && ':' &&
uzeitmp+2(2) && ':' && uzeitmp+4(2).
APPEND ls_retn TO t_retn.
ENDFORM. "mess_retn