Zeiger auf Datensatz in einer Teilmenge setzen

6. September 2007 10:29

Ich kenne diese Art der Programmierung erst seit Kurzem, daher könnte dieses Thema vielleicht (und hoffentlich) auch für andere von Interesse sein:

Wenn ich z.B. auf einem Feld mit einer Artikelnummer stehe und nun den Lookup-Button klicke, möchte ich, dass der Datensatzzeiger auf eben diesem Artikel steht. Dies erledigt Navision über eine TableRelation ja meistens ganz von allein.

Doch was muss ich tun, wenn der Lookup händisch programmiert werden muss? Und was hinzukommt: Was ist, wenn der Lookup mir nur eine Teilmenge der Artikel (also nach irgendwelchen Kriterien gefiltert) anzeigen soll, der Zeiger aber trotzdem korrekt gesetzt werden soll?
Dies einfacher als zumindest meinereiner dachte:

Item No. - OnLookup
Code:
// Setze zuerst den Artikelfilter
Item.SETCURRENTKEY(Feld1, Feld2, Feld3);
Item.SETRANGE(Feld1, Inhalt1);
Item.SETRANGE(Feld2, Inhalt2);
// setze den Zeiger - benuzte den Primärschlüssel
Item."No." := InhaltXY;

IF FORM.RUNMODAL(0, Item) = ACTION::LookupOK THEN ...


Den Filter kann ich nach Belieben setzen. Daher habe ich hier auf einenSETRANGE für Feld3 verzichtet.
Was nun für den Zeiger wichtig ist: Ich weise allen Feldern des Primärschlüssels einen Wert zu.

-------- folgnden Teil konnte ich im Nachhinein nicht mehr reproduzieren und ist daher mit großer Vorsicht zu genießen ----------------

Verwenden kann man dieses Prinzip zur Beantwortung der Frage, ob z.B. ein Artikel in einer vorgegebenen Teillmenge enthalten ist:

Code:
Item.SETRANGE("No.", 'ART0001', 'ART0050); // aktuell sind das 50 Artikel
// setze den Zeiger
Item."No." := 'ART0051';
ArtikelInTeilmengeEnthalten := NOT Item.ISEMPTY;
// Ergebnis: FALSCH


Achtung: Ist der Zeiger nur unvollständig oder gar nicht gesetzt (also nicht alle Felder des aktuellen Schlüssels), liefert ISEMPTY hier das falsche Ergebnis, nämlich nur, ob die Teilmenge selbst Artikel enthält (ja, nämlich alle von ART0001 bis ART0050).
Zuletzt geändert von Natalie am 8. September 2007 19:02, insgesamt 1-mal geändert.

6. September 2007 11:20

*wunder* :-)

das ist doch klar, meines Wissens nach interessiert sich ISEMPTY nicht dafür, wie der Inhalt irgendwelcher Felder des Datensatzes ist, lediglich die gesetzten Filter sind interessant.

ISEMPTY ist ohnehin ein Befehl den die Welt nicht braucht - FIND('-') bringt mir das gleiche Ergebnis (oder COUNT - das ist aber evtl. langsamer als FIND('-'), da je die Datensätze gezählt werden müssen).

In Deinem Fall hätte FIND('=>') das richtige (gewünschte) Ergebnis gebracht

Gruß
Edgar

6. September 2007 11:25

elf hat geschrieben:ISEMPTY ist ohnehin ein Befehl den die Welt nicht braucht - FIND('-') bringt mir das gleiche Ergebnis (oder COUNT - das ist aber evtl. langsamer als FIND('-'), da je die Datensätze gezählt werden müssen).

Da widerspreche ich vehement.
ISEMPTY ist der performanteste (!) Befehl, wenn ich das Ergebnis brauche und mir dabei der Inhalt des evtl. gefundenen Datensatzes egal ist.

Was ich nicht ausschließe, ist, dass ISEMPTY tatsächlich in meinem oben angegeben Beispiel nicht funktioniert - ich habe es noch nicht testen können. Getestet wurde es mal mit FINDFIRST. Mir ist aber nicht bekannt, dass die FIND-Befehle und der ISEMPTY anders mit gesetzten Filtern und gestetzen Felder umgehen.

6. September 2007 11:45

ISEMPTY interessiert sich nur für gesetzte Filter, genauso wie COUNT - der Inhalt des Datensatzes ist dabei egal.

Was die Performance angeht hast Du Recht, ISEMPTY ist tatsächlich schneller als FIND, da ja keine Inhalte in den Datensatz übertragen werden müssen und natürlich allemal schneller als COUNT wenn es um große Teilmengen geht.

Ich relativiere meine Aussage '... den die Welt nicht braucht ...' also dahingehend...

6. September 2007 11:51

Übrigens, ein Beispiel für das Markieren des aktuell gewählten Datensatzes findet sich auch im Standard - ich habs vorher nur nicht zu lesen gewusst:

Tabelle 225 Post Code, Funktion LookUpPostCode

Code:
PostCodeRec.SETCURRENTKEY(Code,City);
PostCodeRec.Code := PostCode;
PostCodeRec.City := City;
IF (FORM.RUNMODAL(FORM::"Post Codes",PostCodeRec,PostCodeRec.Code) = ACTION::LookupOK) AND ReturnValues THEN BEGIN
  [...]
END;

8. September 2007 19:00

Jetzt bin ich ratlos...
Habe eben in einer ruhigen Minute versucht, die Sache mit dem FIND auf einen Wert in einer Teilmenge zu reproduzieren - und kriege es nicht mehr hin. Ich kann euch aber versichern, dass ich es unter 5.0 mal hinbekommen habe. Verstehe die Welt nicht mehr ...

Habe meinen Startbeitrag in dieser (und auch anderer Hinsicht) etwas korrigiert...