1

I'm trying to use RFC_CALL_TRANSACTION_USING to get the SAP ERP software run the transaction code FTE_BSM and print the result of the report to spool. The transaction I am trying to use is FTE_BSM, but in the end I want to be able to use it with any transaction code that can print output to spool.

I am able to connect to SAP using the following code:

    If iConnectionStatus <> 1 Then
        
            Set ObjR3 = CreateObject("SAP.Functions")
            Set ObjR3_Connection = ObjR3.Connection
            
            With ObjR3_Connection
                .System = SAP_SystemID 
                .SystemNumber = SAP_SystemNumber 
                .ApplicationServer = SAP_ApplicationServer
                .Client = SAP_Client 
                .USER = Environ("Username") 
                .password = UserPassword_Temp '
                .Language = SAP_Language 
            End With

            If ObjR3.Connection.Logon(1, False) <> True Then
                GoTo LogInFailed
                Exit Sub
            End If

            ObjR3_Connection.RFCWithDialog = 1
            Call GetIDFromSAP
        
        End If

In a separate routine, I call the RFC Function Module:

    Dim aExecutionMap As Variant

    aExecutionMap = ws_map_FTE_BSM.Range("mask_FTE_BSM").Value

    Set ObjR3_Call_RFC_Transaction = ObjR3.Add("RFC_CALL_TRANSACTION_USING")

        'Define SAP interal Tables
        With ObjR3_Call_RFC_Transaction
            .Exports("TCODE") = sReportName
            .Exports("MODE") = sMode
            Set ObjR3_Call_RFC_Para = .Tables("BT_DATA")
            Set ObjR3_Call_RFC_Errors = .Tables("L_ERRORS")
            
        End With
        
        'Load Map
        r = 0
        For i = LBound(aExecutionMap, 1) To UBound(aExecutionMap, 1)
            r = r + 1
            ObjR3_Call_RFC_Para.AppendRow
            
            c = 0
            For f = LBound(aExecutionMap, 2) To UBound(aExecutionMap, 2)
                c = c + 1
                ObjR3_Call_RFC_Para(r, c) = aExecutionMap(i, f)
            
            Next f
        Next i
        
        
        CallResult = False
        
        CallResult = ObjR3_Call_RFC_Transaction.Call

The aExecutionMap is an Array that is loaded from a named table range containing the rows of the BT_DATA table parameter as recorded using SAP's transaction SHDB. I recorded the transaction twice, once with "Simulate Background Mode" switched on, once with it switched off. This did not seem to make a difference.

In the "Simulate Background Mode" switched ON, the table is:

enter image description here

Note that an empty cell means that the field is left blank. Also, the date is in the same format as the dialog user would input it. For debugging, I looped through the BT_DATA table to double-check the parameters. The parameters are as follows:

Program Dynpro DynBegin FNam FVal
RFEBKAMON01 1000 X
0000 BDC_OKCODE =/BDA
0000 S_BUKRS-LOW 0105
0000 P_STDAT 2020.11.30
0000 P_VARI /STATMONI
SAPMSSY0 0120 X
0000 BDC_OKCODE =&RNT

In the "Simulate Background Mode" switched OFF, the table is:

enter image description here

The parameters sent to built up the BT_DATA table are as follows:

Program Dynpro DynBegin FNam FVal
RFEBKAMON01 1000 X
0000 BDC_OKCODE =/BDA
0000 S_BUKRS-LOW 0105
0000 P_STDAT 2020.11.30
0000 P_VARI /STATMONI
SAPLSPRI 0100 X
0000 BDC_OKCODE =PRIN
0000 RADIO0500_1 X
0000 PRI_PARAMS-PRCOP 1
0000 BDC_SUBSCR SAPLSPRI 0600SUBSCREEN

I do get a True result on the CallResult, so clearly I do get Excel to communicate with SAP, however, I do get errors as well and the spooljob is never created.

I keep getting errors regardless of whether I run the transaction using .Exports("MODE") = "N" or .Exports("MODE") = "E" or .Exports("MODE") = "A":

The errors I'm getting are:

TCODE DYNAME DYNUMB MSGTYP MSGSPRA MSGID MSGNR MSGV1
FTE_BSM RFEBKAMON01 1010 A E 00 341 RAISE_EXCEPTION

or:

TCODE DYNAME DYNUMB MSGTYP MSGSPRA MSGID MSGNR MSGV1
FTE_BSM SAPMSSY0 1000 A E 00 341 DYNPRO_SEND_IN_BACKGROUND

Examining the errors in ST22 gives me "RAISE_EXCEPTION CL_GUI_CUSTOM_CONTAINER=======CP" if run in "N" mode or "DYNPRO_SEND_IN_BACKGROUND CX_SY_SEND_DYNPRO_NO_RECEIVER RFEBKAMON01" if run in "E" or "A" mode.

Does anyone know what I'm doing wrong? Or alternatively: Does anyone maybe have a working example of how to run an SAP transaction with RFC_CALL_TRANSACTION_USING and save the results to spool that I could analyze to learn from?

Tyro
  • 45
  • 1
  • 8
  • 1) You will never be able to run any transaction code, most of time you won't be able to retrieve the data this way. 2) You don't open the RFC connection with the GUI activation (`RfcWithDialog = 1`), it's why it fails badly. – Sandra Rossi Dec 06 '22 at 18:54
  • @SandraRossi: Thanks for commenting. Can you elaborate? 1) Why not? My understanding was that RFC_CALL_TRANSACTION_USING allows you to batch input data as if you were a dialog user, so pretty much whatever the dialog user can do, you can do too. If my understanding is wrong, is there a different function I could use? I know this can be done, there's software out there that gets data from SAP exactly by execute any TCODE in the background and printing to spool. 2) Deleting this did not help, but now I am getting "FTE_BSM | RFEBKAMON01 | 1000 | S | E | 00 | 344 | RFEBKAMON01 | 1000". – Tyro Dec 10 '22 at 11:28
  • 1) You say you want one solution to extract spool to work with "any transaction code". Each transaction code may output data differently, not only spool. Some won't accept to run (your error). 2) Forget it, my comment concerns RFC but not if you use RFC and Batch input at the same time (you don't need GUI to run batch input). Your code fails because `BT_DATA` contains incorrect data so please post a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Sandra Rossi Dec 10 '22 at 13:40
  • 1
    @SandraRossi: Thanks so much for clarification. 1) You're right, let me rephrase it: I want to be able to extract data from any transaction able to print to spool. That covers most of (most likely all) of my intended use-cases. I'm almost sure my problem is either the way I'm envoking the RCF call or how I'm structuring the BT_DATA table. I've adjusted the question to add the instructions used to build the BT_DATA. I hope this is enough to reproduce the problem. 2) Ok, already forgotten :D – Tyro Dec 10 '22 at 14:46

1 Answers1

1

There are 3 big questions here which would each deserve a separate question so that to benefit detailed answers:

  • How Batch Input works
  • How FTE_BSM works (Transaction Code part of SAP ERP, i.e. versions SAP R/3, SAP ECC, S/4HANA)
  • How to extract spool data by RFC

I explain more about how FTE_BSM works and how to run it via Batch Input. I can't go in depth how Batch Input works and how to extract spool data by RFC, if you need more help on one of these two, please ask another question.

You are running the function module RFC_CALL_TRANSACTION_USING through Excel VBA and the RFC Client included in SAP GUI for Windows (used to display the Dynpro screens), but your issue is only due to the automation data passed to the parameter BT_DATA, that is specific to the transaction code FTE_BSM.

The so-called Transaction Codes all run (99%) in Dynpro technology / ABAP, and consequently the user actions can usually be recorded using the Transaction Recorder (Transaction Code SHDB) and played using the function module RFC_CALL_TRANSACTION_USING and more specifically the underlying ABAP statement CALL TRANSACTION ... USING .... This UI automation is officially called Batch Input. There are lots of limitations depending on the exact Dynpro and ABAP logic in each Transaction Code. You need good knowledge of Dynpro and ABAP to understand all subtleties.

In the Transaction Recorder, the option "Simulate background mode" is to simulate a Transaction Code running in background, technically speaking it sets the System Field (kind of environment variable) sy-batch = 'X', the ABAP code may or may not consider this field to display screens so that to permit Batch Input. If a recording is done while using the "Simulate background mode", this recording must be played using an adequate mode which also simulates the background mode:

Mode sy-batch = ' ' sy-batch = 'X' ("Simulate background")
No screen N Q
Show screens starting from error E H
Show all screens A D

When a user runs FTE_BSM without automation, there are the following screens:

  • The first screen is a classical selection screen (screen RFEBKAMON01 1000):
    FTE_BSM selection screen
  • The next screen displays data using an ALV Grid view (screen RFEBKAMON01 1010):
    FTE_BSM ALV Grid View
  • If the user clicks on the Print button, a screen is shown to select print options (screen SAPLSPRI 0100):
    FTE_BSM Print ALV List
  • Then a spool request is created containing the ALV data:
    enter image description here
  • The user can see the spool data by running the Transaction Code SP01:
    Spool data after FTE_BSM Print ALV List

If the user actions are recorded via the Transaction Recorder, I obtain these values for BT_DATA:

  • Without simulating background:
    SHDB on FTE_BSM without simulating background
    • We can see that the click on the Print button above the ALV Grid view was not recorded (should have been inserted before 6). This is because the ALV Grid View and its above Toolbar Control are part of the SAP GUI Control Framework which is not supported by Transaction Recorder and Batch Input.
  • By simulating background:
    SHDB on FTE_BSM while simulating background
    • We can see that the ALV Grid View is not displayed, instead we have this alphanumeric display, which is because the ALV Framework detects sy-batch = 'X' and displays data as an "ABAP List" (character display) instead of the Grid View (graphical display):
      FTE_BSM ALV as ABAP List
    • We can see that the ABAP List corresponds to the screen SAPMSSY0 0120.
    • We can see that "Print" in the ABAP List screen is recorded (BDC_OKCODE =%PRI)

Batch input will work if you use:

  • Parameter MODE = 'Q' (Q is the same as N but it sets sy-batch = 'X')
  • Parameter BT_DATA containing the recording above related to the Background simulation mode
  • After execution, the parameter L_ERRORS will contain one line with the spool request number; the message number SY 355 is "Spool request (number &1) created without immediate output" where the spool request number is in the field MSGV1: | TCODE | DYNAME | DYNUMB | MSGTYP | MSGSPRA | MSGID | MSGNR | MSGV1 | |--|--|--|--|--|--|--|--|--|--|--| | FTE_BSM | SAPLSPRI | 0100 | I | E | PT | 044 | X_65_1024/4 | | FTE_BSM | SAPMSSY0 | 0120 | S | E | SY | 355 | 0000907758 |

You need to run other RFC-enabled function modules to extract the spool data. I advise using XBP because BAPI are officially-supported API = function modules BAPI_XMI_LOGON with parameter INTERFACE = 'XBP', BAPI_XBP_JOB_SPOOLLIST_READ if the spool request is generated from a background job or BAPI_XBP_GET_SPOOL_AS_DAT if you have only the spool request number, and BAPI_XMI_LOGOFF.

Although your question is not about ABAP, I provide here an example which works for me in ABAP:

REPORT.
DATA(tbl) = VALUE bdcdata_tab(
  ( program = 'RFEBKAMON01' dynpro = '1000' dynbegin = 'X' fnam = '' fval = '' )
  ( program = '' dynpro = '0000' dynbegin = '' fnam = 'BDC_OKCODE' fval = 'ONLI' )
  ( program = 'SAPMSSY0' dynpro = '0120' dynbegin = 'X' fnam = '' fval = '' )
  ( program = '' dynpro = '0000' dynbegin = '' fnam = 'BDC_OKCODE' fval = '=%PRI' )
  ( program = 'SAPLSPRI' dynpro = '0100' dynbegin = 'X' fnam = '' fval = '' )
  ( program = '' dynpro = '0000' dynbegin = '' fnam = 'BDC_OKCODE' fval = '=PRIN' )
  ( program = '' dynpro = '0000' dynbegin = '' fnam = 'PRI_PARAMS-PDEST' fval = 'LP01' )
  ( program = 'SAPMSSY0' dynpro = '0120' dynbegin = 'X' fnam = '' fval = '' )
  ( program = '' dynpro = '0000' dynbegin = '' fnam = 'BDC_OKCODE' fval = '=&F03' )
  ( program = 'RFEBKAMON01' dynpro = '1000' dynbegin = 'X' fnam = '' fval = '' )
  ( program = '' dynpro = '0000' dynbegin = '' fnam = 'BDC_OKCODE' fval = '/EE' )
    ).
DATA(bdcmsgcoll_tab) = VALUE tab_bdcmsgcoll( ).
CALL TRANSACTION 'FTE_BSM' USING tbl MODE 'Q' MESSAGES INTO bdcmsgcoll_tab.
Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
  • 1
    This is brilliant. When I asked the question I did not expect that level of detail. This really helps me learn. You've noticed correctly, I don't have much experience in ABAP, but am trying to learn one step at a time. I even bought a book "SAP-R 3 Kommunikation mit RCF", but it didn't even mention Parameter MODE = 'Q'. Just changing this value fixed the error, but I still ended up using your approach to printing (System > List > Print, instead of List > Print). My approach does not return the 355 message so I'd have a harder time identifying the spool request number. Thank you so much. – Tyro Dec 12 '22 at 00:38
  • Interestingly, my `L_ERRORS` contains more than just one line. It's: 1)`FTE_BSM | SAPLSPRI | 0100 | S | E | 00 | 112 | sapfprintCtrl: | FillListOfPrinters | | | CTU | ` 2) `FTE_BSM | SAPLSPRI | 0100 | S | E | 00 | 112 | sapfprintCtrl: | FillListOfPrinters | | | CTU | ` 3) `FTE_BSM | SAPMSSY0 | 0120 | S | E | SY | 355 | 0000032281 | | | | CTU | ` 4) `FTE_BSM | RFEBKAMON01 | 1000 | S | E | 00 | 344 | RFEBKAMON01 | 1000 | | | |` But this doesn't prevent the spool request from being created. – Tyro Dec 12 '22 at 00:45
  • I'll try extracting the spool request using `BAPI_XBP_JOB_SPOOLLIST_READ`, like you suggested. If I get stuck, I'll ask a separate question. One last follow-up, though, if you don't mind: In your first comment you said not to use `RfcWithDialog = 1`. Can you explain why? The book I mentioned made it sound like I can switch to foreground mode by setting `Parameter MODE = 'Q'` and passing `BDC_OKCODE = '=/BDA'` under SAPMSSY0 0120 dynpro in `BT_DATA` . Is that possible, i.e. make Excel pre-fill input parameters then display the SAP GUI window? – Tyro Dec 12 '22 at 01:08
  • Usually, Batch Input is to automate screens in the background, and so there's no need to interact with SAP GUI, it's why I said in a second time that `RfcWithDialog = 1` is not needed in your case. Initially I talked about it because of the exceptions concerning `CL_GUI_CUSTOM_CONTAINER` and `DYNPRO_SEND_IN_BACKGROUND` which were due to running in modes "A" or "E" or other possible combinations of conditions. `/BDA` allows the user to switch from mode "E" to mode "A", when a screen appears due to a batch input error, instead of continuing with mode "E". – Sandra Rossi Dec 12 '22 at 07:39
  • It is possible to pre-fill input parameters then display the SAP GUI window with mode "E": if you fill `BT_DATA` with only the first screen data, when displaying the ALV screen, the Batch Input will fail because there's no match in `BT_DATA` and so the ALV screen will be displayed. But of course, you need to run RFC with connection to SAP GUI (`RfcWithDialog = 1`). – Sandra Rossi Dec 12 '22 at 07:42
  • In `SP01` I see the spool requests I want to extract, (e,g,`Spool no.` = "79634", `User Name` = "XY123456" and `Title or name...` = "LIST1S LOCM RFEBKAMONXY1"). I run`BAPI_XMI_LOGON` (`EXTCOMPANY` = "RFC_Excel", `EXTPRODUCT` = "RFC_Excel", `INTERFACE` = "XBP", `VERSION` = "3.0") and get a valid `SESSION_ID`, but when I run `BAPI_XBP_JOB_SPOOLLIST_READ` (`JOBNAME` = "LIST1S LOCM RFEBKAMONXY1", `JOBCOUNT` = "79634", `EXTERNAL_USER_NAME` = "RFC_Excel" and `STEP_NUMBER` = "1"), the `.Tables("SPOOL_LIST").RowCount` is 0 and the output is empty. Any ideas what I'm doing wrong? – Tyro Dec 22 '22 at 13:05
  • As I said, concerning "How to extract spool data by RFC", it would deserve a new question so that to not mix everything. – Sandra Rossi Dec 22 '22 at 13:46
  • sure, makes sense. I've asked a separate question: https://stackoverflow.com/questions/74929741/extracting-data-from-sap-spool-to-excel-using-bapi-xbp-job-spoollist-read-and-vb If you happen to have the time, your expertise would be highly appreciated. – Tyro Dec 27 '22 at 13:17