Bausteine mit mehrfach verschachtelten Parametern Deutsch

From Theobald Software

Jump to: navigation, search

English Version: RFCs with multi-nested parameters


99% aller RFC-fähigen Funktionsbausteine und BAPIs bestehen aus skalaren oder strukturierten Import- / Export-Parametern sowie aus Tabellenparametern. Darüber hinaus gibt es aber auch die Möglichkeit, komplexere Datentypen zu definieren. Der folgende Artikel zeigt, wie mit ERPConnect auch mehrfach verschachtelte Typen gerufen werden können.

Beispielszenario

Im folgenden Beispiel nutzen wir den Baustein Z_T_CREATE_MULTI_ORDERS. Er soll dazu dienen, mehrere Aufträge pro Aufruf anzulegen. Die anzulegenden Aufträge werden vom Baustein mit einer Auftragsnummer versehen und zurückgegeben.

Alle anzulegenden Aufträge werden in einem einzelnen Import-Parameter namens IN_ORDERS an den Baustein übergeben. Die Rückgabe der abgearbeiteten Aufträge erfolgt im Export-Parameter OUT_ORDERS.

Der Tabellentyp ZTORDERS enthält eine Liste von Aufträgen. Ein einzelner Auftrag wird durch die Struktur ZTORDER definiert. Neben den skalaren Elementen für die Auftragsnummer und die Kundennummer enthält ein Auftrag auch ein Element vom Typ ZTITEMS. Das wiederum ist eine Tabelle mit Zeilen vom Typ ZTITEM, der eine einzelne Auftragsposition repräsentiert.

Somit ergibt sich ein Baum: Die Liste von Aufträgen enthält pro Zeile beliebig viele Auftragspositionen.

XML-Coding

Wäre der Übergabeparameter IN_ORDERS einfach nur ein Struktur, wäre es mit Hilfe der RFCStructure-Klasse kein Problem, darauf zuzugreifen. Selbst ein rein tabellenartiger Import-Datentyp liese sich mit ToTable() in ein Objekt der Klasse RFCTable umwandeln. Im vorliegenden Fall müssen wir aber leider auf ein XML-Konstrukt zurückgreifen, um alle Elemente des Parameter-Baums zu erreichen.

Innerhalb des XMLs wird ein einzelnes Element einfach mit seinem Namen angesprochen und ineinander geschachtelt. Sind tabellenartige Strukturen im Spiel, müssen einzelne Zeilen durch ein <item>-Tag von einander getrennt werden. Das folgende XML zeigt die Auftragsliste IN_ORDERS mit einem Auftrag (<item>-Tag), der wiederum zwei Positionen enthält (Element <ORDERITEMS> mit zwei <item>-tags)

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

Programmierbeispiel in C#

Das folgende Beispiel zeigt der Aufbau des XML-Baums mit Hilfe einer StringBuilder-Klasse und einem XmlWriter. Wie letztendlich das XML aufgebaut wird, ist aber egal. Das ist nur eine von vielen Möglichkeiten.

// 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();

Die ERPConnect Ansteuerung des Bausteins erfolgt nach altbekannter Weise:

R3Connection con = new R3Connection(...)
 
con.Open();
RFCFunction func = con.CreateFunction("Z_T_CREATE_MULTI_ORDERS");
func.Exports["IN_ORDERS"].ParamValue = MyXML.ToString();;
func.Execute();

Im Beispielszenario gibt der Baustein als Output-Parameter dieselbe Struktur zurück. Das folgende Beispiel zeigt, wie der Parameter in ein XML-Objekt überführt wird. Die Auftragsnummern werden dann mit Hilfe eines XPath Ausdrucks extrahiert (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 );
}

Programmierbeispiel in VB

Für alle Leser, die lieber VB anstatt C#-Code lesen, hier nochmal die drei Code-Ausschnitte von oben als VB-Version:

' 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


DeutschEnglish
Personal tools
XtractQL Provider
Xtract RS