How to use SAP Table Data via RFM RFC_READ_TABLE on the fly inside UiPath

In my last experiment here to use SAP remote enabled function modules (RFM) with UiPath I showed how easy it is to call an RFM. In this experiment I want to show how to call an RFM, in this case RFC_READ_TABLE, to read any SAP table and to use this data inside an UiPath process.

Let me at first introduce the RFM RFC_READ_TABLE. To call this RFM you need only the name of the table in the parameter QUERY_TABLE. In this experiment I use also the DELIMITER parameter. The RFM delivers in the table FIELDS the structure of the SAP table and in the table DATA strings with the table data. The table of string is equivalent to a CSV file. Here an important hint: The structure DATA is from type TAB512, this means it contains a table type with a 512 byte field. The maximum length of a record may be not bigger than 512 characters. Here the interface of the RFM:

Okay, it seems not difficult to use. Here an Invoke Code procedure to call this RFM and to write the SAP table data into a variable CSVTableData.

'-Begin-----------------------------------------------------------------

Dim cfgParams As SAP.Middleware.Connector.RfcConfigParameters
Dim destination As SAP.Middleware.Connector.RfcDestination
Dim rfcFunction As SAP.Middleware.Connector.IRfcFunction
Dim table As SAP.Middleware.Connector.IRfcTable
Dim tableLine As SAP.Middleware.Connector.IRfcStructure
Dim strTableLine As String
Dim parts As String()
Dim part As String
Dim i As Long
Dim j As Long

cfgParams = New SAP.Middleware.Connector.RfcConfigParameters
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.Name, "Test" )
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.AppServerHost, "ABAP702")
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.SystemNumber, "00")
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.Client, "001")
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.User, "BCUSER")
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.Password, "minisap")

destination = SAP.Middleware.Connector.RfcDestinationManager.GetDestination(cfgParams)

rfcFunction = destination.Repository.CreateFunction("RFC_READ_TABLE")
rfcFunction.SetValue("QUERY_TABLE", QueryTable)
rfcFunction.SetValue("DELIMITER", Separator)
rfcFunction.Invoke(destination)

table = rfcFunction.GetTable("FIELDS")
i = 0
For Each tableLine In table
  i += 1
  CSVDataTable += tableLine.GetValue("FIELDNAME").ToString.Trim
  If table.Count > i Then
    CSVDataTable += Separator
  End If
Next
CSVDataTable += vbLf

table = rfcFunction.GetTable("DATA")
j = 0
For Each tableline In table
  j += 1
  strTableLine = tableLine.GetValue("WA").ToString
  parts = strTableLine.Split(Separator.ToCharArray)
  i = 0
  For Each part In parts
	i += 1
    CSVDataTable += part.Trim	
    If parts.Count > i Then
	  CSVDataTable += Separator
    End If
  Next
  If table.Count > j Then
    CSVDataTable += vbLf
  End If
Next

'-End-------------------------------------------------------------------

And here my test to use it:

004

I checked it with the table USR01 and it works, great :slightly_smiling_face:

In the next step I want to convert the CSV data in the string to a data table. But the activity Generate Data Table detects different column types, e.g. for the client - field MANDT - or for the field STCOD - start menu.

So it seems to me more advantageous to develop my own routine to convert a CSV file as string into a data table.

'-Begin-----------------------------------------------------------------

  Dim Lines() As String
  Dim Line As String
  Dim Fields() As String
  Dim Field As String
  Dim Header As Boolean = True
  Dim DataColumn As System.Data.DataColumn
  Dim DataRow As System.Data.DataRow
  Dim i As Integer
  
  Lines = CSVDataTable.Split(vbLf.ToCharArray)
  For Each Line In Lines
    Fields = Line.Split(Separator.ToCharArray)
	i = 0
	If Header = False Then
      DataRow = DataTable.NewRow
    End If
	For Each Field In Fields
      If Header = True Then
	    DataColumn = DataTable.Columns.Add(Field, Type.GetType("System.String"))
		DataColumn.AllowDBNull = True
		DataColumn.Unique = False
	  Else
        DataRow(i) = Field
	  End If
	  i += 1
	Next
	If Header = False Then
	  DataTable.Rows.Add(DataRow)	
	End If
	Header = False
  Next

'-End-------------------------------------------------------------------

And it works :grinning:

On this way it is easy possible to read the content of SAP data tables and to convert it into a data table into UiPath context. Now you can use all the UiPath standard possibilities to work with the SAP data tables easily. But you have to be careful because too much data needs processing time. To minimize processing time use also the ROWCOUNT and OPTIONS parameter from the RFM.

7 Likes

Tiny Addendum, C# Codes of the Example Above

At first the Invoke Code procedure to call the RFM and to write the SAP table data into a variable CSVTableData.

//-Begin----------------------------------------------------------------

SAP.Middleware.Connector.RfcConfigParameters cfgParams;
SAP.Middleware.Connector.RfcDestination destination;
SAP.Middleware.Connector.IRfcFunction rfcFunction;
SAP.Middleware.Connector.IRfcTable table;
string[] parts;
int i;
int j;
string strTableLine;

cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.AppServerHost, "ABAP702");
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.SystemNumber, "00");
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.Client, "001");
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.User, "BCUSER");
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.Password, "minisap");

destination = SAP.Middleware.Connector.RfcDestinationManager.GetDestination(cfgParams);

rfcFunction = destination.Repository.CreateFunction("RFC_READ_TABLE");
rfcFunction.SetValue("QUERY_TABLE", QueryTable);
rfcFunction.SetValue("DELIMITER", Separator);
rfcFunction.Invoke(destination);

table = rfcFunction.GetTable("FIELDS");
i = 0;
foreach(SAP.Middleware.Connector.IRfcStructure tableLine in table) {
  i += 1;
  CSVDataTable += tableLine.GetValue("FIELDNAME").ToString().Trim();
  if(table.Count > i) {
    CSVDataTable += Separator;
  }
}
CSVDataTable += Environment.NewLine;

table = rfcFunction.GetTable("DATA");
j = 0;
foreach(SAP.Middleware.Connector.IRfcStructure tableLine in table) {
  j += 1;
  strTableLine = tableLine.GetValue("WA").ToString();
  parts = strTableLine.Split(Separator.ToCharArray());
  i = 0;
  foreach(string part in parts) {
    i += 1;
    CSVDataTable += part.Trim();
    if(parts.Length > i) {
      CSVDataTable += Separator;
    }
  }
  if(table.Count > j) {
    CSVDataTable += Environment.NewLine;
  }
}

//-End------------------------------------------------------------------

And here the code to convert the CSV data to a data table.

//-Begin----------------------------------------------------------------

string[] Lines;
string[] Fields;
bool Header = true;
System.Data.DataColumn DataColumn;
System.Data.DataRow DataRow = DataTable.NewRow();
int i;

Lines = CSVDataTable.Split(Microsoft.VisualBasic.Constants.vbLf.ToCharArray());
foreach(string Line in Lines) {
  Fields = Line.Split(Separator.ToCharArray());
  i = 0;
  if(Header == false) {
    DataRow = DataTable.NewRow();
  }
  foreach(string Field in Fields) {
	if(Header == true) {
      DataColumn = DataTable.Columns.Add(Field, Type.GetType("System.String"));
      DataColumn.AllowDBNull = true;
      DataColumn.Unique = false;
    } else {
      DataRow[i] = Field;
    }
    i += 1;
  }
  if(Header == false) {
    DataTable.Rows.Add(DataRow);
  }
  Header = false;
}

//-End------------------------------------------------------------------

Tiny Addendum, Read SAP Table Data Directly in a DataTable

Here the VBdotNET code for the Invoke Code activity to read SAP table data directly into a DataTable. This is a combination of the approaches above.

'-Begin-----------------------------------------------------------------

Dim cfgParams As SAP.Middleware.Connector.RfcConfigParameters
Dim destination As SAP.Middleware.Connector.RfcDestination
Dim rfcFunction As SAP.Middleware.Connector.IRfcFunction
Dim table As SAP.Middleware.Connector.IRfcTable
Dim tableLine As SAP.Middleware.Connector.IRfcStructure
Dim FieldName As String
Dim Fields As String()
Dim Field As String
Dim DataColumn As System.Data.DataColumn
Dim DataRow As System.Data.DataRow
Dim i As Integer

'-SAP Connection parameters---------------------------------------------
cfgParams = New SAP.Middleware.Connector.RfcConfigParameters
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.Name, "ReadTable" )
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.AppServerHost, AppServerHost)
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.SystemNumber, SystemNumber)
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.Client, Client)
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.User, User)
cfgParams.Add(SAP.Middleware.Connector.RfcConfigParameters.Password, Password)

destination = SAP.Middleware.Connector.RfcDestinationManager.GetDestination(cfgParams)

'-Get data from SAP table via RFM call----------------------------------
rfcFunction = destination.Repository.CreateFunction("RFC_READ_TABLE")
rfcFunction.SetValue("QUERY_TABLE", QueryTable)
rfcFunction.SetValue("DELIMITER", Separator)
rfcFunction.Invoke(destination)

'-Get the field names---------------------------------------------------
table = rfcFunction.GetTable("FIELDS")
For Each tableLine In table
  FieldName = tableLine.GetValue("FIELDNAME").ToString.Trim
  DataColumn = DataTable.Columns.Add(FieldName, Type.GetType("System.String"))
  DataColumn.AllowDBNull = True
  DataColumn.Unique = False
Next

'-Get the records-------------------------------------------------------
table = rfcFunction.GetTable("DATA")
For Each tableline In table
  DataRow = DataTable.NewRow
  Fields = tableLine.GetValue("WA").ToString.Split(Separator.ToCharArray)
  i = 0
  For Each Field In Fields
    DataRow(i) = Field.Trim
    i += 1
  Next
  DataTable.Rows.Add(DataRow)	
Next

'-End-------------------------------------------------------------------

Here the parameters of the Invoke Code activity.

And here the variables of the sequence.

Last but not leas here the sequence itself.

In the debug perspective we see 392 entries in the data table…

…exact the same as in the SAP data table.

With this approach it is very easy possible to get data from an SAP system in the context of an automation workflow. The restrictions of the function module RFC_READ_TABLE are to be considered.

SAPReadTable.zip (2.9 KB)

3 Likes

Hi Stefan, thanks good document! I wrote a little freeware Windows tool in C# that can query and download via RFC_READ_TABLE . I use it as a connector between UIPath and SAP. You may like it: Free SAP Table Download / Connector download | SourceForge.net
Thanks & also keep up the good work on SAP GUI scripting!
Rgds,
George