ABAP Util代码

将长文本分割成行宽一致的行(长文本在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_datasrc_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上,在这过程中如果不经过这样的转换就会出现乱码

原文地址:https://www.cnblogs.com/jiangzhengjun/p/4265908.html