查找数据库表内包含的特殊字符

f380e37289e50158e4dc07949b85d5cd.png

最近比较忙,稍微介绍一下。
本程序的作用是查找并删除数据库表内包含的特殊字符。

通过接口或者Excel上载创建的主数据描述,凭证数据的文本字段等,偶尔会有包含特殊字符的情况,且大部分时候是不可见字符,比如制表符,回车换行,0x0000等等。如果没有工具程序,只用SE16等查找或者更改非常困难,所以特意做了一个程序来干这个事情。

辅助功能1、显示可见字符的ASCII码

2fd1a70cfcfc8f92ce9040b742e47b48.png

辅助功能2、自动创建日志表

eafc04137c00e00e070e814c8b810734.png

e5b304bb7a72d1cfa98a07802033c04e.png

辅助功能3、自定义的更新功能(有更改日志)

cd846cce033f9ad48060fde0503d51ca.png

程序的运行界面:

30695c322c64f1ef23b6f3f71d1401fc.png

6d6d77101ed1f37c28d23da62a352831.png

9482c088202d6a87b3abc98f533702f8.png

7fd059c040fc3f26b27334fe1f314721.png

下面是优美的代码~

*&---------------------------------------------------------------------*
*& Report  ZCHECKSPECIALHEX
*& 检查/修正表内的CNDT类型字段值包含的特殊字符
*&---------------------------------------------------------------------*
*& Baitianzhen
*& 2022.04.16
*&---------------------------------------------------------------------*
REPORT zcheckspecialhex NO STANDARD PAGE HEADING .


TYPE-POOLS: sscr,slis.
TABLES: dd02v,dd03l,tadir,sscrfields.
DATA: fldct  TYPE lvc_t_fcat WITH HEADER LINE,
      slayt  TYPE lvc_s_layo,
      repid  TYPE sy-repid,
      subrc  TYPE sy-subrc,
      char45 TYPE char45,
      tabix  TYPE sy-tabix,
      fmname TYPE funcname,
      whstr  TYPE string,
      tmpstr TYPE string,
      numstr TYPE string,
      keystr TYPE string,
      cspace TYPE char4,
      tmpint TYPE i,
      percnt TYPE i,
      cflag.
DATA: set_str TYPE string,
      con_str TYPE string.
DATA: cxroot  TYPE REF TO cx_root,
      excmsg  TYPE char255.
DATA: paraname  TYPE char40,
      stru_type TYPE REF TO cl_abap_structdescr,
      itab_type TYPE REF TO cl_abap_tabledescr,
      comp_des  TYPE abap_componentdescr,
      comp_tab  TYPE abap_component_tab WITH HEADER LINE.
DATA: logtname TYPE tablename VALUE 'ZCSL'.
DATA: BEGIN OF wa_value ,
        fldname  TYPE string,
        fldtype  TYPE string,
        fldvalue TYPE string,
        hexvalue TYPE string,
      END OF wa_value.
DATA: BEGIN OF it_flds OCCURS 0 ,
        fldname TYPE fieldname,
        ref_tab TYPE tabname,
        ref_fld TYPE fieldname,
        convext TYPE convexit,
        inttype TYPE inttype,
      END OF it_flds.
DATA: BEGIN OF wa_log,
        mandt     TYPE mandt  ,
        tabname   TYPE tabname,
        objectid  TYPE cdobjectv,
        fieldname TYPE fieldname,
        erdat     TYPE erdat    ,
        erzet     TYPE erzet    ,
        ernam     TYPE ernam    ,
        value_old TYPE cdfldvalo,
        value_new TYPE cdfldvaln,
      END OF wa_log.
DATA: it_fkey LIKE TABLE OF it_flds WITH HEADER LINE.
DATA: it_fnok LIKE TABLE OF it_flds WITH HEADER LINE.
DATA: it_dd03 TYPE TABLE OF dd03p   WITH HEADER LINE.
DATA: rf_tabl TYPE REF TO data,
      rf_twa  TYPE REF TO data,
      rf_out  TYPE REF TO data,
      rf_owa  TYPE REF TO data.
FIELD-SYMBOLS: <fs_out>  TYPE STANDARD TABLE,
               <fs_tabl> TYPE STANDARD TABLE,
               <fsx> TYPE x, <fs_owa>, <fs_twa>, <fs_fld>, <fs>.


SELECTION-SCREEN FUNCTION KEY 1.
SELECTION-SCREEN FUNCTION KEY 2.
SELECTION-SCREEN FUNCTION KEY 3.
SELECTION-SCREEN FUNCTION KEY 4.
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE t01.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (31) ctxt0 FOR FIELD p_tname .
PARAMETERS: p_tname TYPE tabname16 MEMORY ID dtb .
SELECTION-SCREEN COMMENT 52(31) ctxtl  .
SELECTION-SCREEN END OF LINE.
SELECT-OPTIONS s_type FOR cflag NO INTERVALS.
SELECT-OPTIONS s_flds FOR dd03l-fieldname NO INTERVALS MATCHCODE OBJECT dd_fieldname.
SELECT-OPTIONS s_conl FOR char45 NO INTERVALS LOWER CASE.
SELECT-OPTIONS s_sfld FOR dd03l-fieldname NO INTERVALS MATCHCODE OBJECT dd_fieldname.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (31) ctxt1 FOR FIELD p_hchar .
PARAMETERS: p_hchar TYPE char18 DEFAULT '0000'.
SELECTION-SCREEN PUSHBUTTON 52(9) but03 USER-COMMAND space .
SELECTION-SCREEN PUSHBUTTON 62(9) but04 USER-COMMAND newline .
SELECTION-SCREEN PUSHBUTTON 72(9) but00 USER-COMMAND minchar .
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN PUSHBUTTON 52(9) but02 USER-COMMAND tab .
SELECTION-SCREEN PUSHBUTTON 62(9) but05 USER-COMMAND cr_lf .
SELECTION-SCREEN PUSHBUTTON 72(9) but01 USER-COMMAND maxchar .
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK b1.


SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE t02.
PARAMETERS p_proind AS CHECKBOX .
PARAMETERS p_update AS CHECKBOX USER-COMMAND updchk.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN POSITION 4.
PARAMETERS pr_rep RADIOBUTTON GROUP typ DEFAULT 'X' MODIF ID a.
SELECTION-SCREEN COMMENT (30) ctxt3 FOR FIELD pr_rep MODIF ID a.
PARAMETERS p_conv AS CHECKBOX MODIF ID a.
SELECTION-SCREEN COMMENT (14) ctxt6 FOR FIELD p_conv MODIF ID a.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN POSITION 4.
PARAMETERS pr_clr RADIOBUTTON GROUP typ MODIF ID a.
SELECTION-SCREEN COMMENT (12) ctxt5 FOR FIELD pr_clr MODIF ID a.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK b2.


SELECTION-SCREEN BEGIN OF BLOCK b3 WITH FRAME TITLE t03.
SELECTION-SCREEN COMMENT /1(79): txt1,txt2,txt3,txt4,txt5,txt6,txt7,txt8.
SELECTION-SCREEN END OF BLOCK b3.


SELECTION-SCREEN BEGIN OF SCREEN 1100 AS WINDOW .
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (8) ctxt7 FOR FIELD p_fval.
PARAMETERS: p_fval TYPE char255 .
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF SCREEN 1100.


SELECTION-SCREEN BEGIN OF SCREEN 1200 AS WINDOW .
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (6) ctxt8 FOR FIELD p_fval.
PARAMETERS: p_uptab TYPE tabname16 OBLIGATORY.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (6) ctxt9 FOR FIELD p_fval.
PARAMETERS: p_upfld TYPE fieldname VISIBLE LENGTH 10 OBLIGATORY .
SELECTION-SCREEN COMMENT (3) ctxta FOR FIELD p_upval.
PARAMETERS: p_upval TYPE string VISIBLE LENGTH 24 LOWER CASE.
PARAMETERS: p_astxt AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN COMMENT (6) ctxtc FOR FIELD p_astxt.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (6) ctxtb FOR FIELD p_fval.
PARAMETERS: p_upwhe TYPE string LOWER CASE OBLIGATORY.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF SCREEN 1200.


AT SELECTION-SCREEN OUTPUT.
  sscrfields-functxt_01 = 'ASCII码'.
  sscrfields-functxt_02 = '创建日志表'.
  sscrfields-functxt_03 = '查看日志'.
  sscrfields-functxt_04 = '单个字段更新'.
  t01 = '数据'.
  t02 = '选项'.
  t03 = '使用说明'.
  ctxt0 = '表名'.
  ctxt1 = '特殊字符的HEX'.
  ctxt3 = 'C类型过滤掉特殊字符,NDT类型改为初始值'.
  ctxt5 = '字段数据清空为初始值'.
  ctxt6 = '并将C类型数据转为内部格式'.
  ctxt7 = '外部格式:'.
  ctxt8 = 'UPDATE'.
  ctxt9 = 'SET'.
  ctxta = ' = '.
  ctxtb = 'WHERE'.
  ctxtc = '常量'.
  but00 = 'MinChar'.
  but01 = 'MaxChar'.
  but02 = 'Tab'.
  but03 = 'Space'.
  but04 = 'NewLine'.
  but05 = 'CR_LF'.
  %_p_proind_%_app_%-text = '显示查找进度'.
  %_p_update_%_app_%-text = '更改数据库数据'.
  %_p_tname_%_app_%-text  = '表名'.
  %_p_hchar_%_app_%-text  = '特殊字符的HEX'.
  %_s_type_%_app_%-text   = '字段类型(C/N/D/T)'.
  %_s_flds_%_app_%-text   = '字段名'.
  %_s_conl_%_app_%-text   = 'WHERE语句'.
  %_s_sfld_%_app_%-text   = '额外输出字段'.
  txt1 = `1、如果不输入要检查字段,则检查表内所有C/N/D/T类型的非KEY字段`.
  txt2 = `2、WHERE语句可以不填写,也可以填写多行,每行不要超过45字符`.
  txt3 = `3、默认输出KEY字段和包含特殊字符的字段,如果想要输出其他字段,可以放到“额外输出字段”`.
  txt4 = `4、如果不勾中"更新数据库数据",则只列出数据,不更新数据库`.
  txt5 = `5、更新数据库的时候,使用INITIAL值覆盖或者只去掉特殊字符`.
  txt6 = `6、如果勾中数据转为内部格式,则先去掉特殊字符然后根据表内字段对应域的转换例程转换为内部格式`.
  txt7 = `7、HEX为空会列出所有在数据库取出的CNDT类型数据,排查错误使用,不支持更新模式`.
  txt8 = `8、HEX为Space有特殊用法,可以查出非INITIAL字段包含空格的情况,比如日期或时间值为空格的,不可以使用过滤模式`.


  CLEAR ctxtl.
  SELECT SINGLE ddtext INTO ctxtl
    FROM dd02t
    WHERE tabname = p_tname AND
          ddlanguage = sy-langu.


  LOOP AT SCREEN.
    IF p_update = ''.
      IF screen-group1 CA 'A'.
        screen-active = '0'.
      ENDIF.
    ENDIF.
    IF screen-name CS 'P_PROIND'.
      screen-input = '0'.
    ENDIF.
    MODIFY SCREEN.
  ENDLOOP.


  IF sy-dynnr = '1100'.
    LOOP AT SCREEN.
      screen-input = '0'.
      MODIFY SCREEN.
    ENDLOOP.
    SET CURSOR FIELD 'CTXT7'.
  ENDIF.


  IF sy-dynnr = '1200'.
    PERFORM selscreen_ext USING 'GET SPOS'.
  ENDIF.


INITIALIZATION.
  PERFORM get_hchar USING space CHANGING cspace.


AT SELECTION-SCREEN.
  CASE sscrfields-ucomm.
    WHEN 'FC01'.
      LEAVE TO LIST-PROCESSING .
      NEW-PAGE NO-HEADING NO-TITLE.
      SET PF-STATUS space.
      SUPPRESS DIALOG.
      PERFORM ascii.
    WHEN 'FC02'.
      PERFORM fill_dd03 USING : 'MANDT    ' 'MANDT'     'X',
                                'TABNAME  ' 'TABNAME'   'X',
                                'OBJECTID ' 'CDOBJECTV' 'X',
                                'FIELDNAME' 'FIELDNAME' 'X',
                                'ERDAT    ' 'ERDAT'     'X',
                                'ERZET    ' 'ERZET'     'X',
                                'ERNAM    ' 'ERNAM'     'X',
                                'VALUE_OLD' 'CDFLDVALO' '',
                                'VALUE_NEW' 'CDFLDVALN' ''.
      SELECT SINGLE * FROM tadir
        WHERE pgmid = 'R3TR'  AND
              object = 'PROG' AND
              obj_name = sy-repid.
      PERFORM create_table TABLES it_dd03
                           USING 'ZCSL' 'ZCHECKSPECIALHEX日志' tadir-devclass .
    WHEN 'FC03'.
      CONCATENATE '/1BCDWB/DB' logtname INTO char45 .
      SUBMIT (char45) VIA SELECTION-SCREEN AND RETURN .
    WHEN 'FC04'.
      CALL SELECTION-SCREEN 1200 STARTING AT 32 6 .
      CHECK sy-subrc = 0 .
      PERFORM update_single_fld USING p_uptab p_upfld p_upval p_upwhe p_astxt .
    WHEN 'MINCHAR'.
      PERFORM get_hchar USING %_minchar CHANGING p_hchar.
    WHEN 'MAXCHAR'.
      PERFORM get_hchar USING %_maxchar CHANGING p_hchar.
    WHEN 'TAB'.
      PERFORM get_hchar USING %_horizontal_tab CHANGING p_hchar.
    WHEN 'SPACE'.
      PERFORM get_hchar USING space CHANGING p_hchar.
    WHEN 'NEWLINE'.
      PERFORM get_hchar USING %_newline CHANGING p_hchar.
    WHEN 'CR_LF'.
      PERFORM get_hchar USING %_cr_lf   CHANGING p_hchar.
    WHEN 'UPDCHK'.
      CHECK p_update = 'X'.
      CALL FUNCTION 'POPUP_TO_CONFIRM'
        EXPORTING
          titlebar       = '确认'
          text_question  = '本程序会直接更改数据库数据!请在专业人员指导下使用,继续选择更改吗?'
          default_button = 'A'
        IMPORTING
          answer         = cflag.
      IF cflag <> '1'.
        p_update = ''.
      ENDIF.
  ENDCASE.


START-OF-SELECTION.
  PERFORM checkinput.
  PERFORM savelog(zreplog) USING sy-repid '' IF FOUND.
  PERFORM get_dd03 USING p_tname.
  PERFORM create_itab.
  PERFORM getdata.
  PERFORM updatelog(zreplog) IF FOUND.
  CHECK <fs_out> IS NOT INITIAL.
  PERFORM outdata.


*&---------------------------------------------------------------------*
*&      Form  checkinput
*&---------------------------------------------------------------------*
FORM checkinput.
  SELECT SINGLE * FROM dd02v WHERE tabname = logtname.
  IF sy-subrc <> 0 AND p_update = 'X'.
    MESSAGE s000(oo) WITH '请先创建日志表'.
    STOP.
  ENDIF.


  IF p_tname IS INITIAL.
    MESSAGE s000(oo) WITH '表名必输'.
    STOP.
  ENDIF.


  tmpint = strlen( p_hchar ) MOD 4.
  IF tmpint <> 0.
    MESSAGE s000(oo) WITH 'HEX长度必须是4的倍数'.
    STOP.
  ENDIF.


  IF p_hchar CN '0123456789ABCDEF '.
    MESSAGE s000(oo) WITH 'HEX只能是数字或者A-F'.
    STOP.
  ENDIF.


  IF p_update = 'X' AND p_hchar = '' .
    MESSAGE s000(oo) WITH 'HEX为空不可以使用更新模式'.
    STOP.
  ENDIF.


  IF p_update = 'X' AND pr_rep = 'X' AND p_hchar = cspace.
    MESSAGE s000(oo) WITH 'HEX为Space不可以使用过滤模式'.
    STOP.
  ENDIF.
ENDFORM.                    "checkinput


*&---------------------------------------------------------------------*
*&      Form  get_dd03
*&---------------------------------------------------------------------*
FORM get_dd03 USING in_tabname.
  DATA tabname TYPE  ddobjname.


  DELETE s_flds WHERE low = ''.
  DELETE s_sfld WHERE low = ''.


  CLEAR: it_dd03[],it_flds[],it_fkey[],it_fnok[].
  tabname = in_tabname.
  CALL FUNCTION 'DDIF_TABL_GET'
    EXPORTING
      name          = tabname
      langu         = sy-langu
    IMPORTING
      dd02v_wa      = dd02v
    TABLES
      dd03p_tab     = it_dd03
    EXCEPTIONS
      illegal_input = 1
      OTHERS        = 2.
  IF it_dd03[] IS INITIAL.
    MESSAGE s000(oo) WITH '表' tabname '不存在'.
    STOP.
  ELSE.
    IF 'TRANSP POOL CLUSTER' CS dd02v-tabclass.
      DELETE it_dd03 WHERE datatype = 'CLNT' OR datatype = ''.
      LOOP AT it_dd03 WHERE fieldname IN s_flds AND
                            inttype CA 'CNDT'   AND
                            inttype IN s_type
                            OR keyflag = 'X'.
        it_flds-fldname = it_dd03-fieldname.
        it_flds-ref_tab = tabname.
        it_flds-ref_fld = it_dd03-fieldname.
        it_flds-convext = it_dd03-convexit.
        it_flds-inttype = it_dd03-inttype.
        APPEND it_flds.


        IF it_dd03-keyflag = 'X'.
          APPEND it_flds TO it_fkey.
        ELSE.
          APPEND it_flds TO it_fnok.
        ENDIF.
      ENDLOOP.
      IF it_fnok[] IS INITIAL.
        MESSAGE s000(oo) WITH '未找到CNDT类型的非KEY字段'.
        STOP.
      ENDIF.
    ELSE.
      MESSAGE s000(oo) WITH '只支持透明表/簇表/池表' DISPLAY LIKE 'E'.
      STOP.
    ENDIF.
  ENDIF.
ENDFORM.                    "get_dd03


*&---------------------------------------------------------------------*
*&      Form  create_itab
*&---------------------------------------------------------------------*
FORM create_itab.
  LOOP AT it_flds .
    CONCATENATE it_flds-ref_tab '-' it_flds-ref_fld INTO paraname.
    comp_des-type ?= cl_abap_datadescr=>describe_by_name( paraname ).
    comp_des-name  = it_flds-fldname.
    APPEND comp_des TO comp_tab.
  ENDLOOP.


  LOOP AT s_sfld.
    READ TABLE it_dd03 WITH KEY fieldname = s_sfld-low.
    CHECK sy-subrc = 0.
    READ TABLE it_flds WITH KEY fldname = s_sfld-low.
    CHECK sy-subrc <> 0.


    CONCATENATE p_tname '-' s_sfld-low INTO paraname.
    comp_des-type ?= cl_abap_datadescr=>describe_by_name( paraname ).
    comp_des-name  = s_sfld-low.
    APPEND comp_des TO comp_tab.
  ENDLOOP.


  stru_type  = cl_abap_structdescr=>create( comp_tab[] ).
  CREATE DATA rf_twa TYPE HANDLE stru_type.
  ASSIGN rf_twa->* TO <fs_twa>.


  itab_type = cl_abap_tabledescr=>create( stru_type ).
  CREATE DATA rf_tabl TYPE HANDLE itab_type.
  ASSIGN rf_tabl->* TO <fs_tabl>.


  LOOP AT it_fkey.
    PERFORM catset TABLES fldct
                   USING it_fkey-fldname 'RSREF' 'STRING' it_fkey-fldname.
  ENDLOOP.
  LOOP AT s_sfld.
    READ TABLE it_dd03 WITH KEY fieldname = s_sfld-low.
    CHECK sy-subrc = 0.
    READ TABLE it_fkey WITH KEY fldname = s_sfld-low.
    CHECK sy-subrc <> 0.


    PERFORM catset TABLES fldct
                   USING s_sfld-low 'RSREF' 'STRING' s_sfld-low.
  ENDLOOP.
  PERFORM catset TABLES fldct
                 USING: 'FLDNAME'  'DD03L' 'FIELDNAME' '字段',
                        'FLDTYPE'  'DD03L' 'INTTYPE'   '数据类型',
                        'FLDVALUE' 'RSREF' 'STRING'    '字段值',
                        'HEXVALUE' 'RSREF' 'STRING'    'HEX'.


  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = fldct[]
    IMPORTING
      ep_table        = rf_out.
  ASSIGN rf_out->* TO <fs_out>.
  CREATE DATA rf_owa LIKE LINE OF <fs_out>.
  ASSIGN rf_owa->* TO <fs_owa>.
ENDFORM.                    "create_itab


*&---------------------------------------------------------------------*
*&      Form  getdata
*&---------------------------------------------------------------------*
FORM getdata.
  CLEAR whstr.
  LOOP AT s_conl.
    CONCATENATE whstr s_conl-low INTO whstr SEPARATED BY space.
  ENDLOOP.


  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
    EXPORTING
      text = '开始在数据库取数...'.


  TRY.
      SELECT * INTO CORRESPONDING FIELDS OF TABLE <fs_tabl>
        FROM (p_tname)
        WHERE (whstr).
    CATCH cx_root INTO cxroot.
      excmsg = cxroot->get_text( ).
      MESSAGE s000(oo) WITH '取数错误:' excmsg(50) excmsg+50(50) DISPLAY LIKE 'E'.
      RETURN.
  ENDTRY.


  IF <fs_tabl> IS INITIAL.
    MESSAGE s000(oo) WITH '数据库未取到数据'.
    RETURN.
  ENDIF.


  WRITE sy-dbcnt TO char45 LEFT-JUSTIFIED.
  numstr = lines( it_fnok ).
  CONCATENATE '开始在' char45 '条记录,' numstr '个字段中查找...' INTO tmpstr.
  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
    EXPORTING
      text = tmpstr.


  LOOP AT <fs_tabl> ASSIGNING <fs_twa>.
    tabix = sy-tabix.
    LOOP AT it_fnok .
      ASSIGN COMPONENT it_fnok-fldname OF STRUCTURE <fs_twa> TO <fs_fld>.
      IF p_hchar IS NOT INITIAL AND <fs_fld> IS INITIAL.
        CONTINUE.
      ENDIF.


      IF p_hchar <> '' .
        PERFORM findx USING p_hchar <fs_fld> CHANGING subrc.
      ENDIF.
      IF subrc = 0 OR p_hchar = '' .
        MOVE-CORRESPONDING <fs_twa> TO <fs_owa>.
        ASSIGN <fs_fld> TO <fsx> CASTING.
        wa_value-fldname  = it_fnok-fldname.
        wa_value-fldtype  = it_fnok-inttype.
        wa_value-fldvalue = <fs_fld>.
        wa_value-hexvalue = <fsx>.
        MOVE-CORRESPONDING wa_value TO <fs_owa>.
        APPEND <fs_owa> TO <fs_out>.


        IF p_proind = 'X'.
          tmpstr = sy-tabix.
          percnt = tabix * 100 / sy-dbcnt.
          CONCATENATE '已经找到' tmpstr '条' INTO tmpstr.
          CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
            EXPORTING
              percentage = percnt
              text       = tmpstr.
        ENDIF.


        IF p_update = 'X' AND p_hchar <> ''.
          CLEAR: keystr,wa_log.
          wa_log-tabname   = p_tname.
          wa_log-fieldname = it_fnok-fldname.
          wa_log-erdat     = sy-datum.
          wa_log-erzet     = sy-uzeit.
          wa_log-ernam     = sy-uname.
          wa_log-value_old = <fs_fld>.


          IF pr_clr = 'X' OR it_fnok-inttype CA 'NDT'.
            CLEAR <fs_fld>.
          ELSE .
            PERFORM replacex USING p_hchar <fs_fld> .
            IF it_fnok-convext IS NOT INITIAL AND p_conv = 'X'.
              CONCATENATE 'CONVERSION_EXIT_' it_fnok-convext '_INPUT' INTO fmname.
              CALL FUNCTION fmname
                EXPORTING
                  input  = <fs_fld>
                IMPORTING
                  output = <fs_fld>
                EXCEPTIONS
                  OTHERS = 1.
            ENDIF.
          ENDIF.
          wa_log-value_new = <fs_fld>.


          CLEAR: con_str,set_str.
          CONCATENATE it_fnok-fldname ` = <fs_fld>` INTO set_str.
          LOOP AT it_fkey.
            ASSIGN COMPONENT it_fkey-fldname OF STRUCTURE <fs_twa> TO <fs>.
            tmpstr = <fs>.
            IF sy-tabix = 1.
              CONCATENATE it_fkey-fldname ` = '` tmpstr `'` INTO con_str.
            ELSE.
              CONCATENATE con_str ` AND ` it_fkey-fldname ` = '` tmpstr `'` INTO con_str.
            ENDIF.


            CONCATENATE keystr <fs> INTO keystr RESPECTING BLANKS.
          ENDLOOP.
          UPDATE (p_tname) SET (set_str) WHERE (con_str).


          wa_log-objectid = keystr.
          INSERT (logtname) FROM wa_log.
          tmpint = tmpint + 1.
        ENDIF.
      ENDIF.
    ENDLOOP.
    IF tmpint > 1000. "超过1000条提交一次
      COMMIT WORK.
      CLEAR tmpint.
    ENDIF.
  ENDLOOP.
  IF <fs_out> IS INITIAL.
    MESSAGE s000(oo) WITH '未找到符合条件的数据'.
  ELSEIF tmpint > 0.
    COMMIT WORK.
  ENDIF.
ENDFORM.                    "getdata


*&---------------------------------------------------------------------*
*&      Form  set_zero
*&---------------------------------------------------------------------*
FORM set_zero CHANGING char.
  FIELD-SYMBOLS <fs_x> TYPE x.


  ASSIGN char TO <fs_x> CASTING.
  CLEAR <fs_x>.
ENDFORM.                    "set_zero


*&---------------------------------------------------------------------*
*&      Form  get_hchar
*&---------------------------------------------------------------------*
FORM get_hchar USING char CHANGING hchar.
  FIELD-SYMBOLS <fs_x> TYPE x.


  ASSIGN char TO <fs_x> CASTING.
  hchar = <fs_x>.
ENDFORM.                    "get_hchar


*&---------------------------------------------------------------------*
*&      Form  findx
*&---------------------------------------------------------------------*
FORM findx USING value(xchar) str CHANGING subrc.
  DATA len TYPE i.
  FIELD-SYMBOLS <fs_x> TYPE x.


  IF xchar = cspace.
    IF str CA ''.
      subrc = 0.
    ELSE.
      subrc = 4.
    ENDIF.
  ELSE.
    len = strlen( xchar ) / 4.
    ASSIGN xchar TO <fs_x> CASTING.
    <fs_x> = xchar.
    FIND xchar(len) IN str .
    subrc = sy-subrc.
  ENDIF.
ENDFORM.                    "findx


*&---------------------------------------------------------------------*
*& 替换字符串的二进制数据,仅用于UNICODE系统
*& 比如PERFORM replacex USING '000D000A' CHANGING str.
*&    PERFORM replacex USING '0009' CHANGING str.
*&---------------------------------------------------------------------*
FORM replacex USING value(xchar) CHANGING value(str).
  DATA len TYPE i.
  FIELD-SYMBOLS <fs_x> TYPE x.


  CHECK xchar <> ''.
  len = strlen( xchar ) / 4.
  ASSIGN xchar TO <fs_x> CASTING.
  <fs_x> = xchar.
  REPLACE ALL OCCURRENCES OF xchar(len) IN str WITH ''.
ENDFORM.                    "replacex


*&---------------------------------------------------------------------*
*&      Form  ASCII
*&---------------------------------------------------------------------*
FORM ascii .
  DATA hex4 TYPE x LENGTH 4.
  DATA hex1 TYPE x VALUE '20'.
  DATA inta TYPE i.
  FIELD-SYMBOLS <fc> TYPE c.


  ASSIGN hex4 TO <fc> CASTING.
  WHILE hex1 < '7F'.
    IF %_endian = 'B'.
      hex4+3 = hex1.
    ELSE.
      hex4+2 = hex1.
    ENDIF.
    WRITE: hex4+2, AT (8) <fc>+1 COLOR 6 INTENSIFIED ON INVERSE ON.
    hex1 = hex1 + 1.


    inta = sy-index MOD 8.
    IF inta = 0. SKIP. ENDIF.
  ENDWHILE.
ENDFORM.                    "ascii


*&---------------------------------------------------------------------*
*&      Form  replace_0x00
*&---------------------------------------------------------------------*
FORM replace_0x00 CHANGING data.
  DATA dtype.
  FIELD-SYMBOLS <fs>.


  DESCRIBE FIELD data TYPE dtype.
  CASE dtype.
    WHEN 'C' OR 'N' OR 'D' OR 'T' OR 'g'.
      REPLACE ALL OCCURRENCES OF %_minchar IN data WITH ''.
    WHEN 'u' OR 'v'.
      DO .
        ASSIGN COMPONENT sy-index OF STRUCTURE data TO <fs>.
        IF sy-subrc <> 0.
          EXIT.
        ELSE.
          DESCRIBE FIELD <fs> TYPE dtype.
          CHECK dtype CA 'CNDTg'.
          REPLACE ALL OCCURRENCES OF %_minchar IN <fs> WITH ''.
        ENDIF.
      ENDDO.
    WHEN 'h'.
      MESSAGE e000(oo) WITH '输入对象不支持内表'.
    WHEN OTHERS.
  ENDCASE.
ENDFORM.                    "replace_0x00


*&---------------------------------------------------------------------*
*&      Form  outdata
*&---------------------------------------------------------------------*
FORM outdata.
  slayt-zebra      = 'X'.
  slayt-no_toolbar = 'X'.
  repid = sy-repid.


  tmpstr = lines( <fs_out> ).
  IF p_update = 'X'.
    MESSAGE s000(oo) WITH '记录数:' tmpstr '.  数据库数据已更改'.
  ELSE.
    MESSAGE s000(oo) WITH '记录数:' tmpstr.
  ENDIF.


  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      it_fieldcat_lvc         = fldct[]
      is_layout_lvc           = slayt
      i_callback_program      = repid
      i_callback_user_command = 'USER_COMMAND'
    TABLES
      t_outtab                = <fs_out>.
ENDFORM.                    " outdata


*---------------------------------------------------------------------*
*       FORM catset                                                   *
*---------------------------------------------------------------------*
FORM catset TABLES fldcat USING p_field p_reftab p_reffld p_text.
  DATA: ls_fldcat TYPE lvc_s_fcat.


  ls_fldcat-fieldname =  p_field.
  ls_fldcat-scrtext_l =  p_text.
  ls_fldcat-coltext   =  p_text.
  ls_fldcat-ref_table =  p_reftab.
  ls_fldcat-ref_field =  p_reffld.
  IF p_field = 'HEXVALUE'.
    ls_fldcat-outputlen = '60'.
  ELSE.
    ls_fldcat-col_opt   = 'A'.
  ENDIF.
  IF 'FLDNAME FLDVALUE HEXVALUE FLDTYPE' CS p_field.
    ls_fldcat-emphasize = 'C300'.
  ENDIF.
  READ TABLE it_fkey WITH KEY fldname = p_field.
  IF sy-subrc = 0.
    ls_fldcat-key = 'X'.
  ENDIF.


  APPEND ls_fldcat TO fldcat .
  CLEAR ls_fldcat .
ENDFORM.                    "catset


*&--------------------------------------------------------------------*
*&      Form  user_command
*&--------------------------------------------------------------------*
FORM user_command USING r_ucomm TYPE sy-ucomm
                        r_field TYPE slis_selfield.
  DATA: lr_fld TYPE REF TO data.


  CASE r_ucomm.
    WHEN '&IC1'.
      READ TABLE <fs_out> INTO <fs_owa> INDEX r_field-tabindex.
      MOVE-CORRESPONDING <fs_owa> TO wa_value.
      CASE r_field-fieldname.
        WHEN 'FLDNAME' OR 'FLDTYPE'.
          CALL FUNCTION 'RS_TOOL_ACCESS'
            EXPORTING
              operation    = 'SHOW'
              object_name  = p_tname
              object_type  = 'TABL'
              position     = wa_value-fldname
            EXCEPTIONS
              not_executed = 01.
        WHEN 'FLDVALUE'.
          PERFORM selscreen_ext USING 'GET CRET NONE SPOS'.


          CONCATENATE p_tname '-' wa_value-fldname INTO paraname.
          CREATE DATA lr_fld TYPE (paraname).
          ASSIGN lr_fld->* TO <fs_fld>.
          <fs_fld> = wa_value-fldvalue.
          WRITE <fs_fld> TO p_fval LEFT-JUSTIFIED .
          CALL SELECTION-SCREEN 1100 STARTING AT 32 6 .
        WHEN 'HEXVALUE'.
          PERFORM show_hex USING wa_value-fldvalue wa_value-hexvalue.
        WHEN OTHERS .
          PERFORM se16_single_show USING <fs_owa>.
      ENDCASE.
  ENDCASE.
ENDFORM.                    "user_command


*&---------------------------------------------------------------------*
*&      Form  show_hex
*&---------------------------------------------------------------------*
FORM show_hex USING fldvalue hexvalue.
  DATA: char255 TYPE char255.
  DATA: lt_txt TYPE TABLE OF char4 WITH HEADER LINE.
  DATA: lt_cat TYPE lvc_t_fcat WITH HEADER LINE.
  DATA: BEGIN OF lt_out OCCURS 0,
          index TYPE sy-index,
          hchar TYPE char4,
          cchar TYPE char2,
        END OF lt_out.


  CHECK hexvalue IS NOT INITIAL.
  char255 = fldvalue.


  CALL FUNCTION 'SCMS_STRING_TO_FTEXT'
    EXPORTING
      text      = hexvalue
    TABLES
      ftext_tab = lt_txt.
  LOOP AT lt_txt.
    tabix = sy-tabix - 1.
    lt_out-index = sy-tabix.
    lt_out-hchar = lt_txt.
    lt_out-cchar = char255+tabix(1).
    APPEND lt_out.
  ENDLOOP.


  PERFORM catset TABLES lt_cat
                 USING: 'INDEX' '' '' 'INDEX',
                        'HCHAR' '' '' 'HCHAR',
                        'CCHAR' '' '' 'CCHAR'.
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      it_fieldcat_lvc       = lt_cat[]
      i_screen_start_column = 60
      i_screen_start_line   = 1
      i_screen_end_column   = 84
      i_screen_end_line     = 20
    TABLES
      t_outtab              = lt_out
    EXCEPTIONS
      program_error         = 1.
ENDFORM.                    "show_hex


*&---------------------------------------------------------------------*
*&      Form  se16_single_show
*&---------------------------------------------------------------------*
FORM se16_single_show USING wa.
  DATA: dba_sellist TYPE TABLE OF tbsellist WITH HEADER LINE.
  DATA: action(4) VALUE 'EANZ'.
  DATA: prog      TYPE rsnewleng-programm.
  DATA: mem_id(32) VALUE 'TABELLENANZEIGER'.
  FIELD-SYMBOLS <ls_fld>.


  LOOP AT it_fkey.
    ASSIGN COMPONENT it_fkey-fldname OF STRUCTURE wa TO <ls_fld>.
    dba_sellist-tablefield = it_fkey-fldname.
    dba_sellist-operator   = 'EQ'.
    dba_sellist-value      = <ls_fld>.
    APPEND dba_sellist.
  ENDLOOP.
  EXPORT action dba_sellist TO MEMORY ID mem_id.


  CONCATENATE '/1BCDWB/DB' p_tname INTO prog.
  SUBMIT (prog) AND RETURN.
ENDFORM.                    "se16_single_show


*&---------------------------------------------------------------------*
*& 创建透明表
*&---------------------------------------------------------------------*
FORM create_table TABLES transfld STRUCTURE dd03p
                  USING transtab ddtext devclass .
  DATA: objstr(40),
        reqnum TYPE trkorr.
  DATA: wa_02v TYPE dd02v ,
        wa_09l TYPE dd09v ,
        subrc  TYPE sy-subrc.
  DATA: lt_03p TYPE TABLE OF dd03p WITH HEADER LINE .


  SELECT SINGLE * INTO wa_02v FROM dd02v
    WHERE tabname = transtab AND
          tabclass = 'TRANSP'.
  IF sy-subrc = 0.
    MESSAGE s000(oo) WITH '透明表' transtab '已存在'.
    RETURN.
  ENDIF.


***传输请求
  CONCATENATE 'TABL' transtab INTO objstr.
  CALL FUNCTION 'RS_CORR_INSERT'
    EXPORTING
      object              = objstr
      object_class        = 'DICT'
      devclass            = devclass
      korrnum             = reqnum
      master_language     = sy-langu
      global_lock         = 'X'
      mode                = 'I'
      suppress_dialog     = ''
    IMPORTING
      ordernum            = reqnum
    EXCEPTIONS
      cancelled           = 1
      permission_failure  = 2
      unknown_objectclass = 3
      OTHERS              = 4.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
            WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4  .
  ENDIF.


***创建透明表并激活
  wa_02v-tabname    = transtab.
  wa_02v-ddtext     = ddtext.
  wa_02v-ddlanguage = sy-langu.
  wa_02v-tabclass   = 'TRANSP'.
  wa_02v-as4user    = sy-uname.
  wa_02v-contflag   = 'C'.
  wa_02v-mainflag   = 'X'.
  wa_09l-tabname    = transtab.
  wa_09l-tabart     = 'APPL1'.
  wa_09l-tabkat     = 6.


  LOOP AT transfld.
    lt_03p-tabname    = transtab.
    lt_03p-ddlanguage = sy-langu.
    lt_03p-position   = sy-tabix.
    lt_03p-fieldname  = transfld-fieldname.
    lt_03p-rollname   = transfld-rollname.
    lt_03p-notnull    = 'X'.
    lt_03p-keyflag    = transfld-keyflag.
    APPEND lt_03p.
    CLEAR lt_03p.
  ENDLOOP.


  CALL FUNCTION 'DDIF_TABL_PUT'
    EXPORTING
      name              = transtab
      dd02v_wa          = wa_02v
      dd09l_wa          = wa_09l
    TABLES
      dd03p_tab         = lt_03p
    EXCEPTIONS
      tabl_not_found    = 1
      name_inconsistent = 2
      tabl_inconsistent = 3
      put_failure       = 4
      put_refused       = 5
      OTHERS            = 6.
  IF sy-subrc = 0.
    CALL FUNCTION 'DDIF_TABL_ACTIVATE'
      EXPORTING
        name        = transtab
      IMPORTING
        rc          = subrc
      EXCEPTIONS
        not_found   = 1
        put_failure = 2
        OTHERS      = 3.
    IF sy-subrc <> 0 OR ( subrc > 4 ).
      MESSAGE s000(oo) WITH '创建成功,激活失败,请手工激活表ZCSL'.
    ELSE.
      MESSAGE s000(oo) WITH '创建成功,激活成功'.
    ENDIF.
  ELSE.
    MESSAGE s000(oo) WITH  '创建失败'.
  ENDIF.
ENDFORM.                    "create_table
*&---------------------------------------------------------------------*
*&      Form  fill_dd03
*&---------------------------------------------------------------------*
FORM fill_dd03 USING fldname rollname key.
  it_dd03-fieldname = fldname.
  it_dd03-rollname  = rollname.
  it_dd03-keyflag   = key.
  APPEND it_dd03. CLEAR it_dd03.
ENDFORM.                    "fill_dd03


*&---------------------------------------------------------------------*
*&      Form  UPDATE_SINGLE_FLD
*&---------------------------------------------------------------------*
FORM update_single_fld USING tabname fldname fldval whestr astxt.
  DATA: lt_setstr TYPE string.
  DATA: lr_table  TYPE REF TO data,
        lr_line   TYPE REF TO data.
  FIELD-SYMBOLS: <lfs_tab> TYPE STANDARD TABLE, <lfs_wa>, <lfs>.


  PERFORM get_dd03 USING tabname.
  TRY.
      CREATE DATA lr_table TYPE TABLE OF (tabname).
      ASSIGN lr_table->* TO <lfs_tab>.
      CREATE DATA lr_line LIKE LINE OF <lfs_tab>.
      ASSIGN lr_line->* TO <lfs_wa>.


      SELECT * INTO TABLE <lfs_tab> FROM (p_uptab) WHERE (p_upwhe).
      IF sy-subrc <> 0.
        MESSAGE e000(oo) WITH '未找到数据'.
      ENDIF.
      LOOP AT <lfs_tab> INTO <lfs_wa>.
        CLEAR: keystr,wa_log.
        LOOP AT it_fkey.
          ASSIGN COMPONENT it_fkey-fldname OF STRUCTURE <lfs_wa> TO <lfs>.
          CONCATENATE keystr <lfs> INTO keystr RESPECTING BLANKS.
        ENDLOOP.
        ASSIGN COMPONENT fldname OF STRUCTURE <lfs_wa> TO <lfs>.
        IF sy-subrc <> 0.
          MESSAGE e000(oo) WITH `数据库列'` fldname `'未知`.
        ENDIF.


        tmpstr = fldval.
        wa_log-tabname   = tabname.
        wa_log-objectid  = keystr.
        wa_log-fieldname = fldname.
        wa_log-erdat     = sy-datum.
        wa_log-erzet     = sy-uzeit.
        wa_log-ernam     = sy-uname.
        wa_log-value_old = <lfs>.
        wa_log-value_new = tmpstr.
        INSERT (logtname) FROM wa_log.
      ENDLOOP.


      IF astxt = 'X'.
        CONCATENATE fldname ` = tmpstr ` INTO lt_setstr.
      ELSE.
        CONCATENATE fldname ` = ` tmpstr INTO lt_setstr.
      ENDIF.
      UPDATE (p_uptab) SET (lt_setstr) WHERE (p_upwhe).
      IF sy-subrc = 0.
        COMMIT WORK.
        MESSAGE s000(oo) WITH '更新数据条数:' sy-dbcnt .
      ELSE.
        ROLLBACK WORK.
        MESSAGE e000(oo) WITH '更新失败'.
      ENDIF.
    CATCH cx_root INTO cxroot.
      ROLLBACK WORK.
      excmsg = cxroot->get_text( ).
      MESSAGE e000(oo) WITH excmsg.
  ENDTRY.
ENDFORM.                    " UPDATE_SINGLE_FLD


*&---------------------------------------------------------------------*
*&  弹出选择屏幕屏蔽按钮
*&---------------------------------------------------------------------*
FORM selscreen_ext USING extfcode.
  DATA: exttab TYPE slis_t_extab.


  SPLIT extfcode AT space INTO TABLE exttab.
  CALL FUNCTION 'RS_SET_SELSCREEN_STATUS'
    EXPORTING
      p_status  = '%_CSP'
    TABLES
      p_exclude = exttab.
ENDFORM.                    "selscreen_ext

761258b2573363155405e8239ec1037c.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值