Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

How to call and implement a local Class in a Function

schmelto
Active Participant

I want to refactor my code from using sub routines to use classes and methods due to a modern clean ABAP approach.

I have a function:

FUNCTION Z_FI_EDI_PAYEXT_2441
  IMPORTING
    IM_MESTYP LIKE EDIDC-MESTYP
    IM_REGUH LIKE REGUH
    IM_REGUD LIKE REGUD
    IM_FLAG_NO_REPLACE TYPE C
  EXPORTING
    EX_FIMSG LIKE FIMSG
  CHANGING
    CH_XAVIS TYPE C
    CH_EDIDC LIKE EDIDC
  TABLES
    T_REGUP LIKE REGUP
    T_EDIDD LIKE EDIDD
  EXCEPTIONS
    DONT_CREATE_IDOC.

" here some code
ENDFUNCTION.

FORM get_x_last_chars USING iv_string
                            iv_num_last_chars TYPE i
                      CHANGING cv_result.
    " here some code
ENDFORM.

I want to declare here a helper class with one method in it like (after `ENDDUNCTION.`):

CLASS helper DEFINITION.
  PUBLIC SECTION.
    METHODS
      get_x_last_chars
        IMPORTING
          string         TYPE string
          num_last_chars TYPE i
        RETURNING
          VALUE(result)  TYPE string.
ENDCLASS.
CLASS helper IMPLEMENTATION.
  METHOD get_x_last_chars.
       " here some code
    ENDIF.
  ENDMETHOD.
ENDCLASS.

If I now want to use the helper class in the function it says that helper is not known.

DATA(helper) = NEW helper( ).

-> Type helper is unknown.

May you can help me.

Further information I need this class only in this function not elsewhere.

1 ACCEPTED SOLUTION

mateuszadamus
Active Contributor

Hello 6e829fd780204f76b10f492049a3773c

You need to defined this class in one of the function groups' includes. This way the class will be global for the function group, but also visible in the function you want to use it in.

If you define right after the function the call in the function does not "know" about the class' existence.

Kind regards,
Mateusz
4 REPLIES 4

mateuszadamus
Active Contributor

Hello 6e829fd780204f76b10f492049a3773c

You need to defined this class in one of the function groups' includes. This way the class will be global for the function group, but also visible in the function you want to use it in.

If you define right after the function the call in the function does not "know" about the class' existence.

Kind regards,
Mateusz

matt
Active Contributor

The correct includes to use are in the help.sap.com. Reproduced here:

Automatically generated by the function builder

  • L<fgrp> TOP: The first include program; contains the global data for the function group.
  • L<fgrp> Uxx: These includes contain the function modules. The numbering xx indicates the sequential order in which the function modules were created. For example, L<fgrp> U01 and L<fgrp> U02 contain the first two function modules in the function group.
  • L<fgrp> F01, L<fgrp> F02... L<fgrp> Fxx: You can use these includes to write subroutines (forms) that can be called as internal forms by all function modules in the group.

The naming convention for includes is the following (xx indicates a two-digit number):

  • Suffix "Exx": Implementation of methods and classes
  • Suffix "Oxx": Implementation of PBO modules
  • Suffix "Ixx" : Implementation of PAI modules
  • Suffix "Exx": Implementation of event blocks
  • Suffix "Fxx": Implementation of local subroutines

In the top include, you can add include programs with the suffix "Dxx" for the declaration parts of local classes.

For ABAP Unit Tests, use T99.

So, declarations in Dxx, implementations in Exx and tests in T99.

Sandra_Rossi
Active Contributor

Even function modules should be abandoned as far as possible and use global classes instead.

If you need a function module for some reason, there's no problem to move the whole code in a class pool, and change the function module to have exactly one call to a method of this class + exception handling.

schmelto
Active Participant

For all with the same question I copy my solution here.

We have following function module:

FUNCTION Z_FI_EDI_PAYEXT_2441
  IMPORTING
    IM_MESTYP LIKE EDIDC-MESTYP
    IM_REGUH LIKE REGUH
    IM_REGUD LIKE REGUD
    IM_FLAG_NO_REPLACE TYPE C
  EXPORTING
    EX_FIMSG LIKE FIMSG
  CHANGING
    CH_XAVIS TYPE C
    CH_EDIDC LIKE EDIDC
  TABLES
    T_REGUP LIKE REGUP
    T_EDIDD LIKE EDIDD
  EXCEPTIONS
    DONT_CREATE_IDOC.
    
    " place for some coding or the creation of the object and calling the method
    
ENDFUNCTION.

In here we generate a new object from a global class in which our futher coding will be placed.

DATA(zcl_fi_edi_payext_2441) = NEW zcl_fi_edi_payext_2441( ).

Note: Use inline declarations!

Now we can call a public method of this class/object and can implement all further logic in here. We should put all parameters from the function module in the call of this method and made some exception handling here.

zcl_fi_edi_payext_2441->change_idoc(
    EXPORTING
      im_mestyp          = im_mestyp
      im_reguh           = im_reguh
      im_regud           = im_regud
      im_flag_no_replace = im_flag_no_replace
    IMPORTING
      ex_fimsg           = ex_fimsg
    CHANGING
      ch_xavis           = ch_xavis
      ch_edidc           = ch_edidc
      t_regup            = t_regup[]
      t_edidd            = t_edidd[]
    EXCEPTIONS
      dont_create_idoc   = 1
      OTHERS             = 2
  ).
  IF sy-subrc <> 0.
    RAISE dont_create_idoc.
  ENDIF.

The [] in t_regup[] is because we do not only want to pass the header line to the class rather then entire table.

The global class can look something like this:

CLASS zcl_fi_edi_payext_2441 DEFINITION
  PUBLIC
  CREATE PUBLIC .
  
  PUBLIC SECTION.
    TYPES: t_regup TYPE TABLE OF regup,
           t_edidd TYPE TABLE OF edidd.
           
    METHODS change_idoc
      IMPORTING
        im_mestyp          TYPE edidc-mestyp
        im_reguh           TYPE reguh
        im_regud           TYPE regud
        im_flag_no_replace TYPE c
      EXPORTING
        ex_fimsg           TYPE fimsg
      CHANGING
        ch_xavis           TYPE c
        ch_edidc           TYPE edidc
        t_regup            TYPE t_regup
        t_edidd            TYPE t_edidd
      EXCEPTIONS
        dont_create_idoc.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_fi_edi_payext_2441 IMPLEMENTATION.
  METHOD change_idoc.
    " Here the logic of the program/method
  ENDMETHOD.
ENDCLASS.

Note: We have to define t_regup TYPE TABLE OF regup and t_edidd TYPE TABLE OF edidd. for using them in the class.

To make the method more readable we can use ABAP doc expressions like this:

"! <p class="shorttext synchronized">Modify payment IDOCs</p>
"! @exception dont_create_idoc | <p class="shorttext synchronized">Don't created a payment IDOC</p>
"! @parameter im_mestyp | <p class="shorttext synchronized">Message type</p>
"! @parameter im_reguh | <p class="shorttext synchronized">Payment data from the payment program</p>
"! @parameter im_regud | <p class="shorttext synchronized">Transfer data form printing</p>
"! @parameter im_flag_no_replace | <p class="shorttext synchronized">SPACE=Special characters conversion required in texts</p>
"! @parameter ex_fimsg | <p class="shorttext synchronized">FI-messages</p>
"! @parameter ch_xavis | <p class="shorttext synchronized">Flag: Advice required</p>
"! @parameter ch_edidc | <p class="shorttext synchronized">Control record (IDoc)</p>
"! @parameter t_regup | <p class="shorttext synchronized">Processed items from the payment program</p>
"! @parameter t_edidd | <p class="shorttext synchronized">Data record (IDoc)</p>