[Gelöst] Funktion mit Parametern vom Typ Record

1. März 2010 13:13

Hallo,

wie kann ich denn in einem Report eine Funktion erstellen die ich mit verschiedenen Parametern vom Typ Record Aufrufe?

Also zum Beispiel:

FillCounty(Rec : Record "Irgendeine Tabelle")
Rec.County := ''
Zuletzt geändert von ralf5 am 4. März 2010 13:20, insgesamt 1-mal geändert.

Re: Funktion mit Parametern vom Typ Record

1. März 2010 13:30

Hallo Ralf,

schau dir mal den Datentyp RecordRef an, der kann genau das, was du suchst.

Re: Funktion mit Parametern vom Typ Record

1. März 2010 13:52

Hallo Timo,

danke für die Antwort. Aber wenn ich die Funktion aufrufe, bekomme ich die Meldung: "Sie haben eine unbekannte Variable angegeben..."

Was mache ich denn falsch?

Code:
FillSellToCounty(Rec : RecordRef)
IF Rec."Sell-to County" = '' THEN BEGIN
  SalesShipmentHeader := Rec;
  IF Customer.GET(Rec."Sell-to Customer No.") THEN
    SalesShipmentHeader."Sell-to County" := Customer.County;
  IF SalesShipmentHeader. "Sell-to County" = '' THEN
     SalesShipmentHeader."Sell-to County" := 'UNKNOWN';
  SalesShipmentHeader.MODIFY;
END;

Re: Funktion mit Parametern vom Typ Record

1. März 2010 14:17

Hallo Ralf,

RecordRef bietet dir das, was du suchst, jedoch ist die Art, wie du mit RecordRef arbeiten musst, eine andere.
Bitte lies dir einmal in Ruhe die Online-Hilfe zu RecordRef und FieldRef durch.
Es wäre doch etwas zu aufwändig, alles nochmal zu erklären, wo es doch relativ gut und umfangreich in der Hilfe steht.

Wenn du dann noch Fragen zu konkreten Problemen hast, darfst du sie hier natürlich jederzeit stellen.

Re: Funktion mit Parametern vom Typ Record

1. März 2010 15:23

Hallo Timo,

ich habe jetzt nochmal hier im Forum geguckt, bei msdn und in der Hilfe.

Ich kriege das aber nicht hin! :-(

Ich habe einen Report der im OnAfterGetRecord() Ereignis immer die Funktion aufrufen soll. Als Parameter soll der aktuelle Datensatz übergeben werden und ein Feld im Datensatz soll aktualisiert werden (s. Code weiter oben)


Bei mir in der Hilfe steht zu RecordRef nur das:

RECORDREF
This complex data type identifies a row in a table. Each record consists of fields (which form the columns of the table). A record is typically used to hold information about a fixed number of properties.

The RecordRef object can refer to any table in the database. Use the RecordRef.OPEN function to select the table you want to access. When you use the RecordRef.OPEN function a new object is created. This object contains references to the open table, filters and the record itself and all the fields it contains.

If one RecordRef variable is assigned to another RecordRef variable, they both refer to the same table instance.


Damit kann ich net viel anfangen. Kannst du mir sagen wo ich in den Tiefen des NAV-Codes ein Beispiel finde?

Danke.

Re: Funktion mit Parametern vom Typ Record

2. März 2010 15:36

Wenn ich dein Codebeispiel richtig interpretiere, dann brauchst du kein RecordRef, sondern einfach nur einen Parameter vom Typ Record, Subtyp 110.

Ändere doch mal deinen Parameter und teste genau den hier geposteten Code damit!

Beste Grüße
Falk

Re: Funktion mit Parametern vom Typ Record

2. März 2010 17:21

FAFL hat geschrieben:Wenn ich dein Codebeispiel richtig interpretiere, dann brauchst du kein RecordRef, sondern einfach nur einen Parameter vom Typ Record, Subtyp 110.

Ändere doch mal deinen Parameter und teste genau den hier geposteten Code damit!

Beste Grüße
Falk


Ich verwende nicht nur die Tabelle 110 sondern auch noch 112 und 114.


Mensch, ich sitze jetzt schon eine Ewigkeit davor und alles was ich probiert habe klappt nicht. Kann mir denn niemand ein kleines Beispiel geben?

Re: Funktion mit Parametern vom Typ Record

2. März 2010 17:38

Code:
SalesShptHeader.FINDFIRST;
RecRef.GETTABLE(SalesShptHeader);
FillSellToCounty(RecRef);

SalesInvHeader.FINDFIRST;
RecRef.GETTABLE(SalesInvHeader);
FillSellToCounty(RecRef);

SalesCrMemoHeader.FINDFIRST;
RecRef.GETTABLE(SalesCrMemoHeader);
FillSellToCounty(RecRef);

FillSellToCounty(RecRef : RecordRef)
SellToCountyFldRef := RecRef.FIELD(DummySalesShptHeader.FIELDNO("Sell-to County"));
SellToCustNoFldRef := RecRef.FIELD(DummySalesShptHeader.FIELDNO("Sell-to Customer No."));

IF FORMAT(SellToCountyFldRef.VALUE) = '' THEN BEGIN

  IF Customer.GET(SellToCustNoFldRef.VALUE) THEN
    SellToCountyFldRef.VALUE := Customer.County;
 
  IF FORMAT(SellToCountyFldRef.VALUE) = '' THEN
     SellToCountyFldRef.VALUE := 'UNKNOWN';

END;

RecRef.MODIFY;

Re: Funktion mit Parametern vom Typ Record

2. März 2010 17:53

Hallo Ralf,

mal eine Frage: Normalerweise sollte die County-Codes in den Verkaufsdokumenten beim Erstellen der Belege korrekt gefüllt werden.

Wenn ich deinen Beitrag von hier mit einbeziehe, komme ich zu dem Schluss, das der ganze Report im normalen Betrieb höchstens einmal laufen sollte, um evtl. früher nicht korrekt angelegte Daten zu korrigieren.

Aus diesem Grunde würde ich mir einen Report mit 3 Einträgen für die Tabellen 110,112,114 bauen, der auf "Sell-to County" filtert (ein Filter auf "Bill-to County" sollte nicht nötig sein, da er den gleichen County-Code enthält, wenn ihr nicht mit abweichender Rechnungsadresse arbeitet) und den Code einfach kopieren. Alles andere kostet nur unnötig Laufzeit, und vor allen Dingen: Programmierzeit :wink: .

Noch besser ist es diese Datenfehler gar nicht erst entstehen zu lassen, und die Stammdaten in Ordnung zu halten :wink:

Gruß, Fiddi

P.S.: Solltest du mit einer nicht VISTA-tauglichen 4er- NAV-Version arbeiten, kann es dir passieren, das dein Report mit RecordRefs und FieldRefs bei größeren Datenmengen einschläft. :-(

Re: Funktion mit Parametern vom Typ Record

2. März 2010 18:53

fiddi hat geschrieben:Hallo Ralf,

mal eine Frage: Normalerweise sollte die County-Codes in den Verkaufsdokumenten beim Erstellen der Belege korrekt gefüllt werden.

Also es betrifft nur die Felder: Bill-to County, Sell-to County, Ship-to County und diese werden nicht immer gefüllt.


Wenn ich deinen Beitrag von hier mit einbeziehe, komme ich zu dem Schluss, das der ganze Report im normalen Betrieb höchstens einmal laufen sollte, um evtl. früher nicht korrekt angelegte Daten zu korrigieren.

Nein, der Report muss täglich einmal laufen, da die Daten aus dem Web-Shop ohne County angelegt werden. Ich weiß, dass ist ein Fehler. Ist aber so.


Aus diesem Grunde würde ich mir einen Report mit 3 Einträgen für die Tabellen 110,112,114 bauen, der auf "Sell-to County" filtert (ein Filter auf "Bill-to County" sollte nicht nötig sein, da er den gleichen County-Code enthält, wenn ihr nicht mit abweichender Rechnungsadresse arbeitet) und den Code einfach kopieren. Alles andere kostet nur unnötig Laufzeit, und vor allen Dingen: Programmierzeit :wink: .

Ich will ja nicht nur das der Bericht läuft, das habe ich ja schon. Ich will auch lernen wie das richtig geht.

Ich habe den Code jetzt einfach redundant 9 mal im Bericht für die Tabellen 110,112,114 jeweils 3 Tabellen mit den 3 erwähnten Feldern. Die Filter müssen auf allen 3 Feldern und allen 3 Tabellen erstellt werden, da die Werte in county unterschiedlich sind.


Noch besser ist es diese Datenfehler gar nicht erst entstehen zu lassen, und die Stammdaten in Ordnung zu halten

Wir bekommen ein komplett neues (Navision) System und das alte fliegt komplett in die Tonne.
P.S.: Solltest du mit einer nicht VISTA-tauglichen 4er- NAV-Version arbeiten, kann es dir passieren, das dein Report mit RecordRefs und FieldRefs bei größeren Datenmengen einschläft. :-(

Danke für den Tipp aber alles ist noch auf XP danach Vista mit NAV 2009


Ich weiß nicht?
Ich bin Anfänger in Navision und in C/AL, (normalerweise programmiere ich in .NET und SQL) deshalb suche ich hier auch Hilfe.

Mein bestreben ist es Navision und C/AL zu lernen und sauberen code abzuliefern der sich soweit wie möglich am Standard orientiert und der leicht wartbar ist. Dafür habe ich auch schon einige Schulungen besucht. Leider helfen die mir momentan auch nicht.

Mein bestreben ist es NICHT einen QUICK and DIRTY code zu erstellen.

Bin ich hier etwa zu optimistisch? Wenn ich mir den Code den unser Partner verzapft hat ansehe fange ich langsam an zu Zweifeln!
:-(

Re: Funktion mit Parametern vom Typ Record

2. März 2010 22:24

<OffTopic>
Hallo Ralf,

erst einmal darf ich dir zu deiner Einstellung gratulieren:
Du möchtest nicht nur einfach eine Lösung für dein aktuell akutes Problem, sondern daraus auch für die Zukunft lernen.
Das nenne ich weitsichtiges Denken!

Wenn ich mir heute meinen Programmcode von vor 5 oder gar 10 Jahren anschaue, dann frage ich mich auch manchmal, was ich mir damals dabei gedacht hatte.
Früher war jeder einzelne halt noch nicht so erfahren und es gab auch nicht die heutigen Möglichkeiten (z. B. RecordRef).

Ich kann jetzt schon auf stolze 13 Jahre Navision-Erfahrung zurückblicken und kann mich somit noch daran erinnern, mit welch bescheidenen Mitteln wir damals programmieren mussten.
Entsprechend "kreativ" sah dann der Programmcode aus.
NAV ist zwar auch heute noch in seinen Programmierfähigkeiten (mit Absicht) stark eingeschränkt, jedoch schon bedeutend flexibler als vor 5 oder gar 10 Jahren.

Der größte Teil meines NAV-Wissens stammt übrigens nicht aus teuer erkauften Schulungen, sondern aus zahlreichen Internet-Communities (Foren, Blogs, Webseiten).
</OffTopic>

Re: Funktion mit Parametern vom Typ Record

2. März 2010 23:40

Hallo Ralf,

einige Anmerkungen:
  • Das mit dem 4er-NAV-Client meinte ich auf den NAV-Client bezogen, nicht auf das Betriebssystem, d.h. ist dein NAV-Client nicht auf einem Vista-PC lauffähig (aktueller Patchlevel), wird dir der Client bei der Arbeit mit vielen RecordRefs bzw. FieldRefs keine Freude machen.
  • Was machst du mit dem "County Code"? Fährst du irgendwelche Auswertungen darüber? In DE benötigt NAV diesen Code normalerweise nicht, d.h. das System läuft auch ohne ganz gut.
  • Als nicht NAV-Programmierer würde ich genauso denken und arbeiten wie du: Code der mehrfach das gleiche tut, gehört in eine Funktion, die mit Parameter aufgerufen wird, um den Code und damit die Fehlermöglichkeiten zu reduzieren. In diesem Fall wird dein Code aber nicht weniger, wenn du ihn in eine Funktion packst, deshalb mein Voschlag von vorhin. Außerdem musst du nicht nur an sauberen Code, sondern auch auf Performance denken, und da sind die RedordRefs nicht unbedingt der Bringer.
  • Lenke deine Energie lieber in die Richtung Performance, d.h. möglichst wenige Datenbankzugriffe zu haben. Denn deine Tabellen werden größer und du musst immer mehr Datensätze durchkämmen. Dies kann man über geeignete Schlüssel bzw. Filter erreichen, oder darüber, das man sich überlegt ob und wann man Daten ändern muss. In deinem Beispiel muss man den "Bill-To County" nur dann auf einen anderen Wert setzen als "Sell-to County" setzen, wenn die der "Bill-to Cust. No." ein anderer ist, als der "Sell-to Cust. No.". Außerdem sparst du dir den zweiten Durchlauf durch die Tabellen.
    Code:
    sav_SellTo := "Sell-to County";
    sav_BillTo := "Bill-to County";

    if ("Sell-to Code" = '') then begin
      Cust.get("Sell-to Cust. No.");
      "Sell-to County" := Cust."County Code";
    end;
    if ("Bill-to County" = '') then
      if ("Bill-to Cust. No." = '') or ("Bill-to Cust. No." = "Sell-to Cust. No.")  then
        "Bill-to County" := "Sell-to County"
      else begin
        Cust.get("Sell-to Cust. No.");
        "Sell-to County" := Cust."County Code";
      end;
    if (sav_SellTo <> "Sell-to County") or (sav_BillTo <> "Bill-to County") then
      modify;
  • Aus eigener Erfahrung kann ich dir nur empfehlen, solche Nachtläufe zu vermeiden, denn du hast immer das Problem, das deine Daten unter Tage nicht aktuell sind und du dich nicht auf deine Daten verlassen kannst. Es gibt mehrere Möglichkeiten den County-Code schon beim Anlegen des Debitors zu ermitteln (Wenn du ihn den überhaupt brauchst), z.B. über den Ort oder die Postleitzahl. Das macht weniger Rechenaufwand, und deine Daten sind aktuell.

Gruß, Fiddi

Re: Funktion mit Parametern vom Typ Record

3. März 2010 18:33

@fiddi

Danke für die Antwort. Mag sein, dass recordref ungeeignet ist. Kannst du mir trotzdem sagen wie ich das ganze in einer Funktion aufrufe?

Der Aufruf erfolgt aus dem Bericht im OnPreDataItem()
Aufruf 1: XY (SalesShipmentHeader);
Aufruf 2: XY (SalesInvoiceHeader);

Sagen wir mal ich möchte das Feld "Sell-to County" aktualisieren und überall XXX reinschreiben.

Also die kurze Funktion:
Function xy(ref : RecordRef)
"Sell-to County" = 'XXX'


Wie mache ich das?

Re: Funktion mit Parametern vom Typ Record

3. März 2010 20:57

Hallo Ralf,

das mit der Funktion ist in diesem Fall rein akademisch, da der Aufruf der Funktion mehr Aufwand bedeutet als die Variable direkt zu ändern.
Wenn deine Tabellen alle ein ähliches Format haben, kannst du mit TRANSFERFIELDS arbeiten. Dann sieht dein Code etwa so aus:
Aufrufende Funktion:
Code:
pSalesLine.TRANSFERFIELDS(ShipLine);
Function(pSalesLine);
ShipLine.TRANSFERFIELDS(pSalesLine); // evtl. nur einzelne Felder übernehmen

Funktion;
Code:
Function(VAR pSalesLine: Record 37)
BEGIN
   pSalesLine."Ship-to County" := XXX;
end;


Aber eine Warnung, wenn du damit mehrere Hunderttausend Datensätze durchlaufen willst, dann dauert das :wink:

Aber eine andere Frage, warum soll deine Funktion im OnPreDataItem aufgerufen werden? Normalerweise würde man so etwas im OnAfterGetRecord des Records machen?

Gruß, Fiddi

Re: Funktion mit Parametern vom Typ Record

4. März 2010 08:23

ralf5 hat geschrieben:@fiddi
...
Sagen wir mal ich möchte das Feld "Sell-to County" aktualisieren und überall XXX reinschreiben.

Also die kurze Funktion:
Function xy(ref : RecordRef)
"Sell-to County" = 'XXX'

Wie mache ich das?
Hallo Ralf,
sicherlich war es plump von mir einfach nur Sourcecode zu posten. Aber in meinem letzten Beitrag in diesem Thread hast du diese Funktion bereits.

Re: Funktion mit Parametern vom Typ Record

4. März 2010 13:18

Ohhhh, man, bin ich blind :shock:
SilverX hat geschrieben:sicherlich war es plump von mir einfach nur Sourcecode zu posten. Aber in meinem letzten Beitrag in diesem Thread hast du diese Funktion bereits.

Da habe ich doch den Wald vor lauter Bäumen nicht gesehen. Habe es gleich mal umgesetzt und siehe da, es funktioniert bestens, herzlichen Dank.
Es gibt auch keine Performance Probleme.

@All :-D
Juuuuhhhhuuuu, habs jetzt endlich - Dank euch - geschaft: Der Report ist optimiert und läuft statt 90 Minuten nur noch weniger als 1 Minute und ist zudem auch noch code optimiert. Was will das programmierer Herz noch mehr.
Vielen Dank auch, für die vielen Vorschläge und Ansätze. Werde die bestimmt zukünftig noch benötigen.