I've been working as an SAP developer for quite some time, and there's something I always have seen and do, and that's write a lot of code. For example, when i create a selection screen I have to type code for every parameter, is very reasonable when it’s a single screen, but imagine when are several screens, it becomes a laborious task, which consumes a lots of hours of development. One posible solution is in some way automatize the code generation, and avoid type code and save time.
The same problem of write code several times happens to me when i call modules functions or standard bapis, the workbench tool provides me the Pattern, witch generates the code for the function call.
!https://lh3.googleusercontent.com/nEOT2GS36RnXSFKKSxJfjBwgrD8JjePerRXj0ot-zm-C2wVNsVjGA4liwDjRTx3zpm...!
This tool gives me the possibility of assign the variables to the function parameters by myself, witch is and advantage because is flexible, but also is an disadvantage (in my opinion) because i have to assign the variables and declares too for all the parameters.
That's how I came with the idea to add variables to the corresponding parameters automatically and declare those variables.
!https://lh6.googleusercontent.com/EE8ITMdbJWHD1RJabGuNHR0VyKGGKYg0se2SvtfQTyNFTW8WTevf0lU8VDxYQkAk_B...!
This is my program, which is in experimental stage n_n, my abapers friends help me with the testing, maybe if you can test it and give me feedback it helps me a lot to make more improvements.
&----
*& Report Z_FM_CALL_CODE
*&
&----
*& Autor: Raúl Vides Mosquera Pumaricra.
*& Lima-Perú 2010.
&----
REPORT z_fm_call_code.
CONSTANTS: c_tip_import TYPE c VALUE 'I',
c_tip_export TYPE c VALUE 'E',
c_tip_tables TYPE c VALUE 'T'.
TYPES: BEGIN OF ty_codigo,
linea TYPE string,
END OF ty_codigo.
TYPES ty_tfdir TYPE STANDARD TABLE OF tfdir.
TYPES ty_tftit TYPE STANDARD TABLE OF tftit.
TYPES ty_funct TYPE STANDARD TABLE OF funct.
TYPES ty_enlfdir TYPE STANDARD TABLE OF enlfdir.
TYPES ty_trdir TYPE STANDARD TABLE OF trdir.
TYPES ty_fupararef TYPE STANDARD TABLE OF sfupararef.
TYPES ty_abaptxt255 TYPE STANDARD TABLE OF abaptxt255.
TYPES ty_line(72) TYPE c.
TYPES ty_line_tab TYPE STANDARD TABLE OF ty_line.
TYPES swbse_max_line(255) TYPE c.
TYPES swbse_max_line_tab TYPE TABLE OF swbse_max_line.
TYPES: BEGIN OF ty_variable,
tipo_var TYPE c,
identificador TYPE string, "char30, "char25,
pertenece_a TYPE char30,
tipo_dato TYPE rs38l_typ,
tipo_tabla TYPE c,
instancia TYPE char15,
valor TYPE char30,
cod_mod TYPE numc5,
in_out TYPE c,
traspaso TYPE c, "Ref o Value
optional TYPE c,
param_origina TYPE char30,
END OF ty_variable.
TYPES: BEGIN OF ty_parametro_cant,
parameter TYPE char30,
cant TYPE i,
END OF ty_parametro_cant.
TYPES: BEGIN OF ty_modulos,
cod_mod TYPE numc5,
tipo_mod TYPE c, "Form o Metodo
identificador TYPE char30,
pertenece_a TYPE char30,
metodo_event TYPE char30,
clase_event TYPE char30,
END OF ty_modulos.
DATA it_codigo TYPE STANDARD TABLE OF ty_codigo.
Parameters
DATA it_import TYPE STANDARD TABLE OF rsimp. "Importing
DATA it_change TYPE STANDARD TABLE OF rscha. "Changing
DATA it_export TYPE STANDARD TABLE OF rsexp. "Exporting
DATA it_tables TYPE STANDARD TABLE OF rstbl. "Tables
DATA it_except TYPE STANDARD TABLE OF rsexc. "Exception
DATA it_param_docu TYPE STANDARD TABLE OF rsfdo.
DATA it_ptfdir TYPE ty_tfdir.
DATA it_ptftit TYPE ty_tftit.
DATA it_pfunct TYPE ty_funct.
DATA it_penlfdir TYPE ty_enlfdir.
DATA it_ptrdir TYPE ty_trdir.
DATA it_pfupararef TYPE ty_fupararef.
DATA it_uincl TYPE ty_abaptxt255.
DATA it_variables TYPE STANDARD TABLE OF ty_variable.
DATA it_parametro_cant TYPE STANDARD TABLE OF ty_parametro_cant.
DATA w_funcname TYPE rs38l_fnam.
DATA it_lines TYPE ty_line_tab.
DATA w_offset TYPE i.
DATA w_max_offset TYPE i.
DATA wa_lines LIKE LINE OF it_lines.
PARAMETER p_func TYPE rs38l_fnam OBLIGATORY.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_func.
CALL FUNCTION 'RS_HELP_HANDLING'
EXPORTING
dynpfield = 'P_FUNC'
dynpname = sy-dynnr
object = 'FB'
progname = 'SAPMS38L'
suppress_selection_screen = 'X'.
START-OF-SELECTION.
DATA rep TYPE swbse_max_line_tab.
w_funcname = p_func.
REFRESH: it_import, it_change, it_export,
it_tables, it_except, it_param_docu.
PERFORM fu_import_interface_ext(sapms38l)
TABLES it_import
it_change
it_export
it_tables
it_except
it_param_docu
USING w_funcname.
REFRESH: it_ptfdir, it_ptftit, it_pfunct,
it_penlfdir, it_ptrdir, it_pfupararef,
it_uincl.
PERFORM func_get_object USING w_funcname
CHANGING it_ptfdir
it_ptftit
it_pfunct
it_penlfdir
it_ptrdir
it_pfupararef
it_uincl.
REFRESH it_parametro_cant.
CLEAR: w_offset, w_max_offset.
PERFORM get_max_longitud_fm_param USING c_tip_tables
CHANGING w_offset.
w_max_offset = w_offset.
CLEAR w_offset.
PERFORM get_max_longitud_fm_param USING c_tip_export
CHANGING w_offset.
IF w_offset GT w_max_offset.
w_max_offset = w_offset.
ENDIF.
CLEAR w_offset.
PERFORM get_max_longitud_fm_param USING c_tip_import
CHANGING w_offset.
IF w_offset GT w_max_offset.
w_max_offset = w_offset.
ENDIF.
PERFORM generar_variables USING 'I'.
PERFORM generar_variables USING 'E'.
PERFORM generar_variables USING 'T'.
PERFORM evitar_parametros_repetidos.
PERFORM codigo_declaracion_variable.
PERFORM generar_llamado_fm USING w_funcname
CHANGING rep.
FIELD-SYMBOLS .
ENDLOOP.
*&----
*& Form get_max_longitud_fm_param
*&----
Obtiene la máxima longitud de los nombres de los parámetros.
*----
--> w_tipo_param Tipo de parámetro
<-- w_length_o Longitud máxima
*----
FORM get_max_longitud_fm_param USING value(w_tipo_param) TYPE c
CHANGING value(w_length_o) TYPE i.
DATA w_length TYPE i.
DATA w_campo TYPE char30.
DATA w_itab_name TYPE char30.
DATA wa_parametro_cant LIKE LINE OF it_parametro_cant.
FIELD-SYMBOLS .
ENDFORM. " get_max_longitud_fm_param
*&----
*& Form get_nombre_parametro
*&----
Obtiene en nombre del parámetro
*----
--> w_tipo_param (I)mport, (E)xport (T)ables
<-- w_itab_name Nombre de tabla interna
*----
FORM get_nombre_parametro USING value(w_tipo_param) TYPE c
CHANGING value(w_itab_name) TYPE char30.
CASE w_tipo_param.
WHEN c_tip_import. "Import
w_itab_name = 'it_import'.
WHEN c_tip_export. "Export
w_itab_name = 'it_export'.
WHEN c_tip_tables. "Tables
w_itab_name = 'it_tables'.
ENDCASE.
ENDFORM. " get_nombre_parametro
*&----
*& Form get_patron_para_declaracion
*&----
text
*----
--> wa_fs_fm
--> w_tipo_param text
<-- w_var text
<-- w_tipo_dato
<-- w_tipo_s
*----
FORM get_patron_para_declaracion USING value(wa_fs_fm) TYPE any
value(w_tipo_param) TYPE c
CHANGING value(w_var) TYPE string
value(w_tipo_dato) TYPE string
value(w_tipo_s) TYPE char10.
DATA w_campo TYPE char30.
FIELD-SYMBOLS -typ'.
ENDIF.
WHEN c_tip_tables. "Tables
w_var = 'it_[NOMBRE]'.
w_tipo_dato = 'STANDARD TABLE OF '.
w_campo = '.
ENDFORM. " get_patron_para_declaracion
&----
*& Form GENERAR_LLAMADO_FM
&----
Genera el código de llamado de la FM.
Nota: tomado del método standard METH_ED_GENERATE_CALL
de la clase CL_FB_FUNCTION_UTILITY.
----
--> funcname Nombre de la función
<-- rep Código
----
FORM generar_llamado_fm USING value(funcname) TYPE rs38l_fnam
CHANGING value(rep) TYPE swbse_max_line_tab.
DATA: BEGIN OF func,
fu1 TYPE c VALUE '''',
name TYPE rs38l-name,
fu2 TYPE c VALUE '''',
END OF func.
DATA: BEGIN OF ip,
ip1 TYPE c VALUE 'I',
num(2),
END OF ip.
DATA: BEGIN OF ep,
ep1 TYPE c VALUE 'E',
num(2),
END OF ep.
DATA: BEGIN OF tp,
tp1 TYPE c VALUE 'T',
num(2),
END OF tp.
DATA: incl TYPE rs38l-include,
length TYPE i,
lengt2 TYPE i,
max TYPE p,
l_com_line TYPE i,
l_lines TYPE i,
mit_try_endtry TYPE c,
l_obli TYPE c.
DATA w_lengt_aux TYPE i.
CONSTANTS: type_ins TYPE i VALUE 2,
parm_ins TYPE i VALUE 4.
DATA: num TYPE i.
FIELD-SYMBOLS LIKE LINE OF it_variables.
E. Crasovan: Work-area's wg. OO definiert
DATA w_enlfdir TYPE enlfdir.
DATA w_p_if_import TYPE rsimp.
DATA w_p_if_export TYPE rsexp.
DATA w_p_if_change TYPE rscha.
DATA w_p_if_tables TYPE rstbl.
DATA w_p_if_except TYPE rsexc.
DATA w_rep TYPE swbse_max_line.
DATA l_rseumod TYPE rseumod.
DATA l_fbpattern TYPE fbpattern.
FIELD-SYMBOLS LIKE LINE OF it_except. "I-RMP
*
CALL FUNCTION 'RS_WORKBENCH_CUSTOMIZING'
EXPORTING
choice = 'EW'
suppress_dialog = 'X'
IMPORTING
setting = l_rseumod.
E. Crasovan: exten3 sagt aus ob der FB mit Exceptionklassen arbeitet
CLEAR l_fbpattern.
MOVE-CORRESPONDING l_rseumod TO l_fbpattern.
mit_try_endtry = l_fbpattern-with_try_endtry.
SELECT SINGLE exten3 FROM enlfdir INTO w_enlfdir-exten3
WHERE funcname = funcname.
Die ganze Logik hier ist eigentlich die Form ed_generate_call_new
*
CLEAR length.
LOOP AT it_import ASSIGNING -exception ).
IF lengt2 GT length.
length = lengt2.
ENDIF.
ENDLOOP.
IF length LT 7.
length = 7.
ENDIF.
lengt2 = length + 13.
length = length + 11.
E. Crasovan
Wenn mit Exceptionklassen gearbeitet wird, soll der Aufruf des FB's in einem
TRY ... ENDTRY Block eingeschlossen werden.
CLEAR: w_rep.
*
Achtung, hier wird entschieden ob TRY...CATCH...ENTRY verwendet wird oder nicht!!!
Sollte TRY...ENTRY doch erscheinen, dann mit_try_endry auf NICHT INITIAL setzen.
IF NOT w_enlfdir-exten3 IS INITIAL.
IF NOT mit_try_endtry IS INITIAL.
w_rep = 'TRY.'.
APPEND w_rep TO rep.
CLEAR w_rep.
ENDIF.
ENDIF.
w_rep = 'CALL FUNCTION'.
func-name = funcname.
CONDENSE func NO-GAPS.
w_rep+20 = func.
CONDENSE w_rep.
APPEND w_rep TO rep. CLEAR w_rep.
*
CLEAR: l_com_line.
l_obli = 'X'.
LOOP AT it_import ASSIGNING -parameter.
w_lengt_aux = 255 - length. "I-RMP
ASSIGN w_rep+length(1) TO <f>. "D-RMP
ASSIGN w_rep+length(w_lengt_aux) TO = '='.
Inicio RMP
READ TABLE it_variables ASSIGNING SEPARATED BY space.
ENDIF.
Fin RMP
IF NOT .
<f> = '"'. "D-RMP
.
<f> = ''' '''. "D-RMP
ELSE.
ASSIGN w_rep+lengt2(28) TO .
<f> = '"'. "D-RMP
.
<f> = '"'. "D-RMP
-parameter.
w_lengt_aux = 255 - length. "I-RMP
ASSIGN w_rep+length(1) TO <f>. "D-RMP
ASSIGN w_rep+length(w_lengt_aux) TO = '='.
Inicio RMP
READ TABLE it_variables ASSIGNING SEPARATED BY space.
ENDIF.
Fin RMP
IF l_fbpattern-formal_eq_actual .
<f> = '"'. "D-RMP
-parameter.
ASSIGN w_rep+length(1) TO <f>. "D-RMP
ASSIGN w_rep+length(w_lengt_aux) TO = '='.
Inicio RMP
READ TABLE it_variables ASSIGNING SEPARATED BY space.
ENDIF.
Fin RMP
IF l_fbpattern-formal_eq_actual -optional IS INITIAL.
w_rep(1) = '"'. "D-RMP
w_rep(1) = '*'. "I-RMP
IF l_obli = 'X'.
CLEAR l_obli.
ENDIF.
ELSE.
l_obli = '1'.
ENDIF.
APPEND w_rep TO rep. CLEAR w_rep.
ENDLOOP.
IF l_obli IS INITIAL.
READ TABLE rep INDEX l_com_line INTO w_rep.
ASSIGN w_rep(1) TO .
<f> = '"'. "D-RMP
.
<f> = '"'. "D-RMP
.
<f> = '"'. "D-RMP
= '*'. "I-RMP
MODIFY rep FROM w_rep INDEX l_com_line.
CLEAR w_rep.
ENDIF.
*
E. Crasovan
Wenn mit Exceptionklassen gearbeitet wird, soll der Aufruf des FB's in einem
TRY ... ENDTRY Block eingeschlossen werden.
*
*
IF NOT w_enlfdir-exten3 IS INITIAL.
CLEAR w_rep.
w_rep+10 = '.'.
APPEND w_rep TO rep.
*
IF NOT mit_try_endtry IS INITIAL.
DESCRIBE TABLE it_except LINES l_lines.
IF NOT l_lines IS INITIAL.
LOOP AT it_except ASSIGNING -exception '.' INTO w_rep.
w_rep+5(1) = space.
APPEND w_rep TO rep.
CLEAR w_rep.
ENDLOOP.
ENDIF.
*
w_rep = 'ENDTRY.'.
APPEND w_rep TO rep.
CLEAR w_rep.
ENDIF.
ELSE.
dieser Teil kommt aus ed_generate_call_new
DESCRIBE TABLE it_except LINES l_lines.
IF NOT l_lines IS INITIAL.
w_rep = '"'. "D-RMP
w_rep = '*'. "I-RMP
w_rep+type_ins = 'EXCEPTIONS'.
APPEND w_rep TO rep. CLEAR w_rep.
LOOP AT it_except ASSIGNING .
<f> = '"'. "D-RMP
= num.
APPEND w_rep TO rep. CLEAR w_rep.
ENDLOOP.
IF l_fbpattern-exc_wo_others = space.
num = num + 1.
w_rep = '"'. "D-RMP
w_rep = '*'. "I-RMP
w_rep+parm_ins = 'OTHERS'.
ASSIGN w_rep+length(1) TO .
Wegen zu starken Moserns der Anwendung wieder ausgebaut
if num = 1.
Keine Exception vorhanden, wegen des SLIN auf 0 abbilden.
num = 0.
endif.
= num.
APPEND w_rep TO rep. CLEAR w_rep.
ENDIF.
ENDIF.
CLEAR w_rep.
w_rep+10 = '.'.
APPEND w_rep TO rep.
*EC's
ENDIF.
ENDFORM. " GENERAR_LLAMADO_FM
&----
*& Form GENERAR_VARIABLES
&----
Genera las variables en base a los parámetros de la función
----
--> w_tipo_param (I)mport, (E)xport (T)ables
----
FORM generar_variables USING value(w_tipo_param) TYPE c.
DATA w_itab_name TYPE char30.
DATA w_var TYPE string.
DATA w_tipo_dato TYPE string.
DATA w_tipo_ref TYPE rs38l_typ.
DATA w_campo TYPE char30.
DATA w_tipo_s TYPE char10.
DATA wa_variables LIKE LINE OF it_variables.
FIELD-SYMBOLS -structure.
ENDIF.
REPLACE '[TIPO]' IN w_tipo_dato WITH w_tipo_ref.
wa_variables-tipo_dato = w_tipo_dato.
wa_variables-in_out = w_tipo_param.
APPEND wa_variables TO it_variables.
ENDLOOP.
ENDFORM. " GENERAR_VARIABLES
&----
*& Form CODIGO_DECLARACION_VARIABLE
&----
Genera el código acerca de la declaración de variables.
----
FORM codigo_declaracion_variable .
DATA w_line TYPE swbse_max_line.
DATA w_line_aux TYPE swbse_max_line.
FIELD-SYMBOLS .
REPLACE '[VAR]' IN w_line WITH -instancia.
w_offset = w_max_offset + 9.
SPLIT w_line AT '%' INTO w_line w_line_aux.
w_line+w_offset = w_line_aux.
WRITE / w_line.
ENDLOOP.
ENDFORM. " CODIGO_DECLARACION_VARIABLE
&----
*& Form EVITAR_PARAMETROS_REPETIDOS
&----
Evita los parámetros repetidos.
----
FORM evitar_parametros_repetidos .
DATA w_i TYPE n.
FIELD-SYMBOLS -identificador.
ENDIF.
ENDLOOP.
ENDFORM. " EVITAR_PARAMETROS_REPETIDOS
&----
*& Form FUNC_GET_OBJECT
&----
FM: FUNC_GET_OBJECT
----
--> w_funcname Nombre del módulo de función
<-- it_ptfdir
<-- it_ptftit
<-- it_pfunct
<-- it_penlfdir
<-- it_ptrdir
<-- it_pfupararef
<-- it_uincl
----
FORM func_get_object USING value(w_funcname) TYPE rs38l_fnam
CHANGING value(it_ptfdir) TYPE ty_tfdir
value(it_ptftit) TYPE ty_tftit
value(it_pfunct) TYPE ty_funct
value(it_penlfdir) TYPE ty_enlfdir
value(it_ptrdir) TYPE ty_trdir
value(it_pfupararef) TYPE ty_fupararef
value(it_uincl) TYPE ty_abaptxt255.
REFRESH: it_ptfdir, it_ptftit, it_pfunct,
it_penlfdir, it_ptrdir, it_pfupararef,
it_uincl.
CHECK w_funcname IS NOT INITIAL.
CALL FUNCTION 'FUNC_GET_OBJECT'
EXPORTING
funcname = w_funcname
TABLES
ptfdir = it_ptfdir
ptftit = it_ptftit
pfunct = it_pfunct
penlfdir = it_penlfdir
ptrdir = it_ptrdir
pfupararef = it_pfupararef
uincl = it_uincl
EXCEPTIONS
function_not_exist = 1
version_not_found = 2
OTHERS = 3.
ENDFORM. " FUNC_GET_OBJECT
</textarea></p>