Freigeben über


“Wutschen und Wedeln” Teil 3: Evanesco - und weg! Filtern wie die Zauberer

Im dritten Teil meiner kleinen Serie, möchte ich Sie mit einem Zaubertrick vertraut machen, der zumindest mich vor kurzem erst wahnsinnig verblüfft hat.

Vorbereitung

Implementiert war der vermeintliche "Trick" in einer Branchenlösung, in der man, ähnlich einem Buch.-Blatt, Zeilen verbuchen konnte. Diese Zeilen wurden als verbucht gekennzeichnet, danach aber nicht gelöscht. Implementiert war auch eine programmatische Vergabe von Zeilennummern, AutoSplitKey wurde nicht verwendet.

clip_image002

Die Ausgangslage des Buch.-Blattes ist oben zu sehen. Alle Zeilen bis zum 10.01.12 sind bereits gebucht. Die implementierte Buchungsroutine in diesem Beispiel ist recht einfach gehalten und setzt das Buchungsdatum und ein Kennzeichen.

Auch die Funktion zur Vergabe von Zeilennummern ist kein Hexenwerk und erhöht die Nummer immer um 10, Einfügen von Zeilen ist nicht erlaubt. Nicht schön, aber schnell:

clip_image004

Zum Buchen ausgewählt werden immer die letzten Datensätze mit aktuellem Belegdatum, im obigen Fall also nur die Seitenwand vom 23.01.12, Artikel 1960-S nicht, da dazwischen der Artikel vom 20.01.12 liegt.

clip_image006

Natürlich war die tatsächlich implementierte Lösung um einiges komplexer als diese Demonstration, aber es geht hier ja eher um den Effekt.

 

Der Trick

Also, frisch gebucht mit F9, erhalte ich nach der Routine folgendes Ergebnis:

clip_image008

Es wurde also, natürlich wie erwartet, nur die letzte Zeile 140 gebucht. Füge ich nun eine neue Zeile ein, wird mir die Funktion GetLineNo() die 150 zurückgeben und diese im OnInsert() Trigger der Tabelle setzen. Alles funktioniert also wie erwartet, straight forward wie der gemeine Entwickler zu sagen pflegt.

Ich sage ja immer, entwickeln ist kein Hexenwerk! Programmlogik ist oft einfach zu durchschauen, gerade bei so übersichtlichen Projekten wie diesem. Mit Magie hat das nichts zu tun…

clip_image010

Ups! Oder etwa doch?

Zunächst könnte man daran glauben. Aber wer glaubt schon an Magie? Die eilig im Classic Client aufgerufene Tabelle enthüllt – nichts. Die letzte Zeile ist die Nummer 140. Natürlich existiert sie.

clip_image011

Aber warum ermittelt die Funktion GetNewLineNo(), die nach allen Gesetzen der Logik korrekt arbeiten sollte, offensichtlich die Nummer 130 als letzten Datensatz? Befragen wir den RTC und öffnen eine zweite Instanz der Page:

clip_image013

In der Tat, spannend! Wo ist die 140? Auch nach gefühlt 17 mal F5 ändert sich trotzdem nichts am Ergebnis, in beiden Pages nicht:

clip_image015

Die zwei Pages beide geschlossen und nochmals aufgerufen zeigen 130 als letzten Datensatz. Zauberei vom Feinsten, Ladies and Gentlemen!

 

Der Hut

Um es vorweg zu nehmen: Ein Neustart des RoleTailored Client beendet die Magie und der Datensatz 140 ist wieder zu sehen. Also ein programmatisches Problem...

Ein Blick in den unteren Teil der Funktion Select(), die vor dem Buchen aufgerufen wird offenbahrt folgendes:

clip_image017

In kurzen Worten zur Funktion Select() am obigen Beispiel:

  • Filterung auf das aktuelle Arbeitsdatum (23.01.12).
  • Letzten Datensatz ermitteln und Zeilennummer (140) speichern.
  • Filter lösen und rückwärts lesen, bis entweder ein bereits gebuchter oder ein Datensatz mit einem Belegdatum ungleich dem Arbeitsdatum gefunden wird (Durchlauf 1: 140, Durchlauf 2: 130). Belegdatum 20.01.12, deshalb Schleife verlassen. Aber Achtung: MyJnl.NEXT(-1) liest noch einen weiteren Datensatz rückwärts, so dass der Zeiger nun auf Zeile 120 steht.
  • Wurde einer gefunden, dann den Datensatzzeiger wieder einen vorwärts bewegen, hier auf Zeile 130.
  • In der Filtergruppe 1 auf ungebuchte Datensätze und die folgenden Zeilen Filtern: 131..140, das schließt nur die neue Zeile 140 ein, die dann gebucht wird.

Der nächste Schritt die Funktion Deselect():

  • In Filtergruppe 1 den Filter auf „Gebucht“ entfernen
  • Letzten Datensatz mit aktuellem Arbeitsdatum lesen (140)
  • Bei Fund die Zeilen auf folgenden Bereich filtern: 0..139

Der Filter bis 139 würde erklären, warum die Zeile 140 in der aktuellen Page nicht gefunden bzw. nicht angezeigt wird. Aber warum nicht in einer neu geöffneten Page?

 

Die Auflösung

Es handelt sich dabei um ein Feature!

In Dynamics NAV gibt es die verschiedene Filtergruppen (siehe auch FILTERGROUP Function (Record): https://msdn.microsoft.com/en-us/library/dd338919.aspx). Über die Filtergruppen definieren Sie im allgemeinen Filter, die vom Benutzer nicht mehr gelöst werden dürfen oder sollen. Beispielsweise die Gruppe 2, wenn Sie Filter setzen möchten, die normalerweise über SETTABLEVIEW oder der Eigenschaft SourceTableView gesteuert werden. Diese haben dann Gültigkeit und vererben sich in weitere Objekte, sofern der Datensatz übergeben wird.

Die Gruppe 1 hat dabei eine ganz besondere Bedeutung. In der Online-Hilfe im MSDN finden Sie dazu: „Used for filters that apply globally to the entire application“. Das führt dazu, dass eine neu geöffnete Page auch nur die gefilterten Datensätze anzeigt, also die Datensätze entsprechend der in der Filtergruppe 1 vorhandenen Filter.

Die alten Hasen unter Ihnen werden das aus uralten Navision-Versionen kennen und es wurde zwischenzeitlich entfernt. Dann allerdings in Version Dynamics NAV 5.0 SP1 mit dem Hotfix 28913 auf vielfachen Wunsch wieder eingeführt. Gleiches gilt für Dynamics NAV 2009 SP1/R2.

Der globale Filter in der Gruppe 1 wirkt sich ebenfalls auf temporäre Datensätze aus.

Erläutert wird das Feature im folgenden KB-Artikel: You require a new platform feature to provide the functionality to limit the general visibility for users in Microsoft Dynamics NAV 5.0 with Service Pack 1.

Nun dürfen Sie entscheiden, welche Möglichkeiten Sie über den globalen Filter haben. Schreiben in einer gefilterte Tabelle funktioniert immer, sofern nicht bei aktiviertem Filter lesend der nächste Schlüssel über die Zieltabelle ermittelt werden muss.

Für mich war dieses Feature bis vor Kurzem unbekannt. Sollte es Ihnen auch so gehen, willkommen im Club. Winken Sie nun ab, „das kennen Sie schon“, freuen Sie sich an den 10 Minuten, in denen Sie von Ihrer Arbeit etwas abgelenkt wurden Smile

In diesem Sinne, ran an den Speck!

Carsten Scholling

Microsoft Dynamics Germany
Microsoft Customer Service und Support (CSS) EMEA

Email: cschol@microsoft.com
Microsoft Connect: https://connect.microsoft.com
Online Support: https://www.microsoft.com/support
Sicherheitsupdates: https://www.microsoft.de/sicherheit

Microsoft Deutschland GmbH
Konrad-Zuse-Straße 1
D-85716 Unterschleißheim
https://www.microsoft.de

Comments

  • Anonymous
    February 05, 2012
    "Frau K." bedankt sich für das ausführliche Beispiel ;-)

  • Anonymous
    February 05, 2012
    :P

  • Anonymous
    February 06, 2012
    Wer kennt das nicht? Man verwendet eine temporäre Record-Variable und wunder sich, warum der Datensatz, den man eingefügt hat, nicht mehr gefunden wird? Und irgendwann in einem Gespräch mit den Kollegen stellt sich herraus, dass einer von Ihnen an einer anderen Stelle die Filtergruppe 1 verwendet hat.