[Gelöst] Noch ne Frage zum Excel Import

7. März 2006 14:45

Hallo zusammen

ich habe mal wieder eine Frage zum Excel Import. Mein vorheriges Problem wurde dank eurer Hilfe schnell mit einem Dataport gelöst. Nun habe ich ein etwas komplexeres Import Problem:

Wir verwenden die Form 43 - Sales Invoice, deren Soucre Table die Tabelle 36 - Sales Header ist. Außerdem hat sie eine Subform 47 - Sales Invoice Subform, deren Source Tabel die Tabelle 37 - Sales Line ist.

Nun die Frage:

Ich habe eine Excel-Tabelle mit 2 Spalten bekommen (Gliederungsnummern und Beträge).

Jede Gliederung, die in der Excel Tabelle vorkommt und in der Spalte "Betrag" ein Wert stehen hat, soll nun in das Feld "Unit Price" der Tabelle "Sales Line" geschrieben werden.

1. Kann ich das Problem ebenfalls mit einem Dataport lösen?
2. Bei meinem vorherigen Excel Import Problemchen musste für bestimmte GLiederungsnummern der Wert des Feldes auf TRUE gesetzt werden. Der Code im OnAfterImportRecord Trigger lautete:


IF GET (Structure."Structure No.") THEN
BEGIN
Structure."Zugang Webportal" := TRUE;
MODIFY;
END;

Hierbei gab es nur eine Spalte mit Gliederunsnummern in der Excel Tabelle. Immer, wenn eine Gliederungsnummer in der Navisiontabelle gefunden wurde, sollte der Wert des Boolean Feldes "Zugang Webportal" auf TRUE gesetzt werden. Soweit so gut. Nun habe ich aber min. 2 Spalten (Gliederungsnummer und Betrag). Woher weiß Navision jetzt, welche Spalte der Excel Tabelle in welche Feld der Navision Tabelle geschrieben wird?

Grundsätzlich. Gibt es irgendwo Unterlagen zum Thema Excel Import/Export?

Danke für Eure Hilfe!
Zuletzt geändert von mgerhartz am 10. April 2006 13:31, insgesamt 1-mal geändert.

7. März 2006 15:16

Ich versteh nicht so richtig was du hier vorhast. Hast du bereits Daten in der Tabelle SalesLine enthalten zu denen du deine Excel-Tabelle mappen willst? Was für Gliederungsnummern stehen in deinem Excel-File? Rechnungsnummern?

Gruß Jan

7. März 2006 15:37

Ok, ich versuche mich mal besser auszudrücken. Ich habe eine Excel Tabelle mit zwei Spalten. Gliederungsnummern und Beträge. In der Tabelle Sales Line stehen bereits Datensätze. Also u. a. Gliederungsnummern und Beträge.

Ich möchte jetzt also mit einem Dataport die Felder Gliederungsnummer vergleichen. Sobald eine Gliederungsnummer aus der Excel Tabelle in der Tabelle Sales Line gefunden wird, soll das Feld Betrag mit dem Wert aus der Excel Tabelle ersetzt werden.

Die Form "Sales Invoice" hat ja als Source Table die Tabellen Sales Line Header und Sales Line. Also müsste doch nach einem erfolgreichen Import in die Tabellen die Form aktualisiert werden, oder?

7. März 2006 15:49

Ok, jetzt wirds schon ungemein klarer :-).

Also ich persönlich würde das nicht mit einem Dataport sondern einem Report machen, allerdings arbeite ich mit der Version 3.7 und nicht 4.0, weiss also nicht inwieweit es in deiner Version eine standardmäßige Schnittstelle gibt (hat sich in dem anderen Thread irgendwie so angehört).
Grund für den Report wäre dass du ja im Grunde nicht importieren sondern eher aktualisieren willst.

Wenns ein Report werden soll:

Als erstes benötigst du eine Excel-Automation, diese kannst du von Navision aus ansteuern und im Grunde Excel "fernsteuern". Die benötigten Automationen wären folgende:

Name DataType Subtype Length
xlApp Automation 'Microsoft Excel 10.0 Object Library'.Application
xlWorkbook Automation 'Microsoft Excel 10.0 Object Library'.Workbook
xlSheets Automation 'Microsoft Excel 10.0 Object Library'.Sheets
xlWorkSheet Automation 'Microsoft Excel 10.0 Object Library'.Worksheet

Hier noch ein "Stückchen" Code in welchem du siehst wie man das dann verwenden könnte:
Code:
Report - OnPreReport()

Aktualisieren(1,WORKDATE);

Report - OnPostReport()

Report - OnCreateHyperlink(VAR URL : Text[1024])

Report - OnHyperlink(URL : Text[1024])

Aktualisieren("TabNr." : Integer;EndDatum : Date)
IF ISCLEAR(xlApp) THEN
  CREATE(xlApp);
xlApp.Workbooks._Open(FileName,FALSE,FALSE);
xlWorkbook := xlApp.ActiveWorkbook;
xlSheets := xlWorkbook.Worksheets;
xlWorkSheet := xlSheets.Item(1);
xlWorkSheet.Activate;
LineNoArtikelbuchblattZeile:=10000;
i := 2;
REPEAT
      //ArtikelInventurEinlesen;
      PositionenInventurEinlesen;
      i += 1;
      LineNoArtikelbuchblattZeile:=LineNoArtikelbuchblattZeile+10000;
UNTIL ((FORMAT(xlWorkSheet.Range('A'+ FORMAT(i)).Value) =''));
xlWorkbook.Save;
xlWorkbook.Close;
CLEAR(xlApp);

ArtikelInventurEinlesen()
HerstArtNummer:=FORMAT(xlWorkSheet.Range('A'+ FORMAT(i)).Value);
ArtBezeichnung1:=FORMAT(xlWorkSheet.Range('B'+ FORMAT(i)).Value);
ArtBezeichnung2:=FORMAT(xlWorkSheet.Range('C'+ FORMAT(i)).Value)+' '+FORMAT(xlWorkSheet.Range('D'+ FORMAT(i)).Value);
Hersteller:=FORMAT(xlWorkSheet.Range('E'+ FORMAT(i)).Value);


EKPreis:=xlWorkSheet.Range('F'+ FORMAT(i)).Value;
VKPreis:=xlWorkSheet.Range('G'+ FORMAT(i)).Value;


locItem.SETRANGE(locItem."Manufacturer Item No.",HerstArtNummer);
IF locItem.FIND('-') THEN BEGIN
  xlWorkSheet.Range('H'+ FORMAT(i)).Value:=FORMAT(locItem."No.");
  xlWorkSheet.Range('I'+ FORMAT(i)).Value:='JA';
END ELSE BEGIN
  locItem.INIT;
  locItem.INSERT(TRUE);
  locItem."Manufacturer Item No.":=HerstArtNummer;
  locItem.Description:=ArtBezeichnung1;
  locItem."Description 2":=ArtBezeichnung2;
  locItem.VALIDATE(locItem."Manufacturer Code",Hersteller);
  locItem."Unit Cost":=EKPreis;
  locItem."Unit Price":=VKPreis;
  locItem.VALIDATE(locItem."Service Item Group",'KEINEID');
  locItem.VALIDATE(locItem.Garantiecode,'00-00-06');
  locItem.VALIDATE(locItem."Gen. Prod. Posting Group",'ERSATZTEIL');
  locItem.VALIDATE(locItem."Inventory Posting Group",'LAGER');
  locItem.VALIDATE(locItem."Item Category Code",'ERSATZTEIL');
  locItem.VALIDATE(locItem."Requisition Template",'SERVICE');
  locItem.MODIFY;
  locArtikeleinheit.INIT;
  locArtikeleinheit."Item No.":=locItem."No.";
  locArtikeleinheit.Code:='STÜCK';
  locArtikeleinheit.INSERT;
  locArtikeleinheit."Qty. per Unit of Measure":=1;
  locArtikeleinheit.MODIFY;
  locItem."Base Unit of Measure":='STÜCK';
  locItem.MODIFY;
  xlWorkSheet.Range('H'+ FORMAT(i)).Value:=FORMAT(locItem."No.");
  xlWorkSheet.Range('I'+ FORMAT(i)).Value:='NEIN';
END;

PositionenInventurEinlesen()

locArtbuchBlattZeile.INIT;
locArtbuchBlattZeile."Journal Template Name":='ARTIKEL';
locArtbuchBlattZeile."Journal Batch Name":='STANDARD';
locArtbuchBlattZeile."Line No.":=LineNoArtikelbuchblattZeile;
locArtbuchBlattZeile.INSERT;
locArtbuchBlattZeile."Posting Date":=TODAY;
locArtbuchBlattZeile."Entry Type":=2;
locArtbuchBlattZeile."Document No.":='Anfangsbestand';
locArtbuchBlattZeile.VALIDATE(locArtbuchBlattZeile."Item No.",FORMAT(xlWorkSheet.Range('A'+ FORMAT(i)).Value));
locArtbuchBlattZeile.VALIDATE(locArtbuchBlattZeile.Quantity,xlWorkSheet.Range('C'+ FORMAT(i)).Value);
locArtbuchBlattZeile.VALIDATE(locArtbuchBlattZeile."Location Code",FORMAT(xlWorkSheet.Range('D'+ FORMAT(i)).Value));
locArtbuchBlattZeile.MODIFY;
IF locItem.GET(locArtbuchBlattZeile."Item No.") THEN BEGIN
  locArtbuchBlattZeile."Unit Amount":=locItem."Unit Cost";
  locArtbuchBlattZeile."Unit Cost":=locItem."Unit Cost";
  locArtbuchBlattZeile.Amount:=locArtbuchBlattZeile.Quantity*locItem."Unit Cost";
END;
locArtbuchBlattZeile.MODIFY;


Das ist ein Report über welchen wir Inventurdaten in ein Artikelbuchblatt eingelesen haben. In diesem Report wird im "OnPreReport"-Trigger eine Funktion aufgerufen, innerhalb dieser Funktion läuft dann der gesamte Code ab.

Falls noch Fragen offen sind: Fragen :-)

Gruß Jan

7. März 2006 16:03

mgerhartz hat geschrieben:Die Form "Sales Invoice" hat ja als Source Table die Tabellen Sales Line Header und Sales Line.

Forms können nur eine Tabelle als SourceTable besitzen. In deinem Fall somit die Tabelle "Sales Header".

So wie ich das verstanden habe, möchtest du nun die Verkaufsrechnugszeilen aktualisieren. Also die Tabelle "Sales Line".

Du hast zwei Spalten in der Excelliste (Gliederungsnr. und Betrag). Gibt es das Feld "Gliederungsnr." auch in der Tabelle "Sales Line"? Ich kenne das Feld gar nicht.

Gruß, Marc

7. März 2006 16:08

Also so wie ich das verstanden hatte waren die Gliederungsnummern bereits in der Tabelle Sales Line vorhanden, also könnten das ja zum Beispiel Rechnungsnummern sein (??). Da Verkaufszeilen ja nicht ohne einen zugehörigen "Kopfdatensatz" angelegt werden können bin davon ausgegangen dass also alle Rechnungen (oder eine riesige Rechnung) bereits im System sind. Somit würden sich ja dann auch die Forms entsprechend aktualisieren (sofern man dann im entsprechenden Datensatz steht).

Oder mach ich hier gerade einen grandiosen Denkfehler?

7. März 2006 16:12

Hier nochmals der Link zu dem ursprünglichen Beitrag, auf dem dieses Problem aufbaut:
http://mbs-support.info/viewtopic.php?t=1667

7. März 2006 16:20

Um nochmals ein wenig Licht ins Dunkle zu bringen. Ich hatte natürlich was falsches geschrieben. Das Feld in der Tabelle Sales Line heißt "Sell-to Cusomter No."

7. März 2006 16:22

Im Feld "Sell-to Customer No." stehen die Gliederungsnummern.

7. März 2006 16:24

Das heisst du willst in Abhängigkeit vom Kunden bestimmte VK-Preise hinterlegen?
Das würde aber ja nur dann funktionieren wenn bei euch sämtliche Artikel den selben Preis hätten, oder?

Sonst hättest du ja folgendes Problem:
Vor Import:
Kd1 Art1 Preis: 100 €
Kd1 Art2 Preis: 200 €

Nach Import:
Kd1 Art1 Preis: 50 €
Kd1 Art2 Preis: 50 €

oder läuft das bei euch gaaaanz anders?

7. März 2006 16:40

Wieder mein Fehler. Warum ich überhaupt das Formular "Sales Invoice" in Spiel gebracht habe ist, dass Jeder Kunde natürlich mehrere Rechnung bekommen kann.

Konkret:

Wir wollen unseren Kunden Beträge für die Abwicklung der Buchhaltung für die Jahre 2003 - 2005 in Rechnung stellen. Für jedes Jahr eine. Ich dachte, ich könnte einfach die Rechnungsbeträge in die Tabelle Sales Line schreiben. Natürlich wird dann der Rechnungsbetrag jedes mal überschrieben. Unsinnig!

Also wie könnte ich denn dann das Problem lösen? Wenn eine neue Rechnung erstellt wird, wird automatisch eine neue Rechnungsnummer generiert. So kann man also einem Kunden mehrere Rechnungen zuordnen. Als Source Tables habe ich aber nur die zwei Tabellen Sales Line Header und Sales Line gefunden.

Das ist ein bissl kompliziert, oder? Hoffe ich habe nicht zu viel Unsinn geschrieben.

7. März 2006 16:44

Über wieviele Rechnungen reden wir denn hier?

7. März 2006 16:53

Pro Jahr ca. 100

7. März 2006 16:58

Und die betreffenden Kunden hast du in dem Excel-File à la:

Kd.Nr. Name
1000 harry Hirsch GmbH ?

7. März 2006 17:00

Also pro Kunde pro Jahr eine Verkaufsrechnung. Welche Kunden das sind, das steht in deiner Excelliste. Auch der Betrag, den ihr eurem Kunden berechnen wollt steht dort drin.

Ich würde eine neue Tabelle in Navision erstellen. Diese neue Tabelle enthält zwei Felder: "Debitornr." und "Rechnungsbetrag". Diese Tabelle wird über einen Dataport mit den Daten aus deiner Excelliste gefüllt. Somit hast du die Daten ersteinmal in Navision drin. Zukünftig braucht ihr dann nicht mehr die Daten in Excel pflegen sondern könnt das dann direkt in Navision machen. Dazu hat man ja auch Navision: Um die Daten dort zu pflegen und nicht in Exceltabellen.

Dann würde ich einen Report schreiben, der diese neue Tabelle durchgeht. Bei jedem Datensatz ("OnAfterGetRecord"), müsste dann per Programmierung eine neue Verkaufsrechnung mit einer zugehörigen Verkaufszeile erstellt werden.

Gruß, Marc

7. März 2006 17:02

Ich würds ähnlich machen wie Marc, nur würde ich direkt per Report auf die Excel-Tabelle gehen und die Daten ggf. dort nachpflegen. Das würde dann die neue Tabelle sparen, letztendlich ists aber geschmackssache und Marcs Weg wäre wahrscheinlich auch der leichtere.

Aber ich find Excel-Reports einfach cool :-)

7. März 2006 17:09

JanV hat geschrieben:Ich würds ähnlich machen wie Marc, nur würde ich direkt per Report auf die Excel-Tabelle gehen und die Daten ggf. dort nachpflegen. Das würde dann die neue Tabelle sparen, letztendlich ists aber geschmackssache und Marcs Weg wäre wahrscheinlich auch der leichtere. Aber ich find Excel-Reports einfach cool :-)

Geht natürlich auch. Nur werden die Mitarbeiter dann nie von ihren Excellisten wegkommen. :-)

Gruß, Marc

7. März 2006 17:11

Achjee, ich bin ja schon froh wenn die davon wegkommen alles auszudrucken und abzulegen in ihrer Sammlungswut ;-)

7. März 2006 17:13

Hört sich jedenfalls alles gut an. Ich werde mich gleich mal dran setzen und später berichten. Gruß

Markus

7. März 2006 17:14

Hau rein Kollege :-)

7. März 2006 17:47

Melde mich morgen wieder. Bis dahin....

8. März 2006 10:38

Guten Morgen Leute,

ich scheitere schon beim Versuch die Daten der Exceltabelle in eine neu angelegte Navision Tabelle (BuHaPauschale) zu importieren. Die neue Tabelle hat ebenfalls zwei Felder (1. Gliederungsnummer, Code, Länge 20 UND 2. Betrag, Decimal)

Ich habe jetzt die Exceltabelle soweit auf 2 Spalten reduziert (Gliederungsnummer [Spalte A] und Betrag [Spalte B]). Dann habe ich einen Dataport gebastelt, der als DataItem die neue Tabelle verwendet. Bei den DataportFields habe ich beide Felder angegeben. Die Exceltabelle wurde im *.txt Format abgespeichert. Wenn ich versuche, den Dataport arbeiten zu lassen erscheint folgende Meldung:

"Typenkonfertierung des Ausdrucks Boolean in einen Codewert ist nicht möglich"

1. Ich habe doch gar kein Booleanfeld angelegt?!?
2. Wofür sind eigentlich die Felder Startpos und Width bei den DataportFields?
3. Welche Code muss ich schreiben um zu sagen "nehme den Wert der Exceltabelle aus Spalte B und schreibe ihn Feld xy der Navisiontabelle?

Zum Thema Dataports habe ich keine gescheiten Unterlagen :-(

8. März 2006 12:44

Hallo Markus,

wie werden denn die Felder in der Textdatei voneinander getrennt? Mit dem Semikolon? Wenn ja, muss dies beim Dataport (Eigenschaft "FieldSeparator") eingestellt werden. Standardmäßig wird nämlich das Kommazeichen benutzt.

Bei den Dataporteigenschaften "FieldStartDelimiter" und "FieldEndDelimiter" muss wahrscheinlich "<None>" eingestellt werden.

Kontrolliere noch mal die genannten Eigenschaften und versuchs noch mal.

Gruß, Marc

8. März 2006 13:02

Die Zuweisung der Felder funktioniert im Übrigen so:

Du markierst das entsprechende DataItem (in deinem Fall "BuHaPauschale") und klickst im Anschluss auf "Ansicht">"Dataport Fields" hier wählst du dann die zu befüllenden Felder in derselben Reihenfolge aus wie sie in deinem TXT-File stehen.

Gruß JAn

8. März 2006 13:43

wegen der Umlaute musst du die Exceltabelle als Text(MSDOS) abspeichern, dann wird als Feldtrennung <TAB> und als Satztrennung <New Line> verwendet. Diese musst du in deinem Dataport auch angeben.
Ausserdem musst du im Dataprot dafür sorgen, dass die erste Zeile mit den Überschriften nicht eingelesen wird. z.B mit Seek.
anbei ein Dataport mit dem ich für die Artikel den zu verwendenen Chargennummerncode einlese
Code:

Artikelzusatzdaten - OnBeforeImportRecord()
Artikelzusatzdaten.ChNrCode:='';
i+=1;
IF i<2 THEN CurrFile.SEEK(364);  //letzte Spalte der Überschriftenzeile + 1

Artikelzusatzdaten - OnPostDataItem()
MESSAGE (STRSUBSTNO('%1 Artikel eingelesen',i));

Als startpos und width trägst du bei den Feldern jeweils 0 ein und dein Import sollte gelingen.