将长文本分割成行宽一致的行(长文本在ScriptForm显示美观整齐)
DATA: l_tline TYPE TABLE OF tline WITH HEADER LINE.
DATA: rf_tlinetab TYPE REF TO data.
FIELD-SYMBOLS:<l_tab> TYPE STANDARD TABLE,<fs_wa>,<l_dec>.
DATA: l_rows TYPE i .
CLEAR: l_tline[].
l_tline-tdline = con_tab-ojtxp.将某个字符串按照每行指定英文字符数分隔成多行,如果是读取的长文本,则直接将长文本内表传递给split_ltx即可
APPEND l_tline.
PERFORM split_ltx TABLES l_tline USING rf_tlinetab 37.
ASSIGN rf_tlinetab->* TO <l_tab>.
DESCRIBE TABLE <l_tab> LINES l_rows.
IF l_rows > 1.
LOOP AT <l_tab> ASSIGNING <fs_wa>.
ASSIGN COMPONENT 'TDLINE' OF STRUCTURE <fs_wa> TO <l_dec>.
...
ENDLOOP.
ELSE.
*&---------------------------------------------------------------------*
*& Form split_ltxt_to_print
*&---------------------------------------------------------------------*
* 将 READ_TEXT 函数读取的长文本按指定的行字符宽度截取成多行,
* 以便长文本在ScriptForm显示整齐美观(注:每个中文本将按二个英文进行计算)
*----------------------------------------------------------------------*
* -->P_TLINE READ_TEXT函数返回的 tline 类型内表
* -->P_RC_TAB 返回分割好的长文本内表引用
* -->p_linewidth 每行最多可显示的英文字符个数,一个中文会兑换成两个英文
*----------------------------------------------------------------------*
FORM split_ltxt_for_scrptfrm_outprt TABLES p_tline STRUCTURE tline
USING p_rc_tab TYPE REF TO data value(p_linewidth) TYPE i.
DATA: rf_strc TYPE REF TO data,
rf_tab TYPE REF TO data,
rf_elem_typ TYPE REF TO cl_abap_elemdescr,
rf_strc_typ TYPE REF TO cl_abap_structdescr,
rf_tab_typ TYPE REF TO cl_abap_tabledescr,
t_component TYPE cl_abap_structdescr=>component_table WITH HEADER LINE.
FIELD-SYMBOLS: <fs_wa> ,
<fs_tab> TYPE STANDARD TABLE.
rf_elem_typ ?= cl_abap_elemdescr=>get_c( p_linewidth ).
t_component-name = 'TDLINE'.
t_component-type = rf_elem_typ.
APPEND t_component.
rf_strc_typ = cl_abap_structdescr=>create( t_component[] ).
rf_tab_typ = cl_abap_tabledescr=>create( p_line_type = rf_strc_typ
p_table_kind = cl_abap_tabledescr=>tablekind_std ).
CREATE DATA rf_strc TYPE HANDLE rf_strc_typ.
ASSIGN rf_strc->* TO <fs_wa>.
CREATE DATA rf_tab TYPE HANDLE rf_tab_typ.
ASSIGN rf_tab->* TO <fs_tab>.
FIELD-SYMBOLS:<fs_field>.
ASSIGN COMPONENT 'TDLINE' OF STRUCTURE <fs_wa> TO <fs_field> .
DATA: l_len TYPE i,i_counter TYPE i,l_c,l_cc(4) ,i_start TYPE i,
at_fist VALUE 'X',last_blankline,i_off_set TYPE i .
FIELD-SYMBOLS: <fs_c> TYPE x.
ASSIGN l_c TO <fs_c> CASTING.
LOOP AT p_tline .
IF ( p_tline-tdformat = '*' AND at_fist <> 'X' ) OR i_counter >= p_linewidth .
INSERT <fs_wa> INTO TABLE <fs_tab>.
CLEAR:i_off_set ,i_counter, <fs_wa>.
ENDIF.
l_len = STRLEN( p_tline-tdline ).
DO l_len TIMES.
IF i_counter >= p_linewidth.
INSERT <fs_wa> INTO TABLE <fs_tab>.
CLEAR:i_off_set,i_counter, <fs_wa>.
ENDIF.
i_start = sy-index - 1.
l_c = p_tline-tdline+i_start(1).
<fs_field>+i_off_set(1) = l_c.
i_off_set = i_off_set + 1.
*如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
*big-endian: 0x0000 0x0001 0x0002 0x0003
* 0x12 0x34 0xab 0xcd
*little-endian: 0x0000 0x0001 0x0002 0x0003
* 0xcd 0xab 0x34 0x12
*little-endian与人的阅读习惯是反的(阅读习惯:高位放在前,低
*位放在后,而little-endian则是将高位放在后,低们放在前,但内
*地址是越往后越大,即后面是高字符,靠前的是低字节),但我们在
*程序中给一个变量赋值是按照人的阅读习惯来书写的——即认为是高字节序的方式赋值,而在低字节序的系统中,
*以little-endian低字节序的字节内容读取出来给l_c变量后,l_c变量内容也是低字节序方式显示存储的,此时将l_c赋值给X类型字段符号<fs_field>时,需要将l_c转换为赋值方式所采用的高字节序方式
IF cl_abap_char_utilities=>endian = 'L'.
l_cc = <fs_c>."将十六进制(字符的Unicode码)转换为字面意义上的字符串
SHIFT l_cc BY 2 PLACES CIRCULAR.
<fs_c> = l_cc."再将字符转换为十六进制数(字符的Unicode码)
ENDIF.
IF <fs_c> > 255.
i_counter = i_counter + 2.
ELSE.
i_counter = i_counter + 1.
ENDIF.
ENDDO.
AT LAST.
IF l_len = 0 .
last_blankline = 'X'.
ENDIF.
ENDAT.
CLEAR at_fist .
ENDLOOP.
IF i_counter <> 0 OR last_blankline = 'X' .
INSERT <fs_wa> INTO TABLE <fs_tab>.
CLEAR:i_off_set ,i_counter, <fs_wa>.
ENDIF.
p_rc_tab = rf_tab.
ENDFORM. "split_ltxt_to_print
结构拷贝(拷贝的列名可以不同)
*&---------------------------------------------------------------------*
*& Form strc_copy
*&---------------------------------------------------------------------*
* 结构拷贝,如果要拷贝的两个字段名不同时使用 SRC_FILEDNAME-DEST_fILEDNAME
* 将两个不同的名映射起来,并通过field_maping内表参数进行转递,如果相同,则
* 不需要
*----------------------------------------------------------------------*
* -->FIELD_MAPING 不同名称字段映射
* -->SRC 源结构
* -->DEST 目标结构
*----------------------------------------------------------------------*
FORM strc_copy TABLES field_maping USING src dest .
FIELD-SYMBOLS : <fs_field_src> TYPE x,
<fs_field_dest> TYPE x.
DATA: field_name_src TYPE string,
field_name_dest TYPE string.
LOOP AT field_maping.
SPLIT field_maping AT '-' INTO field_name_src field_name_dest .
ASSIGN COMPONENT field_name_src OF STRUCTURE src TO <fs_field_src> CASTING.
ASSIGN COMPONENT field_name_dest OF STRUCTURE dest TO <fs_field_dest> CASTING.
<fs_field_dest> = <fs_field_src>.”原汁原味的进行赋值,因为都是X类型,在赋值过程中不会发生类型转换而可能会出现的问题
ENDLOOP.
MOVE-CORRESPONDING src TO dest.
ENDFORM. " FRM_STRC_COPY
结构不同的两个内表之间进行拷贝
*&---------------------------------------------------------------------*
*& Form tab_copy
*&---------------------------------------------------------------------*
* 内表拷贝,如果要拷贝的两个字段名不同时使用 SRC_FILEDNAME-DEST_fILEDNAME
* 将两个不同的名映射起来,并通过field_maping内表参数进行转递,如果相同,则
* 不需要
*----------------------------------------------------------------------*
* -->FIELD_MAPING 不同名称字段映射
* -->SRC_TAB 源内表
* -->DEST_TAB 目标内表
*----------------------------------------------------------------------*
FORM tab_copy TABLES field_maping USING src_tab TYPE ANY TABLE dest_tab TYPE ANY TABLE .
FIELD-SYMBOLS: <wa_src>,
<wa_dest>.
FIELD-SYMBOLS: <fs_src_tab> TYPE ANY TABLE.
DATA: rf_tabdecr TYPE REF TO cl_abap_tabledescr.
DATA: rf_linetype TYPE REF TO cl_abap_structdescr.
ASSIGN src_tab TO <fs_src_tab>.
rf_tabdecr ?= cl_abap_tabledescr=>describe_by_data( dest_tab ).
rf_linetype ?= rf_tabdecr->get_table_line_type( ).
DATA: rf_wa_dest_tmp TYPE REF TO data.
CREATE DATA rf_wa_dest_tmp TYPE HANDLE rf_linetype.
ASSIGN rf_wa_dest_tmp->* TO <wa_dest>.
LOOP AT <fs_src_tab> ASSIGNING <wa_src>.
PERFORM strc_copy TABLES field_maping USING <wa_src> <wa_dest>.
INSERT <wa_dest> INTO TABLE dest_tab.
ENDLOOP.
"SORT dest_tab .
"DELETE ADJACENT DUPLICATES FROM dest_tab.
ENDFORM. "frm_tab_copy
将内表中的某一列转换为RANG条件内表
RANGES: r_dispo FOR zkpipp02-dispo.
"将内表转换为 Range Internal table
PERFORM tab_to_rang TABLES lt_zkpipp02 r_dispo USING 'DISPO'.
*&---------------------------------------------------------------------*
*& Form tab_to_rang
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->SRC_TAB text
* -->RANG_TAB text
* -->VALUE(FIELDNAME) text
*----------------------------------------------------------------------*
FORM tab_to_rang TABLES src_tab rang_tab USING value(fieldname) TYPE c.
TYPES: BEGIN OF rang_line_type ,
sign TYPE c LENGTH 1,
option TYPE c LENGTH 2 ,
low LIKE t001-bukrs,
high LIKE t001-bukrs,
END OF rang_line_type.
"动态创建 Range Internal table
DATA: rang_elemt_type_ref TYPE REF TO cl_abap_elemdescr,
rang_line_type_ref TYPE REF TO cl_abap_structdescr,
rang_tab_type_ref TYPE REF TO cl_abap_tabledescr,
component_rang_tab TYPE cl_abap_structdescr=>component_table WITH HEADER LINE,
src_line_type_ref TYPE REF TO cl_abap_structdescr,
src_tab_type_ref TYPE REF TO cl_abap_tabledescr.
DATA: rang_strc_ref TYPE REF TO data,
rang_tab_ref TYPE REF TO data.
FIELD-SYMBOLS: <rang_wa> ,
<rang_tab> TYPE STANDARD TABLE.
component_rang_tab-name = 'SIGN'.
rang_elemt_type_ref ?= cl_abap_elemdescr=>get_c( 1 ).
component_rang_tab-type = rang_elemt_type_ref.
APPEND component_rang_tab.
component_rang_tab-name = 'OPTION'.
rang_elemt_type_ref ?= cl_abap_elemdescr=>get_c( 2 ).
component_rang_tab-type = rang_elemt_type_ref.
APPEND component_rang_tab.
component_rang_tab-name = 'LOW'.
src_tab_type_ref ?= cl_abap_tabledescr=>describe_by_data( src_tab[] ).
src_line_type_ref ?= src_tab_type_ref->get_table_line_type( ).
component_rang_tab-type = src_line_type_ref->get_component_type( fieldname ).
APPEND component_rang_tab.
component_rang_tab-name = 'HIGH'.
APPEND component_rang_tab.
rang_line_type_ref = cl_abap_structdescr=>create( component_rang_tab[] ).
rang_tab_type_ref = cl_abap_tabledescr=>create( p_line_type = rang_line_type_ref
p_table_kind = cl_abap_tabledescr=>tablekind_std ).
CREATE DATA rang_strc_ref TYPE HANDLE rang_line_type_ref.
ASSIGN rang_strc_ref->* TO <rang_wa>.
CREATE DATA rang_tab_ref TYPE HANDLE rang_tab_type_ref.
ASSIGN rang_tab_ref->* TO <rang_tab>.
* SORT src_tab BY (fieldname).
DATA: src_tab_rows TYPE i.
FIELD-SYMBOLS: <src_tab_fld>,
<rang_tab_fld>,
<src_tab_fld_last>.
DATA: curr_i TYPE i VALUE 1,
next_i TYPE i.
READ TABLE <rang_tab> ASSIGNING <rang_wa> INDEX curr_i.
ASSIGN COMPONENT 'SIGN' OF STRUCTURE <rang_wa> TO <rang_tab_fld>.
<rang_tab_fld> = 'I'.
ASSIGN COMPONENT 'OPTION' OF STRUCTURE <rang_wa> TO <rang_tab_fld>.
<rang_tab_fld> = 'EQ'.
ASSIGN COMPONENT 'LOW' OF STRUCTURE <rang_wa> TO <rang_tab_fld>.
LOOP AT src_tab.
ASSIGN COMPONENT fieldname OF STRUCTURE src_tab TO <src_tab_fld>.
IF <src_tab_fld> <> <rang_tab_fld>.
<rang_tab_fld> = <src_tab_fld>.
APPEND <rang_wa> TO <rang_tab>.
ENDIF.
ENDLOOP.
rang_tab[] = <rang_tab>.
ENDFORM. "tab_to_rang
通过正则分组,查找所有子匹配串
*&---------------------------------------------------------------------*
*& Form fin_all_submatch
*&---------------------------------------------------------------------*
* 找出所有的子匹配项(正则式中使用括号括起来的部分)
*----------------------------------------------------------------------*
* -->P_RESULT text
* -->P_STR text
* -->P_REG text
*----------------------------------------------------------------------*
FORM find_all_submatch TABLES p_result USING p_str p_reg.
DATA: result_tab TYPE match_result_tab WITH HEADER LINE.
DATA: subresult_tab TYPE submatch_result_tab WITH HEADER LINE.
"注意:带表达时 result_tab 后面一定要带上中括号,否则激活时出现奇怪的问题
FIND ALL OCCURRENCES OF REGEX p_reg IN p_str RESULTS result_tab[].
LOOP AT result_tab .
* p_result = p_str+result_tab-offset(result_tab-length).
* APPEND p_result.
subresult_tab[] = result_tab-submatches.
LOOP AT subresult_tab.
p_result = p_str+subresult_tab-offset(subresult_tab-length).
APPEND p_result.
ENDLOOP.
ENDLOOP.
ENDFORM. "find_all_submatch
读取长文本
*&---------------------------------------------------------------------*
*& Form read_text
*&---------------------------------------------------------------------*
* 读取长文本,可以自动在中英两种语言间切换,如果指定的语言不存在,
* 则自动切换到另一种语言;如果输入的语言为空时,则先会默认使用当前语言,如果没
*有,则也会自动切换到另一种语言
*----------------------------------------------------------------------*
FORM read_text TABLES lines STRUCTURE tline USING txtid language txtname txtobj.
DATA: cnt VALUE 2,
l_name TYPE thead-tdname,
lang(1).
IF language IS INITIAL.
lang = syst-langu.
ELSE.
lang = language.
ENDIF.
l_name = txtname.
WHILE cnt >= 1.
CALL FUNCTION 'READ_TEXT'
EXPORTING
id = txtid
language = lang
name = l_name
object = txtobj
TABLES
lines = lines
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.
EXIT.
ENDIF.
CASE lang.
WHEN '1'.
lang = 'E'.
WHEN 'E'.
lang = '1'.
ENDCASE.
cnt = cnt - 1.
ENDWHILE.
ENDFORM.
读取长方本,并按指定字符长度拼接单个字符串
*&---------------------------------------------------------------------*
*& Form read_text_bylen
*&---------------------------------------------------------------------*
* 读取长文本(可以自动在中英两种语言间切换,如果指定的语言不存在,
* 则自动切换到另一种语言),并将前 MAXLEN 个字符拼接一个字符串。
* 该函数主要用在在ALV单元格显示长文本
*----------------------------------------------------------------------*
* -->LINE_SEPARAT 行分隔符
* -->MAXLEN 需拼接字符数
* -->RETURN 返回的拼接字符串
*----------------------------------------------------------------------*
FORM read_text_bylen USING txtid language txtname txtobj line_separat maxlen return.
DATA: lines TYPE TABLE OF tline ,
txt_len TYPE i,
diff_len TYPE i,
tmp_str TYPE string,
l_line_separat TYPE string,
i_separat_len TYPE i.
FIELD-SYMBOLS: <tline> TYPE tline.
PERFORM read_text TABLES lines USING txtid language txtname txtobj.
LOOP AT lines ASSIGNING <tline> .
IF sy-tabix = 1.
l_line_separat = ``.
ELSE.
l_line_separat = line_separat.
i_separat_len = i_separat_len + STRLEN( line_separat ).
ENDIF.
diff_len = maxlen - txt_len.
IF diff_len > 132 .”因为TDLINE-TDLINE的最大长度为,每次截取时不能超过这个数,否则越界
diff_len = 132.
ENDIF.
CONCATENATE tmp_str <tline>-tdline(diff_len)
INTO tmp_str
SEPARATED BY l_line_separat .
txt_len = STRLEN( tmp_str ) - i_separat_len.
IF txt_len >= maxlen.
EXIT.
ENDIF.
ENDLOOP.
return = tmp_str.
ENDFORM.
读取长方本,并按指定行数拼接单个字符串
*&---------------------------------------------------------------------*
*& Form read_text_byline
*&---------------------------------------------------------------------*
* 读取长文本(可以自动在中英两种语言间切换,如果指定的语言不存在,
* 则自动切换到另一种语言),并将前 MAXLINES 行长文本拼接成字符串。
* 该函数主要用在在ALV单元格显示长文本
*----------------------------------------------------------------------*
* -->ID text
* -->LANGUAGE text
* -->NAME text
* -->OBJECT text
* -->LINE_SEPARAT 行分隔符
* -->MAXLINES 要拼接的行数
* -->RETURN 返回拼接好的字符串
*----------------------------------------------------------------------*
FORM read_text_byline USING id language name object line_separat maxlines return.
DATA: lines TYPE TABLE OF tline ,
l_line_separat TYPE string.
FIELD-SYMBOLS: <tline> TYPE tline.
PERFORM read_text TABLES lines USING id language name object.
LOOP AT lines ASSIGNING <tline> .
IF sy-tabix = 1.
l_line_separat = ``.
ELSE.
l_line_separat = line_separat.
ENDIF.
CONCATENATE return <tline>-tdline
INTO return
SEPARATED BY l_line_separat .
IF sy-tabix = maxlines.
EXIT.
ENDIF.
ENDLOOP.
ENDFORM. "read_text_byline
将含有数字类型字段内表转化为可写入到服务器文本文件的内表
data: begin of lt_tab occurs 0,
content(300),
end of lt_tab .
perform itab_to_exceltab tables t_div lt_tab.
form itab_to_exceltab tables p_src_tab p_excel_tab.
data:strct_type_ref type ref to cl_abap_structdescr,
tab_type_ref type ref to cl_abap_tabledescr,
t_component type cl_abap_structdescr=>component_table,
wa_component like line of t_component.
field-symbols: <fldvalue>.
data: begin of t_fldinfo occurs 0,
fldname type string,
fldtype,
end of t_fldinfo,
begin of lt_tab occurs 0,
content(300),
end of lt_tab .
data :l_str type string,fldtype,firsttime value 'X'.
tab_type_ref ?= cl_abap_tabledescr=>describe_by_data( p_src_tab[] ).
strct_type_ref ?= tab_type_ref->get_table_line_type( ).
t_component = strct_type_ref->get_components( ).
loop at p_src_tab.
firsttime = 'X'.
loop at t_component into wa_component.
fldtype = wa_component-type->type_kind.
assign component wa_component-name of structure p_src_tab to <fldvalue>.
l_str = <fldvalue>.
if fldtype = 'P' or fldtype = 'F'
or fldtype = 'I' or fldtype = 'b'
or fldtype = 's'.
call function 'CLOI_PUT_SIGN_IN_FRONT'
changing value = l_str.
endif.
if firsttime = 'X'.
lt_tab-content = l_str .
clear firsttime.
else.
concatenate lt_tab-content l_str into lt_tab-content separated by cl_abap_char_utilities=>horizontal_tab .
endif.
endloop.
append lt_tab.
clear: lt_tab.
endloop.
p_excel_tab[] = lt_tab[].
endform.
上面的程序是将内表转换为可以直接写入到服务器上文件的字符串,如果是要将内表下载到客户端,则只需要使用GUI_DOWNLOAD就可以直接做到,这与将内表写入服务器上是不一样的。GUI_DOWNLOAD可以将内表中的任何类型组件字段转换为字符类型后下载,并且以 DAT 模式下载时(此时以TAB键分隔),还可直接由Excel打开:
call function 'GUI_DOWNLOAD'
exporting
filename = l_filename
filetype = 'DAT' 使用TAB键分隔
codepage = '8400'
tables
data_tab = itab
上面Form程序就是模拟GUI_DOWNLOAD,将内表转换为可以直接使用open dataset l_file for output IN TEXT MODE语句写入文件的纯字符内表,因为如果内表中包数字类型的字段时,如果不经过转换,在以IN TEXT MODE模式写入时,会出现乱码。
该程序就是用在将内表写入SAP服务器上的文件中,再上传到FTP上,在这过程中如果不经过这样的转换就会出现乱码