[gelöst] NAV Import

21. Oktober 2009 11:56

Hallo,

ich habe nun schon nen schicken Import über den Dataport aber irgendwie gefällt mir das noch nicht so richtig. Hab Probleme mit dem Zeichensatz und es sind auch irgendwie zu viele Schritte nötig. Derzeit importiere ich die Daten in eigens dafür angelegte Tabellen in NAV und versuche sie dann in die entsprechnenden Tabellen zu schieben. Das klappt auch alles super wenn ich den zwischenschritt über nen Dataport mache, das heißt ich schieb die Daten in die Tabelle (kann aber keine Trigger ausführen) und exportiere und importiere über nen Dataport. Ist nen unnötiger schritt.

Ich habe mal irgendwo was zum Import über NAV Tabellen gelesen aber ich find es einfach nicht wieder. Hat jemand von euch nen Tipp wie ich das hinbekomme, ich zieh die Daten derzeit per C/FRONT oder SQL direkt in die DB und müsste irgendwie nen Script durchlaufen lassen welches jeden Record in der Tabelle öffnet und nen C/AL drüber laufen lässt. Wie kann ich das denn machen? Hab es probiert wenn ich über NAV den Record änder oder einfüge dann könnte ich das über die Trigger machen und das geht auch aber ich hau ja mit einem Schwung nen haufen Datensätze rein.

Bin für jeden Tipp dankbar.

Gruß
René
Zuletzt geändert von kockiren am 27. Oktober 2009 15:04, insgesamt 1-mal geändert.

Re: NAV Import

21. Oktober 2009 12:00

Hallo kockiren,

zunächst zwei Fragen:
Wo kommen die Daten her?
Wo sollen die Daten in NAV hin (Tabellen)?

Gruß, Fiddi

Re: NAV Import

21. Oktober 2009 12:16

Hallo Fiddi,

also die Daten kommen von unserer Webseite über eine Schnittstelle, wir rufen die Daten ab, bereiten sie auf (in teile zerlegen, konvertieren, prüfen usw) und dann pack ich sie in eine eigen erstellte Tabelle in NAV. Aus diesen Daten sollen Customer, Vendor, Items, Salesheader, salesline, purchaseheader, purchaseline werden.

Die Aufteilung der Daten würde ich gern über C/AL machen, ich habe eine Tabelle intern_customer, intern_items, intern_invoices und daraus möchte ich nach bestimmten Kriterien die NAV Tabellen füllen. Die Daten aus einem CSV File zu lesen geht schon gut aber ich möchte das gern über die Tabellen pflegen, das ist irgendwie eleganter und lässt sich besser automatisieren. Ich brauch quasi nur noch eine Stelle wo ich meinen C/AL Code reinschmeißen kann und er durch ne Schleife für jeden Record meiner Tabellen durchlaufen wird.

Geht das irgendwie?

Gruß
René

Re: NAV Import

21. Oktober 2009 13:48

kockiren hat geschrieben:...Ich brauch quasi nur noch eine Stelle wo ich meinen C/AL Code reinschmeißen kann und er durch ne Schleife für jeden Record meiner Tabellen durchlaufen wird.


Sind die Daten schon drin oder nicht? (Du schreibst etwas von C/FRONT bzw.SQL)
Ok, ich gehe mal davon aus, das du die Daten schon in den Puffertabellen drin hast.

Variante 1.
Eine Variante die Daten zu Verarbeiten wäre mit einer Form, auf dieser das Propertie TimerIntervall setzten, z.B. 1000 (=1 Sekunde).
Auf dem Trigger OnTimer die Funktionsarufe plazieren. Du könntest auch den gesammten Code hier plazieren, das wird i.d.R aber unübersichtlich.

Variante 2.
Alternativ, könntest du einen NAS einsetzten. Dieser würde halt die weitere Verarbeitung starten.

Zwecks zeitgesteuerter Ausführung, schau mal hier: Message für bestimmten User
Oder suche nach OnTimer

Variante 3.
Du kannst auch den Dataport modifizieren, das nach dem Importieren die Daten weiter verarbeitet werden, z.B. auf dem Trigger OnPostDataItem oder OnPostDataport

Ist etwas schwer zu sagen, da die Angaben für mich recht "dünn" sind :wink:

Re: NAV Import

21. Oktober 2009 21:01

Hallo und guten Abend :-)

also die Daten sind bereits in der Puffertabelle das klappt ohne Probleme und ich habe mir auch schon ein onChange und onInsert event in die C/ALs geschrieben, die funktionieren auch schon. Aber ich müsste jetzt denke ich ne CodeUnit schreiben die alle Records der Puffertabelle durchläuft und dann die onInsert oder onModify methoden ausführt.

Weiß nur nicht wie ich das angehe, hm aber ich guck mir mal die Links von Mikka an.

Gruß
René

Re: NAV Import

22. Oktober 2009 08:22

Guten Morgen,

also am einfachsten erscheint mir das mit dem Form, vielleicht kann man ja einfach irgendwann mal das Form weglassen. Ich probier das einfach mal aus.

Nur nochmal zum Verständnis wenn ich das mit dem Form und dem Timer löse wird jedes Element der Tabelle durch das Form aufgerufen und im Trigger OnTimmer des Forms schreibe ich meine Funktionen rein? Was passiert denn wenn die abarbeitung der Funktion länger dauert als mein Timer bricht der dann meine Funktion ab oder wartet er bis diese ausgeführt wurde und startet dann den Timer?

VG
René

Re: NAV Import

22. Oktober 2009 09:11

Hallo René,

also ich würde den Weg über den NAS und eine Codeunit gehen, das kann man dann automatisch ohne laufenden NAV-Client machen, da der NAS als Dienst im Hintergrund läuft.
Wenn du es geschickt anstellst, kannst du den NAS auch direkt mit deinen Daten aus dem WEB- Shop füttern. (existierende Schnittstellen zu WEB- Shops wie z.B. xtCommerce oder Magento mach das auf diesem Wege).

Gruß, Fiddi

Re: NAV Import

22. Oktober 2009 09:33

Hallo Fiddi,

also der NAS ist der Navision Application Server? Ich habe im ADG nur einmal NAS gefunden, mir ist nicht ganz klar wie ich diesen NAS dazu verwenden kann die Daten aus meiner API in die Tabelle zu schieben und von da aus in meine entsprechenden Customer, Vendor ... usw Tabellen zu schieben.

Kann man den den NAS dazu verwenden bestimmte Programmabläufe in NAvision zu starten, also setzt NAS quasi an der stelle an an der das C/FRONT endet?

VG
René

Re: NAV Import

22. Oktober 2009 09:43

Der NAS ist der NAV- Application- Server. Er kann im Prinzip alles, was ein normaler NAV- Client auch kann, nur das er keine GUI hat und deshalb nichts mit Forms, Dataports und Reports mit Requestform anfangen kann. Der NAS kann z.B. über die Socketschnittstelle Daten aus dem Internet empfangen, in einer Codeunit aufbereiten und verarbeiten.

Gruß, Fiddi

Re: NAV Import

22. Oktober 2009 12:05

kockiren hat geschrieben:... mir ist nicht ganz klar wie ich diesen NAS dazu verwenden kann die Daten aus meiner API in die Tabelle zu schieben und von da aus in meine entsprechenden Customer, Vendor ... usw Tabellen zu schieben.

Kann man den den NAS dazu verwenden bestimmte Programmabläufe in NAvision zu starten, also setzt NAS quasi an der stelle an an der das C/FRONT endet?

Hallo René,
So wie ich deine Postings interpretiere, stehst du noch etwas auf dem Schlauch?!
-->Na, dann wollen wir dir mal vom "Schlauch" runter helfen :-)

Wie den NAS verwenden? --> Er würde genauso wie die TimerForm in intervallen eine CodeUntit aufrufen, die die Verarbeitung der Daten vornimmt.
Ungefähr so (das ganze als Schleife, die Zeile für Zeile einliest):
- Datensatz aus der Puffertabelle aufrufen
- ggf. Vorverarbeiten
- und in der(n) Zieltabelle(n) einfügen
- ggf. in der Puffertabelle den Datensatz als "verarbeitet" markieren (dann oben beim Aufrufen nur die "nicht verarbeiteten" aufrufen) oder löschen

Ich denke du solltest dein Projekt in kleinere Abschnitte einteilen.
(Sonst siehst du vor lauter Wald die Bäume nicht mehr)
z.B.:
1. Wie soll die Datenverarbeitung angestossen werden (z.B. NAS, oder Form mit OnTimer - Trigger)
(hier währe dann ersteinmal die Einarbeitung und Erstellung der NAS funktionalität notwendigt bzw. erstellen einer Form)
2. Erstellung der Funktionen, die die eigentliche Verarbeitung vornhemen sollen (wie oben beschrieben)

Re: NAV Import

22. Oktober 2009 12:46

Hallo Mikka,

ja das mit den kleinen Teilen gefällt mir ganz gut :-) Ich denke ich werd es folgendermaßen angehen. Ich schreibe mir die onTimer auf ein Form und lass es durchlaufen so habe ich nen Überblick darüber was gerade abläuft und kann dann die Funktionen Stück für Stück aufbauen. Wenn ich das durch hab und die Funktion gewährleistet ist kann ich mich in den NAS einarbeiten und versuchen die Funktionalität darüber zu bauen, dann kann ich mir meine C/FRONT Krücke auch sparen :-)

Aber erstmal zu dem ersten Teil, ich habe eine Puffertabelle customerImported, dort sind alle meine Customer drin. Nun geh ich unter C/AL auf den onTimer Trigger und tipp dort meine Funtkion rein
Code:
CUSTOMER.INIT;
CUSTOMER.VALIDATE("No:",PUFFERTABELLE."No.");
...
CUSTOMER.INSERT;

Dann sollte doch bei jedem Aufruf durch onTimer der jeweilige Record der Puffertabelle in die Customer Table geschrieben werden? Ich habe auch schon ein Form gebaut welches die Records der Puffertabelle anzeigt. Wie kann ich den jetzt den OnTimer setzen das er alle Records der Puffertabelle über das Form durchläuft?

Gruß
René

Re: NAV Import

22. Oktober 2009 13:09

Nichts leichter als das :-)
(Aber C/FRONT als "Krücke" zu bezeichen ist nicht ganz richtig. Wenn ich das recht weiß, ist es deutlich schneller als ein Dataport (und erst recht gegenüber ODBC)!)

Zunächst, lege dir in der Form eine neue Function an z.B.:CustomerImport, den Aufruf würde dann so aussehen:
(Das hat den Vorteil, wenn das "Ding" wächst, dass du den Überblick behälst, wann was gemacht wird.)
Code:
// Trigger - OnTimer
CustomerImport;


Deine Puffertabelle nenne ich mal CustTmpRec, ist leichter zu schreiben und verstehen :-)
Code:
// Funktion - CustomerImport
CustTmpRec.SETRANGE(CustTmpRec.Verarbeitet,FALSE);  // Nur wenn die DS als Verarbeitet markiert werden!
IF NOT CustTmpRec.ISEMPTY THEN BEGIN  // Also nur ausführen, wann auch Datensätze da sind!
  IF CustTmpRec.FINDSET(TRUE); THEN BEGIN        // Zugfriff auf die Tmp-Daten
    REPEAT                                                 // Start der Schleife
      IF NOT Customer.GET(CustTmpRec."No.") THEN BEGIN  // Nur ausführen, wenn es die Nr. noch nicht gibt
        CUSTOMER.INIT;
        CUSTOMER.VALIDATE("No:",CustTmpRec."No.");
        // ...
        // Die Buchungsgruppen, Zahlungsbedinung, usw. nicht vergessen     
        IF CUSTOMER.INSERT THEN BEGIN
          CustTmpRec.Verarbeitet := TRUE;  // Nur wenn die DS als Verarbeitet markiert werden!   
          CustTmpRec.MODIFY;
        END;
      END;
    UNTIL CustTmpRec.NEXT = 0;                 // Ende der Schleife (0 = kein DS gefunden)
  END;
END;

// Dieses nur wenn statt Kennzeichnung der DS diese gelöscht werden sollen
// CustTmpRec.DELETEALL;


**Edit by Mikka**
So, nun bist du vorerst auf dich gestellt, ich muß noch ein wenig arbeiten :wink:

Re: NAV Import

22. Oktober 2009 13:35

Ganz wichtiger Hinweis zu C/Front:

C/Front führt keine Trigger in der Datenbank aus, d.h. wenn du die Daten mit C/front in die NAV-DB einfügst, dann nur über die Zwischentabelle, wie du das schon richtig gemacht hast.
Ein Dataport oder jede andere Methode, die dazu führt, das C/AL- Code ausgeführt werden kann, führt die DB- Trigger aus (wenn man sie den aufruft mit VALIDATE,INSERT(TRUE),MODIFY(TRUE))).

Das ist auch ein Grund warum ein Dataport langsamer ist.

Als die Lösung mit der Form halte ich immer noch für eine ganz schlechte :wink: .
Wenn du deine Puffertabelle weiter benutzen willst, würde ich das ganze mit einem Report und der Projektwarteschlange (Job- Queue) machen. Das funktioniert auch ohne laufenden NAV-Arbeitsplatz über den NAS.

Bei den großen Tabellen in NAV (alle Stammdaten, Verkaufsbelege,..) würde ich INSERT/MODIFY immer mit TRUE aufrufen, da die OnInsert/OnModify- Trigger in diesen Tabellen noch sehr viel Nachbearbeitung an den Datensätzen durchführen.

Gruß, Fiddi

Re: NAV Import

23. Oktober 2009 02:01

Also erstmal vielen Dank für eure Infos,

das mit den Forms klappt ganz gut, zumindest bei der Customer Tabelle, nun wollt ich das ganze für die SalesHeader basteln und schlage mich seit stunden mit einer Fehlermeldung rum.

Also ich habe eine Tabelle TmpRec mit folgenden Werten:
invoiceId;customerId;year;month usw

Ich habe dann ein Form angelegt welche alle werte der Tabelle anzeigt, hab den timer auf 1000 gesetzt und 3 Variablen erzeugt: TmpRec;customer;salesHeader alle als typ Record auf die entsprechenden Tabellen.

Dann habe ich im onTimer folgenden C/AL Code eingebaut:
Code:
IF NOT tmpRec.ISEMPTY THEN BEGIN
  IF tmpRec.FINDSET(TRUE) THEN BEGIN
    REPEAT
      IF NOT SalesHeader.GET(tmpRec.InvoiceId) THEN BEGIN
        IF Customer.GET(tmpRec.CustomerId) THEN BEGIN   
          SalesHeader.INIT;
          SalesHeader."Document Type" := SalesHeader."Document Type"::Invoice;
          SalesHeader.VALIDATE("No.", tmpRec.InvoiceId);
          SalesHeader.VALIDATE("Order Date", TODAY);
          SalesHeader.VALIDATE("Posting Date", TODAY);
          SalesHeader.VALIDATE("Sell-to Customer No.", tmpRec.CustomerId);
          SalesHeader.INSERT;
          IF Customer.INSERT THEN BEGIN
            tmpRec.Verarbeitet := TRUE;
            tmpRec.MODIFY;
          END;
        END;
      END;
    UNTIL tmpRec.NEXT = 0;
  END;
END;


Den Code habe ich einem Dataport verwendet und da funzt er auch, hier bekomm ich nun aber an der Stelle wo ich die prüfe ob es diesen SalesHeader gibt eine Fehlermeldung: Eine Typkonvertierung des Ausdrucks Code in einen Optionwert ist nicht möglich.Ich habe auch schon als typ text Probiert aber da kommt das die Konvertierung von Text nach Code nicht geht???
Ich raff hier gar nix mehr. Also die SalesHEader hat doch als typ bei No. code (20) stehen also sollte das doch klappen? Hängt das mit den Nummernserien zusammen? Also müsste ich erst eine Nummernserie erzeugen die einen Code hat den ich dan einfüge? Ich brauch doch aber genau diese Nummer als Rechnungsnummer.

Hat irgendwer noch nen Tipp für mich?

Gruß
René

Re: NAV Import

23. Oktober 2009 02:10

Das merkwürdige an der ganzen Sache ist wenn ich in meiner tmpRec einen Datensatz einfüge den es in der SalesHEader nicht gibt und ich die Prüfung nicht einbaue IF NOT salesHeader.GET(tmpRec."invoiceId") THEN BEGIN dann fügt er den Rechnungskopf ein also versteh ich das erst recht nicht mit dieser Typkonvertierung :-(

Hat jemand nen Tipp was ich falsch mache?

Gruß
René

Re: NAV Import

23. Oktober 2009 08:21

Hallo Kockiren,

der SalesHeader hat zwei Primärschlüsselfelder "Document Type" (das ist das OptionsFeld) und "Document No." als zweites Feld.

einige Anmerkungen:
1. Was Soll der Customer.Insert, du änderst doch den Record gar nicht?
2. Solltest du Customer tatsächlich ändern, musst du das machen und Einfügern, bevor du den SalesHeader anlegst, sonst findet der den Kunden nicht.
3. Bei den Inserts und Modifys solltest du dringend :!: :!: den Parameter TRUE angeben, sonst fehlt dir die Hälfte der Daten.

Gruß, Fiddi

Re: NAV Import

23. Oktober 2009 08:35

fiddi hat geschrieben:..Als die Lösung mit der Form halte ich immer noch für eine ganz schlechte :wink: .


Das stimmt wohl, aber ich vermute, das "kockiren" schon so vor einer kleinen Herausforderung steht. Denn NAS zusätzlich auch noch integrieren ist vermutlich ein wenig viel für den Anfang?!


@kockiren
Dein GET kann nicht klappen, da der Prim.Key. im SalesHeader aus zwei Feldern besteht, aus
- Belegart (Datentyp= Option)
- Nr. (Datentyp = Code20)

Siehe hierzu Natalies Beitrag: Records: GET SETFILTER FIND etc.

**Edit by Mikka**
Oh, ich war mal wieder zu langsam :roll:

Re: NAV Import

27. Oktober 2009 15:03

Hallo,

also ich hab mich in die Anleitung von Natalie eingelesen und kann nun auch Tabellen mit 2 Prim Keys abfragen :-) Es ist echt toll wenn sich langsam der Schleier löst. Jetzt bau ich noch nen bisschen an den Imports rum und wenn die richtig funktionieren dann kann ich mich auch mal an den NAS machen, aber dazu dann später mehr :-)

Nochmals vielen lieben Dank für eure Mühe.

VG
René