[Gelöst] Schleifenproblem

24. November 2006 10:46

Hallo zusammen,

ich habe ein kleines Schleifenproblem. Der nachfolgende Code (kleiner Auszug) steht in einer Funktion, die in einer Subform ausgeführt wird.

Code:

  VerbandKontakte.SETFILTER(VerbandKontakte."Show as Contact Person",'%1',TRUE);
  VerbandKontakte.SETFILTER(VerbandKontakte."Organization Type",'%1',VerbandKontakte."Organization Type"::City);
  IF VerbandKontakte.FIND('-') THEN
     AnzVerteiler := VerbandKontakte.COUNT;
   
  WHILE (AnzVerteiler > 1) DO BEGIN
    AnzVerteiler := AnzVerteiler - 1;
    VerteilerCode_v := VerbandKontakte."Mailing Group";
    SETFILTER("Mailing Group Code",'%1',VerteilerCode_v);
    SETRANGE("Structure No.",GliederungsNr);
  END;


Hier noch einmal meine verbale Erklärung, was der Code eigentlich machen soll:

In der Tabelle VerbandKontakte können mehrere KontaktVerteiler jeweils für einen Organisationstyp hinterlegt werden.

Es soll für jeden möglichen OrgaTyp geprüft werden, ob mehrere Kontaktverteiler bestehen. Wenn ja, dann soll der Filter entsprechend oft ausgeführt werden, sodass im Ergebnis nur die Kontakte ausgegeben werden, die für den jeweiligen OrgaTyp hinterlegt wurden.

Bsp.: Es gibt für den Orgatyp xy die drei Verteiler A, B und C. Dann filtere nur auf die Kontakte, die den Verteiler A, B und C haben.

Ich hoffe, ich konnte mein Anliegen einigermaßen verständlich erklären.
Zuletzt geändert von mgerhartz am 6. Dezember 2006 17:10, insgesamt 1-mal geändert.

24. November 2006 10:52

Kleiner Nachtrag:

Im grunde wird der Code richtig ausgeführt. Allerdings wird immer nur ein Kontakt ausgegeben. Und zwar nur der erste (VerteilerCode), der in der Tabelle VerbandKontakte hinterlegt wurde.

24. November 2006 11:03

Hallo,

Markiere die Datensätze mit MARK und nach dem alle Datensätze gekennzeichnet wurden verwende MARKEDONLEY.
(Alle mit MARK gekennzeichneten Datensätze haben links in der Tableform eine kleine schwarze Raute! )
Du kannst in mehreren durchläufen die Datensätze Markieren.

Gruß Mikka

Re: Schleifenproblem

24. November 2006 11:06

mgerhartz hat geschrieben:Hallo zusammen,

ich habe ein kleines Schleifenproblem. Der nachfolgende Code (kleiner Auszug) steht in einer Funktion, die in einer Subform ausgeführt wird. (...)


Warum schreibst du nicht einfach:

Code:
  VerbandKontakte.SETRANGE("Show as Contact Person",TRUE);
  VerbandKontakte.SETRANGE("Organization Type",VerbandKontakte."Organization Type"::City);
  IF VerbandKontakte.FIND('-') THEN
    REPEAT
      VerteilerCode_v := VerbandKontakte."Mailing Group";
      SETRANGE("Mailing Group Code",VerteilerCode_v);
      SETRANGE("Structure No.",GliederungsNr);
    UNTIL VerbandKontakte.NEXT = 0;


...oder hab' ich deine Anliegen nicht richtig verstanden?

24. November 2006 11:28

@ Striker

das habe ich auch schon probiert. Dann bekomme ich irgendwie überhaupt keine Kontakte angezeigt. Ich werde mal das mit dem MARK und MARKEDONLY probieren.

Trotzdem Danke für Deine Antwort.

24. November 2006 11:32

Hallo Striker,
ich habe es so verstanden, das alle unterschiedlichen VerteilerCode angezeigt werden sollen.
Wenn das Korrekt ist, dann würde bei deinen Code der Filter nicht zum gewünschten Ergebniss führen.
Ungefähr so müsste der Code aussehen:
Code:
VerbandKontakte.SETRANGE("Show as Contact Person",TRUE);
VerbandKontakte.SETRANGE("Organization Type",VerbandKontakte."Organization Type"::City);
  IF VerbandKontakte.FIND('-') THEN
    REPEAT
      // Schleife auf die Subform Datensätze
      IF rec.FIND('-') THEN
        REPEAT
          MARK(TRUE);                        // (Markieren zum Anzeigen)
        UNTIL rec.NEXT = 0;
    UNTIL VerbandKontakte.NEXT = 0;
MARKEDONLY(TRUE);                      // Zeige die Datensätze
 

Gruß Mikka

24. November 2006 11:35

Hallo mikka,

ja, in diesem speziellen Fall ist deine Lösung wohl die richtige :)

Grüße
Gerhard

24. November 2006 11:49

Sorry,
ich habe im Code noch einen SETRANGE auf die Subformdaten vergessen
:oops:

Code:

VerbandKontakte.SETRANGE("Show as Contact Person",TRUE);
VerbandKontakte.SETRANGE("Organization Type",VerbandKontakte."Organization Type"::City);
  IF VerbandKontakte.FIND('-') THEN
    REPEAT
      // Schleife auf die Subform Datensätze
      rec.RESET;
      rec.SETCURRENTKEY(...);      //Evtl. wg. der Performance!
      rec.SETRANGE("Mailing Group Code",VerteilerCode_v);
      SETRANGE                           // Evtl. noch weitere!
      IF rec.FIND('-') THEN
        REPEAT
          MARK(TRUE);                        // (Markieren zum Anzeigen)
        UNTIL rec.NEXT = 0;
    UNTIL VerbandKontakte.NEXT = 0;
MARKEDONLY(TRUE);                      // Zeige die Datensätze
 

24. November 2006 11:52

Hi Micha,

habe den Code wie folgt angepasst. Allerdings ist das wohl eine Endlosscheife geworden. Der Client hängt sich auf.

Code:
CASE Gliederung."Organization Type" OF
 
  Gliederung."Organization Type"::State:BEGIN

  VerbandKontakte.SETFILTER(VerbandKontakte."Show as Contact Person",'%1',TRUE);
  VerbandKontakte.SETFILTER(VerbandKontakte."Organization Type",'%1',VerbandKontakte."Organization Type"::State);
  IF VerbandKontakte.FIND('-') THEN
    REPEAT
      IF Rec.FIND('-') THEN
        REPEAT
          MARK(TRUE);                        // (Markieren zum Anzeigen)
        UNTIL Rec.NEXT = 0;
    UNTIL VerbandKontakte.NEXT = 0;

    MARKEDONLY(TRUE);
    VerteilerCode_v := VerbandKontakte."Mailing Group";
    SETFILTER("Mailing Group Code",'%1',VerteilerCode_v);
    SETFILTER("Structure No.",COPYSTR(GliederungsNr,1,2) + '??????');
END;

24. November 2006 11:56

Muss es außerdem nicht heißen

Code:
IF VerbandKontakte.FIND('-') THEN
REPEAT
  VerbandKontakte.MARK(TRUE);
UNTIL VerbandKontakte.NEXT = 0;

Schließlich will ich ja die Datensätze in der Tabelle VerbandKontakte markieren und später auf diese filtern.

24. November 2006 12:05

Wenn ich das richtig sehe werden die Verbandkontakte gefiltert und Schritt für Schritt durchlaufen (z.B. A/B/C).
Zwischen jeden Schritt, muss ein SETRANGE auf die Daten in der Subform gemacht werden, damit diese in einer Schleife Markiert werden können.

Da ich deine Form nicht kenne, gehe ich davon aus, das die Subform auf eine andere Tabelle wie Verbandkontakte zeigt, oder?
Gruß Mikka

24. November 2006 12:10

Hi Mikka,

die Subform zeigt Kontaktdaten aus der Tabelle Contact an. Und es sollen eben nur die angezeigt werden, die in der Tabelle Verbandkontakte markiert wurden. (A/B/C). Also Datensätze in der Tabelle Verbandkontakte markieren und nur diese für den Filter auf die Tabelle Contact verwenden.

24. November 2006 12:17

Und noch etwas.

Diese Zeile kann eigentlich nicht funktionieren:

Code:
rec.SETRANGE("Mailing Group Code",VerteilerCode_v);


Da ich die Variable VerteilerCode_v doch erst hier befülle:

Code:
    MARKEDONLY(TRUE);
    VerteilerCode_v := VerbandKontakte."Mailing Group";
    SETFILTER("Mailing Group Code",'%1',VerteilerCode_v);
    SETRANGE("Structure No.",GliederungsNr);

24. November 2006 12:46

Keine Idee?

Hier zum Verständnis noch mal den ganzen Part:

Code:

  Gliederung."Organization Type"::City:BEGIN
           
  VerbandKontakte.SETFILTER(VerbandKontakte."Show as Contact Person",'%1',TRUE);
  VerbandKontakte.SETFILTER(VerbandKontakte."Organization Type",'%1',VerbandKontakte."Organization Type"::City);
  IF VerbandKontakte.FIND('-') THEN
    REPEAT
      Rec.RESET;
      Rec.SETRANGE("Mailing Group Code",VerteilerCode_v);
      IF Rec.FIND('-') THEN
        REPEAT
          MARK(TRUE);                        // (Markieren zum Anzeigen)
        UNTIL Rec.NEXT = 0;
    UNTIL VerbandKontakte.NEXT = 0;
   
    MARKEDONLY(TRUE);
    VerteilerCode_v := VerbandKontakte."Mailing Group";
    SETFILTER("Mailing Group Code",'%1',VerteilerCode_v);
    SETRANGE("Structure No.",GliederungsNr);
END;

24. November 2006 13:12

mgerhartz hat geschrieben:Keine Idee?


Jetzt müsste ich deine DB haben, dann gäb's sicher auch 'ne Lösung.

24. November 2006 13:15

Tja, das dürfte schwierig werden ;-)

24. November 2006 13:54

mgerhartz hat geschrieben:Tja, das dürfte schwierig werden ;-)


Ich weiß :wink:

...aber könntest du dein Problem, bzw. deine Aufgabenstellung nicht an einem Beispiel aus der Standard-DB aufhängen?

Das würde sicher helfen :-)

24. November 2006 14:15

mgerhartz hat geschrieben:Hi Mikka,
die Subform zeigt Kontaktdaten aus der Tabelle Contact an. Und es sollen eben nur die angezeigt werden, die in der Tabelle Verbandkontakte markiert wurden. (A/B/C). Also Datensätze in der Tabelle Verbandkontakte markieren und nur diese für den Filter auf die Tabelle Contact verwenden.


Ziel ist es die Subform zu Filtern (Tabelle Contact), auf diese muss der Befehl MARK ausgeführt werden.
Um die Tabelle zu Filtern wird erst die Tabelle Verbandkontakte mit einem SETRANGE gefiltert und Zeile für Zeile durchlaufen.
Bei jedem Durchlaufsschritt müssen dann die Subformdaten Markiert werden.
Wenn alle Verbandkontakte verabeitet wurden, setzte den MARKEDONLEY.
Dann müsste es eigentlich Funktionieren. (Ich habe es nicht probiert, reine Theorie!)
Gruß Mikka

24. November 2006 15:03

Oh man! Ich habe jetzt den Code geändert und als Ergebnis kommen jetzt gar keine Kontaktdaten mehr raus. :cry:

Code:
Gliederung.GET(GliederungsNr);
RESET;
SETCURRENTKEY("Structure No.","Customer Type","Mailing Group Code");
FILTERGROUP(50000);
SETRANGE("Customer Type","Customer Type"::Member);

CASE Gliederung."Organization Type" OF
 
  Gliederung."Organization Type"::State:BEGIN

  VerbandKontakte.SETFILTER(VerbandKontakte."Show as Contact Person",'%1',TRUE);
  VerbandKontakte.SETFILTER(VerbandKontakte."Organization Type",'%1',VerbandKontakte."Organization Type"::State);
  IF VerbandKontakte.FIND('-') THEN
  BEGIN
    REPEAT
      VerbandKontakte.MARK(TRUE);                        // Markieren der VerteilerCodes in Tab. VerbandKontakte
    UNTIL VerbandKontakte.NEXT = 0;
  END;

  VerbandKontakte.MARKEDONLY(TRUE);                     // Zeige nur markierte Datensätze
  IF VerbandKontakte.FIND('-') THEN
  BEGIN
    REPEAT
      VerteilerCode_v := VerbandKontakte."Mailing Group";                  // in der Schleife soll die VAR VerteilerCode_v mit dem
      SETFILTER("Mailing Group Code",'%1',VerteilerCode_v);                // Verteiler Code gefüllt werden, um dann in der Sub-Form
      SETFILTER("Structure No.",COPYSTR(GliederungsNr,1,2) + '??????');    // (Tabelle) alle Kontakte auszugeben, auf die zuvor
    UNTIL VerbandKontakte.NEXT = 0;                                        // gefiltert wurde.
  END;
END;


Ich verstehe das nicht!

24. November 2006 17:09

Hat denn wirklich keiner mehr eine Idee?

Hier der letzte Stand meiner Versuche:

Code:
  Gliederung."Organization Type"::City:BEGIN
           
  VerbandKontakte.SETFILTER(VerbandKontakte."Show as Contact Person",'%1',TRUE);
  VerbandKontakte.SETFILTER(VerbandKontakte."Organization Type",'%1',VerbandKontakte."Organization Type"::City);
  IF VerbandKontakte.FIND('-') THEN
    REPEAT;
      VerbandKontakte.MARK(TRUE);
    UNTIL VerbandKontakte.NEXT = 0;

 
  VerbandKontakte.MARKEDONLY(TRUE);
  REPEAT;
    VerteilerCode_v := VerbandKontakte."Mailing Group";
    SETFILTER("Mailing Group Code",'%1',VerteilerCode_v);
    SETRANGE("Structure No.",GliederungsNr);
  UNTIL VerbandKontakte.NEXT = 0;
END;


- SCHLEIFE
- markiere die Datensätze der Tabelle VerbandKontakte, die in den Filter passen
- SCHLEIFE ENDE

- rufe alle markierten Datensätze der Tabelle VerbandKontakte auf

- SCHLEIFE
- fülle die Variable VerteilerCode_v
- Filter den SourceTable auf VerteilerCode_v und GliederungsNr
- SCHLEIFE ENDE (Wenn alle markierten Datensätze der Tabelle VerbandKontakt abgearbeitet wurden.
- SCHLEIFE ENDE

24. November 2006 19:09

Du hast im Mainform eine Liste von organisationstypen und und in einer nicht angezeigten Tabelle eine Liste von Verteilern für die Organisationstypen, soweit richtig?
und im Subform willst du für alle Verteiler des im Mainform ausgewählten Orgatyps die Kontakte angezeigen lassen,bei denen einer dieser Verteiler eingetragen ist, noch immer richtig?
Die Verteiler bekommst du ja schon zusammen, denke ich. Jetzt geht es nur noch darum, die Kontakte zu filtern.
Wenn du wie vorgeschlagen mit MARK arbeitest, musst du den Filter aber auch in dieser SChleife unterbringen.
Da du ja in der Subform bist, ist rec die Kontakt-tabelle.

Code:
 //hier sind deine Filter auf die Verteiler....
  IF VerbandKontakte.FIND('-') THEN begin
    rec.RESET;  //zuerst mal alle Marks von vorher löschen
    rec.SETRANGE("Structure No.",GliederungsNr);  //und gemeinsames Filterkriterium setzen
    REPEAT; //für jeden Verteiler wird diese Schleife durchlaufen
      rec.SETRANGE("Mailing Group Code",VerbandKontakte."Mailing Group");
      if rec.FIND(-) then REPEAT  //diese Schleife für jeden Kontakt des aktuellen Verteilers
        rec.MARK(TRUE);
      UNTIL rec.NEXT=0;
  UNTIL VerbandKontakte.NEXT = 0;
  rec.MARKEDONLY(TRUE);
  CURRFORM.UPDATE(FALSE) //false, damit er in den Kontakten nicht versucht etwas zu speichern.


Du musst nun nur noch dafür sorgen, dass im OnAfterGetRecord der Mainform diese Funktion in der Subform angestossen wird.
den Filter auf die Gliederungsnummer könntest du natürlich auch im Subformlink unterbringen, weiter sollte da aber nichts drin stehen.

27. November 2006 10:57

Guten Morgen Michael,

danke für Deine Antwort. Macht Sinn, was Du da geschrieben hast. Ich habe den Code wie folgt angepasst:

Code:

  Gliederung."Organization Type"::City:BEGIN
           
  VerbandKontakte.RESET;
  VerbandKontakte.SETFILTER(VerbandKontakte."Show as Contact Person",'%1',TRUE);
  VerbandKontakte.SETFILTER(VerbandKontakte."Organization Type",'%1',VerbandKontakte."Organization Type"::City);
  IF VerbandKontakte.FIND('-') THEN
  BEGIN
    VerteilerCode_v := VerbandKontakte."Mailing Group";
    Rec.RESET;
    Rec.SETRANGE("Structure No.",GliederungsNr);
    REPEAT;
      Rec.SETRANGE("Mailing Group Code",VerteilerCode_v);
      IF Rec.FIND('-') THEN
      REPEAT
        Rec.MARK(TRUE);
      UNTIL Rec.NEXT = 0;
    UNTIL VerbandKontakte.NEXT = 0;
    Rec.MARKEDONLY(TRUE);
    CurrForm.UPDATE(FALSE);
  END;
END;


Allerdings wird trotzdem immer nur ein Kontakt angezeigt. Wie Du siehst, verwende ich wieder die Variable VerteilerCode_v. Wenn ich direkt auf das Feld verweise (VerbandKontakte.MailingGroup), dann wird überhaupt kein Kontakt angzeigt. Allerdings kann die Variable immer nur einen VerteilerCode speichern. Setze ich die Variable in die Schleife, damit sie mehrfach verwendet werden kann, dann kommt auch kein Ergebnis zu stande. :-(

28. November 2006 06:40

Die Zuweisung der Variable VerteilerCode_v muss unbedingt innerhalb der äusseren Repeatschleife erfolgen, damit auch alle vorkommenden Mailinggroups durchsucht werden.
So, wie Dein Prg jetzt aussieht, suchst du bei jedem Schleifendurchlauf nach der gleichen, nämlich der ersten Mailing Group.

Mehr kann ich Dir aber jetzt ohne Ansicht der Daten nicht helfen, wenn das dann noch nicht klappt muss in den Daten irgendwo der Wurm stecken, oder ein Denkfehler bei der Datenstruktur vorliegen....

4. Dezember 2006 16:12

Sorry für die späte Rückmeldung. Ich habe es jetzt gelöst. Hier mein CodeStück:

Code:
Gliederung.GET(GliederungsNr);
RESET;
SETCURRENTKEY("Contact No.","Mailing Group Code","Alternative Gliederung");
VerbandKontakte.RESET;
VerbandKontakte.SETFILTER(VerbandKontakte."Show as Contact Person",'%1',TRUE);
VerbandKontakte.SETFILTER(VerbandKontakte."Organization Type",'%1',Gliederung."Organization Type");
IF VerbandKontakte.FIND('-') THEN
BEGIN
  REPEAT
    IF VerteilerCode_v = '' THEN
     VerteilerCode_v := VerbandKontakte."Mailing Group"
    ELSE
     VerteilerCode_v := VerteilerCode_v + ' | ' + VerbandKontakte."Mailing Group";
  UNTIL VerbandKontakte.NEXT = 0;
  SETFILTER("Structure No.",GliederungsNr);
  SETFILTER("Alternative Gliederung",'');
  SETFILTER("Mailing Group Code",VerteilerCode_v);
  IF FIND('-') THEN
    REPEAT
      MARK(TRUE)
    UNTIL NEXT = 0;
END;



Keine Ahnung, warum ich zuvor so kompliziert gedacht habe. Trotzdem nochmals danke für eure Antworten.

Gruß

Markus