Der NAV-Entwickler Kurs (für Rookies)- Part 2: der erste AL Code

Veröffentlicht: 17. Juli 2012 in Allgemein, Der NAV-Entwickler Kurs, Rookie, Tipp

So, wollen wir uns ersteinmal vor weiterer trockener Theorie drücken und fangen vor unserem Projekt an, eine kleine Übungsaufgabe zu programmieren. Die Aufgabe wird sein, einen sechsseitigen Spielwürfel zu entwickeln. Dies ist eine Aufgabe, die fernab der Realität ist, da diese Zufallszahlen in einem ERP System kaum Sinn ergeben (falls er ein realistisches Szenario dafür hat, ich würde es gern im Kommentarbereich lesen :D).

Zu Allererst startest du Dynamics NAV mit einer Entwicklerlizenz (Lizenz im zweifel per Ändern laden) und wählst über Datei->Datenbank->Öffnen deine Datenbank aus (wenn nicht schon geöffnet).
Nachdem du über Strg+O oder Datei->Mandant->Öffnen den Mandanten gewählt hast, brauchen wir den Object Explorer. Dieser ist das wichtigste Fenster für den Entwickler, denn dort hat man alle Objekte in einer Übersicht vor sich und kann neue erstellen.

Um einen Würfel zu realisieren, brauchen wir eine Oberfläche. In der aktuellen NAV Version (2009 R2) können wir noch Forms verwenden, was wir in diesem Fall auch tun werden.

Klicke also auf Form dann unten auf den Button [New].

In unserem Fall brauchen wir keine Datenquelle, da der Würfel nur unser Ergebnis anzeigen, aber nicht speichern soll. Also verwenden wir „Create a blank form“. Du kannst, bzw. solltest dich sogar in einer ruhigen Minute aber dennoch daran machen, die weiteren Optionen in diesem Assistenten zu testen und damit rumspielen. Diese nehmen einem häufig viel arbeit am Anfang ab. Wenn der Assistent mit [Ok] bestätigt wurde, erscheint das folgende Fenster.

ich habe dies mit der ID 90555 und den treffenden Namen  „Dice“ gespeichert (Datei->Speichern oder strg+s).
Daraufhin können wir uns über das Design der Anwendung gedanken machen. Dies darf in keiner weise vernachlässigt werden, denn auch bei Software wirkt der erste Eindruck. Ich habe mir angewöhnt so Standard nah wie möglich zu designen, damit sich der Benutzer so schnell wie möglich zurecht findet und die Software wieder erkennt. Dazu sollte man direkt sauber Designen. Im Allgemeinen heisst das, dass die Anwendung ordentlich ausformuliert wird, die Buttons an die richgen Stellen platziert werden, keine obzöhne oder beleidigede Meldungen (Hinweis da dies sehr beliebt unter Berufsschüllern ist…ich hab nie verstanden warum…) verwenden und bekannte Eigenschaften der Controlls direkt (glues) wie gewünscht setzen …. lasse Kleinigkeiten nicht den ersten Eindruck zerstören. Ebenfalls sollte auf Tippfehler und Rechtschreibfehler geachtet werden.

Da ich in diesem Tutorial aber davon ausgehe, dass man den Standard noch garnicht kennt, werde ich dies nach bestem Wissen und Gewissen immer mit dazu schreiben (In diesemfall meine ich vor allem die Microsoft Richtlinien) 😀

Da wir uns nun schon gedanken gemacht haben, wie unser Würfel aussehen soll, designen wir unsere Form wie folgt. Wie dies genau funktioniert, wird kann nach der kurzen Erläuterung erklärt. Du kannst allerdings gerne versuchen dies ohne meine Beschreibung zu erstelllen:

Hierbei habe ich folgendes erstellt:

  1. Textbox für die Würfelausgabe
  2. Button zum würfeln
  3. Button um den Würfel zu reseten

dabei wurde folgendes beachtet:

Controlbeschreibung

Würfelausgabe:
  • Die Textbox wurde zwei Grids vom linken und rechten Rand, sowie von oben entfernt platziert
  • Die Textbox hat den HorzGlue Both: Damit zieht sich das Textfeld in die Horizontale mit dem Fenster (teste später Vollbild ;))
  • Die Textbox hat den VertGlue Top: Hiermit verankere ich die Textbox an den oberen Rand
  • Die Textbox wird auf Editable No gesetzt
  • Variable „DiceResult“ vom Typen Integer erstellen
  • Der Textbox die Variable „DiceResult“ zuweisen. Dies wird über die Eigenschaft „SourceExpression“ sichergestellt.
[Würfeln]-Button
  • Diesen Button an den unteren rechten Rand geschoben
  • Zwei Grids von Rechts und von unten vom Form-Rand entfernt
  • Dieser Button hat den HorzGlue auf Right: Dieser Button bleibt immer am Rechten Rand
  • Dieser Button hat den VertGlue auf Bottom: Hiermit bleibt der Button immer am „Boden“ 😉
  • Die Eigeschaft „CaptionML“ wie folgt gesetzt: „DEU=Würfeln;ENU=Roll the Dice“
[Würfel-Zurücksetzen]-Button
  • Diesen Button an den unteren rechten Rand, links neben den „Würfeln“-Button geschoben
  • Zwei Grids von dem  „Würfeln“-Button und von dem unteren  Form-Rand entfernt
  • Dieser Button hat den HorzGlue auf Right: Dieser Button bleibt immer am Rechten Rand
  • Dieser Button hat den VertGlue auf Bottom: Hiermit bleibt der Button immer am „Boden“ 😉
  • Die Eigeschaft „CaptionML“ wie folgt gesetzt: „DEU=Würfel-Zurücksetzen;ENU=Reset Dice“

Wie designe ich diese Form?

Derzeit haben wir noch die leere Form, wie im Screenshot zuvor gezeigt. Um hier Controls (Buttons, Textbox etc.)  zu erstellen, muss die Toolbox eingeblendet werden:  Dies geht entweder über das Werkzeugsymbol oder über Ansicht->Toolbox. Hier gibt es eine kleine Auswahl an Controls. In unserem Fall brauchen wir oben Rechts die TextBox. Diese ist nicht zu verwechseln mit dem Label daneben. In dem Label können keine Dynamischen Daten eingetragen werden sondern immer nur ein Fester Wert. Wir brauchen hier aber immer unser Würfelergebnis, also wird die TextBox verwendet.

Klicke auf das Symbol in der Toolbox und klicke erneut (nicht gedrückt halten oder ähnliches) in das leere Fenster. Nun siehst du die TextBox.  Nun brauchen wir die zuvor beschriebenen Eigenschaften des Controls. Diese findest du entweder wieder in der Symbolleiste oder über Ansicht->Properties. Alternativ (mein Favorit) verwendet man das Tastenkürzel Shift+F4. Daraufhin öffnet sich eine lange Liste mit vielen Einstellmöglichkeiten. Dies sind die Eigenschaften! Hierüber können Beschriftungen, Positionen, Größen, Schriftarten, Funktionen, Farben etc. gesteuert werden. Da wir aber nur die oben genannten Eigenschaften benötigen, setze die Werte bitte wie beschrieben.

Um die Buttons zu positionieren verwendest du aus der ToolBox das vierte Symbol von oben links vertikal gezählt. Hier kannst du, wie gerade beschrieben, die Eigenschaften öffnen und die des Buttos nach belieben verändern. Bitte versuch dich vorerst an die oben beschriebenen vorgaben zu halten. Witzigerweise ist Horz,- und Vertglue genau entgegegesetzt von dem, was der Styleguide verwendet.

Was ist ein Grid?

Es wurde in der Controlbeschreibung definiert, wieviele „Grids“ das Control z.B. vom Rand entfernt sein soll. Ein Grid ist laut Übersetzung ein Gitter und genau ein solches ist über einer Form. Dieses sieht man nicht ist aber da, um Controls etwas kontrollierter zu Platzieren. Wenn du dir ein Control mit der Maus einmal schnappst und versuchst zu verschieben, dann merkst du, das dies nicht milimeter genau Funktioniert, sondern immer an gewissen Stellen „einrastet“. Dies wird „ein Grid“ genannt. Das heisst, zwei „einraster“ = zwei Grids. Solange man die Einstellungen nicht verändert, ist der Styleguide das jede Form einen Rand von zwei Grids besitzt. Das bedeutet, dass kein Control bis an den Rand geht, sondern immer zwei Grids in die Form Mitte verschoben wird.  Ausserdem werden Buttons unten Rechts in die Ecke zwei Grids unter dem letzten Control gesetzt. Jeder weiterer Button wird zwei Grid links von dem letzten Button angelegt.

In einer Form und in der RequestForm des Classic Client Reports gibt es für die Form selbst, die Eigenschaften HorzGrid und VertGrid. Hiermit kann das Grid nach belieben verändert werden. Allerdings wird damit der Styleguide ziemlich sicher gebrochen. Nebenher, wenn man die Grid-Funktion nur kurz deaktivieren will geht dies über Format->Snap to Grid. Wenn diese Option deaktiviert wurde, kann ein Control an jede Stelle des Forms platziert werden.

Nun verschiebe die Buttons und die Textbox, wie beschrieben an die entsprechenden Stellen.

Damit ist die Form an und für sich Fertig.

Der erste AL Code!

Wir wollen einen Würfel Programmieren! also, was braucht man für einen Würfel? eine Zufallszahl zwischen Eins und Sechs (wir gehen mal von einemm 6-er Würfel aus)  und hier sind die Stichpunkte die man dafür benötigt: RANDOM und RANDOMIZE. Auf dem Klick unseres Würfelbuttons soll eine Zahl zwischen Eins und Sechs erscheinen und dafür brauchen wir die Funktion-NAV „RANDOM“ die zu Deutsch „Zufall“ bedeutet:

Zu dem Random-Befehl sagt uns die Dynamics NAV Hilfe dies: „returns a pseudo random number“. Das bedeutet im Klartext: Immer wenn die Funktion RANDOM verwendet wird, kommen die selben Zahlen in der selben Reihenfolge. Mit anderen Worten: Jedesmal wenn wir unseren Würfel neustarten kommen die selben Zahlen in der gleichen Reihenfolge.

Dies ist in fast allen Programmiersprachen der Fall, da ein Computer eigentlich gar keine Zufälle kennt. Daher verwendet der RANDOM Befehl eine gewisse (immer gleiche) Reihenfolge auf Basis eines internen Wertes. Dieser interne Wert kann mit Hilfe von RANDOMIZE gesetzt und verändert werden:

Über den Parameter Seed kann ein neues neues Set von Nummern für die RANDOM Funktion erstellt werden.

Kleiner Ex-Kurs, Syntax einer Funktion:

Funktion(Parameter);

Das heisst wenn wir hier nun Beispielhaft Randomize benutzen:

RANDOMIZE(5);
MESSAGE( FORMAT( RANDOM(6) ) );

auf einen Button programmieren würden, würde mit dem internen Wert 5 ein neues Set an Zahlen erstellt werden. Dies wird mit jeder verwendung von RANDOM von vorn durchgegangen. Wir haben also eine Variation zu dem Zahlenset ohne unser Randomize.

Durch den Parameter bei RANDOM wird die maximal höchste Zahl definiert. In unserem Beispiel ist die Maximal höchste Zahl also Sechs.

Wir haben noch immer keine richtigen Zufallszahlen aber sind schon nahe dran!

Um im im besten Fall immer ein neues Set an Zahlen zu bekommen, brauchen wir also für Randomize eine sich ändernde Zahl. Was ändert sich regelmäßig? Genau, die Uhrzeit! Also verwenden wir die Zeit (TIME) um Randomize zu füllen. Da Randomize allerdings eine Variable vom DatentypInteger“ benötigt, müssen wir unsere „Time“ in Integer umwandeln (Typecasten).  Aber fangen wir mal klein an:

Der NAV Befehl „TIME“ gibt die aktuelle Uhrzeit mit Sekunden zurück und diese wollen wir für Randomize verwenden. Also kopieren wir uns TIME ersteinmal in eine Text Variable.

Wie erstelle ich eine Variable in NAV?

Um die Variable vom Datentypen Text zu erstellen, muss man im Vorfeld folgendes Wissen: Es gibt Globale und Lokale Variablen. Diese beiden Unterscheiden sich nur im sogenannten „Scope“ (dt. Bereich). Das bedeutet, wie weit wir die Variablen in der Porgrammierung noch im Zugriff haben.

  • Globale Variablen: Überalll in diesem  NAV Objekt im Zugriff. Das bedeutet, wenn so eine Variable angelegt wurde, dass diese in jedem Trigger, jeder Funktion etc. im Zugriff ist. Nicht aber in Irgendeinem anderen Objekt.
  • Lokale Variablen: Sind nur in der aktuellen Funktion im Zugriff. Soll heissen: Wenn eine Lokale Variable in einem OnPush-Trigger angelegt wird, dann kann diese auch nur in diesem Ereignis angesprochen werden.

Variablen erstellt man, anders als in vielen anderen Programmiersprachen nicht im Code selbst, sondern über einen Menüpunkt: Ansicht–>Globale/Lokale Variable. Für unseren Fall benötigen wir eine Globale Variable die wir einfach TimeTxt nennen. Hier vergeben wir nun den Typen Text und die Maximale länge von 30 Zeichen (dies kann bei belieben gerne optimiert werden ;)). Nun kann diese Variable überall in dem Fenster verwendet werden.

Auf Knopfdruck Code Ausführen

Nun setzten wir unseren ersten Trigger/Event. Ein Trigger (Synonym Event) ist nichts anderes als ein bestimmtes Ereignis, welches an einer bestimmten Stelle eintritt. Zum Beispiel das klicken auf unseren Knopf, welchen wir auch nun das erste mal verwenden und auch das erste mal Code verwenden können:

Klicke im Designer auf den „Würfeln„-Button und drücke F9 (Alternativ Ansicht–>C/AL Code) und gebe dort den folgenden Code ein:

TimeTxt := FORMAT(TIME);
MESSAGE(TimeTxt);

Jedesmal wenn nun auf den Button geklickt wird, wird die aktuelle Zeit angezeigt. Das FORMAT() ist eine Internefunktion die sehr mächtig ist, wir verwenden sie aber diesesmal nur um aus einer Time Variable eine Text Variable zu machen (Typecasting). Genau für diesen Zweck brauche ich die Funktion am meisten 😉

Dieser sich veränderner Wert kann nun verwendet werden um immer ein neues Set aus „Zufallszahlen“ zu bekommen.

Das Symbol Menu

Da es in Dynamics NAV kein intellisense gibt, gibt es diese geniale Alternative! Überall wo wir Zugriff auf den Programmcode haben, können wir über Extras–>Symbol Menu oder F5 dieses öffnen. Dort werden die System Variablen, System Funktionen, Lokale und Globale Variablen, Unterfunktionen der Variablen (wenn diese z.B. Codeunits sind), interne Funktionen etc…. aufgelistet.
Hier kann man also gelegentlich mal nach interessanten Funktionen stöbern. Es erscheinen mit neuen Versionen auch häufig neue Funktion.

Schneiden wir den Text in Integer!

Da wir in dem Parameter Seed von Randomize einen Integer (also eine Ganzzahl) benötigen, müssen aus der Uhrzeit die Punkte heraus, da diese in eine Ganzzahl nicht herein passen. Außerdem ist es von Vorteil, wenn wir eine neue Variable anlegen, in der wir diese geschnittene Uhrzeit festhalten. Also legen wir (wie in „Wie erstelle ich eine Variable in NAV“?) eine Variable vom Typ Integer an, die TimeInteger heißt. Um diese ordentlich zu befüllen, schreiben nun den folgenden Code:

TimeTxt := FORMAT(TIME);
EVALUATE(TimeInteger, DELCHR(TimeTxt, '=',':'));

Mit DELCHR löschen wir  jeden Doppelpunkt aus unserem TimeTxt und diesen geschnittenen Text, Typecasten( 😉 ) wir  in TimeInteger mit Evaluate (bitte alles weitere dazu in der C/Side Reference Hilfe heraus suchen).

Diesen Integer-Wert könnten wir über den folgenden Befehl anzeigen lassen:

MESSAGE( FORMAT( TimeInteger ) );

Wir nutzen diesen Wert aber nun als Seed Parameter in RANDOMIZE:

TimeTxt := FORMAT(TIME);
EVALUATE(TimeInteger, DELCHR(TimeTxt, '=',':'));
RANDOMIZE(TimeInteger);

Aufgrund eines nicht definierbaren NAV Problems, darf dieser Code nicht direkt in dem onPush des Buttons, sondern sollte ausgelagert werden. Ich schlage vor, dies immer bei öffnen der Form (in dem OnOpen Trigger) auszuführen. Also fokussiere auf deiner Form im Designer nur die Hauptform (ESC bis zur Schliessen-Abfrage, diese zur not mit „Abbrechen“ schliessen) und drücke F9 um in den C/AL Code zu gelangen. Hier sehen wir die verschiedenen Events und in dem „OnPush“ fügen wir den Code ein. Das bedeutet, dass immer beim starten des Fensters die aktuelle Zeit verwendet wird, um ein neues Set an pseudo Zufallszahlen zu generieren. So hat man mit jedem Start des Fensters eine andere Zufallszahlreihenfolge.

Mit all diesen Events können verschiedenste Anforderungen gelöst werden. Mein Tipp ist, die Hilfe der Form Triggers einfach mal zu überfliegen (suche in der Online Hilfe nach „C/Side Form Trigger“, der erste Treffer).

Endlich wird gewürfelt!

Nun entwickeln wir Endlich das finale Würfeln. Wenn wir nun wieder in den OnPush Trigger des Buttons gehen, löschen wir erst den ganzen bestehenden Code daraus und tragen nur die folgende Zeile ein:

DiceResult := RANDOM(6);

Jetzt starten wir die Form über Datei–>Run oder der Tastenkombie STRG+R und klicken auf würfeln! und voila, es wird eine Zufallszahl zwischen 1 und 6 ausgegeben. Beim nächsten Starten des Würfel-Fensters wird es eine andere Reihenfolge von Würfelergebnissen geben, dies stellen wir im OnRun Trigger sicher.

Und zu guter letzt brauchen wir noch die „Würfel zurücksetzen“ Funktion. Dafür brauchen wir nur in das Event des entsprechenden Buttons..

CLEAR(DiceResult);

.. einprogrammieren und auch diese Funktion, kann getestet werden!

So, das wars für diesen Teil ersteinmal! Ich hoffe es hat euch trotz der großen Verzögerung gefallen. Bitte lasst euch doch im Kommentarbereich aus, wie Sinnvoll und gelungen dieser Artikel ist.

Mit freundlichen Grüßen, Matthias König

Kommentare
  1. winfy sagt:

    Gut das du den 2. Teil erstellt hast! Gute Arbeit!

    Ich wollte nur darauf hinweisen das RANDOMIZE() ohne Parameter automatisch die Uhrzeit (in ms) nimmt.
    Aber hier ging es ja auch nicht darum den kürzesten Code zu finden. 😉

    mfg,
    winfy

  2. winfy sagt:

    Ich habe dank eines Forums auch gerade herausgefunden das die erste Pseudozufallszahl immer ungerade ist. Demnach würfelt man hier am Anfang nie eine 2,4 oder 6…

    Lösung am Anfang nach dem Randomize schon vorher 2 bis 3 mal Random ausführen und erst dann die Pseudozufallszahlen verwenden…

    mfg,
    winfy

  3. Ahh Danke für die Hinweise 🙂
    Das mit dem mehrmals Randomize hatte ich kurz nach dem Beitrag auch erfahren aber wollte das erstmal rauslassen, da man das nicht ordentlich erklären könnte. Danke dennoch 🙂

  4. Anonymous sagt:

    lol ist das alles -2 seiten?

  5. Hallo Anonym 😉

    naja, leider bisher schon. Ich versuche den Blog zwischen Arbeit, Familie, Freunde und Freizeit zu pflegen und komme aktuell einfach nicht mehr dazu 😉 ergo: ganz ruhig Anonym. Das hier ist alles auf rein privater Basis, daher kann man sich IMO auch Zeit lassen.

    Gruß,
    Matthias König

  6. Good day! This is my first visit to your blog! We are a team of volunteers and starting a new project in a community in the same niche. Your blog provided us beneficial information to work on. You have done a outstanding job!

  7. Mario sagt:

    Hallo, danke für den kleinen Exkurs – Beschäftige mich in letzter Zeit immer mehr mit NAV und habe schon die eine oder andere Kleinigkeit realisiert und würde mich gerne etwas austauschen – bei Interesse bitte melden – die email Adresse sollte für dich ja sichtbar sein 😉

    lg

    P.s.: Mandanten öffnen lassen sich auch über F12

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s