Introduction
In my last customer project, I had to implement a kind of "quick ordering software" for a machine manufacturer company. The goal of this project was to give the construction engineers the possibility to send an auto-generated order list to the buying department. The construction department uses a PDM system based on SQL Server 2000, with an Access front-end, while the buying department and the other economic departments use a SAP system. So, the main task in my project was to implement an interface for these two systems, especially to receive the necessary data from the SAP system into my .NET application. After a short search on the Internet, I found ERPConnect by Theobald Software. This tool allowed me to directly access the data from BAPIs and Tables in the SAP system I needed.
On The Code Project, I only found some articles about the .NET Connector by SAP, but no article dealing with ERPConnect, so I thought that it might be interesting for the other users to read about the usage, the features, and my personal experience with a second tool for SAP interface programming. Because of understandable reasons, I don't want to publish the code of my customer project, so I wrote two examples that explain the usage of ERPConnect basically. The first example deals with BAPI access, while the second example deals with directly reading from SAP tables.
I have included the two examples in VB.NET and C# in the download section above. I have removed the SAP login and connection data from the projects; to try the examples, you have to fill them with your own connection and login information.
SAP Background
For those of you with no SAP experience, I want to explain the most important SAP terms for interface programming.
Function Modules: A Function Module is equivalent to a normal function/procedure in any conventional programming language. Function Modules are SAP integrated modules written in ABAP and are accessible from any other ABAP program in the System. Like a function in any other programming language, Function Modules accept import and export parameters. Function modules also provide a third opportunity the bidirectional Tables. To access a Function Module from outside SAP (just like in our case) the Function Module has to be RFC-enabled. There is also a possibility to access Function Modules being RFC-disabled, this possibility I want to describe later in this article.
BAPIs: BAPIs work like Function Modules, the only difference is that they are the programming interface (API) for the SAP Business Object Repository.
IDocs: IDocs are used to exchange data between two SAP systems or an SAP system and a subsystem. You can imagine IDocs as an electronic kind of receipt written on paper. An IDoc can be uniquely identified by its name (and eventually the name of its extension). IDocs are also well structured; they have a header containing administrative information like the sender, information about the receiving system and the transport. Beside the header an IDoc has segments that are hierarchical like a tree structure. Every segment has one or more fields containing the economic data.
SAP Queries: SAP Queries work just like any other query. For unique identifying of a SAP Query there are three pieces of information necessary: user area (global or local); user group and the name of the query.
How to use ERPConnect
After installing ERPConnect on your computer, you just have to add a reference (ERPConnect.dll for use with .NET Framework 1.1 or ERPConnect20.dll for use with .NET Framework 2.0) to your project and add the using ERPConnect;
statement in the header, that's all.
Example 1: Reading Data from a BAPI using the RFCFunction Object
In this short example, I want to show you how to receive the BANK_KEY
value of customer 0000001172
and display the result on the console.
After creating a R3Connection
object and opening the connection, we create a RFCFunction
object on the connection calling our BAPI. Then we fill the Exports
parameter of our RFC function object with the Import
parameter of the BAPI. That means we send the Import value to the BAPI. After this is done, we execute the function and extract the data of interest from the result table. That's all.
class Program
{
static void Main(string[] args)
{
Connect();
}
static void Connect()
{
ERPConnect.LIC.SetLic("licence code");
R3Connection con = new R3Connection("name of the application server",
"system number",
"user",
"password",
"language",
"client");
con.Open();
RFCFunction func = con.CreateFunction("BAPI_CUSTOMER_GETDETAIL2");
func.Exports["CUSTOMERNO"].ParamValue = "0000001172";
try
{
func.Execute();
}
catch (ERPException e)
{
Console.WriteLine(e.Message);
}
string Bank_Key =
Convert.ToString(func.Tables["CUSTOMERBANKDETAIL"].Rows[0, "BANK_KEY"]);
con.Close();
Console.WriteLine("Customer: 0000001172");
Console.WriteLine("Bank Key: {0}", Bank_Key);
Console.ReadLine();
}
}
The result should look like this:
It is also possible to store the result in a DataTable
, by adding the line...
DataTable dt = func.Tables["CUSTOMERBANKDETAIL"].ToADOTable();
... after the Try Catch
block, then we receive all data from CUSTOMERBANKDETAIL
according to customer number 0000001172.
In this example, I have shown the basic use of ERPConnect to communicate with Function Modules, but there are some more very interesting features (I'm going to describe later on in this article) handling the RFC and IDoc communication and even the possibility to directly read from SAP tables.
Example 2: Reading Directly from a SAP Table using the ReadTable Class
In my opinion, the ReadTable
class is one of the most useful special classes, because it provides the possibility to directly read from SAP tables. For my customer project, it was very important to extract data from a SAP table into a .NET DataSet
, so this class was very helpful for me.
This example shows how to use the ReadTable
class by using a "where - like" statement to get the address of all customers in table KNA1
that match an entered name criteria and display the result in a DataGridView
.
The logic of this example is encapsulated in a class called SAPConnect
. Just like in the example above the using ERPConnect;
statement and also the using ERPConnect.Utils;
for using the ReadTable
class have to be added to the header.
The private
properties we need are:
private string _userName;
private string _password;
private string _client;
private R3Connection _con;
Parameters for the constructor are username
, password
and client
that are stored in local properties.
public SAPConn(string userName, string password, string client)
{
_userName = userName;
_password = password;
_client = client;
}
Because the address of the application server, the system number and the language mostly have the same value we can enter these parameters directly into the code or store it in a configuration
file. In my customer project, I had a lot of methods using the same connection string, so I thought it was useful to store the procedure of opening the connection in a separate private
function called openConnection
:
private void openConnection()
{
ERPConnect.LIC.SetLic("licence code");
R3Connection con = new R3Connection("name of the application server",
"system number",
_userName,
_password,
"language",
_client);
try
{
connection.Open();
}
catch (ERPException e)
{
MessageBox.Show(e.Message);
}
_con = connection;
}
And of course we need a method to close the connection:
private void closeConnection()
{
_con.Close();
}
Now we can implement the method to read directly from a SAP table and return the result in a DataSet
. Let me first explain the way this function works:
At first, we have to create a ReadTable
object and fill the TableName
property with the name of the SAP table we want to read from. After that, we can add the fields of interest by using the AddField
method. When this is done, we can fill the WhereClause
with our Like
string. In this example I have set the optional RowCount
property on 100
, so that we only receive 100 rows in our result. After executing the query, we have the Result
as DataTable
.
public DataTable WhereLikeSearch(string sapTable, string nameCriteria)
{
openConnection();
ReadTable table = new ReadTable(_con);
table.TableName = sapTable;
table.AddField("NAME1");
table.AddField("STRAS");
table.AddField("ORT01");
table.AddField("PSTLZ");
table.AddField("TELF1");
table.AddField("TELFX");
table.WhereClause = string.Format("NAME1 LIKE '%{0}%'", nameCriteria);
table.RowCount = 100;
try
{
table.Run();
}
catch(ERPException e)
{
MessageBox.Show(e.Message);
}
DataTable dt = table.Result;
closeConnection();
return dt;
}
Instead of the like
clause we can use the =
operator to search for results that match our nameCriteria
exactly, then the table.WhereClause
looks like that:
table.WhereClause = string.Format("NAME1 = '{0}'", nameCriteria);
In this statement, it is important to care about the correct syntax especially the spaces before and after the =
or an ERPException
will be raised.
To display the data in a DataGridView
, we have to add the following code to the button1_Click
eventhandler. After the button is clicked, the content of textBox1
will be our nameCriteria
.
private void button1_Click(object sender, EventArgs e)
{
string nameCriteria = textBox1.Text;
SAPConn sapConn = new SAPConn("userName", "password", "client");
DataTable dt = sapConn.WhereLikeSearch("KNA1", nameCriteria);
dataGridView1.DataSource = dt;
}
After executing the program we should have the DataGridView
filled with 100 Customers
matching our criteria (e.g. entering t
in the TextBox
returns all customers with a t
in their name).
Other ERPConnect Features
There are a lot of more features coming along with ERPConnect than the classes I have used in the two examples above. I haven't used them all yet, but I have also worked with the following classes for my customer project.
Not RFC-enabled Function Modules: If a Function Module is not RFC-enabled, ERPConnect provides a solution to access these Function Modules and use them like RFC-enabled Function Modules by building an internal wrapper around the Function Module executing this Function Module indirectly. In the .NET application, you just have to set the UseRFCWrapper
property of the RFCFunction
object on true
.
ASP.NET: ERPConnect also can be integrated into an ASP.NET application. To use ERPConnect in a Web Application, you have to add a reference on ERPConnect20.dll and the libfcr32.dll which can be found in the System32 directory of a SAP client computer. After adding these references, you can use ERPConnect described above.
SAP Queries: It is also possible to access any kind of SAP queries by using the namespace ERPConnect.Queries
.
To execute a query, the following steps are necessary:
- Create an
R3Connection
object and open the connection (just like in the examples above) - Create a query object
Query q = con.CreateQuery("user area","user group","query name");
- Add the criteria
q.SelectionParameters["the parameter"].Ranges.Add(Sign.Include, RangeOption.Equals, "criteria");
- Execute the query
q.Execute
- Now we find the result in
DataTable dt = q.Result;
In this namespace
, you also find the very helpful class ERPConnect.Query.QueryHelper.QueryHelper
providing kind of "search for Queries" functionality.
IDocs: Another interesting feature is the sending of IDocs by using the CreateIDoc
method. Let me explain this using a short listing taken from the ERPConnect online documentation. This example will send a STATUS IDoc. The STATUS IDoc is designed to manipulate the status of another IDoc. The STATUS IDoc can be used to confirm the successful processing of receiving another IDoc.
static void Main(string[] args)
{
R3Connection con = new R3Connection("hamlet", 11,"Theobald",
"pw", "DE", "800");
con.Open(false);
Console.WriteLine("Which Idocnumber would you like to manipulate?");
string IdocNo = Console.ReadLine();
Idoc i = con.CreateIdoc("SYSTAT01", "");
i.MESTYP = "STATUS";
i.RCVPRN = "PT4_800";
i.RCVPRT = "LS";
i.SNDPOR = "ERPCONNECT";
i.SNDPRN = "ERPCONNECT";
i.SNDPRT = "LS";
i.Segments["E1STATS", 0].Fields["LOGDAT"].FieldValue = "20060101";
i.Segments["E1STATS", 0].Fields["LOGTIM"].FieldValue = "152301";
i.Segments["E1STATS", 0].Fields["STATUS"].FieldValue = "12";
i.Segments["E1STATS", 0].Fields["DOCNUM"].FieldValue = IdocNo;
i.Send();
Console.WriteLine("Idoc sent");
Console.ReadLine();
}
Receiving IDocs is a little bit different from sending IDocs. To receive IDocs, we have to implement an small IDoc server by setting the CanReceiveIdocs
property on true
and catch the incoming IDocs:
RFCServer s = new RFCServer();
s.Logging = true;
s.GatewayHost = "";
s.GatewayService = "";
s.ProgramID = "";
s.CanReceiveIdocs = true;
s.IncomingIdoc += new ERPConnect.RFCServer.OnIncomingIdocs(s_IncomingIdoc);
s.Start;
s.Stop;
In this short listing, I show how to receive the IDOCTYPE
of the received IDoc:
private static void s_IncomingIdoc(RFCServer Sender, Idoc idoc)
{
Console.WriteLine(idoc.IDOCTYP);
}
Of course, you can read all the content of the received IDoc, but for details I refer to the documentation. For implementation of the server in a productive area, you also have to implement a kind of threading to manage plenty of incoming IDocs.
The IDoc
classes also provides the possibility to handle IDocs as XML files. For example you can create an XML scheme defining how the IDoc has to look like or an XML file storing the data of an IDoc.
Special Classes: For recurring tasks, ERPConnect provides the special classes encapsulated in the ERPConnect.Utils namespace
, like the ReadTable
class demonstrated in example 2.
Another special class is the ABAPCode
class that allows you to generate ABAP code on the fly in your .NET application. Instead of writing a Function Module in the SAP system, you can write the ABAP code in your .NET application without declaring a new Function Module in your SAP system.
Just as written above, there are some more features that come along with ERPConnect like an XML based SOAP/HTTP protocol or the RFC-Server, so that nearly every interface programming task can be solved.
Summary
In my opinion, one of the major tasks for consultants and software engineers in our days is to develop interfaces for the different IT-Systems like ERP, PDM or CRM systems. One of the most used ERP systems in bigger companies is SAP. In consideration of this fact, it is very important to know an easy way of programming an interface for SAP. I think ERPConnect is a very big help for this task because it supports the possibilities of the .NET Framework like ASP.NET or the Compact Framework, also ERPConnect supports any IDE like SharpDevelop. The documentation coming along with the software was very understandable (I have only read the German one, but I think the English one is the same) with a lot of examples explaining the usage of the classes. You can also download the documentation from here.
History
- 23rd May, 2007: Initial post