SAP动态程序

0.1.    在数据库中动态创建、使用、删除程序

在SAP数据库中动态生成程序,调用后删除(该程序没有分配到包)

REPORT z14143_13.
"创建report
DATA: code      TYPE TABLE OF string,
      prgnm(10) TYPE c VALUE 'ZTEST_SUB',
      lw_string TYPE string.
* form the dynamic-program
CONCATENATE 'PROGRAM' prgnm '.' INTO lw_string SEPARATED BY space.
APPEND lw_string TO code.
APPEND 'WRITE:/10 ''Hello, this is the transient program!''.' TO code.
INSERT REPORT prgnm FROM code."通过内表code创建report
* call the transiet program
SUBMIT (prgnm) AND RETURN."执行程序
* append the transient program
READ REPORT prgnm INTO code."读取report到内表code
APPEND 'WRITE:/10 ''Hello, this is the transient program! 2nd Time append.''.' TO code.
INSERT REPORT prgnm FROM code."通过内表code重写report
SUBMIT (prgnm) AND RETURN."再次执行程序
DELETE REPORT  prgnm."删除程序

0.2.    动态临时子程序

0.2.1.    动态子例程

REPORT z14143_13.
DATA:
  code        TYPE TABLE OF string,
  subrtnm(10) TYPE c VALUE 'TEST',
  prog        TYPE program,
  msg(20)     TYPE c,
  line(10)    TYPE c,
  word(10)    TYPE c,
  off(3)      TYPE c,
  lw_string   TYPE string,
  sid         TYPE string.
* prepare the ”Dynamic Subroutine sentence”
APPEND 'PROGRAM SUBPOOL.' TO code.
CONCATENATE 'FORM' subrtnm '.' INTO lw_string SEPARATED BY space.
APPEND lw_string TO code.
APPEND 'Write:/10 ''This is one transient subroutine''.' TO code.
APPEND 'ENDFORM.' TO code.
* create subroutine dynamically
GENERATE SUBROUTINE POOL code NAME prog MESSAGE msg LINE line WORD  word OFFSET off SHORTDUMP-ID sid. "生成子程序
IF sy-subrc = 0.
  PERFORM (subrtnm) IN PROGRAM (prog) IF FOUND.
ELSEIF sy-subrc = 4.
  WRITE:/ 'Error occurs in line:',line, / msg, /'Word:', word, / 'Offset:', off.
ELSEIF sy-subrc = 8.
  MESSAGE sid TYPE 'I'.
ENDIF.

0.2.2.    动态类

0.2.2.1.    静态方法的类

DATA itab  TYPE TABLE OF string.
DATA prog  TYPE string.
DATA class TYPE string.
APPEND:  `program.`                     TO itab,
          `class main definition.`       TO itab,
          `  public section.`            TO itab,
          `    class-methods: meth,meth2.`      TO itab,
          `endclass.`                    TO itab,
          `class main implementation.`   TO itab,
          `  method meth.`               TO itab,
          `    message 'Test' type 'I'.` TO itab,
          `  endmethod.`                 TO itab,
          `  method meth2.`               TO itab,
          `    message 'Test2' type 'I'.` TO itab,
          `  endmethod.`                 TO itab,
          `endclass.`                    TO itab.
GENERATE SUBROUTINE POOL itab NAME prog.
CONCATENATE `\PROGRAM=` prog `\CLASS=MAIN` INTO class.
CALL METHOD (class)=>meth2.

0.2.2.2.    实例方法的类

DATA itab  TYPE TABLE OF string.
DATA prog  TYPE string.
DATA class TYPE string.
DATA oref  TYPE REF TO object.
APPEND:  `program.`                     TO itab,
          `class main definition.`       TO itab,
          `  public section.`            TO itab,
          `    methods meth.`            TO itab,
          `endclass.`                    TO itab,
          `class main implementation.`   TO itab,
          `  method meth.`               TO itab,
          `    message 'Test' type 'I'.` TO itab,
          `  endmethod.`                 TO itab,
          `endclass.`                    TO itab.
GENERATE SUBROUTINE POOL itab NAME prog.
CONCATENATE `\PROGRAM=` prog `\CLASS=MAIN` INTO class.
CREATE OBJECT oref TYPE (class).
CALL METHOD (class)=>meth.

1.   SAP动态RFC

1.1.    动态类测试DEMO

1.1.1.    正常的方式创建一个类并调用

CLASS rfccallDEFINITION.
  PUBLICSECTION.
    CLASS-METHODS:method1
                          IMPORTING
                           method1input1  TYPE i
                           method1input2  TYPE i
                          EXPORTING
                           method1output1 TYPE i
                           method1output2 TYPE i,
                    method2 IMPORTING
                             method2input1  TYPE i
                              method2input2  TYPE i
                            EXPORTING
                             method2output1 TYPE string.
ENDCLASS.
CLASS rfccall IMPLEMENTATION.
  METHOD method1.
    method1output1 = method1input1 + method1input2.
    method1output2 = method1input1 * method1input2.
  ENDMETHOD.
  METHOD method2.
    method2output1 = method2input1 && method2input2.
  ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA: liTYPE i,
      lm TYPEi,
      ls TYPEstring.
call METHOD rfccall=>method1
EXPORTING
  method1input1 =1
  method1input2 =2
IMPORTING
  method1output1 =li
  method1output2 =lm.
CALL METHOD rfccall=>method2
EXPORTING
  method2input1 =1
  method2input2 =2
IMPORTING
  method2output1 =ls.

1.1.2.    动态构造类、方法,动态调用

TYPES BEGIN OF transtru.
TYPES datatype TYPE char36.
TYPES dataname TYPE char36.
TYPES datavalue TYPE char36.
TYPES END OF transtru.

DATA BEGIN OF ls_rfcparameter.
DATA methodname TYPE char36.
DATA inputdata TYPE TABLE OF transtru.
DATA outputdata TYPE TABLE OF transtru.
DATA body TYPE  string.
DATA END OF ls_rfcparameter.
DATA lt_classmethod LIKE TABLE OF ls_rfcparameter.
DATA: inputstring TYPE string,
      outputstr   TYPE string,
      codestr     TYPE TABLE OF string WITH HEADER LINE,
      bodystr     TYPE TABLE OF string WITH HEADER LINE.
DATA prog  TYPE string.
DATA: ptab TYPE abap_parmbind_tab,
      etab TYPE abap_excpbind_tab.
inputstring = '{"METHODS":[{"METHODNAME":"METHOD1","INPUTDATA":[{"DATATYPE":"CHAR36","DATANAME":"METHOD1INPUT1","DATAVALUE":"1"}' &&
',{"DATATYPE":"CHAR36","DATANAME":"METHOD1INPUT2","DATAVALUE":"2"}],"OUTPUTDATA":[{"DATATYPE":"CHAR36","DATANAME":"METHOD1OUTPUT1"}' &&
 ',{"DATATYPE":"CHAR36","DATANAME":"METHOD1OUTPUT2"}],"BODY":"METHOD1OUTPUT1 = METHOD1INPUT1 +' &&
  ' METHOD1INPUT2.METHOD1OUTPUT2 = METHOD1INPUT1 * METHOD1INPUT2."},{"METHODNAME":"METHOD2","INPUTDATA"' &&
  ':[{"DATATYPE":"CHAR36","DATANAME":"METHOD2INPUT1","DATAVALUE":"1"},{"DATATYPE":"CHAR36","DATANAME":"METHOD2INPUT2","DATAVALUE":"2"}],"OUTPUTDATA"' &&
   ':[{"DATATYPE":"CHAR36","DATANAME":"METHOD2OUTPUT1"}],"BODY":"METHOD2OUTPUT1 = METHOD2INPUT1 && METHOD2INPUT2."}]}'.

CALL TRANSFORMATION id SOURCE XML inputstring RESULT methods = lt_classmethod.

codestr[] = VALUE #( ( `PROGRAM.` ) ( `CLASS MAIN DEFINITION.` ) ( `  PUBLIC SECTION.` ) ( `    CLASS-METHODS: ` ) ).

* 动态定义所有类方法
CLEAR codestr.
LOOP AT lt_classmethod ASSIGNING FIELD-SYMBOL(<fs_classmethod>).
  APPEND `                     ` &&  <fs_classmethod>-methodname    TO codestr.
  IF <fs_classmethod>-inputdata IS NOT INITIAL.
    APPEND  `      IMPORTING `    TO codestr.
    LOOP AT <fs_classmethod>-inputdata ASSIGNING FIELD-SYMBOL(<fs_transtru>).
      APPEND `                ` &&  <fs_transtru>-dataname && ` TYPE `  && <fs_transtru>-datatype TO codestr.
    ENDLOOP.
  ENDIF.
  IF <fs_classmethod>-inputdata IS NOT INITIAL.
    APPEND  `      EXPORTING `    TO codestr.
    LOOP AT <fs_classmethod>-outputdata ASSIGNING <fs_transtru>.
      APPEND `                ` &&  <fs_transtru>-dataname && ` TYPE `  && <fs_transtru>-datatype TO codestr.
    ENDLOOP.
  ENDIF.
  APPEND `               ,`  TO codestr.
ENDLOOP.
codestr[ lines( codestr ) ] = '          .'.
codestr[] = VALUE #( BASE codestr[] ( `ENDCLASS.` ) ( `CLASS MAIN IMPLEMENTATION.` ) ).

LOOP AT lt_classmethod ASSIGNING <fs_classmethod>.
  CLEAR codestr.
  APPEND `  METHOD ` && <fs_classmethod>-methodname && `.` TO codestr.
  SPLIT <fs_classmethod>-body AT '.' INTO TABLE bodystr.
  LOOP AT bodystr.
    IF bodystr IS INITIAL.
      CONTINUE.
    ENDIF.
    CONCATENATE bodystr '.' INTO codestr.
    APPEND codestr.
    CLEAR codestr.
  ENDLOOP.
  APPEND `  ENDMETHOD.` TO codestr.
ENDLOOP.
APPEND   `ENDCLASS.`  TO codestr.

GENERATE SUBROUTINE POOL codestr[] NAME prog.
CONCATENATE `\PROGRAM=` prog `\CLASS=MAIN` INTO DATA(class).

"动态调用
LOOP AT lt_classmethod ASSIGNING <fs_classmethod>.
  CLEAR: ptab,etab.
  IF <fs_classmethod>-inputdata IS NOT INITIAL.
    LOOP AT <fs_classmethod>-inputdata ASSIGNING <fs_transtru>.
      ptab = VALUE #( BASE ptab ( name = <fs_transtru>-dataname  kind = cl_abap_objectdescr=>exporting value = REF #( <fs_classmethod>-inputdata[ sy-tabix ]-datavalue ) ) ).
    ENDLOOP.
  ENDIF.

  "动态调用类方法
  IF <fs_classmethod>-outputdata IS NOT INITIAL.
    LOOP AT <fs_classmethod>-outputdata ASSIGNING <fs_transtru>.
      ptab = VALUE #( BASE ptab ( name = <fs_transtru>-dataname  kind = cl_abap_objectdescr=>importing value = REF #( <fs_classmethod>-outputdata[ sy-tabix ]-datavalue ) ) ).
    ENDLOOP.
  ENDIF.
  CALL METHOD (class)=>(<fs_classmethod>-methodname)
    PARAMETER-TABLE ptab "参数
    EXCEPTION-TABLE etab. "异常
  IF etab IS INITIAL.
    LOOP AT <fs_classmethod>-outputdata ASSIGNING <fs_transtru>.
      ASSIGN ptab[ name = <fs_transtru>-dataname kind = cl_abap_objectdescr=>importing ]-value TO FIELD-SYMBOL(<fs_test>).
      ASSIGN <fs_test>->* TO FIELD-SYMBOL(<fs_testdata>) .
      <fs_transtru>-datavalue = <fs_testdata>.
      CONDENSE <fs_transtru>-datavalue.
    ENDLOOP.
    outputstr = /ui2/cl_json=>serialize( data = lt_classmethod compress = '' pretty_name = /ui2/cl_json=>pretty_mode-none ).
  ELSE.
    outputstr = /ui2/cl_json=>serialize( data = etab compress = '' pretty_name = /ui2/cl_json=>pretty_mode-none ).
  ENDIF.
  cl_demo_output=>display_json( outputstr ).
  CLEAR outputstr.
ENDLOOP.

1.1.3.    改写成RFC

参数类型必须为string

FUNCTION z14143_dy_class.
*"----------------------------------------------------------------------
*"*"本地接口:
*"  IMPORTING
*"     VALUE(I_STRING) TYPE  STRING OPTIONAL
*"  EXPORTING
*"     VALUE(O_STRING) TYPE  STRING
*"----------------------------------------------------------------------

*  i_string = '{"METHODS":[{"METHODNAME":"METHOD1","INPUTDATA":[{"DATATYPE":"CHAR36","DATANAME":"METHOD1INPUT1","DATAVALUE":"1"},{"DATATYPE":"CHAR36","DATANAME":"METHOD1INPUT2","DATAVALUE":"2"}],"OUTPUTDATA":[{"DATATYPE":"CHAR36",
*"DATANAME":"METHOD1OUTPUT1"},{"DATATYPE":"CHAR36","DATANAME":"METHOD1OUTPUT2"}],"BODY":"METHOD1OUTPUT1 = METHOD1INPUT1 + METHOD1INPUT2.METHOD1OUTPUT2 = METHOD1INPUT1 * METHOD1INPUT2."},{"METHODNAME":"METHOD2","INPUTDATA":[{"DATATYPE":"CHAR36",
*"DATANAME":"METHOD2INPUT1","DATAVALUE":"1"},{"DATATYPE":"CHAR36","DATANAME":"METHOD2INPUT2","DATAVALUE":"2"}],"OUTPUTDATA":[{"DATATYPE":"CHAR36","DATANAME":"METHOD2OUTPUT1"}],"BODY":"METHOD2OUTPUT1 = METHOD2INPUT1 && METHOD2INPUT2."}]}'.

  TYPES BEGIN OF transtru.
  TYPES datatype TYPE char36.
  TYPES dataname TYPE char36.
  TYPES datavalue TYPE string.
  TYPES END OF transtru.

  DATA BEGIN OF ls_rfcparameter.
  DATA methodname TYPE char36.
  DATA inputdata TYPE TABLE OF transtru.
  DATA outputdata TYPE TABLE OF transtru.
  DATA body TYPE  string.
  DATA END OF ls_rfcparameter.
  DATA lt_classmethod LIKE TABLE OF ls_rfcparameter.
  DATA:codestr TYPE TABLE OF string WITH HEADER LINE,
       bodystr TYPE TABLE OF string WITH HEADER LINE,
       linestr TYPE TABLE OF string WITH HEADER LINE.
  DATA: prog      TYPE string,
        prostring TYPE string.
  DATA: ptab TYPE abap_parmbind_tab,
        etab TYPE abap_excpbind_tab.
  DATA errorstring TYPE string.
  DATA: msg(20)  TYPE C,
        LINE(10) TYPE C,
        word(10) TYPE C,
        off(3)   TYPE C,
        sid(3)   TYPE C.
  CALL TRANSFORMATION id SOURCE XML i_string RESULT methods = lt_classmethod.
  codestr[] = VALUE #( ( `PROGRAM.` ) ( `CLASS MAIN DEFINITION.` ) ( `  PUBLIC SECTION.` ) ( `    CLASS-METHODS: ` ) ).

* 动态定义所有类方法
  CLEAR codestr.
  LOOP AT lt_classmethod ASSIGNING FIELD-SYMBOL(<fs_classmethod>).
    APPEND `                     ` &&  <fs_classmethod>-methodname    TO codestr.
    IF <fs_classmethod>-inputdata IS NOT INITIAL.
      APPEND  `      IMPORTING `    TO codestr.
      LOOP AT <fs_classmethod>-inputdata ASSIGNING FIELD-SYMBOL(<fs_transtru>).
        APPEND `                ` &&  <fs_transtru>-dataname && ` TYPE `  && <fs_transtru>-datatype TO codestr.
      ENDLOOP.
    ENDIF.
    IF <fs_classmethod>-inputdata IS NOT INITIAL.
      APPEND  `      EXPORTING `    TO codestr.
      LOOP AT <fs_classmethod>-outputdata ASSIGNING <fs_transtru>.
        APPEND `                ` &&  <fs_transtru>-dataname && ` TYPE `  && <fs_transtru>-datatype TO codestr.
      ENDLOOP.
    ENDIF.
    APPEND `               ,`  TO codestr.
  ENDLOOP.
  codestr[ lines( codestr ) ] = '          .'.
  codestr[] = VALUE #( BASE codestr[] ( `ENDCLASS.` ) ( `CLASS MAIN IMPLEMENTATION.` ) ).

  LOOP AT lt_classmethod ASSIGNING <fs_classmethod>.
    CLEAR codestr.
    APPEND `  METHOD ` && <fs_classmethod>-methodname && `.` TO codestr.
    SPLIT <fs_classmethod>-body AT '.' INTO TABLE bodystr.
    LOOP AT bodystr.
      IF bodystr IS INITIAL.
        CONTINUE.
      ENDIF.
      "一行不能超过128个字符
      IF strlen( bodystr ) > 127.
        REFRESH linestr.
        SPLIT bodystr AT space INTO TABLE linestr.
        prostring = ''.
        LOOP AT linestr INTO DATA(lv_str).
          IF strlen( prostring && ` ` && lv_str ) < 127.
            prostring = prostring && ` ` && lv_str.
          ELSE.
            codestr = prostring.
            APPEND codestr.
            CLEAR codestr.
            prostring = lv_str.
          ENDIF.
        ENDLOOP.
        bodystr = prostring.
      ENDIF.
      CONCATENATE bodystr '.' INTO codestr.
      APPEND codestr.
      CLEAR codestr.
    ENDLOOP.
    APPEND `  ENDMETHOD.` TO codestr.
  ENDLOOP.
  APPEND   `ENDCLASS.`  TO codestr.
  GENERATE SUBROUTINE POOL codestr[] NAME prog MESSAGE msg LINE line WORD  word OFFSET off SHORTDUMP-ID sid.
  IF sy-subrc <> 0.
    o_string = 'Error occurs in line:' && line && msg && 'Word:' && word && 'Offset:' && off.
    RETURN.
  ENDIF.
  CONCATENATE `\PROGRAM=` prog `\CLASS=MAIN` INTO DATA(class).

  "动态类所有方法调用
  LOOP AT lt_classmethod ASSIGNING <fs_classmethod>.
    CLEAR: ptab,etab.
    IF <fs_classmethod>-inputdata IS NOT INITIAL.
      LOOP AT <fs_classmethod>-inputdata ASSIGNING <fs_transtru>.
        ptab = VALUE #( BASE ptab ( name = <fs_transtru>-dataname  kind = cl_abap_objectdescr=>exporting value = REF #( <fs_classmethod>-inputdata[ sy-tabix ]-datavalue ) ) ).
      ENDLOOP.
    ENDIF.

    "动态调用类方法
    IF <fs_classmethod>-outputdata IS NOT INITIAL.
      LOOP AT <fs_classmethod>-outputdata ASSIGNING <fs_transtru>.
        ptab = VALUE #( BASE ptab ( name = <fs_transtru>-dataname  kind = cl_abap_objectdescr=>importing VALUE = REF #( <fs_classmethod>-outputdata[ sy-tabix ]-datavalue ) ) ).
      ENDLOOP.
    ENDIF.
    CALL METHOD (class)=>(<fs_classmethod>-methodname)
      PARAMETER-TABLE ptab "参数
          EXCEPTION-TABLE etab. "异常
    IF etab IS INITIAL.
      LOOP AT <fs_classmethod>-outputdata ASSIGNING <fs_transtru>.
        ASSIGN ptab[ name = <fs_transtru>-dataname kind = cl_abap_objectdescr=>importing ]-value TO FIELD-SYMBOL(<fs_test>).
        ASSIGN <fs_test>->* TO FIELD-SYMBOL(<fs_testdata>) .
        <fs_transtru>-datavalue = <fs_testdata>.
        CONDENSE <fs_transtru>-datavalue.
      ENDLOOP.
    ELSE.
      errorstring = /ui2/cl_json=>serialize( data = etab compress = '' pretty_name = /ui2/cl_json=>pretty_mode-none ).
    ENDIF.
  ENDLOOP.
  IF errorstring IS NOT INITIAL.
    o_string = errorstring.
  ELSE.
    o_string = /ui2/cl_json=>serialize( data = lt_classmethod compress = '' pretty_name = /ui2/cl_json=>pretty_mode-none ).
  ENDIF.
ENDFUNCTION.

1.1.4.    调用RFC

REPORT z14143_12.
DATA i_string TYPE string.
DATA o_string TYPE string.
i_string = '{"METHODS":[{"METHODNAME":"METHOD1","INPUTDATA":[{"DATATYPE":"CHAR36","DATANAME":"METHOD1INPUT1","DATAVALUE":"1"}' &&
',{"DATATYPE":"CHAR36","DATANAME":"METHOD1INPUT2","DATAVALUE":"2"}],"OUTPUTDATA":[{"DATATYPE":"CHAR36","DATANAME":"METHOD1OUTPUT1"}' &&
',{"DATATYPE":"CHAR36","DATANAME":"METHOD1OUTPUT2"}],"BODY":"METHOD1OUTPUT1 = METHOD1INPUT1 +' &&
' METHOD1INPUT2.METHOD1OUTPUT2 = METHOD1INPUT1 * METHOD1INPUT2."},{"METHODNAME":"METHOD2","INPUTDATA"' &&
':[{"DATATYPE":"CHAR36","DATANAME":"METHOD2INPUT1","DATAVALUE":"1"},{"DATATYPE":"CHAR36","DATANAME":"METHOD2INPUT2","DATAVALUE":"2"}],"OUTPUTDATA"' &&
':[{"DATATYPE":"CHAR36","DATANAME":"METHOD2OUTPUT1"}],"BODY":"METHOD2OUTPUT1 = METHOD2INPUT1 && METHOD2INPUT2."}]}'.

CALL FUNCTION 'Z14143_DY_CLASS'
EXPORTING
  i_string = i_string
IMPORTING
  o_string = o_string
.
cl_demo_output=>display_json( o_string ).


猜你喜欢

转载自blog.csdn.net/qq_16635325/article/details/80242057
SAP