Delphi-Systeme an SAP R/3 andocken

Delphi goes SAP
Kommentare

Feuer und Wasser, David und Goliath, Politik und Vernunft, Delphi und SAP. Scheinbare Gegensätze? Dass sich zwischen diesen scheinbar unvereinbaren Welten leicht eine Brücke schlagen lässt, die völlig neue Perspektiven eröffnet, will diese Artikelserie in kleinen Schritten zeigen. SAP R/3 ist weit verbreitet und demzufolge ist entsprechendes Know-how eine wertvolle Bereicherung des Werkzeugkastens, den wir Entwickler in unseren Köpfen mit uns herum tragen. So wie SAP die Plattformen Windows und Linux gleichermaßen unterstützt, verwenden wir das Gespann Delphi/Kylix, um unsererseits auch für beide Betriebssysteme gewappnet zu sein.

Vom Typus her ist der gemeine Delphi/Kylix-Entwickler völlig anders als der SAP-Berater. Freut sich der erstere an Bits und Bytes und findet seine Erfüllung nicht selten im Ausprogrammieren komplizierter Algorithmen, so bewegt sich letzterer mehr in der Welt der Prozesse und verabscheut es, Code generieren zu müssen. So verachtet mancher SAP-Berater die Delphi-Hacker und umgekehrt hat so mancher Delphi-Programmierer für die Gestaltung und Bedienung der SAP-Oberfläche eine Vielzahl hässlicher Bezeichnungen parat. Beide wissen einfach zu wenig vom Anderen. Das dürfte die Ursache dafür sein, dass diese Welten recht selten vereinigt werden, obwohl man damit schier unendliche Möglichkeiten schaffen kann. Spätestens seit man bei SAP kostenfrei DVDs mit den aktuellen Basisversionen Ihres R/3 Systems bestellen kann, gibt es auch für Delphi-Entwickler keine Ausrede mehr dafür, ihre Systeme nicht elegant mit SAP zu koppeln. Warum also nicht den Horizont erweitern und die Anbindung an SAP-Systeme in das Repertoire aufnehmen? Für diejenigen, die noch nie Kontakt zu SAP hatten, werden wir einen kurzen technischen Einblick geben und das System entmystifizieren. Anschließend nehmen wir Kontakt mit SAP auf und entwickeln ein Programmbeispiel, das in den nächsten Teilen zu einer komfortablen Delphi-Schnittstelle ausgebaut wird, die es ermöglicht, recht einfach Subsysteme zu SAP R/3 zu entwickeln. Wenn im Folgenden nur noch von Delphi die Rede ist, so wird trotzdem versucht, eine Plattformunabhängigkeit zu gewährleisten, die eine Übersetzung des Codes auch mit Kylix 3 erlaubt. Für die parallele Entwicklung Delphi/Kylix steht das geniale Cross Kylix Plug-in zur Verfügung, mit dem man den Kylix 3 Compiler in die Delphi 7 oder Delphi 2005 IDE unter Windows einbinden und so auf Knopfdruck das gerade bearbeitete Projekt auch für Linux übersetzen kann. Cross Kylix findet man unter [1].

Unser eigenes SAP R/3 System

Unter [2] können Sie kostenlos SAP-Basisysteme für Linux auf DVD bestellen. Diese Systeme lassen sich problemlos und einfach unter Suse 9 und neuer installieren. Ich empfehle Ihnen die Version, die auf SAP-DB basiert, diese benötigt etwas weniger Plattenplatz als die DB2-Version. Sie sollten mindestens 256 MB Hauptspeicher und 15 MB Plattenplatz für die Installation bereitstellen. Alternativ gibt es auch das sogenannte MINI-SAP, das z.B. verschiedenen SAP-Büchern (z.B. ABAP Objects von Gallileo) als Zugabe beiliegt und das allein unter Windows installiert werden kann. Es beinhaltete zuletzt den 6.1 Applikationsserver und kann sehr gut verwendet werden, um auf einem Notebook Server und Client zu installieren und ein komplettes SAP-Basissystem mit sich herumzutragen. Dieser Artikel ist größtenteils auf einem Notebook mit dieser Konfiguration entstanden. Man sollte allerdings nicht unter 512 MB Hauptspeicher einsetzen, da die Performance sonst durch das erforderliche Swapping auf die Festplatte erheblich einbricht. Auf den DVDs bzw. CDs ist eine detaillierte Installationsanleitung vorhanden. Alle Details sollten unbedingt beachtet werden, da sonst unter Umständen die Installation, die durchaus im Stundenbereich dauern kann, erst im vorletzten Schritt abbricht. Der neue SAP-Applikationsserver 6.4 besteht eigentlich aus zwei Applikationsservern: Dem ursprünglichen SAP R/3 Applikationsserver und dem neuen Web Application Server, der auf J2EE basiert. Letzterer benötigt gewaltige Ressourcen und ist für die hier gezeigten Beispiele nicht erforderlich. In der Datei INSTALL.HTM finden Sie Instruktionen, um diesen Teil abzuschalten. Das Mini-SAP unter Windows verfügt nicht über den Java-Teil. Nach Aufsetzen des Applikationsservers müssen wir uns um die Client-Seite kümmern. Unter Windows ist dazu die so genannte SAP-GUI zu installieren. Diese müssen Sie ebenfalls über SAP beziehen, dem Mini-SAP liegt sie bei. Für die eigentliche Anbindung seitens Delphi ist die SAP GUI eigentlich nicht erforderlich, wir benötigen Sie aber, um im SAP-System verschiedene Dinge vorzubereiten und nachzusehen. Es genügt in jedem Fall die Minimalinstallation. Mit der SAP-GUI können Sie auf mehrere Applikationsserver verbinden. Schlüssel dafür ist das SAP-Log-on-Programm, in dem für jeden Server ein Eintrag vorzunehmen ist. Abpictureung 1 zeigt die Einstellungen für ein lokal installiertes Mini-SAP, bei Benutzung einer fremden Linux-Maschine oder Linux in VMWare ist die entsprechende IP-Adresse einzugtragen.

Abb. 1: Eintragen des lokalen Servers für SAP-Log-on

Anschließend können Sie die SAP-GUI mit diesem Server verbinden und sich mit den Benutzer/Passwortkombinationen anmelden, die beim Mini-SAP im Eingangspictureschirm angezeigt werden bzw. bei den Linux-Varianten in den Readme-Dateien auf den DVDs zu finden sind. Wenn alles glatt gegangen ist, können Sie sich anmelden und sollten in der Lage sein, versuchsweise eine Transaktion aufzurufen:

Abb. 2: Unser SAP-System läuft!

[ header = Seite 2: Der erste Kontakt für SAP-Neulinge ]

Der erste Kontakt für SAP-Neulinge

SAP R/3 ist ein gewaltiges System mit vielen Modulen für die einzelnen Unternehmensbereiche, z.B. HR für Personalabteilung (Human Resources), PP für die Produktionsplanung, SD für den Vertrieb (Sales & Distribution) um nur ein paar zu nennen. Technisch ist SAP deshalb sehr interessant, da es zum einen ein waschechtes Three-Tier-System ist (Datenbankserver, Applikationsserver und Client) und vor allem, weil nahezu die gesamte Logik in Datenbanktablen steckt. Das System verfügt über die Programmiersprache ABAP, die der Applikationsserver ausführen kann. Die anwendungsspezifischen Module sind allesamt in dieser Sprache geschrieben und liegen in der Datenbank vor, werden von dort geladen, beim ersten Mal kompiliert und vom Applikationsserver ausgeführt. Dadurch ist das System, das eine komplette Entwicklungsumgebung für diese Sprache mitbringt, gut modifizier- und erweiterbar, was natürlich erhebliche Kenntnisse der Prozesse und des Innenlebens von SAP erfordert. Anders aber als die in der Delphi-Welt eher üblichen Anwendungen, die durch Anflanschen von DLLs oder Packages erweitert werden, kann hier online Code geschrieben und ausgeführt werden. Grundsätzlich sind alle Operationen eines SAP-R/3-Systems in so genannte Transaktionen gekapselt, die sicherstellen, dass der Datenbestand nicht inkonsistent wird. Diese Transaktionen sind von der Logik mit Datenbanktransaktionen vergleichbar. Im SAP-Sprachgebrauch hat sich der Begriff Transaktion aber auch als Synonym für Funktionsmodul eingebürgert, das kann manchmal verwirren. Diese SAP-Transaktionen haben Kürzel, über die sie schnell aufgerufen werden können. Aufgrund der strengen Kapselung werden Datenbanktablen niemals direkt am Datenbankserver angesprochen, sondern nur über das SAP-System, das teilweise eine Abstrahierung durchführt. So wird beispielsweise bei der Buchung eines Beleges nicht nur ein einzelner Eintrag in irgendeine Tabelle vorgenommen, sondern es wird eine Vielzahl von Aktivitäten auf der Datenbank angestoßen einschließlich Plausibilitäts- und Rechteprüfung. Das Ganze wird zusätzlich in eine Transaktion gekapselt, durch die eine Integrität der Datenbank sichergestellt ist. Unser Basissystem verfügt nicht über businessspezifische Module, sondern enthält nur die Basisfunktionalität, Benutzerverwaltung und die Entwicklungstools. Das ist für unsere Zwecke auch völlig ausreichend. Die Entwicklungstools erlauben es, Tabelleninhalte anzuzeigen, Funktionsbausteine aufzurufen und auch eigene Funktionsbausteine zu entwickeln und zu testen. Um den Kontakt zur Außenwelt herzustellen, verfügt SAP R/3 über eine Reihe eleganter Möglichkeiten, von denen wir hier die sogenannten RFCs, die Remote Function Calls verwenden werden. RFCs sind Funktionsbausteine, die eine definierte Schnittstelle anbieten und im SAP-System bestimmte Funktionen ausführen und von außen aufgerufen werden können. Die zentralen SAP-Transaktionen für unseren Job möchte ich Ihnen kurz vorstellen. Hier ist zum einen die SE16 zu nennen, mit der man Tabellen anzeigen und bearbeiten kann. Diese Transaktion kann schnell durch Eingabe von SE16 aufgerufen werden (Abb. 3). Wenn Sie sich bereits in einer anderen Transaktion befinden, stellen Sie bitte ein /N davor, um SAP R/3 mitzuteilen, dass Sie wechseln wollen. Bestätigt wird mit Enter oder Return.

Abb. 3: Aufrufen einer Transaktion

Hier können wir nun eine Tabelle ansehen, günstig ist eine des in den Basissystemen zu Trainingszwecken vorhandenen Flugdatenbankmodells, z.B. die der Flüge, SPFLI. Man gelangt zunächst auf eine Art Query by Example Screen, den man bei dieser recht übersichtlichen Tabelle leer lassen kann und bekommt anschließend den Inhalt angezeigt (Abb. 4).

Abb. 4: Anzeige einer SAP-Tabelle

Eine weitere interessante Transaktion ist der Function Builder SE37, mit dem wir Informationen über das Interface eines aufzurufenden Funktionsbausteins bekommen und selber Funktionsbausteine entwickeln können. Mit /NSE37 können Sie aus der Tabellenanzeige in den Function Builder wechseln. Ein weiterer Funktionsbaustein ist RFC_READ_TABLE, mit dem man von außen eine Tabelle öffnen und auslesen kann. Schauen wir uns diesen Funktionsbaustein einmal an, er wird unser Objekt der Begierde sein, wenn wir mit Delphi ankoppeln (Abb. 5).

Abb. 5: Anzeige eines Funktionsbausteins

Unter den Reitern Import, Export, Changing und Tabellen findet sich die eigentliche Schnittstellendefinition, die wir benötigen, um den Funktionsbaustein korrekt aufzurufen. Genau das gehen wir nun an.

[ header = Seite 3: In medias res ]

In medias res

Der erste Schritt in Richtung Ankopplung eines Delphi/Kylix-Systems besteht in der Einbindung einer Bibliothek, die von SAP für diesen Zweck bereitgestellt wird. Sie ist auch Bestandteil des so genannten Java Connectors und eines SDK, das mit der SAP-GUI mitinstalliert werden kann. Diese Bibliothek ist sowohl für Windows als librfc32.dll als auch für Linux als librfccm.so verfügbar. Es gibt verschiedene Versionen dieser Dateien. Sie sollten darauf achten, möglichst aktuelle Versionen zu verwenden, da es veraltete DLLs gibt, die nicht alle benötigten Funktionen enthalten. Die mit der SAP-GUI 6.4 installierte Version passt auf alle Fälle. Sollten Beispiele in diesem Artikel nicht funktionieren, so suchen Sie die Ursache zuerst hier. Möglicherweise hilft auch Google weiter. Beginnen wir also mit dem Einbinden der Bibliothek. Der Einfachheit halber führen wir das Programm als Konsolenprogramm aus, was es uns später ermöglichen wird, die gesamte Funktionalität in eine eigene Bibliothek zu kapseln. Für die Plattformunabhängigkeit sehen wir gleich entsprechende IFDEFS vor. Da die Kompilierung hier abbricht, wenn weder Linux noch 32 Bit Windows verwendet werden, können wir die Abfrage im folgenden Code auf Linux oder Nicht-Linux (=Windows) beschränken. Wir gehen weiter davon aus, dass die SAP-RFC-Bibliothek in dem Verzeichnis liegt, in das wir die ausführbare Datei kompilieren (Listing 1 auf der Heft-CD). Unter Type definieren wir eine Struktur, in der uns die SAP-Bibliothek eine eventuelle Fehlermeldung übergibt und den Prototypen für die Funktion, mit der eine Verbindung aufgebaut wird. Die Funktion OpenSAPConnection lädt zunächst plattformabhängig die korrekte Bibliothek und versucht dann, die Funktion RfcOpenEx zu verbinden. Tritt dabei ein Fehler auf, wird eine Exception geworfen. Anschließend wird versucht, eine Verbindung zu dem SAP-System aufzubauen. Dazu ist der Funktion RfcOpenEx ein String mit den Verbindungsinformationen zu übergeben, ähnlich, wie man mit ADO arbeitet. Der Beispielstring oben enthält die Verbindungsdaten zum Mini-SAP-System, das auf dem gleichen Rechner (Q25) läuft. Der Parameter TRACE=1 führt zur Erzeugung einer recht umfangreichen Trace-Datei im Programmverzeichnis, die zur Fehlersuche eingesetzt werden kann und die auch Dumps der übertragenen Datenblöcke enthält. In Produktivsystemen sollten Sie diese Datei abschalten, um das Programmverzeichnis nicht mit Traces zu überschwemmen. Unser erstes Testprogramm gibt auf der Konsole Gelungen aus, wenn eine Verbindung aufgebaut werden konnte, ansonsten die entsprechende Fehlermeldung, die vom SAP-System bzw. der Schnittstelle selbst kommt. Wir können einen Fehler provozieren, in dem wir versuchsweise den Applikationsserver Host modifizieren: ASHOST=FALSCH. Naturgemäß dauert es einen Moment, bis die Suche nach diesem nicht vorhandenen Host fehlschlägt, dann erhalten wir eine recht ausführliche Fehlermeldung.

Abb. 6: Umfangreiche Fehlermeldung bei Verbindungsproblemen

Wir haben die Türe geöffnet, nun sollten wir auch eintreten. Nachdem wir erfolgreich an das SAP-System angekoppelt haben, schaffen wir uns die Möglichkeit, einen RFC aufzurufen. Dazu müssen zunächst noch eine Reihe weiterer Strukturen abgepictureet werden. Zunächst müssen wir uns noch einmal die Schnittstelle zu RFC-Bausteinen in SAP genau ansehen. Hier werden mehrere Parametergruppen unterstützt:

  • Import: Eingabeparameter des RFC
  • Export: Ausgabeparameter des RFC
  • Changing: Ein/Ausgabe-Parameter des RFC
  • Tabellen: Ein/Ausgabe Tabellen des RFC
  • Ausnahmen: Exceptions des RFC.

Unter Import, Export und Changing finden sich normale Parameter wie Strings und Integer. Ausnahmen sind die vom entsprechenden Funktionsbaustein möglicherweise generierten Exceptions mit Ihrem Fehlertext. Tabellen sind Tabellenstrukturen, mit denen sich Zeilenweise beliebige Datenmengen transportieren lassen. Um die interessanten Parameter zu analysieren, bietet die SAP-Transaktion SE37 eine einfache Möglichkeit: Klickt man doppelt auf das Feld in der Spalte Bezugstyp, so wird automatisch dieser Feldtyp im Dictionary angezeigt. Hier erfahren wir, dass das FeldQUERY_TABLE ein 30-Zeichen-Charakterfeld ist.

Abb. 7: Anzeige Datentyp im Dictionary

Für die Kommunikation mit dem RFC rfc_read_table sind die in Tabelle 1 enthaltenen Felder essenziell:

Paremeter

Inhalt

Wert für unseren Test

QUERY_TABLE

Abzufragende Tabelle

SPFLI

NO_DATA

Signal, ob wir die Tabellenstruktur, oder die Tabellendaten lesen wollen. Leerzeichen bedeutet Daten lesen

leer

DATA

Tabellenfeld, liefert 512 Zeichen Ergebnisblöcke

Rückgabewert

Der Aufruf des RFC geschieht über die Funktion RfcCallReceiveEx, der neben dem Namen des aufzurufenden RFC auch Zeiger auf die vorgenannten Strukturen Import, Export, Changing, Tables undException zu übergeben sind.

type
TRfcCallReceiveEx = function(connHandle: THandle; funcName: PChar; exporting, importing,
changing, tables, exception: pointer): integer; stdCall;

var
FRfcCallReceiveEx: TRfcCallReceiveEx;

An dieser Stelle sollten wir unserem Beispielprogramm auch die nötige Funktion zum sauberen Schließen der Verbindung spendieren, da wir sonst mit jedem Durchlauf möglicherweise eine Zombie-Verbindung schaffen, die unnötigerweise Ressourcen belegt.

type
TRfcClose = procedure(connHandle: THandle); stdCall;

var
FRfcClose: TRfcClose;

Import- und Exportgeschäft

Wenn wir nun beginnen, die Parameterstrukturen für den Aufruf aufzubauen, so ist es nach dem SAP SDK üblich, die Betrachtungsrichtung zu berücksichtigen. Wir bezeichnen nun die Parameter, die wir an den RFC übergeben, als die Exportparameter, während diese auf der SAP-Seite Importparameter sind. Dies kann leicht zu Verwirrung führen, da wir die Parameter, die wir in der SAP-Transaktion SE37 im Bereich Import identifiziert haben, hier in der Struktur Export übergeben müssen. Zwei Strukturen werden benötigt, nämlich der normale Parameter, mit dem z.B. eine Zeichenkette übergeben wird und die Tabellen, die eine Reihe Besonderheiten aufweisen, da sie quasi eine unbegrenzte Länge aufweisen können und Blockweise abgefragt werden müssen (Listing 2).

TRfcParam = record
name: pointer;
nlen: integer;
atype: integer;
leng: integer;
addr: pointer
end;

TRfcTable = record
name: pointer;
nlen: integer;
atype: integer;
leng: integer;
ithandle: integer;
itmode: integer;
newitab: integer;
end;

Für den Aufruf des RFC benötigen wir mehrere Strukturen auf Basis dieser Records. Es ist speichertechnisch vertretbar, an dieser Stelle Arrays zu verwenden, da wir wissen, wie viele Parameter wir maximal übergeben müssen. Um dennoch die Möglichkeit zu behalten, dieses Limit einfach zu verändern, definieren wir diesen Wert als Konstante und verwenden diese bei der Definition der Arrays. Mit maxArrays=10 bedienen wir maximal 11 Parameter, da die Zählung bei 0 beginnt.

const
maxParams = 10;

var
FExporting, FChanging, FImporting: array[0..maxParams] of TRfcParam;
FTables: array[0..maxParams] of TRfcTable;

Man sieht den Strukturen an, dass nicht unerhebliche Arbeit für das korrekte Füllen der Records für jeden Parameter erforderlich ist. Daher schreiben wir uns eine Funktion, die uns diese Arbeit abnimmt und automatisch den Array-Index mitzählt. Wir machen dabei uns die Tatsache zu Nutze, dass wir beim Öffnen der Verbindung alle name-Felder auf NIL setzen (Listing 3).

...
// Parameterstrukturen initialisieren
for i := 0 to maxparams do begin
FExporting[i].name := nil;
FImporting[i].name := nil;
FTables[i].name := nil;
end;
...
procedure setRFCInputParam(paramName, paramValue: string; paramType: integer);
// Setzt Eingabeparameter für den RFC
var
i: integer;
begin
i := 0;
while (i < maxparams) and (FExporting[i].name  nil) do inc(i);
if i = maxparams then raise exception.create('Max params exeeded!');
FExporting[i].name := pchar(paramName);
FExporting[i].nlen := length(paramName);
FExporting[i].atype := paramType;
FExporting[i].leng := length(paramValue);
FExporting[i].addr := pchar(paramValue);
end;

Auch für den eigentlichen Aufruf des RFC schreiben wir eine Wrapperfunktion, die uns die Arbeit erleichtert und bei einem Fehler eine Exception wirft. SAP liefert als Exception-Parameter in der Regel einen String zurück. Sollte dieses Feld trotz eines aufgetretenen Fehlers leer sein, so liefern wir wenigstens die SAP-Fehlernummer als Exception-Text zurück (Listing 4).

procedure callRFC(RfcName: string);
var
funcres: integer;
s: string;
pException: pointer;
begin
funcRes := FRfcCallReceiveEx(connHandle, pchar(RfcName), @FExporting, @FImporting,
@FChanging, @FTables, @pException);
if funcres  0 then begin
s := pchar(pException);
// Wenn wir keinen Klartext-Fehler bekommen, geben wir den Fehlercode aus
if s = '' then s := 'Error ' + IntToStr(funcres);
raise exception.create(s);
end;
end;

Das Feld paramType ist bei normalen Datenfelden mit 0 zu besetzen. Jetzt können wir recht einfach die Eingabeparameter für unseren RFC füllen und ihn dann aufrufen. In Listing 5 (auf der Heft-CD) zeigt den Quellcode des zweiten Testprogramms im kompletten Zusammenhang. Wie sein Vorgänger lässt es sich für Windows und Linux kompilieren.

[ header = Seite 4: Geben und Nehmen ]

Geben und Nehmen

Wir haben dem RFC zwar nun die Struktur der Tabelle SPFLI abgerungen, doch außer dem netten Gelungen! zeigt unser Programm nichts weiter an. Wir müssen nun die zurückgelieferten Daten abholen und dazu die Tabellenstruktur nutzen. Um eine Tabelle als Parameter zurückgeliefert zu bekommen, muss man dafür die vorbereitete Struktur bereits beim Aufruf des RFC übergeben. Dies ist darin begründet, dass Tabellen sowohl Eingabe- als auch Ausgabeparameter sein können. Zusammen mit der Tabellenstruktur ist auch eine interne Struktur vom Typ RfcIt zu erzeugen, die intern als Puffer für die übergebenen Zeilen dient und von der wir nur ein Handle bekommen. Über dieses Handle können wir später dann die Tabelleninhalte abrufen. Diese Technik ist erforderlich, da wir in unserem Programm überhaupt nicht in der Lage sein können, entsprechende Puffer für die zurückgelieferten Daten zu erzeugen. Daher werden Sie im Applikationsserver über das Handle der RfcIt-Struktur Blockweise abgerufen. Wir benötigen zusätzlich zu der vorhandenen Tabellenstruktur nun noch drei Funktionen, die uns ebenfalls von der Bibliothek zur Verfügung gestellt werden (Listing 6).

type
TRfcItCreate = function(name: PChar; leng, occu, memo: integer): integer; stdCall;
TRfcItDelete = procedure(ithandle: integer); stdCall;
TRfcItGetLine = function(ithandle, recno: integer): pchar; stdCall;

var
FRfcItCreate: TRfcItCreate;
FRfcItDelete: TRfcItDelete;
FRfcItGetLine: TRfcItGetLine;

Analog zur Definition eines Eingabeparameters schreiben wir wieder einen Wrapper, diesmal für die Definition eines Tabellenparameters. Die Vorgehensweise ist weitgehend identisch, allerdings erzeugen wir zusätzlich die RfcIt-Struktur und übergeben das Handle an das Feld handle in der Tabellenstruktur (Listing 7).

procedure setRFCTable(tableName: string; rowsize: integer);
// Setzt Eingabeparameter für den RFC
var
i: integer;
begin
i := 0;
while (i < maxparams) and (FTables[i].name  nil) do inc(i);
if i = maxparams then raise exception.create('Max tables exeeded');
FTables[i].name := pchar(tableName);
FTables[i].nlen := length(tableName);
FTables[i].ithandle := FRfcItCreate(PChar(Tablename), rowsize, 0, 0);
FTables[i].atype := 0;
FTables[i].leng := rowSize;
FTables[i].itmode := 0;
end;

Genau dieses Handle ermöglich es uns später, auf die Daten der Tabelle zuzugreifen. Für unser Beispiel schreiben wir uns eine ganz rudimentäre Funktion, die einfach die Tabelle Zeile für Zeile in eine Stringliste einliest und diese als Funktionsergebnis übergibt. Die Funktion RfcGetLine liefert so lange Pointer auf Strings, bis wir alles gelesen haben, dann ist der Rückgabewert NIL und wir brechen die Schleife ab (Listing 8).

function getTable(index: integer): TStringList;
var
i: integer;
p: pchar;
begin
result := TStringList.create;
i := 1;
repeat
p := FRfcitGetLine(FTables[0].itHandle, i);
if p  nil then result.add(p);
inc(i);
until p = nil;
end;

Nach Erweiterung unserer Funktion OpenSAPConnection um die Zuordnung der neuen Funktionen können wir nun den Inhalt der Tabelle SPFLI aus dem SAP-System in Rohform auf unserer Konsole ausgeben (Abb. 8).

Abb. 8: Ausgabe der Tabelle SPFLI aus dem SAP-System

Listing 9 (auf der Heft-CD) zeigt den Quellcode des dritten Beispiels noch einmal im kompletten Zusammenhang. Ich lade Sie ein, damit zu experimentieren! Longum iter est per praecepta, breve et efficax per exempla – frei übersetzt: Mit Beispielen lernt man am Besten. Diesem Motto bleiben wir auch in den kommenden Teilen dieser Serie treu, indem wir versuchen werden, die Ausgabe der Daten zu strukturieren und alles elegant in eine Komponente zu packen, selbstverständlich weiterhin für die Windows- und Linux-Plattform!

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -