SAP .NET Connector – RFC_READ_TABLE in 50 lines
Consider the below code for educational purposes only. Avoid using RFC_READ_TABLE as it’s not released by SAP – see note 382318 – FAQ|Function module RFC_READ_TABLE.
Find below a simple RFC_READ_TABLE call using the SAP .net connector 3.x
ReadTable(“PR1”, “MARA”, “MATNR,MTART,MATKL”, “MTART EQ ‘HAWA'”, rows);
where “PR1” – destination system
“MARA” – string, table to query
“MATNR,xxx” – string, coma separated column names. If empty “”, then all table fields are retrieved.
“MTART EQ ‘HAWA'” – string, WHERE clause in ABAP SQL syntax
rows – output variable, list of strings to hold the result table rows. Columns delimited by “~”
Current limitation: in the below version of the code, the filter can be only upto 72 characters long. If you need longer, I suggest to involve a word wrapping function like this one: http://bryan.reynoldslive.com/post/Wrapping-string-data.aspx
public bool ReadTable(string dest, string table, string fields, string filter, out List<string> rows) {
string[] field_names = fields.Split(",".ToCharArray());
RfcDestination destination = RfcDestinationManager.GetDestination(dest);
IRfcFunction readTable;
try {
readTable = destination.Repository.CreateFunction("BBP_RFC_READ_TABLE");
} catch (RfcBaseException ex) {
//Log.Error(String.Format("\nError in function module RFC_READ_TABLE ({0})", ex.Message));
rows = null;
return false;
}
readTable.SetValue("query_table", table);
readTable.SetValue("delimiter", "~");
IRfcTable t = readTable.GetTable("DATA");
t.Clear();
t = readTable.GetTable("FIELDS");
t.Clear();
if (field_names.Length > 0) {
t.Append(field_names.Length);
int i = 0;
foreach (string n in field_names) {
t.CurrentIndex = i++;
t.SetValue(0, n);
}
}
t = readTable.GetTable("OPTIONS");
t.Clear();
t.Append(1);
t.CurrentIndex = 0;
t.SetValue(0, filter);
//Log.Debug(string.Format("SELECT {0} FROM {1} WHERE {2}",
// fields, table, filter));
readTable.Invoke(destination);
t = readTable.GetTable("DATA");
int a = t.Count;
rows = new List<string>();
for (int i = 0; i < t.RowCount; i++) {
t.CurrentIndex = i;
rows.Add(t.GetString(0));
}
return true;
}
I have updated the above function for the possibility to retrieve all the table fields. For that call the function with fields = "":
ReadTable("PR1", "MARA", "", "MTART EQ 'HAWA'", rows);
Hi Hynek,
Referring to RFC_READ_TABLES
When I try to download a table from DD03M tabname = "PA0001" (selecting no fields so all fields selected then I get an error
DATA_BUFFER_EXCEEDED
I think that the returned string will be more than 512 char.
How can I solve this?
Thanks
Ton
Hi Hynek
Here is my code
Dim QUERY_TABLE As Object
Dim DELIMITER As Object
Dim NO_DATA As Object
Dim ROWSKIPS As Object
Dim ROWCOUNT As Object
'Dim COLUMNCOUNT As Object
' Where clause
Dim OPTIONS As Object
' Fill with fields to return. After function call will hold
' detailed information about the columns of data (start position
' of each field, length, etc.
Dim FIELDS As Object
' Holds the data returned by the function
Dim DATA As Object
' Use to write out results
Dim ROW As Object
Dim Result As Boolean
Dim i As Long, j As Long, iRow As Long
Dim iColumn As Long, iStart As Long, iStartRow As Long, iField As Long, iLength As Long
Dim outArray, vArray, vField
Dim iLine As Long
Dim noOfElements As Long
'**********************************************
'Create Server object and Setup the connection
'use same credentials as SAP GUI login
' On Error GoTo abend
R3 = CreateObject("SAP.Functions")
R3.Connection.SYSTEM = rtdetails.SapSystem
R3.Connection.Client = rtdetails.SapClient
R3.Connection.User = rtdetails.SapUser
R3.Connection.Password = rtdetails.SapPassword
R3.Connection.Language = "EN"
If R3.connection.logon(0, True) <> True Then
MessageBox.Show("ERROR - logon to SAP failed")
Exit Function
End If
MyFunc = R3.add("BBP_RFC_READ_TABLE")
QUERY_TABLE = MyFunc.exports("QUERY_TABLE")
DELIMITER = MyFunc.exports("DELIMITER")
NO_DATA = MyFunc.exports("NO_DATA")
ROWSKIPS = MyFunc.exports("ROWSKIPS")
ROWCOUNT = MyFunc.exports("ROWCOUNT")
OPTIONS = MyFunc.tables("OPTIONS")
QUERY_TABLE.Value = TABLE
DELIMITER.value = ""
NO_DATA = ""
ROWSKIPS = "0"
ROWCOUNT = "0"
OPTIONS.Rows.add()
OPTIONS.value(1, "TEXT") = FILTER
Result = MyFunc.call
If Result = True Then
DATA = MyFunc.tables("DATA")
FIELDS = MyFunc.tables("FIELDS")
OPTIONS = MyFunc.tables("OPTIONS")
R3.Connection.LOGOFF()
Else
R3.Connection.LOGOFF()
MessageBox.Show(MyFunc.EXCEPTION)
Exit Function
End If
noOfElements = FIELDS.ROWCOUNT
iRow = 2
iColumn = 1
ReDim outArray(0 To DATA.ROWCOUNT, 0 To noOfElements - 1)
For Each ROW In FIELDS.Rows
xlsSheetTables.Cells(iRow, iColumn).value = ROW("FIELDNAME")
'outArray(iRow, iColumn) = ROW("FIELDNAME")
iColumn += 1
Next
Dim ColLetB As String = Replace(xlsSheetTables.Cells(2, noOfElements).Address(False, False), _
xlsSheetTables.Cells(2, 2).Row, "")
ColLetB = ColLetB & 2.ToString
rng = xlsSheetTables.Range("A2:" & ColLetB)
rng.Font.Color = System.Drawing.Color.Blue
rng.Font.Size = 14
rng.Font.Bold = True
rng.EntireColumn.AutoFit()
' Display Contents of the table
ROW = 3
iColumn = 0
For Each ROW In FIELDS.rows
outArray(iRow, iColumn) = ROW("FIELDNAME")
iColumn += 1
Next
Dim map As String = ""
Dim okmap As Boolean = False
iRow = 3
iColumn = 1
Dim resultaat As String = ""
For iLine = 1 To DATA.ROWCOUNT
For iColumn = 1 To FIELDS.ROWCOUNT
iStart = FIELDS(iColumn, "OFFSET") + 1
If iColumn = FIELDS.ROWCOUNT Then
iLength = (DATA(iLine, "WA")).Length - iStart + 1
Else
iLength = FIELDS(iColumn + 1, "OFFSET") - FIELDS(iColumn, "OFFSET")
End If
If iStart > (DATA(iLine, "WA")).Length Then
'outArray(iRow, iColumn - 1) = Nothing
Else
resultaat = Strings.Mid(DATA(iLine, "WA"), iStart, iLength)
'outArray(iRow, iColumn - 1) = Strings.Mid(DATA(iLine, "WA"), iStart, iLength)
xlsSheetTables.Cells(iRow, iColumn).value = "'" & resultaat.ToString
End If
Next
iRow += 1
Next
Hi,
yes apparently the length of a single row (sum of length of each column, including separator?) shall not exceed 512 characters. Just the field length itself for DD03M is 587. So you have to name your fields explicitly and exclude some of them, not to exceed the row size.
Hynek
Thanks!
Hi Hynek
Is it also possible to read a structure for example Q588M
KR
Ton
Structure is a data type, it's not a data table.
Hi Hynek
Thanks for the info.
My problem is that I want to retrieve some info of info types in T588M
And this info I need
But I don't know how to get it.
Could you please advise
Thanks
Ton
Hi Ton,
I suggest you to check SCN or open another Discussion thread. This discussion shall be related to the above article and I'm afraid we are drifting away.
Regards, Hynek