RFCs with multi-nested parameters 
From Theobald Software
|
|
99% of all RFC enabled function modules / BAPIs consist of scalar or structured imports / exports and of table parameters. But there's also an option to define more complex parameters. This article shows how to handle multi-nested parameters with ERPConnect.
Sample Scenario
In the following sample we use the function module Z_T_CREATE_MULTI_ORDERS. This function is able to create multiple orders per call. The function adds the order number to each order passed and returns all orders back to the caller.
All orders to be created are passed within one single parameter named IN_ORDERS. The export parameter containing the processed orders is named OUT_ORDERS.
The table type ZTORDERS contains a list of orders. A single order is represented by the structure ZTORDER. Besides the scalar elements for the customer's number and the order number there is an additional element ZTITEMS. ZTITEMS is again a table type that holds multiple instances of ZTITEM. A sigle instance of ZTITEM represents a single order line.
Just imagine a tree: A list of orders and each order has an unlimited number of items.
XML Coding
If IN_ORDERS was a simple structure it would be no problem to handle it with an RFCStructure object. Even a table-like parameter could be handled by calling the ToTable() method. In case of our sample scenario we need an XML object to handle all elements of the order parameter.
Within the XML a single element is addressed by its name. If there are multiple rows, each row is separated by an <item> tag. The following XML shows a sample of the order parameter. It is a single order with two order lines (ORDERITEMS).
<IN_ORDERS>
<item>
<ORDERNO>4711</ORDERNO>
<CUSTNO>00571020</CUSTNO>
<ORDERITEMS>
<item>
<MATNR>100-100</MATNR>
<QUANTITY>12.230</QUANTITY>
</item>
<item>
<MATNR>100-200</MATNR>
<QUANTITY>45.670</QUANTITY>
</item>
</ORDERITEMS>
</item>
</IN_ORDERS>
Coding in C#
This sample code shows how to build the XML shown above by using a StringBuilder and a XmlWriter object. But this is only one under lots of options to do this.
// Create XML document with StringBuilder // and XmlWriter StringBuilder MyXML = new StringBuilder(); XmlWriter writer = XmlTextWriter.Create(MyXML); writer.WriteStartDocument(true); writer.WriteStartElement("IN_ORDERS"); writer.WriteStartElement("item"); writer.WriteElementString("CUSTNO", "00571020"); // create first order item writer.WriteStartElement("ORDERITEMS"); writer.WriteStartElement("item"); // Begin item writer.WriteElementString("MATNR", "100-100"); writer.WriteElementString("QUANTITY", "12.23"); writer.WriteEndElement(); // End item // create second order item writer.WriteStartElement("item"); // Begin item writer.WriteElementString("MATNR", "100-200"); writer.WriteElementString("QUANTITY", "45.67"); writer.WriteEndElement(); // End item writer.WriteEndElement(); // End ORDERITEMS // close header tags writer.WriteEndElement(); // End item writer.WriteEndElement(); // End OUT_ORDER writer.WriteEndDocument(); writer.Close();
Here you can see how to use ERPConnect and how to assign the XML string.
R3Connection con = new R3Connection(...) con.Open(); RFCFunction func = con.CreateFunction("Z_T_CREATE_MULTI_ORDERS"); func.Exports["IN_ORDERS"].ParamValue = MyXML.ToString();; func.Execute();
In the sample scenario the function returns the same structure as output parameter. The follwoing sample shows how to generate an XmlDocument object out of the XML string and how to find the order numbers by using an XPath statement (SelectNodes...).
XmlDocument outorder = new XmlDocument(); outorder.LoadXml(func.Imports["OUT_ORDERS"].ParamValue.ToString()); XmlNodeList MyOrderList = outorder.SelectNodes("/OUT_ORDERS/item/*"); for (int i = 0; i < MyOrderList.Count; i++) { if (MyOrderList[i].Name.Equals("ORDERNO")) Console.WriteLine("Order created: " + MyOrderList[i].InnerText ); }
Coding in VB
If you like VB more than C# here's the code in VB:
' Create XML document with StringBuilder ' and XmlWriter Dim MyXML As StringBuilder = New StringBuilder() Dim writer As XmlWriter = XmlTextWriter.Create(MyXML) writer.WriteStartDocument(True) writer.WriteStartElement("IN_ORDERS") writer.WriteStartElement("item") writer.WriteElementString("CUSTNO", "00571020") ' create first order item writer.WriteStartElement("ORDERITEMS") writer.WriteStartElement("item") ' Begin item writer.WriteElementString("MATNR", "100-100") writer.WriteElementString("QUANTITY", "12.23") writer.WriteEndElement() ' End item ' create second order item writer.WriteStartElement("item") ' Begin item writer.WriteElementString("MATNR", "100-200") writer.WriteElementString("QUANTITY", "45.67") writer.WriteEndElement() ' End item writer.WriteEndElement() ' End ORDERITEMS ' close header tags writer.WriteEndElement() ' End item writer.WriteEndElement() ' End OUT_ORDER writer.WriteEndDocument() writer.Close()
Dim con As R3Connection = New R3Connection(...) con.Open() Dim func As RFCFunction = con.CreateFunction("Z_T_CREATE_MULTI_ORDERS") func.Exports("IN_ORDERS").ParamValue = MyXML.ToString() func.Execute()
Dim outorder As XmlDocument = New XmlDocument() outorder.LoadXml(func.Imports("OUT_ORDERS").ParamValue.ToString()) Dim MyOrderList As XmlNodeList = outorder.SelectNodes("/OUT_ORDERS/item/*") Dim i As Integer For i = 0 To MyOrderList.Count- 1 Step i + 1 If MyOrderList(i).Name.Equals("ORDERNO") Then Console.WriteLine("Order created: " + MyOrderList(i).InnerText) End If Next


