If you work with large companies, you’ve most likely heard of SAP, a widely used enterprise software solution. With the RFC classes of the MBS Xojo Plugin you can build RFC (Remote Function Call) interfaces so that Xojo apps can communicate with SAP systems. I’ve done this to SAP R/3 and SAP S/4 HANA. The MBS plugin covers the libraries of the SAP NetWeaver RFC SDK 7.50.
The SAP interface has four steps:
- Determine the path to the SAP library
- Build a connection to the SAP system
- Transfer data to the SAP system
- Receive data from the SAP system
Connect the SAP System
Your SAP user must have the authority for RFC connections. If so, you must know some data of your SAP logon to connect to an SAP system, such as:
- host name – a name or an IP address (ashost)
- router string
- system number (sysnr)
- client (client)
- language (lang)
- user (user)
- password (passwd)
At first you must set the path to the SAP libraries. In Windows you have some DLL’s around SAPNWRFC.DLL and on macOS you have some DYLIB’s around LIBSAPNWRFC.DYLIB.
If TargetWin32 var LibFile as string = "sapnwrfc.dll" Else // get the actual folder and handle the exception var MacOsFolder as folderitem = app.ExecutableFile.Parent System.EnvironmentVariable("DYLD_LIBRARY_PATH") = MacOsFolder.NativePath If System.EnvironmentVariable("DYLD_LIBRARY_PATH") = "" Then MessageBox("DYLD_LIBRARY_PATH variable not set") return end if var LibFile as FolderItem = MacOsFolder.Child("libsapnwrfc.dylib") var LibPath As String = LibFile.parent.NativePath Call RFCModuleMBS.SetCurrentWorkingDirectory(libPath) EndIf
I’ve copied the SAP libraries with the Xojo build settings into the application resource folders.
If the setting of the LibPath fails then send the error message:
If not RFCModuleMBS.LoadLibrary(LibFile) Then // Failed to load library Messagebox RFCModuleMBS.LibraryLoadErrorMessage return End If
And if the LibPath is set you can do the logon as second step:
var loginParams As New Dictionary loginParams.Value("ashost") = "12.345.67.89" loginParams.Value("sysnr") = "10" loginParams.Value("client") = "100" loginParams.Value("user") = "MYUSERNAME” loginParams.Value("passwd") = "MyPassword" loginParams.Value("lang") = "EN" var ConnectionToSAP As New RFCConnectionMBS(loginParams)
Please note if you have a router string you must build the host name (ashost) with a concatenation of router string and host name like this:
loginParams.Value("ashost") = <router string> + "/H/" + <host name>
If the connection fails you will get the reason with:
Exception r As RFCErrorExceptionMBS MessageBox r.message
Calling an SAP Function Module
If you are calling a SAP Function Module you will export key values to SAP and you will receive data or i.e. error messages. To understand the import and export parameters you must look out of the SAP function module in the surrounding world.
This example calls the SAP function module RFC_READ_TABLE. With this standard RFC module you can get the content of a database table and/or the SAP data dictionary description of this table.
Exporting key values to SAP
For exporting the key values to the SAP function module you must load a functions description and create a data container for executing the function module.
var fd as RFCFunctionDescriptionMBS = app.ConnectionToSAP.FunctionDescription("RFC_READ_TABLE") var f as RFCFunctionMBS = fd.CreateFunction
The function module RFC_READ_TABLE has two parameters:
- the name of the table as import parameter: QUERY_TABLE
- the select options of the where clause as tables parameter: OPTIONS
f.StringValue("QUERY_TABLE") = "<name of the table>" var it_OPTIONS as RFCTableMBS = f.TableValue("OPTIONS") var is_OPTIONS as RFCStructureMBS is_OPTIONS = it_OPTIONS.AppendNewRow is_OPTIONS.StringValue("TEXT") = "(MATNR = '4711')" // WHERE clause
You must consider that the maximum length of a where clause for the table OPTIONS is 72 digits. If the where clause length is greater than 72 you must split the clause to several lines. The clause must look like this “(MATNR = ‘1234’ AND WERKS = ‘1000’) OR (MATNR = ‘3456’ AND WERKS = ‘1000’)”.
And now you can execute the function module into the backend system:
Receiving data from SAP
The function module RFC_READ_TABLE returns now to tables parameters:
- FIELDS – contains the SAP data dictionary description of the returned table
- DATA – contains the data found for the transferred where clauses
TableFields as RFCTableMBS = f.TableValue("FIELDS") TableData as RFCTableMBS = f.TableValue("DATA")
If the TableFields.RowCount = 0 then the returned table contains no data. To get the content of a returned table you must loop like this:
If TableData.RowCount > 0 then TableData.MoveToFirstRow End if For iRow as integer = 1 to TableData.RowCount // get a field value Var FieldValue as string = TableData.StringValue("<Fieldname in the table record>") If iRow < TableData.RowCount then TabeData.MoveToNextRow End if next
To catch an exception, you should code into your method something like this:
Exception r As RFCErrorExceptionMBS MessageBox r.message
Interpretation of Returned Data
If you want to get after the INVOKE the returned data you will have
- a table or
- a structure or
- a field
If you have a table you will get a certain field with:
Var TableContent as RFCTableMBS TableContent = f.TableValue("<Name of the returned table parameters>") If TableContent.RowCount > 0 then TableContent.MoveToFirstRow End if For iRow as integer = 1 to TableContent.RowCount ListBox1.AddRow(TableContent.StringValue("FieldOne"), TableContent.StringValue("FieldTwo")) If iRow < TableContent.RowCount then TableContent.MoveToNextRow End if Next
If you have a structure you will get a certain field with:
var s As RFCStructureMBS = f.StructureValue("ES_MESSAGE")
TextField1.Value = s.StringValue("FieldOne")
If you have a field you will get the data with:
TextField1.Value = f.StringValue("FieldName")
Using the above techniques with the MBS plugin, your Xojo apps can now access information contained in SAP.
Michael Eckert studied economics from 1982-1986 and has been employed at T-Systems as a software architect since 1989. Michael has worked with ERP systems for 34 years, until 1998 with PL/1, since 1998 with ABAP in SAP R/3 and SAP S/4 HANA. He’s been developing with Xojo for about 9 years.