Daten per Dataport einlesen und VALIDATE ausführen

2. Februar 2007 16:49

Hi zusammen,

ich bin gerade fast am verzweifeln weil ich eigentlich - aus meiner Sicht - etwas ganz einfaches machen möchte.

Ich habe eine Textdatei die neue Artikel enthält. Die Textdatei sieht so aus:
Code:
Neuer Artikel 1
Neuer Artikel 2
Neuer Artikel 3


Dann habe ich einen kleinen Dataport. Als DataItem habe ich "Item" gewählt mit dem dazugehörigen Dataport Field "Description".

Wenn ich nun den Dataport starte und die Textdatei importiere wird selbstverständlich nur ein Artikel (Neuer Artikel 3) erstellt, da ja der Primärschlüssel fehlt. Das Feld "No." bleibt leer. Ich möchte nun vor dem Import ein VALIDATE("No.") ausführen, damit eine neue Nr. vergeben wird. Ich habe schon alles ausprobiert - nichts funktioniert.

Hat jemand eine Idee? Vielen Dank!

Gruß, Marc

2. Februar 2007 17:10

Hi Marc!

Um eine neue Artikelnummer zu erhalten, bietet es sich vielleicht an die "Mimik" des OnInsert Triggers der Artikeltabelle zu verfolgen:

Code:
OnInsert()
IF "No." = '' THEN BEGIN
  GetInvtSetup;
  InvtSetup.TESTFIELD("Item Nos.");
  NoSeriesMgt.InitSeries(InvtSetup."Item Nos.",xRec."No. Series",0D,"No.","No. Series");
END;


Mein Vorschlag ist also, entweder diesen Code in den Dataport zu übernehmen, oder wie folgt vorzugehen:

Code:
Item - OnBeforeImport
INIT;


Code:
Item - OnAfterImport;
"No." := '';
INSERT(TRUE);


Also kein autom. Insert ... vielleicht klappt's ... ?!

2. Februar 2007 17:18

z.B. im OnAfterImportRecord-Trigger diesen Code einfügen:

Code:
InventorySetup.GET;
InventorySetup.TESTFIELD("Item Nos.");
Item2.INIT;
Item2.VALIDATE("No.",NoSeriesManagement.GetNextNo(InventorySetup."Item Nos.",WORKDATE,TRUE));
Item2.VALIDATE(Description,Description);
Item2.INSERT(TRUE);

2. Februar 2007 17:47

@Jörg: Danke, das hat funktioniert. Ich hatte das auch mal ausprobiert hatte aber ein INIT und das TRUE bei INSERT(TRUE) vergessen. Klasse. Danke noch mal.

@Kowa: Auch dir danke für deine Lösung. Da die von Jörg jedoch kürzer ist, werde ich bei der bleiben. ;-)

Gruß und danke!
Marc

2. Februar 2007 18:49

Marc Teuber hat geschrieben:
@Kowa: Auch dir danke für deine Lösung. Da die von Jörg jedoch kürzer ist, werde ich bei der bleiben. ;-)

Eine kürzere Variante hätte ich auch noch anzubieten :wink: . Die längere hat nur den Vorteil , dass man beim Debuggen am Anfang und nicht erst am Ende die neue Nr. sieht. Wenn man sehr viele Felder importiert ist dies manchmal angenehmer zu verfolgen. Wenn in Fieldvalidates mit der neuen Nr. gearbeitet werden soll, geht es ohnehin nicht anders ( für Artikeleinheitentabelle beim Validieren des Basiseinheitencodes Datensätze generieren etc.)
Code:
Item2.INIT;
Item2."No." := '';
Item2.VALIDATE(Description,Description);
Item2.INSERT(TRUE);
Zuletzt geändert von Kowa am 16. März 2007 18:10, insgesamt 1-mal geändert.

2. Februar 2007 18:59

Yo, danke für den Hinweis!

8. Juni 2007 10:46

Sorry dass ich den Thread wieder aufgreife, aber ich stehe gerade vor dem selben Problem.
Bei mir soll allerdings immer eine neue Nummer generiert werden, egal ob schon eine vorhanden ist oder nicht.

Wenn ich es mache wie stryk es in seinem 1. Post geschrieben hat, sprich mit Init und Insert (True), dann sagt er mir dass ein DS mit der Nummer '' schon vorhanden ist.

8. Juni 2007 11:00

Wird im OnInit Trigger der entsprechenden Tabelle eine neue Nummer ermittelt?

Gruesse
feri

30. Oktober 2007 12:39

Ich habe ein ähnliches Problem. Ich habe eine CodeUnit die mit Hilfe der ExcelBuffer Tabelle eine Excel Datei in die Contact Tabelle importiert. Da gibt es natürlich eine laufende Nummer. Leider verstehe ich dir hier vorgeschlagenen Ansätze nicht so ganz. Kann mir vielleicht jemand auf die Sprünge helfen?

30. Oktober 2007 13:20

Der Trick ist, immer den OnInsert-Trigger der Zieltabelle zu benutzen - denn dort ist die automatische Nummernserienvergabe standardmäßig implementiert.

Also quasi so:
Code:
// FALSCH
Zieltabelle.INIT;
Zieltabelle."No." := Irgendwas, vielleicht eine Funktion;
Zieltabelle.INSERT;

// RICHTIG
Zieltabelle.INIT;
Zieltabelle."No." := '';
Zieltabelle.INSERT(TRUE); // setzt "No." automatisch
Zuletzt geändert von Natalie am 30. Oktober 2007 14:09, insgesamt 1-mal geändert.

30. Oktober 2007 13:28

Ah danke. Das scheint geholfen zu haben. Zumindest kommt jetzt eine andere Fehlermeldung (die ich aber denke ich, auch schnell lösen werde).

Nachtrag:

Liegt das an der Nummernserienprogrammierung oder an meiner CodeUnit?

Ich habe die Contact Tabelle kopiert und nur mit dem letzten Datensatz aus der Original Tabelle gefüllt. Der hat die Nummer:

K124727

Wenn ich jetzt meine CodeUnit laufen lasse bekomme ich ne Fehlermeldung das die Nummer K124728 (also eine Nummer nach dem obrigen Datensatz) schon exestieren würde.

30. Oktober 2007 14:07

Ohne den Quelltext mitverfolgen zu können, behaupte ich einfach mal, es liegt an der Nummernserienprogrammierung. Gehe in die Nummsernserienverwaltung, wechsle zu der Nummernserie, die mit den Kontakten verknüpft ist (siehe hier zu Marketing & Vertrieb Einrichtung) und setze manuell das Feld "Letzte Nr. verwendet" hoch.

Edit: Das Feld zu finden geht einfacher: Gehe in deiner Kontaktform auf das Feld "Nr." und betätige dort den Assist-Button. Im sich nun öffnenden Fenster ist jetzt schon die richtige Nummernserie und das Feld "Letzte Nr. verwendet" zu sehen.

Edit2: Vielleicht liegt das Problem aber auch darin, dass du - wie ich eben - vergessen hast, vor dem INSERT No. = '' zu setzen (habs jetzt oben korrigiert).

30. Oktober 2007 14:18

Ich habe die Nummer auf K124730 gesetzt. Und nun kommt die gleiche Fehlermeldung nur mit K124731.

Hier mal mein Code aus der CodeUnit:

Code:
ExcelBuffer.OpenBook('D:\\Vermittler_suche.xls','Vermittler_suche');
ExcelBuffer.ReadSheet;

IF ExcelBuffer.FIND('+') THEN
   CountRows := ExcelBuffer."Row No.";

FOR Idx := 1 TO CountRows DO BEGIN
    Contact.INIT;

  IF ExcelBuffer.GET(Idx, 1) THEN
     Contact.Name := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 2) THEN
     Contact.Address := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 3) THEN
     Contact."Post Code" := ExcelBuffer."Cell Value as Text";
     Pos := STRPOS(Contact."Post Code",' ');
     PLZ := COPYSTR(Contact."Post Code",1,Pos-1);
     Contact."Post Code" := PLZ;
  IF ExcelBuffer.GET(Idx, 3) THEN
     Contact.City := ExcelBuffer."Cell Value as Text";
     Pos := STRPOS(Contact.City,' ');
     Ort := COPYSTR(Contact.City,Pos+1);
     Contact.City := Ort;
  IF ExcelBuffer.GET(Idx, 4) THEN
     Contact."Phone No." := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 5) THEN
     Contact."Vermittler Nr." := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 6) THEN
     Contact."Fax No." := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 7) THEN
     Contact."E-Mail" := ExcelBuffer."Cell Value as Text";

  Contact.INSERT(TRUE);
END;


Nachtrag:

Grad dein Edit gelesen. Ich probiers mal mit dem "No." := '';

30. Oktober 2007 14:40

Wie ich eben sagte: Es fehlt Contact."No." := ''; direkt nach dem INIT.
Außerdem fehlen bei dir wichtige BEGIN und ENDs...!

Hier nochmal alles:
Code:
ExcelBuffer.OpenBook('D:\\Vermittler_suche.xls','Vermittler_suche');
ExcelBuffer.ReadSheet;

IF ExcelBuffer.FIND('+') THEN
   CountRows := ExcelBuffer."Row No.";

FOR Idx := 1 TO CountRows DO BEGIN
    Contact.INIT;
    Contact."No." := '';

  IF ExcelBuffer.GET(Idx, 1) THEN
     Contact.Name := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 2) THEN
     Contact.Address := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 3) THEN BEGIN
     Contact."Post Code" := ExcelBuffer."Cell Value as Text";
     Pos := STRPOS(Contact."Post Code",' ');
     PLZ := COPYSTR(Contact."Post Code",1,Pos-1);
     Contact."Post Code" := PLZ;
  END;
  IF ExcelBuffer.GET(Idx, 3) THEN BEGIN
     Contact.City := ExcelBuffer."Cell Value as Text";
     Pos := STRPOS(Contact.City,' ');
     Ort := COPYSTR(Contact.City,Pos+1);
     Contact.City := Ort;
  END;
  IF ExcelBuffer.GET(Idx, 4) THEN
     Contact."Phone No." := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 5) THEN
     Contact."Vermittler Nr." := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 6) THEN
     Contact."Fax No." := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 7) THEN
     Contact."E-Mail" := ExcelBuffer."Cell Value as Text";

  Contact.INSERT(TRUE);
END;


EDIT: Wieso prüfst du zweimal hintereinander
Code:
IF ExcelBuffer.GET(Idx, 3) THEN
ab?

30. Oktober 2007 14:52

Die BEGIN und ENDs sind mir auch shcon aufgefallen und sind schon eingefügt.
Ich prüfe das zweimal weil das ein Feld ist wo 2 Werte drinn stehen die eigentlich getrennt gehören. Aber wenn ich so drüber nachdenke, könnte ich das auch nur einmal aufrufen und den Code zusammen führen. Werd ich nachher mal testen.

Nachtrag:

Funktioniert jetzt alles. Auch die automatische Vergabe der Nummernserie.

Code:
ExcelBuffer.OpenBook('D:\\Vermittler_suche.xls',Vermittler_suche');
ExcelBuffer.ReadSheet;

IF ExcelBuffer.FIND('+') THEN
   CountRows := ExcelBuffer."Row No.";

FOR Idx := 1 TO CountRows DO BEGIN
    Contact.INIT;
   
  IF ExcelBuffer.GET(Idx, 1) THEN
     Contact.Name := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 2) THEN
     Contact.Address := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 3) THEN BEGIN
     CLEAR(PostCodeCity);
     PostCodeCity := ExcelBuffer."Cell Value as Text";
     CLEAR(PLZ);
     PLZ := COPYSTR(PostCodeCity,1,5);
     Contact."Post Code" := PLZ;
     CLEAR(Ort);
     PreOrt := COPYSTR(PostCodeCity,6);
     Ort := DELCHR(PreOrt,'<',' ');
     Contact.City := Ort;
  END;
  IF ExcelBuffer.GET(Idx, 4) THEN
     Contact."Phone No." := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 5) THEN
     Contact."Vermittler Nr." := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 6) THEN
     Contact."Fax No." := ExcelBuffer."Cell Value as Text";
  IF ExcelBuffer.GET(Idx, 7) THEN
     Contact."E-Mail" := ExcelBuffer."Cell Value as Text";

  Contact."No." := '';
  Contact.INSERT(TRUE);
END;
MESSAGE('Import erfolgreich');

[Gelöst]Re: Daten per Dataport einlesen und VALIDATE ausführ

29. Juli 2009 10:56

Hallo!

Ich habe auch ein Problem mit Validate und Dataport.

In meinem Dataport habe ich die Zeile
Code:
"Gen. Journal Line".VALIDATE( "Shortcut Dimension 1 Code", vKost );


Wenn ich eine Testbuchung durchführe, bekomme ich die Warnung, dass ein Dimensionswertcode für den Dimensionscode KOSTENSTELLE ausgewählt werden muss. Wenn ich im Buchungsblatt auf die importierte Kostenstelle manuell ein Validate ausführe ist die Warnung verschwunden.

Was kann ich tun?

Gruß
Matt Kirby
Zuletzt geändert von Matt Kirby am 29. Juli 2009 16:33, insgesamt 1-mal geändert.

Re: Daten per Dataport einlesen und VALIDATE ausführen

29. Juli 2009 10:58

Mir scheint, als wäre deine Variable vKost leer - hast du das mal gedebuggt?

Re: Daten per Dataport einlesen und VALIDATE ausführen

29. Juli 2009 11:22

Matt Kirby hat geschrieben:Wenn ich eine Testbuchung durchführe, bekomme ich die Warnung, dass ein Dimensionswertcode für den Dimensionscode KOSTENSTELLE ausgewählt werden muss. Wenn ich im Buchungsblatt auf die importierte Kostenstelle manuell ein Validate ausführe ist die Warnung verschwunden.

Was kann ich tun?

Klappt das:
Erst Insert(true), damit der dortige Aufruf "DimMgt.InsertJnlLineDim" durchlaufen wird, danach das validate auf das Feld?

Re: Daten per Dataport einlesen und VALIDATE ausführen

29. Juli 2009 11:22

Ja debuggt habe ich schon. Die Variable ist mit der Kostenstelle gefüllt. Steht auch im Buchungsblatt nach dem Import. Ich bekomme aber trotzdem die Warnung. Wenn ich im Buchungsblatt manuell die Kostenstelle validiere, bleibt die Warnung weg.

Re: Daten per Dataport einlesen und VALIDATE ausführen

29. Juli 2009 11:24

Dann halte dich an den Vorschlag von McClane.
Wenn er recht hat, dann wundert mich allerdings, dass du beim Validieren keine Fehlermeldung bekommen hast ...

Aber nach deinem Import wird der Datensatz an sich wirklich ins Buchungsblatt geschrieben (nur halt ohne Dimension), richtig?

Re: Daten per Dataport einlesen und VALIDATE ausführen

29. Juli 2009 11:27

bei den Buchblättern kommt es teilweise auf die Reihenfolge der Validates an. Deshalb mit dem Dataport genauso die Felder füllen, wie von Hand.

Gruß, Fiddi

Re: Daten per Dataport einlesen und VALIDATE ausführen

29. Juli 2009 11:42

Mein Traum vom Himmel ist, dass es da ein Navision ohne diese blöden Dimensionen gibt :roll:

Re: Daten per Dataport einlesen und VALIDATE ausführen

29. Juli 2009 11:52

Nun, nach dem Import steht auch die Kostenstelle im Buchungsblatt. Ich kann sie sehen. Aber in der Testbuchung kommt die Warnung wg. fehlenden Dimensionswert. Validiere ich Buchungsblatt nochmal manuell, erscheint die Warnung für den Buchungssatz nicht mehr.

Mit
Code:
INSERT(TRUE)


hab ichs gerade probiert. Bringt keinen Effekt :-(

Auf die Reihenfolge habe ich auch geachtet. Sollte passen.

Re: Daten per Dataport einlesen und VALIDATE ausführen

29. Juli 2009 12:00

Liest dein Dataport direkt in die Buchblatfelder ein, oder benutzt du dort eigene Felder und füllst das Buchblatt nachher?
Falls ersteres wird u.U. schon ein Validate beim Einlesen ausgeführt.
Manchmal liegt es auch an der Reihenfolge:
  • Leeren Datensatz mit Primärschlüssel initialisieren.
  • Insert(True);
  • restliche Felder in der korrekten Reihenfolge mit Validate füllen.
  • modify(true);

Das ist genau das Verfahren, wie es auch ein Form durchführt. Das Problem dürfte sein, dass die Dimensionswerte nicht eingefügt werden können, weil der Datensatz in der Referenztabelle (hier Buchblatt) noch nicht existiert.

Gruß, Fiddi

Re: Daten per Dataport einlesen und VALIDATE ausführen

29. Juli 2009 12:06

fiddi hat geschrieben:Das ist genau das Verfahren, wie es auch ein Form durchführt. Das Problem dürfte sein, dass die Dimensionswerte nicht eingefügt werden können, weil der Datensatz in der Referenztabelle (hier Buchblatt) noch nicht existiert.

Sicher? Ich meine, das Fibububl komplett füllen zu können, und der Insert erst danach (beim Verlassen der Zeile) erfolgt.