SAP for Utilities Blogs
Discover insights and practical tips to optimize operations, reduce costs, and deliver reliable energy with SAP technology. Contribute your own blog post!
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

Recently I was in a need of changing Contract Account based on the indicator in the non-character-delimited text file in which each line consists of set of data. Business scenario behind it is the following: on a set date each month bank sends the text file to the customer. In that file they specify who contracted direct debit service with the bank. The file consists of a number of lines, grouped in three types of lines (header line, data lines and footer). The data lines consists of several data, among which are contract account number and direct debit status (contracted / revoked). Data is not separated by separation character, but the lenght of each data is the same (meaning you always know the position of each data element).

Being a functional consultant with programming experience, I decided to write an ABAP program which would do the following:

  • Upload the text file into the SAP
  • Separate the needed data and fill in the internal table
  • Check the Contract Account (read all its data)
  • Change the Contract Account (update the Incoming Payment Method field with the value entered on the selection screen)

Checking SCN and other places I could find bits of code that helped me create the needed. The least documented thing was the BAPIs BAPI_ISUACCOUNT_GETDETAIL and BAPI_ISUACCOUNT_CHANGE. Thats why I decided to give the example of the whole program in this blog post, having in mind it could help someone who has the similar needs.

Prerequisites

I will assume you opened a new package (if needed) and created a new program in SE80 for this purpose.

Data

First, lets start with the definition of the data we will be needing in the program:

TYPES:

       BEGIN OF DD_STRUCT,

         line_type  TYPE c LENGTH 3,

         ntp_number TYPE c LENGTH 22,

         indicator  TYPE c LENGTH 2,

       END OF DD_STRUCT.

DATA : l_file              TYPE string,

            gv_line_space(256) TYPE c,

            l_testrn          TYPE c,

            w_return        TYPE bapiret2,

            l_ca               TYPE BAPICAPARA,

            l_p                 TYPE BAPIBPPARA.

DATA : it_file TYPE STANDARD TABLE OF DD_STRUCT,

            wa_file LIKE LINE OF it_file.

DATA : lt_cadata    TYPE bapiisuvkp  OCCURS 0 WITH HEADER LINE,

            lt_cadatax   TYPE bapiisuvkpx OCCURS 0 WITH HEADER LINE.

Defining our own structure, DD_STRUCT, will help us have a set of data in one place. The definition is connected with the position of the data elements in the text file: line_type data is the first data in the file line and its length is 3 characters. On the next position (which is fourth column in the text file) is the ntp_number data which is 22 characters long. The last data element starts at 26th column and its 2 characters long.

Local variables l_ca, l_p, l_file and l_testrn will hold the contract account, business partner, file and test run checkbox data. Global variable gv_line_space will be used to enter a new line when displaying messages, and w_return workplace variable will handle the BAPI return data.

Data definition is important, can not be skipped and should not be missconfigured. Every BAPI offers the possibilities to check the needed data types by opening it (in SE80) and doubleclicking on the Associated Type entry in Import, Export, Changing, Exceptions or Tables tabs.

Selection screen

In case you decide to expand the program and divide the selection screen into more sections, the following code might come handy. If not, just take the Parameters definition out and remove the b1 block definition:

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.

PARAMETERS: p_file   TYPE rlgrap-filename OBLIGATORY,

             p_paymtd TYPE FKKVKP-EZAWE    OBLIGATORY,

             p_testrn AS CHECKBOX.

SELECTION-SCREEN END OF BLOCK b1.


AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.

   CALL FUNCTION 'F4_FILENAME'

     EXPORTING

       program_name  = syst-cprog

       dynpro_number = syst-dynnr

       field_name    = ' '

     IMPORTING

       file_name     = p_file.

START-OF-SELECTION.

   l_file = p_file.

   l_testrn = p_testrn.

Since GUI_UPLOAD (used via CL_GUI_FRONTEND_SERVICES) does not accept p_file as an input parameter, we should fill the l_file local variable contents with the p_file contents. The same is done with the l_testrn/p_testrn parameter.

Note: If you need help with creating selection screens, you can use the program RSDBGENA (start it using transaction code SE38).

Importing the file

With the help of the SCN web, I concluded that the best way of uploading a text file is using  CL_GUI_FRONTEND_SERVICES and GUI_UPLOAD function modules. My file does not have field separator, which makes it even easier. Note: GUI_UPLOAD recognizes tab as a field separator. In other cases, you need to use either SPLIT function or some other way of handling semicolon or other separators.

In order to use the mentioned functions, we need to send the minimum of the data: filename (l_file) and return table (it_file). The definition of the it_file, type DD_STRUCT, will help this function automaticaly fill the needed table columns with the data, creating new table row for each file line read.

Besides FILENAME parameter, there are several parameters which could come handy: HAS_FIELD_SEPARATOR, READ_BY_LINE, HEADER_LENGTH, CODEPAGE and others (as always, you can check the possibilities in the documentation).

CALL METHOD CL_GUI_FRONTEND_SERVICES=>GUI_UPLOAD

   EXPORTING

     FILENAME                = l_file

   CHANGING

     DATA_TAB                it_file.

Once executed, we need to check for the errors. In case there are errors, we will display them. If not, we can continue with the execution of the program.

   IF sy-subrc <> 0.

     MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

   ENDIF.


Showing the read content


As a control of the read content, we can go through the it_file table and output the data. We will only deal with the lines of type "DAT", which is the code for the data line:


LOOP AT it_file INTO wa_file.

     IF wa_file-line_type = 'DAT'.

       WRITE :/ 'Reading the file: ', wa_file-ntp_number, wa_file-indicator.

Note: The loop line is written in italic. Regardles if youre using the code to output the read data, the loop will be used to go through the read lines and call the BAPIs. Corresponding ENDLOOP will also be written in italic in the end of this document.

As the total length of the contract account number in SAP is 12, and the length of the contract account number in the text file is 10, we need to add the two zeros in front of the read number:

    CONCATENATE '00' wa_file-ntp_number+0(10) into l_ca-account.


Reading the Contract Account data


Its always good to read the BAPI documentation before using it. You can do so by opening SE80, choosing Function Module and entering the BAPI name there.


BAPI BAPI_ISUACCOUNT_GETDETAIL expects CONTRACTACCOUNT as mandatory input parameter. For that purpose we defined l_ca variable and populated it with the data from the file (and subsequentialy it_table) in the previous step. As an output parameter, you can use RETURN, which will give you the error message if the error happens, or it wont return anything in case of success.


The table that will get populated as a result of this BAPI is lt_cadata. You can check the fields that will get populated by double-clicking on the bapiisuvkp keyword in the definition of the local table lt_cadata.


In case BAPI runs successfully, w_return variable will stay in its initial state. If there is an error, it will get populated with that information (for example, it will say that the contract account does not exist). If you want, you can output that message, as a measure of control.


CALL FUNCTION 'BAPI_ISUACCOUNT_GETDETAIL'

             EXPORTING

               CONTRACTACCOUNT             = l_ca-account

             IMPORTING

               RETURN                                  = w_return

             TABLES

               TCONTRACTACCOUNTDATA  = lt_cadata.

IF w_return IS NOT INITIAL.

   WRITE :/ 'Error:', w_return-MESSAGE.

ENDIF.

Outputing the read data


Assuming we did not get an error, our lt_cadata local table contains the states Contract Account data. Since we are changing the Incoming Payment Method data, we will print out the read data, as an info what was the previous information.


Also, now we have the information about the Business Partner for that Contract Account, and since that is the mandatory input parameter for our next BAPI, we will populate the l_p-partner variable here.


At the end of this section, we will clear the w_return variable so we can use it for the next BAPI.


    l_p-partner = lt_cadata-partner.

       WRITE :/ 'Contract account:', l_ca-account.

       WRITE :/ 'Business partner:', l_p-partner.

       WRITE :/ 'Payment method (previous):', lt_cadata-PAYM_METHOD_IN.

CLEAR: w_return.

Setting the new Contract Account data

When using  BAPI_ISUACCOUNT_CHANGE, in order to change any data, we need to state which data will we change and set the new value. For that purpose, two variables are used. First is lt_cadata which we already populated with all the information. In lt_cadata we will change the incoming payment method value into the one that the user entered at the selection screen (p_paymtd).

The second one is the matching variable lt_cadatax. In order to change a parameter in Contract Account master data, we need to put 'X' as a value to that parameter.

To make it more clear: lt_cadata-paym_method_in value will be p_paymtd, and lt_cadatax-paym_method_in value will be 'X'.


    lt_cadatax-paym_method_in = 'X'.

     lt_cadata-paym_method_in  = p_paymtd.

         CALL FUNCTION 'BAPI_ISUACCOUNT_CHANGE'

             EXPORTING

               CONTRACTACCOUNT            = l_ca-account

               PARTNER                               = l_p-partner

               CONTRACTACCOUNTDATA   = lt_cadata

               CONTRACTACCOUNTDATAX = lt_cadatax

               TESTRUN                                = l_testrn

             IMPORTING

               RETURN                                  = w_return.

IF w_return IS NOT INITIAL.

   WRITE :/ 'Error:', w_return-MESSAGE.

ENDIF.

BAPI BAPI_ISUACCOUNT_CHANGE gives us the possibility to run it as a test run. To make it easier to control, I put the parameter (p_testrn) to the selection screen. The same as before, if the BAPI run successfully, we will not get any data in the RETURN parameter. If, on the other hand, we get an error, BAPI will populate that parameter and we will be able to print it out using the stated code.

Commiting the transaction

The last step in the program is commiting the transaction. If we skip this step, the new data will not get written into the Contract Account master record. We will commit the transaction only if we didnt get an error from the previous step.

    IF w_return IS INITIAL.

       CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'

        EXPORTING

          WAIT          = 'X'

        IMPORTING

          RETURN    = w_return.

        WRITE :/ 'Payment method (new):', lt_cadata-PAYM_METHOD_IN, gv_line_space, gv_line_space.

       ENDIF.

     ENDLOOP.


If you want to try the code yourself, just copy the code (without my descriptions and comments) into a new program, activate it and run. Its purpose its to show the usage of importing the text file to SAP, populating local table, extracting data from the text file and changing the Contract Account master record using BAPIs.


I hope this instructions and code examples will be useful to people who have similar business needs or who want to see an example of how to use the BAPI_ISUACCOUNT_GETDETAIL and BAPI_ISUACCOUNT_CHANGE BAPIs.

2 Comments
Top kudoed authors