Filtern

25. Januar 2015 16:04

Hallo liebe Leute,

ich habe hier eine Aufgabe, die ich irgendwie nicht lösen kann.

Wir haben eine Tabelle (Zeiterfassung) gegeben, mit mehreren Datensätzen. Die Felder sind "Personal_NR, Arbeitstag und Arbeitszeit"..
Nun sollen die drei Datensätze mit der längen Arbeitszeit in der Tabelle ausgewählt und über eine Messagebox der Reihe nach ausgegeben werde.

Meine Lösung hierfür wäre.
1. Sortierung nach Arbeitszeit, um eben den ersten Datensatz mit der höchsten Arbeitszeit darstellen zu können.
recz.SETCURRENTKEY(Arbeitszeit);
2. Filter setzen
recz.SETFILTER(Arbeitszeit)
3. Die ersten drei Datensätze (Hier hab ich das Problem)
IF recz.FIND('<=3') THEN BEGIN
REPEAT
MESSAGE ('Erster Datensatz ist: %1, %2, %3', recz."Personal_NR", recz.Arbeitstag, recz.Arbeitszeit);
UNITIL recz.NEXT= 0;
nli
Und eine andere Aufgabe wäre, dass wir eine Tabelle haben, mit mehreren Datensätzen und verschiedenen Feldern.
wie zb: Name etc.
Hier soll ich alle Datensätze der Personen die mit z.b mit "M" anfangen. Wie kann ich hier voran gehen? Wie kann ich den Filter so setzen, dass es alle Namen mit "M" ausgibt. Es wäre unglaublich nett wenn ihr mir helfen könnten. Gibt es eig. eine gute Doku, wo ähnliche Aufgaben gut erklärt werden? Hab am zweiten Februar meine Prüfung und bräuchte bisschen Hilfe :). Danke im Voraus

Re: Filtern

25. Januar 2015 18:34

Hallo,
was deine erste Frage betrifft, so ist wohl der "FIND('<=3')" nicht dazu geeignet. Wenn du im Entwicklungsclient stehst, mit F1 die Hilfe öffnest und nach "FIND" suchst (wie geil ist das denn :-) ) erklärt die Hilfe, was du für den Parameter "Which" einsetzen darfst:

Um im deinem Beispiel nur die ersten drei Datensätze auszugeben (mit der längsten Arbeitszeit) probiere mal folgendes:
Code:
recz.SETCURRENTKEY(Arbeitszeit);
recz.ASCENDING(FALSE) ;  // Absteigende Reihenfolge
IF recz.FIND('-') THEN
  REPEAT
    MyRecCounter += 1;
    Message'Erster Datensatz ist: %1, %2, %3', recz."Personal_NR", recz.Arbeitstag, recz.Arbeitszeit);
  UNTIL (recz.NEXT = 0) OR (MyRecCounter = 3);

Dein gesetzter SETFILTER hat keine Auswirkungen, da du dem SETFILTER ja kein FILTERKRITERIUM mitgibst, womit wir schon bei deinem zweiten Problem wären.

Zunächst solltest du dir auch unter Zuhilfenahme der Hilfe (schon wieder so ein Satz :lol: ) einen Überblick über die Filtermöglichkeiten schaffen.

Ich hab mal deine Frage 1 und 2 in folgendem Code zur Tabelle Customer zusammengeführt:

Code:

MyFilter := 'Meier*';  // Textvaiable
Customer.RESET;
Customer.SETCURRENTKEY(Name);
Customer.ASCENDING(FALSE);  // Absteigende Reihenfolge
Customer.SETFILTER(Name,'%1',MyFilter);  // Das Wichtigste
IF Customer.FIND('-') THEN
  REPEAT
    MyCounter += 1;  //Integervariable
    MESSAGE('%1 %2 %3 %4',MyCounter,Customer."No.",Customer.Name,Customer.City);
  UNTIL (Customer.NEXT = 0) OR (MyCounter = 3); // Bis nimmer geht aber maximal drei


Ich hoffe du kommst damit weiter. Wenn Du Dokumentationen hierzu willst, kann zumindest ich nur auf die Hilfe (und den einschlägigen BLOGS) verweisen.
In der Hilfe findest du auch immer wieder Code-Beispiele.

Viel Glück bei deiner Prüfung.

MFG
Micha

Re: Filtern

27. Januar 2015 00:08

Verstanden Danke :) ..
Eine andere Aufgabe:

Legen Sie innerhalb der Codeunit eine Funktion Function1 an. Sie soll prüfen, ob es in der NAV-Tabelle Produkte einen Datensatz zum Primärschlüssel ZARTIKEL=„P-100“ gibt. Falls es einen solchen Datensatz gibt, soll der zugehörige Losgroessenschluessel per Messagebox ausgeben werden! Geben Sie den C/AL-Code an.
Meine Lösung wäre: (Habe ich anhand des Beispiels mit Teller lösen können :-D

Produkte.GET("P-100");
IF Produkte.FIND('-') THEN BEGIN
REPEAT
MESSAGE ('Die Losgroesse betraegt: %1', Produkte.Losgroesse)
ELSE
MESSAGE ('Kein Datensatz');
END;
UNUTIL Produkte.NEXT = 0;


Eine weitere Funktion Function2 soll für alle Datensätze in der Tabelle Produkte ohne angegebenen Losgroesenschluessel (also Losgroesenschluessel = ‘‘) den Wert von Losgroessenschluessel auf ‘EXAKT‘ setzen! Geben Sie den C/AL-Code an.
Meine Lösung:
(Hier würde man doch jetzt SETFILTER benutzen, da Losgroesse kein PK ist)

Produktion.SETFILTER(Losgroesse, '');
IF Produkte.FIND('-') THEN
REPEAT
Produkte.Losgroesse := 'EXAKT';
Produkte.INSERT;
ELSE
MESSAGE ('keine Losgroesse die leer ist');
UNUTIL Produkte.NEXT =0;

Legen Sie innerhalb der Codeunit eine Funktion IhrVorName an. Diese Funktion soll prüfen, ob es in der NAV-Tabelle 123456752 (UmsatzWuerfel) einen Datensatz zu einem vorgegebenen Primärschlüssel gibt. Die Daten (ZName, Zartikel, ZJAhr) sollen als Parameter der Funktion übergeben werden. Rückgabewert ist das boolsche Ergebnis.

Cihan( Zname: Text[10]; Zartikel: decimal; Zjahr: Date) VAR ok:Boolean
IF recUmsatzwuerfel.GET (Zname, Zartikel, Zjahr) THEN // DIe übergeenen Parameter Filtern
BEGIN
ok := TRUE
MESSAGE ('Datensatz bereits vorhanden');
ELSE BEGIN
MESSAGE ('Kein Datensatz vorhanden')

GET, weil alle drei Felder PK in der Tabelle Umsatzwürfel sind.

Ich kann es leider nicht auf NAV eingeben, da ich NAV nur an der FH zur Verfügung habe. Aber es wäre dennoch unglaublich nett wenn ihr mir bisschen helfen könnten.

Viele Dank schonnmal..

Re: Filtern

27. Januar 2015 09:46

Hallo Cihan,

auch wenn ich kein Programmierer bin und andere das bestimmt besser beurteilen können... :-)

Beispiel 1:
Cihan61 hat geschrieben:Produkte.GET("P-100");
IF Produkte.FIND('-') THEN BEGIN
REPEAT
MESSAGE ('Die Losgroesse betraegt: %1', Produkte.Losgroesse)
ELSE
MESSAGE ('Kein Datensatz');
END;
UNUTIL Produkte.NEXT = 0;


Der Get am Anfang führt zum Absturz, wenn der Satz nicht da ist.
Der Find ist eigentlich überflüssig, da Du ja schon den GET gemacht hast.
Die Repeat-Schleife brauchst Du nicht, da es ja nur einen Satz geben kann (Primärschlüssel)
Das END müsste über dem ELSE stehen, m.E. geht der ELSE in der REPEAT-Schleife so aber auch nicht.

Einfacher:
IF Produkte.GET("P-100") THEN
MESSAGE ('Die Losgroesse betraegt: %1', Produkte.Losgroesse)
ELSE
MESSAGE ('Kein Datensatz');

Beispiel 2:
Der Insert führt zum Abbruch, da der Satz ja schon da ist.

Beispiel 3:
Prinzipiell ok, aber die ENDs fehlen.

Viele Grüße
Mike

Re: Filtern

27. Januar 2015 12:53

Vielen vielen Dank :)

Das mit Primärschlüssel habe ich aber nicht ganz verstanden. Obwohl, doch klar.. Primärschlüssel P-100 kann es ja nur einmal geben weil es eben ein Primärschlüssel ist, richtig? :-D

Die Action soll ausgeben, wie viele verschiedene Produkte in der Tabelle 123456752 vorkommen und das Ergebnis mittels einer Message-Box anzeigen! PK ist wiederr Name, Artikel und Jahr.

// Hier muss ich ja repeat nehmen, weil es eben mehrere Datensätze sind.
// Mit GET könnt ichhier nicht arbeiten, weil nach mehreren Datensätzen gesucht wird, stimmt?
// Jetzt die Frage, ich müsste doch hier aber auf PK zugreifen, um Doppeleinträge zu vermeiden? Oder etwa nicht?
Code:
IF uw.FIND('-') THEN
REPEAT
   Counter += 1;
   MESSAGE ('Anzahl der Datensätze beträgt: %1', Counter);
UNITIL uw.NEXT = 0;


Diese Action soll zunächst alle Datensätze in der Tabelle 123456752 löschen und dann alle Kombinationen der Felder (Zname, Zartikel, Zjahr), die in der Tabelle 123456750 vorkommen, als Datensätze in die Tabelle 123456752 ablegen. Allerdings sollen keine doppelten Datensätze angelegt werden (Dubletten vermeiden).


Code:
rec52.DELETEALL
IF rec50.FINDFIRST THEN
  REPEAT
         IF rec52.GET( rec50.Zname, rec50.zArtikel, rec50.zJahr ) THEN BEGIN //Vergleicht mit den Datensätzen aus ec50
        MESSAGE ('Datensatz bereits vorhanden');
  END ELSE BEGIN
        rec52.COPY(rec50)
        rec52.INSERT; << Diesmal geht es ja, weil ich keine Datensätze mehr in der Tabelle hatte.
  END;
UNITIL rec50.next=0;


Letzte Aufgabe :) Die ich aber fast gar nicht verstanden habe. Ich habe versucht es folgendermaßen zu lösen.
Diese Action soll eine temporäre Tabelle zu 123456750 mit den drei größten Einzelumsätzen (Netto) befüllen


Code:
rec50.SETCURRENTKEY(Zumsatz)
rec50.ASCENDING(FALSE) // Absteigend sortieren
IF rec50.FIND('-') THEN
REPEAT
  MyCounter +=1; //Integervariable
  tmp50.COPY(rec50); //Kopieren in die temporäre Tabelle 50
  tmp50.INSERT; // Einfügen
UNITIL (rec50.NEXT=0)  OR (MyCounter = 3);

Das müsste dann ja richtig sein :-)

Und zuletzt noch eine Frage..
Bei der letzten Prüfung kam die Frage "was verstehen sie unter w1" vor, nur die Antwort kennt irgendwie niemand so wirklich.
Hab auch bereits im Internet recherchiert aber hab irgendwie keine Antwort bekommen die dazu passend wäre..
Tut mir leid dass ich dich bisschen genervt habe aber hast mir wirklich ein großen gefallen getan :) ..Vielen vielen Dank

Re: Filtern

27. Januar 2015 13:18

Cihan61 hat geschrieben:Bei der letzten Prüfung kam die Frage "was verstehen sie unter w1" vor, nur die Antwort kennt irgendwie niemand so wirklich.

W1 ist die Worldwide-Version. Die wird in keinem Land eingesetzt und ist auch nirgends zugelassen, dient nur als Grundlage für alle Länderversionen und ist somit der kleinste gemeinsame Nenner für die Entwicklung und den Abgleich des Quellcodes.
Außer dem Code, der für das jeweilige Land ergänzt wird, werden in manchen Ländern auch Objekte, die in der W1 vorhanden sind, entfernt. In der NA-Version (Nordamerika, Canada, Mexico) fehlt z.B. der Report 3, weil dort stattdessen der länderspezifische Report 10019 im Einsatz ist.

Re: Filtern

27. Januar 2015 13:24

Hallo,

benutzt bitte den CODE- Tag um Quellcode zu formatieren, das Liest sich besser
:wink:

zu deiner ersten Frage:

Code:
MESSAGE('Anzahl der Datensätze beträgt: %1',uw.COUNT);


Sollte hier vollkommen ausreichen. Außerdem ist es sicher nicht gewollt, mit jedem gezählten Datensatz den Zähler auszugeben (MESSAGE in der Schleife) :-?

zu deiner zweiten Frage:

hier kommt es jetzt auf das Layout der Tabelle 123456752 an. Wenn die Tabelle 123456752 exakt "Zname, Zartikel, Zjahr" (oder ein andere Reihenfolge davon) als Primärschlüssel vorhanden ist, dann ist die Lösung relativ einfach mit "IF REC52.INSERT THEN;", ansonsten musst du zunächst mit SETRANGE,SETFILTER und FIND nach einem evtl. vorhandenen Datensatz suchen.
Ein weiteres Problem ist die Zuweisung der Datensätze. Da du zwei unterschiedliche Tabellen hast, wird COPY hier nicht funktionieren. da wirst du dich mit TRANSFERFIELDS oder einzelnen Feldzuweisungen behelfen müssen.

zu deiner 3. Frage:

das könnte so funktionieren, wenn die Tabellen das passende Layout haben. :wink:

Gruß, Fiddi

Re: Filtern

27. Januar 2015 15:00

http://www.bildhochladen.de/waV

Hallo Fiddi,

Hab hier unser ER-Diagramm mal hochgeladen.. Layout der Tabelle 50 ist nicht identisch mit der Tabelle 52 bzw.
In der Tabelle 50 ist PK = LFD_NR, Zname = FK, und Zartikel= FK und Jahr keins von beiden. In der Tabelle 52 sind genau die drei als PK.

Das heißt, GET würde hier ja schonmal wegfallen, da wir auf beiden Tabellen nichtt die selben PK's haben
Deshalb müssten wir ja zunächst Tabelle 50 auf Felder Zname, Artikel Jahr filtern.

Code:
rec50.SETFILTER(rec50.Zname, rec50.zartikel, rec50.jahr);

IF rec50.FINDFIRST THEN
     REPEAT
        rec52.zname := rec50.zname;
        rec52.zartikel := rec50.zartikel;
        rec52.zjahr := rec50.jahr;
        rec52.INSERT;
    UNITIL rec50.NEXT = 0;

aber das kommt mir bisschen unlogisch vor, kann ich überhaupt mit SETFILTER auf 3 Felder zugreifen ohne auf Wert zugreifen zu müssen?
wie könnt ich denn hier jetzt die ELSE Bedingung einfügen? Also die nach Doppeleinträge sucht? Mit GET wäre es ja einfach.

Re: Filtern

27. Januar 2015 15:32

Hallo,

noch eine Bitte: Du kannst hier im Forum problemlos ein Bild hoch laden, das bleibt dann auch länger erhalten (zumindest solange wie der Beitrag existiert) :-)

Ich würde dir empfehlen dich noch einmal mit den Befehlen GET, SETRANGE, SETFILTER, FINDXXX und das Filtern in der Hilfe (einfach mal F1 drücken und in der Hilfe suchen :wink:) auseinanderzusetzen. Denn ohne diese Funktionalität funktioniert in NAV nichts.
Diese Funktionen und die damit verbundene Funktionalität der einzelnen Feldarten ( Primärschlüssel, Sekundärschlüssel, normale Felder) sollte eigentlich Bestandteil der Ausbildung sein, wenn du hier derartige Aufgaben gestellt bekommst.

Ohne das verstanden zu haben, wirst du leider nicht sehr viel weiter kommen, und dir nicht selbst helfen können. :-(

Zu deiner Frage:

- Natürlich kannst du mit GET arbeiten, du musst nur die passenden Parameter übergeben.
- SETFILTER erwartet andere Parameter, als du angegeben hast.
- der INSERT wird sehr schnell zu einer Fehlermeldung führen, da du nicht prüfst ob der Datensatz bereits vorhanden ist, bzw. den Fehlerfall nicht abfängst.

Gruß, Fiddi

Re: Filtern

27. Januar 2015 18:56

Hallo Fiddi,

Ich würde es ja gerne, nur bin ich leider erst am Freitag an der FH und schreibe schon am Montag die Prüfungen. Da ich zuhause am PC kein NAV habe, sind mir die Hände gebunden. Kannst du mir trotzdem eventuell eine Lösung für diese Aufgabe hier aufschreiben. Anders komme ich leider nicht weiter.. :(

Diese Action soll zunächst alle Datensätze in der Tabelle 123456752 löschen und dann alle Kombinationen der Felder (Zname, Zartikel, Zjahr), die in der Tabelle 123456750 vorkommen, als Datensätze in die Tabelle 123456752 ablegen. Allerdings sollen keine doppelten Datensätze angelegt werden (Dubletten vermeiden).