Schnittstellenstrategie

12. Oktober 2015 14:20

Guten Tag Zusammen,

es führen bekanntlich viele Wege nach Rom. Die Frage ist jedoch, welcher erfahrungsgemäß der "beste" ist.
Da wir eines Tages auf NAV2013R2 oder NAV2015 upgraden werden, fallen Dataports schon mal aus.

Ich habe für mein Projekt zwei Ideen. Doch kurz ein paar Randinformationen.

1. Ich lese Flat File Dateien ein und aus. Es gibt keinen Seperator. Die Länge ist fest definiert.

z.B.

Die Positionierung der einzelnen Felder in der Datei sind fest vorgeschrieben.

Bezeichnung: Quelle
Länge: 10

Bezeichnung: Ziel
Länge: 10

Bezeichnung: Anlegezeit
Länge: 14

Code:
ERP       EXTERN    YYYYMMDDHHMMSS


Eine Zeile entspricht ein Datensatz in der Datei. In NAVwerden die einzelnen Inhalte in einzelne Tabellenfelder geschrieben.
Eine Zeile kann hierbei insgesamt maximal Zeichenlänge von 3000 Zeichen haben.
Dazu kommt, dass mehrere Zeilen in der Datei zu einer "Einheit" gehören können. Quasi eine Masterzeile und dazugehörige Subzeilen, dann wieder eine Masterzeile etc.
Beim Import werden in NAV ja automatisch anhängende leer Zeilen "ERP " einfach abgeschnitten. Für den Export werde ich in einer CU eine Funktion entwickeln, die den String, die aufzufüllende Länge und den FillCharacter mitbekommt und dann mit dem tollen Befehl PADSTR einfach mit dem FillCharacter - in meinem Fall Leerzeilen - auffüllt.


Meine Frage ist nun, welcher Weg für die Schnittstelle die "zukunftssicherste" wäre. Nur mit CU und File-Funktionen oder erstmal die Informationen in eine Tab XML-IN in ein BLOB-Feld reinschreiben und durch zusätzliche Felder wie "Nachrichten-Nr.", Version, Sender, Empfänger etc. anreichern um dann schließlich den Inhalt über XML-Port in definierte Tabellen(Felder) übertragen?

Welche Erfahrungen habt ihr gemacht? Eine Empfehlung für mich? Ist die feste Positionsdefinierung im XML-Port überhaupt möglich? Falls nicht, brauch ich so ein XML-Port überhaupt? Wäre es dann nicht sinnvoller einfach über File-Funktionen einzulesen und dabei immer zu definieren welche Positionsrange was ist und wo hingehört?

Danke für den Austausch mit euch im voraus.

Re: Schnittstellenstrategie

12. Oktober 2015 15:12

Hallo,

ich persönlich bevorzuge für solche Zwecke Reports (wenn man eine Requestpage benötigt) oder Codeunits (egal ob TXT, CSV oder XML).

Wenn man anspruchsvollere Aufgaben hat (deine würde ich für eine solche halten), ist man damit flexibler. Wenn man so etwas häufiger machen muss, dann kann man sich einen Rahmen für so einen Dataportersatz bauen, den man dann immer wieder verwenden kann.

Gruß Fiddi

Re: Schnittstellenstrategie

12. Oktober 2015 15:20

MSNAVLerner hat geschrieben: Ist die feste Positionsdefinierung im XML-Port überhaupt möglich?

Ab NAV 2009 R2 geht das, da kommen diverse Properties bei XMLports dazu:
http://dynamicsuser.net/blogs/marcos/archive/2011/04/18/the-dataport-is-dead-long-live-the-xmlport.aspx
Umbauen muss man die alten Dataports dafür aber schon, dafür gibt es keine Upgradekonvertierung.

Re: Schnittstellenstrategie

12. Oktober 2015 15:34

Danke für deine Empfehlung.

Die XML-Port-Variante wäre wirklich, wenn man neben dem Projekt mal mit vielen anderen Systemen unterschiedliche Dokumente austauscht, empfehlenswert. In meinem Fall gibt es "erstmal" nur das eine Schnittstellenprojekt.

Nun wird es in diesem Projekt viele verschiedene Nachrichtentypen geben, inkl. Austausch von Acknowledge-Belegen (von NAV & Externe Software), die alle in unterschiedlichen Verzeichnissen abgelegt (danach gelöscht/archiviert) werden.
Was denkst du über die Idee zwei zwei Reports (einen für Inbound und einen für Outbound) zu nutzen, die lediglich erstmal die Flat Files in die Tabellen "Schnittstelle-Inbound" und "Schnittstelle-Outbound" in BLOBs - inkl. Randinfos wie Datum, Zeit etc. reinschreiben (oder in mehrere 250er-Text-Feld er), gleichzeitig hierbei dann noch Dublettenprüfungen durchgeführt werden und ein Job arbeitet diese Tabellen dann Zeile für Zeile durch und schreibt die Daten dann in die jeweilige Tabellen rein. Ich könnte dann in diesen Schnittstellen-Tabellen zudem noch schöne Felder aufnehmen wir "bolBearbeitet", "datDatum" etc., diesen dann auch nach einer bestimmten Löschroutine löschen. Das macht dann nämlich auch Fehlersuche/Nachvollziehrbarkeit einfacher.

Ich erkenne zudem teilweise nur in den Flat Files worum es sich genau handelt. Obs Artikelstammdaten, oder Artikeleinheiten etc. sind.
Ich weis somit schon, was in welchem Verzeichnis abgestellt wird, doch diese Flat Files können innerhalb dann noch verschiedene Kennungen haben.

Re: Schnittstellenstrategie

13. Oktober 2015 13:48

Es gibt für solche Szenarien auch Lösungen, welche standardisiert Daten austauschen können.
Ich habe Erfahrung mit Yaveon ProESCM und kann nur Gutes darüber sagen.

Re: Schnittstellenstrategie

9. Februar 2016 10:57

Entschuldigt die späte Antwort. Gehe momentan durch viele anderen To Do´s etwas unter.

Eine B2B/EDI- Lösung ist leider momentan keine Option. Muss das Projekt mit den vorhandenen Mitteln lösen und stehe da leider etwas in der Wüste, da ich nicht weis, welche Vorangehensweise die sinnvollste, gerade in Bezug auf das darauf folgende Projekt: Umstieg auf NAV 2013R2 oder 2015 ansteht.

Habt ihr einen Tipp, wie ich die Flatfiles am besten einlese? Mir machen hier zwei Dinge ein Problem:

1. kein Separator, Felder sind durch Länge fest definiert
2. 3000 Zeichen pro Flatfilezeile (somit dürfte die READ-Funktion schon mal flach fallen).

Wäre der Weg über InStream eine Option, indem ich binär einlese und immer gewisse Anzahl von Zeichensätzen in die einzelnen Tabellenfelder schreibe?

Re: Schnittstellenstrategie

9. Februar 2016 11:35

Hallo MSNAVLerner,

InStream ist eine Möglichkeit. Oder READ im Binärmodus. Der XMLPort im TextFile-Modus würde wohl auch gehen. Und das geht auch alles in 201X.

LG Jens

Re: Schnittstellenstrategie

9. Februar 2016 12:08

Der XMLPort im TextFile-Modus würde wohl auch gehen.


wenn ich mich nicht irre aber nicht in NAV 4

Gruß Fiddi

Re: Schnittstellenstrategie

10. Februar 2016 09:35

fiddi hat geschrieben:
Der XMLPort im TextFile-Modus würde wohl auch gehen.


wenn ich mich nicht irre aber nicht in NAV 4

Gruß Fiddi


Muss dir zustimmen. Habe diese Möglichkeit nicht gefunden.


Ist es nicht so, dass INSTREAM CR/LF ignoriert?
Aus Sicht der Performance, wäre eurer Erfahrung INSTREAM schneller als byteweise Auslese per File im Binärmodus?

Wie könnte das INSTREAM Coding aussehen, damit er nach 3000 Zeichen weis, dass die nächste Textzeile zu bearbeiten ist, wobei ich Ihm nach dem Einlesen sage, dass beispielsweise erste 10 Zeichen in Feld X von Tabelle Y kommen und Feld 11-18 in Feld Y von Tabelle Y gehören? Ich muss vorher erst noch "lesen" eine bestimmte Stelle in jeder Zeile auslesen, damit ich weis, um welche Satzart es sich handelt. Es sind nämlich immer unterschiedliche.

Die Funktion ist quasi eine zentrale Einlesestelle, nach der dann entschieden geht, mit welcher Funktion es weiter geht.

Grüße

Re: Schnittstellenstrategie

10. Februar 2016 11:40

Hallo,

wenns mit NAV4 Runtime funktionieren soll, kann XMLPort keinen File-Modus, leider. Bezüglich InStream: Ja, ignoriert CR/LF und andere nicht druckbare Zeichen. Habe mal Code für sowas geschrieben:

Code:
FDestination.CREATE(FileNameDestination);
FDestination.TEXTMODE(TRUE);
FSource.OPEN(FileNameSource);
//OS004s os.jgl
FSource.TEXTMODE(FALSE);
FSource.CREATEINSTREAM(FInStream);
//OS004e os.jgl
OldContent := '';
D.OPEN(TEXT001);
L_StartTime:=TIME;

FSource.SEEK(0);
REPEAT
  //OS004s os.jgl
  //handle the file transfer with instream/outstream. More complicated, but so we can get around the 1024C limit and varying text
  //delimiters.
  L_StartPos := FSource.POS;
  FInStream.READTEXT(Content);
  L_EndPos := FSource.POS;
  L_ContentLen := STRLEN(Content);
  L_HasUnprintablechars := L_EndPos-L_StartPos > L_ContentLen;
  IF L_HasUnprintablechars THEN BEGIN
    FSource.SEEK(L_StartPos+L_ContentLen);
    FOR k:=1 TO L_EndPos-L_StartPos-L_ContentLen DO
      FSource.READ(L_UnprintableChars[k]);
  END;
  OriginContent := Content;
  //Test for the RDLDATA section. Pass through the following lines (which can easily exceed the 1024C limit) until we find
  //closing parantheses.
  IF STRPOS(Content,SectionRDLDATA)=1 THEN BEGIN
    FDestination.WRITE(Content);
    FDestination.SEEK(FDestination.POS-2);
    IF L_HasUnprintablechars THEN BEGIN
      FDestination.TEXTMODE(FALSE);
      FOR k:=1 TO L_EndPos-L_StartPos-L_ContentLen DO
        FDestination.WRITE(L_UnprintableChars[k]);
      FDestination.TEXTMODE(TRUE);
    END;
    REPEAT
      CLEAR(Content);
      L_StartPos := FSource.POS;
      FInStream.READTEXT(Content);
      L_EndPos := FSource.POS;
      L_ContentLen := STRLEN(Content);
      L_HasUnprintablechars := L_EndPos-L_StartPos > L_ContentLen;
      IF L_HasUnprintablechars THEN BEGIN
        FSource.SEEK(L_StartPos+L_ContentLen);
        FOR k:=1 TO L_EndPos-L_StartPos-L_ContentLen DO
          FSource.READ(L_UnprintableChars[k]);
      END;
      FDestination.WRITE(Content);
      FDestination.SEEK(FDestination.POS-2);
      IF L_HasUnprintablechars THEN BEGIN
        FDestination.TEXTMODE(FALSE);
        FOR k:=1 TO L_EndPos-L_StartPos-L_ContentLen DO
          FDestination.WRITE(L_UnprintableChars[k]);
        FDestination.TEXTMODE(TRUE);
      END;
    UNTIL STRPOS(Content,SectionRDLCLOSE)=1;


Wie man sieht ist das etwas komplizierter. Der Text geht über den InStream, die nicht druckbaren Zeichen byteweise über das File Handle.

LG Jens

Re: Schnittstellenstrategie

10. Februar 2016 12:39

puuuhh das ist wirklich sehr komplex.
Wie würde die Alternative mit dem READ im Binärmodus aussehen?

Wäre evtl. BigText eine Möglichkeit das Problem zu lösen?

Wie mich diese Flatfiles ärgern! :evil:

Re: Schnittstellenstrategie

10. Februar 2016 13:09

Also, wenn ich mir das so anschaue, würde ich dir raten, das ganze in NAV 4 mit einem Dataport zu lösen. :wink:

Den Dataport später auf NAV 2013+ in einen Report zu konvertieren ist kein Hexenwerk, erfordert etwa 100 bis 150 Zeilen Code, den man größtenteils für andere Dataports recyceln kann, und es funktioniert dann auch noch wie im CC gewohnt mit der Abfrage des Dateinamens in der Requestpage.

Der große Vorteil der späteren NAV- Versionen ist der Umgang mit max. 2GB großen Textvariablen, die dort keine Probleme bereiten, und Problemlos aufgeteilt werden können.

READTEXT ignoriert so viel ich weiß auch in NAV4 keine Sonderzeichen (außer CRLF vielleicht, habe jetzt mit TEXTMODE noch nicht experimentiert). Ebenso wäre ein Versuch mit READ interessant, mit dem man binär in eine Textvariable einlesen kann, auch mit Sonderzeichen.
Was man bei der ganzen Sache allerdings auch berücksichtigen muss, ist das NAV4 in DE intern mit Codepage 450 arbeitet, und die eingelesene Datei evtl. Ansi oder etwas anderes ist, und konvertiert werden muss.

Gruß Fiddi

Re: Schnittstellenstrategie

10. Februar 2016 13:49

fiddi hat geschrieben:[…]NAV4 in DE intern mit Codepage 450 arbeitet

Bislang habe ich immer in Codepage 850 konvertiert :wink: .

Re: Schnittstellenstrategie

10. Februar 2016 13:52

Bislang habe ich immer in Codepage 850 konvertiert


Sorry, du hast natürlich recht :oops:

Gruß Fiddi

Re: Schnittstellenstrategie

10. Februar 2016 14:12

fiddi hat geschrieben:Also, wenn ich mir das so anschaue, würde ich dir raten, das ganze in NAV 4 mit einem Dataport zu lösen. :wink:

Den Dataport später auf NAV 2013+ in einen Report zu konvertieren ist kein Hexenwerk, erfordert etwa 100 bis 150 Zeilen Code, den man größtenteils für andere Dataports recyceln kann, und es funktioniert dann auch noch wie im CC gewohnt mit der Abfrage des Dateinamens in der Requestpage.

Der große Vorteil der späteren NAV- Versionen ist der Umgang mit max. 2GB großen Textvariablen, die dort keine Probleme bereiten, und Problemlos aufgeteilt werden können.

READTEXT ignoriert so viel ich weiß auch in NAV4 keine Sonderzeichen (außer CRLF vielleicht, habe jetzt mit TEXTMODE noch nicht experimentiert). Ebenso wäre ein Versuch mit READ interessant, mit dem man binär in eine Textvariable einlesen kann, auch mit Sonderzeichen.
Was man bei der ganzen Sache allerdings auch berücksichtigen muss, ist das NAV4 in DE intern mit Codepage 450 arbeitet, und die eingelesene Datei evtl. Ansi oder etwas anderes ist, und konvertiert werden muss.



Wie wird das bei Dataport ohne Separatoren gehen?
Die Importfunktion soll nämlich noch von einem NAS gesteuert werden.

Re: Schnittstellenstrategie

10. Februar 2016 14:22

Hallo MSNAVLerner,

da eine Textvariable maximal 1024 Zeichen haben kann, und wenn ich mich nicht irre ein Array auch, fällt bei 3000 Zeichen Satzlänge ein ReadText() des ganzen Satzes aus. Wie wärs mit binary, anfahren der Dateiposition mit pos, byteweise lesen in Textvariable (mache ich im Beispielcode ja auch)? Damit kannst Du jedes Feld einzeln betrachten.
Und wenn Du das von einem NAS auch machen willst... Dataport *sollte* gehen, aber wäre wahrscheinlich nicht meine erste Wahl. Codeunit oder ProcessingOnly-Report.

LG Jens

Re: Schnittstellenstrategie

10. Februar 2016 15:28

jglathe hat geschrieben:Und wenn Du das von einem NAS auch machen willst... Dataport *sollte* gehen,

NAS und Dataport geht grundsätzlich nicht:
You cannot use C/AL variables of type DATAPORT when running the Microsoft Business Solutions-Navision Application Server.

Bleibt Codeunit oder ProcessingOnly-Report :wink: .

Re: Schnittstellenstrategie

10. Februar 2016 15:39

Man lernt nie aus... intuitiv hätte ich Dataport aber auch nicht probiert. :-)

LG Jens

Re: Schnittstellenstrategie

10. Februar 2016 15:40

Wie wird das bei Dataport ohne Separatoren gehen?

Der Dataport kennt das FileFormat "Fixed"

Die Importfunktion soll nämlich noch von einem NAS gesteuert werden.


Was den Dataport wiederum ausschließt :-(

Was benutzt Ihr denn für eine technische NAV- Umgebung?

Gruß Fiddi

Re: Schnittstellenstrategie

10. Februar 2016 16:00

jglathe hat geschrieben:Hallo MSNAVLerner,

da eine Textvariable maximal 1024 Zeichen haben kann, und wenn ich mich nicht irre ein Array auch, fällt bei 3000 Zeichen Satzlänge ein ReadText() des ganzen Satzes aus. Wie wärs mit binary, anfahren der Dateiposition mit pos, byteweise lesen in Textvariable (mache ich im Beispielcode ja auch)? Damit kannst Du jedes Feld einzeln betrachten.
Und wenn Du das von einem NAS auch machen willst... Dataport *sollte* gehen, aber wäre wahrscheinlich nicht meine erste Wahl. Codeunit oder ProcessingOnly-Report.



Ich bin bei deinem Code einfach noch nicht ganz durchgestiegen. Wie würde beispielsweise die READ in Binärversion aussehen bei folgendem Beispiel?

Bezeichnung: Quelle
Länge: 10

Bezeichnung: Ziel
Länge: 10

Bezeichnung: Anlegezeit
Länge: 15

Bezeichnung: Auftragsnr.
Länge: 11

Bezeichnung: Auftragsposnr.
Länge: 3

Code:
ERP       EXTERN    YYYYMMDDHHMMSS A123456789
ERP       EXTERN    YYYYMMDDHHMMSS A123456789 15

Re: Schnittstellenstrategie

10. Februar 2016 16:01

fiddi hat geschrieben:
Wie wird das bei Dataport ohne Separatoren gehen?

Der Dataport kennt das FileFormat "Fixed"

Die Importfunktion soll nämlich noch von einem NAS gesteuert werden.


Was den Dataport wiederum ausschließt :-(

Was benutzt Ihr denn für eine technische NAV- Umgebung?

Gruß Fiddi


Unseres leider nicht. V 4.00 SP2
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Re: Schnittstellenstrategie

10. Februar 2016 16:04

Unseres leider nicht. V 4.00 SP2


Ich meinte die Dataport- Properties, nicht die des Records :wink:
(Properties des letzten leeren Zeile unter den Records)

Gruß Fiddi

Re: Schnittstellenstrategie

10. Februar 2016 16:15

fiddi hat geschrieben:
Unseres leider nicht. V 4.00 SP2

Ich meinte die Dataport- Properties, nicht die des Records :wink:
(Properties des letzten leeren Zeile unter den Records)


Tatsächlich. Habe damit noch nicht gearbeitet. Gibt es im Forum hierzu weitere Infos?
Auch wenn das aufgrund des NAS in diesem Fall nicht möglich ist, würde ich mir das doch näher anschauen.

Re: Schnittstellenstrategie

10. Februar 2016 16:42

Hallo,

zu "Fixed" gibt es nicht viel zu sagen. Du gibst dann bei den Dataport- Feldern die Startposition und Länge ein, der Rest läuft wie bei "Variabel".

wie groß ist denn das größte Feld in dem Datensatz?

Gruß Fiddi

Re: Schnittstellenstrategie

10. Februar 2016 16:47

Hallo MSNAVLerner,

MSNAVLerner hat geschrieben:
Ich bin bei deinem Code einfach noch nicht ganz durchgestiegen. Wie würde beispielsweise die READ in Binärversion aussehen bei folgendem Beispiel?

Bezeichnung: Quelle
Länge: 10

Bezeichnung: Ziel
Länge: 10

Bezeichnung: Anlegezeit
Länge: 15

Bezeichnung: Auftragsnr.
Länge: 11

Bezeichnung: Auftragsposnr.
Länge: 3

Code:
ERP       EXTERN    YYYYMMDDHHMMSS A123456789
ERP       EXTERN    YYYYMMDDHHMMSS A123456789 15


In Pseudocode:

MyFile.open(MyFileName);
MyFile.textmode(false);
//Schleife
//erstes Feld ansteuern - nehmen wir YYYYMMDDHHHMMSS, also Offset 20
RecordOffset := MyFile.pos;
MyFile.seek(RecordOffset + 20);
for i := 1 to 15 do
MyFile.read(MyDTString[i]);
//nächstes Feld ansteuern - nehmen wir die 15, also Offset 47
MyFile.seek(RecordOffset + 47);
for i := 1 to 2 do
MyOtherField.read(MyOtherField[i]);
// und so weiter
// zum Schluss CR/LF suchen (bei variabler möglicher länge) oder RecordOffset um Recordlänge plus CR/LF erhöhen
RecordOffset := RecordOffset + 3002;
//Ende Schleife

Die Feldlesefunktion würde ich kapseln, und innerhalb dieser jede Dateioperation mit if not MyFile.EOF() absichern.

LG Jens