ABAP Util代码

时间:2022-12-28 20:33:44
ABAP Util代码
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4265908.html

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