Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Transferring Data from SAP to .NET using ERPConnect

4.76/5 (21 votes)
23 May 2007CPOL10 min read 6   9K  
Description of an interface programming tool for SAP and .NET integration.

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.

C#
class Program
{
    static void Main(string[] args)
    {
        Connect();
    }

    static void Connect()
    {
        //licence
        ERPConnect.LIC.SetLic("licence code");

        //creating the connection object
        R3Connection con = new R3Connection("name of the application server",
                    "system number",
                    "user",
                    "password",
                    "language",
                    "client");
            
        //open the connection
        con.Open();
            
        //creating the RFCFunction object 
        RFCFunction func = con.CreateFunction("BAPI_CUSTOMER_GETDETAIL2");

        //sending the import parameter to the BAPI 
        func.Exports["CUSTOMERNO"].ParamValue = "0000001172";

        try
        {
            //execute the function
            func.Execute();
        }
        catch (ERPException e)
        {
            Console.WriteLine(e.Message);
        }

        /*Reading the BANK_KEY from func and store it in a string.
        We do only have one row in our result table, because there 
        can be only one customer according to our customer number
        so we only have to select the column of interest from the result table*/
        string Bank_Key = 
        Convert.ToString(func.Tables["CUSTOMERBANKDETAIL"].Rows[0, "BANK_KEY"]);

        //after all don't forget to close the connection
        con.Close();

        //display the Data 
        Console.WriteLine("Customer: 0000001172");
        Console.WriteLine("Bank Key: {0}", Bank_Key);
        Console.ReadLine();
    }
}

The result should look like this:

BAPI Call

It is also possible to store the result in a DataTable, by adding the line...

C#
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:

C#
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.

C#
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:

C#
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:

C#
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.

C#
public DataTable WhereLikeSearch(string sapTable, string nameCriteria)
{
    openConnection();

    //creating a ReadTable object
    ReadTable table = new ReadTable(_con);

    //setting the table name that we want to read from
    table.TableName = sapTable;

    //adding the fields we want to display in our DataTable
    table.AddField("NAME1");
    table.AddField("STRAS");
    table.AddField("ORT01");
    table.AddField("PSTLZ");
    table.AddField("TELF1");
    table.AddField("TELFX");
         
    //this is the 
    table.WhereClause = string.Format("NAME1 LIKE '%{0}%'", nameCriteria);    

    //this is an optional property
    table.RowCount = 100;

    //executing the query
    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:

C#
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.

C#
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).

ReadTable in action

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.

C#
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", "");

    // Fill Message Type 
    i.MESTYP = "STATUS";

    // Fill Information about Idoc Receiver
    i.RCVPRN = "PT4_800"; // Partner number 
    i.RCVPRT = "LS"; // Partner type


    // Fill information about idoc sender
    i.SNDPOR = "ERPCONNECT"; // Partner port
    i.SNDPRN = "ERPCONNECT"; // Partner number
    i.SNDPRT = "LS";// Partner type 


    // Fill the right fields in the segments 
    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:

C#
//create an RFCServer object

RFCServer s = new RFCServer();
s.Logging = true;

//setting the properties (you have to fill the empty
//strings with your specific values)

s.GatewayHost = "";
s.GatewayService = "";
s.ProgramID = "";

//this property is important
s.CanReceiveIdocs = true;

//here we catch the incoming IDocs to handle them in function s_IncomingIdoc
s.IncomingIdoc += new ERPConnect.RFCServer.OnIncomingIdocs(s_IncomingIdoc);

//start the server
s.Start;
        
//let the server work
//after all stop the server

s.Stop;

In this short listing, I show how to receive the IDOCTYPE of the received IDoc:

C#
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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)