Dynamics AX Blog - Dynamics AX 2009 - Microsoft Dynamics AX (Axapta) - Seite 19

Momentan angezeigt werden nur Beiträge der Kategorie »Microsoft Dynamics AX (Axapta)« Filter entfernen

In den letzten Jahren, in denen ich mich fast hauptsächlich mit der Entwicklung im Umfeld von Microsoft Dynamics AX (vormals Axapta) beschäftigt habe, ist das eine oder andere Code-Fragment entstanden, von dem ich mir vorstellen könnte, daß es auch für andere AX-Entwickler ganz nützlich sein könnte. Aber auch Tips und Tricks zu dem mächtigen ERP-System werde ich in dieser Kategorie präsentieren.

RSS-Feed dieser Kategorie
Momentan angezeigt werden nur Beiträge, welche für die Dynamics AX-Version »Dynamics AX 2009« relevant sind. Filter entfernen

RSS-Feed dieser Version

Dynamics AX: Warten auf das Vorhandensein einer Datei

Manchmal ist es notwendig, in AX externe Programme (zb. per WinApi::shellExecute) aufzurufen und deren Rückmeldung abzuwarten. Mir ist z.B. in letzter Zeit immer wieder der Fall untergekommen, daß ich über ein externes Programm eine Datei erstellen musste, und diese anschließend in AX einlesen bzw. weitervearbeiten musste.

Für diesen Fall habe ich eine ganz simple Logik gebastelt, die eine bestimmte Anzahl Sekunden lang prüft, ob es die benötigte Datei schon gibt und erst dann mit den weiteren Schritten fortfährt.

static void WaitForFileExists(Args _args)
{
    int         startTime;
    int         endTime;
    int         seconds2Wait = 5;
    boolean     fileExists = false;
    fileName    searchFileName = "c:\\temp\\ax.txt";
    ;
 
    startTime   = timeNow();
    endTime     = startTime + seconds2Wait;

    while (!fileExists && timeNow() <= endTime)
    {
        fileExists = WinApi::fileExists(searchFileName);
    }

    // ...continue...
    if(fileExists)
    {
        info(strFmt("File '%1' exists", searchFileName));
    }
    else
    {
        warning(strFmt("File '%1' does not exist and time is up", searchFileName));
    }
}

 
 

Dynamics AX: Container Quicktipp

Container sind ja was feines, und aus diesem Grund verwende ich sie immer wieder gerne beim Programmieren unter Dynamics AX. Durch einen Blog-Beitrag bei SysDictCoder bin ich auf einen kleinen Trick gestossen, der mir in Zukunft etwas Tipp-Arbeit ersparen wird.

Und zwar habe ich bisher Container immer ähnlich wie im folgenden befüllt:

container fieldCon = conNull();
;
fieldCon = conIns(fieldCon, conLen(fieldCon)+1, "accountNum");
fieldCon = conIns(fieldCon, conLen(fieldCon)+1, "name");
fieldCon = conIns(fieldCon, conLen(fieldCon)+1, "zipcode");
fieldCon = conIns(fieldCon, conLen(fieldCon)+1, "countryregionid");
fieldCon = conIns(fieldCon, conLen(fieldCon)+1, "county");

Wesentlich rascher ist die folgende Schreibweise:

container fieldConFast = conNull();
;
fieldConFast += "accountNum";
fieldConFast += "name";
fieldConFast += "zipcode";
fieldConFast += "countryregionid";
fieldConFast += "county";

SysDictCoder geht in seinem Artikel etwas mehr ins Detail, deshalb meine Empfehlung dort mal vorbeizuschauen.


 
 

AX 2009 What's New Technical training - Technical

Diese Woche genoß ich einen eintägigen Ausflug in die neue Welt von Dynamics AX 2009 und lernte einige Aspekte der neuen Version aus technischer Sicht kennen. Anbei eine kurze Liste der für mich herausragensten Neuerungen:

  • Teilweise neue bzw. zumindest veränderte Oberfläche, sicherlich etwas gewöhnungsbedürftig
  • Grids sind scheinbar standard-mässig nach Excel exportierbar
  • Einführung der UTC-Timestamps, womit Zeitzonen-übergreifende Applikationen über einen AOS laufen können
  • Der Task-Rekorder ist scheinbar nun fixer Bestandteil von AX, wodurch zumindest rudimentäre Dokumentationen von Abläufen ermöglicht werden
  • Das neue Fill-Utility für Massenaktualisierungen
  • Erweiterung und Verbesserung im Umgang mit RecordSets
  • Erweiterung und Verbesserung im Umgang mit Queries (z.b. Union-Selects)
  • Einführung eines neuen, ax-basierenden Versionskontrollsystem namens MorphX VCS
  • Cross-Company-Support ermöglicht Formularen und Berichten mandantenübergreifend Daten anzuzeigen
  • Stapelverabeitung läuft komplett am AOS und wurde in einigen Belangen verbessert

Diese Liste ist weder vollständig noch wirklich validiert, hoffe in den nächsten Wochen etwas mehr Zeit mit der neuen Version verbringen zu dürfen :-)


 
 

Dynamics AX: SalesTable2LineField

In der Auftragserfassung gibt es im Auftragskopf Felder, die, wenn sie aktualisiert werden, entweder vollautomatisch bzw. nach Rückfrage beim Benutzer in den Auftragszeilen ebenfalls aktualisiert werden. Welche Felder das sind kann in den Debitorenparametern, Register Aktualisierungen über die Schaltfläche Auftragspositionen aktualisieren eingesehen werden. Dort kann auch parametriert werden, wie sich Dynamics AX bei der Aktualisierung dieser Felder verhalten soll.

Debitorenparameter - Auftragspositionen aktualisieren

Um nun ein weiteres Feld in diese Logik mitaufzunehmen bedarf es einiger Schritte. Im folgenden demonstriere ich die notwendigen Änderungen anhand des neuen Feldes DevReceiptDateRequested (abgeleitet vom EDT DevSalesReceiptDateRequested):

 

  • Neues Feld in Tabelle Salestable und Salesline anlegen
  • Das neue Feld in der Salestable in die Fieldgroup HeaderToLineUpdate integrieren
  • In der Klasse SalesTable2LineField die Methode lineUpdateDescription um das neue Feld erweitern (einfach die Logik eines bestehenden Feldes abschreiben)
  • In der Klasse SalesLineType die Methode initFromSalesTable um das neue Feld erweitern (einfach die Logik eines bestehenden Feldes abschreiben)
  • In der Klasse AxSalesline eine neue Methode wie folgt erstellen
    protected boolean isDevReceiptDateRequestedSet()
    {
         return this.isFieldSet(fieldNum(SalesLine, DevReceiptDateRequested)) ||
                this.AxSalesTable().isFieldModified(fieldNum(SalesTable, DevReceiptDateRequested));
    }
  • In der Klasse AxSalesline eine weitere Methode wie folgt erstellen
    public DevSalesReceiptDateRequested DevReceiptDateRequested(DevSalesReceiptDateRequested _DevReceiptDateRequested = dateNull())
    {
       if (!prmisdefault(_DevReceiptDateRequested))
       {
           this.setField(fieldNum(SalesLine, DevReceiptDateRequested), _DevReceiptDateRequested);
       }
     
       return SalesLine.DevReceiptDateRequested;
    }
  • In der Klasse AxSalesline eine dritte neue Methode wie folgt erstellen
    protected void setDevReceiptDateRequested()
    {
       if (this.isMethodExecuted(funcName(), fieldNum(SalesLine, DevReceiptDateRequested)))
       {
           return;
       }
       if (this.isDevReceiptDateRequestedSet())
       {
           this.DevReceiptDateRequested(this.AxSalesTable().DevReceiptDateRequested());
       }
    }
  • In der Klasse AxSalesLine muss nun die Methode setTableFields um den Aufruf der zuvor angelegten Methode setDevReceiptDateRequested erweitert werden
  • In der Klasse AxSalesTable eine neue Methode wie folgt anlegen
    protected void setDevReceiptDateRequested()
    {
        ;
        if (this.isMethodExecuted(funcName(), fieldNum(SalesTable, DevReceiptDateRequested)))
        {
            return;
        }
    }
  • In der Klasse AxSalesTable eine weitere Methode wie folgt anlegen
    public DevSalesReceiptDateRequested DevReceiptDateRequested(DevSalesReceiptDateRequested _DevReceiptDateRequested = dateNull())
    {
        ;
        if (!prmisdefault(_DevReceiptDateRequested))
        {
            this.setField(fieldNum(SalesTable, DevReceiptDateRequested), _DevReceiptDateRequested);
        }
    
        return salesTable.DevReceiptDateRequested;
    }
  • In der Klasse AxSalesTable muss nun die Methode setTableFields um den Aufruf der zuvor angelegten Methode setDevReceiptDateRequested erweitert werden
  • Nun muß noch folgender Code einmalig ausgeführt werden (z.B. per Job) um das neue Feld in die Aktualisierungslogik einzubinden
    SalesTable2LineParameters salesTable2LineParameters;
    ;
    ttsbegin;
    salesTable2LineParameters.clear();
    salesTable2LineParameters.initValue();
    salesTable2LineParameters.fieldId           = fieldNum(SalesTable, DevReceiptDateRequested);
    salesTable2LineParameters.table2LineUpdate  = Table2LineUpdate::Prompt;
    salesTable2LineParameters.insert();
    ttscommit;

Übrigens, die gleiche Logik gibt es natürlich auch einkaufsseitig. Die obige Abfolge und die Codebeispiele wurden unter AX3 entwickelt.

Update vom 28.07.2010: In Dynamics AX 2009 funktioniert die beschriebene Lösung genauso. Lediglich beim auszuführenden Job hat sich der Datentyp des Feldes table2LineUpdate geändert.


 
 

Dynamics AX: Methode des "Callers" aufrufen

Immer wieder besteht die Notwendigkeit, ein Formular über ein anderes zu öffnen und aus diesem heraus Methoden des Aufrufers aufzurufen.

Einfaches Beispiel: Ich öffne aus der Auftragsmaske (Salestable) irgendein anderes Formular (über einen MenuItemButton) und möchte nun beim Schliessen dieses Formulares eine Methode in der Salestable-Maske aufrufen.
Um dies zu realisieren muß ich einfach in der Close-Methode des Subformulars folgenden Code einbinden. myMethod steht dabei für die aufzurufende Methode des Salestable-Formulares.

Achtung: IntelliSense funtioniert in diesem Fall nicht (außer ich möchte eine Methode aufrufen, die im FormRun-Objekt enthalten ist).

if (element.args() && element.args().caller())
{
    if (element.args().caller().name() == formStr(Salestable))
    {
        element.args().caller().myMethod();
    }
}

 
 

Dynamics AX: Excel-Datei erstellen aus einer CSV-Datei

Manchmal ist es notwenig, aus Dynamics AX heraus per X++ eine "echte" Excel-Datei zu erstellen. Dazu stellt AX ja bekanntermaßen Objekte wie SysExcelApplication, SysExcelWorkBooks usw. zur Verfügung. Der Nachteil dieser Objekte ist rasch erwähnt: Sie sind langsam!

Aber es geht auch wesentlich rascher, allerdings mit dem Umweg per TextIO zuerst eine CSV-Datei zu erstellen und diese anschließend von AX in eine Excel-Datei umzuwandeln.

Der Code für letztere Umwandlung ist diesem Microsoft-Knowlegebase-Artikel zu entnehmen (erfordert PartnerSource-Zugriff).


 
 

Dynamics AX: Notizen zu Labelfiles

Es gibt vier verschiedene Dateien, in welchen serverseitig Informationen zu Labels gespeichert werden:

Datei-erweiterung Beschreibung
*.ald Axapta Application Label Data
  Kann per Editor bearbeitet werden (z.b. Notepad). Ist gleichzeitig auch die einzige Datei, die man selbst bearbeiten kann/soll
*.alc Axapta Application Label Comments
  Axapta Application Label Comments
*.ali Axapta Application Label Index
  Diese Dateien können eigentlich jederzeit gelöscht werden, sie werden zu verschiedenen Zeitpunkten automatisch neu generiert (z.B. wenn der Client gestartet wird, wird zumindest jenes Index-File in der gerade verwendeten Sprache erstellt; Wenn man im Labeleditor nach einem Label sucht, werden die Index-Files aller Sprachen neu aufgebaut)
*.alt Axapta Application Label Temp Store
  Hier werden Labels temporär gespeichert, wenn ein Entwickler welche anlegt Erst bei Beenden des Clients bzw. des AOS werden diese neuen Label ins ald-File übertragem (dazu wird übrigens kurzfristig ein alb-file generiert)

 

Bei den Datetypen, ald, alc und ali existiert pro Sprache und Labelfile jeweils eine Datei im AX-Applikationsverzeichnis (z.b. axSYSde-at wobei SYS für die Labeldatei und de-at für die jeweilige Sprache steht).

Bei den alt-Dateien existiert lediglich pro Sprache eine eigene Datei (z.b. axap*.alt wobei * für die jeweilige Sprache steht).

Einige Labels werden allerdings clientseitig im bin-Verzeichnis gespeichert. Dies sind z.b. jene des Menüs (Datei - Bearbeiten - Werkzeuge ...). Hier gibt es eigene Dateitypen:

Datei-erweiterung Beschreibung
*.ktd Axapta Application Kernel Translation Data
  Kann per Editor bearbeitet werden (z.b. Notepad). Ist gleichzeitig auch die einzige Datei, die man selbst bearbeiten kann/soll
*.kti Axapta Application Kernel Translation Index

Bei beiden Dateitypen existiert pro verwendeter Sprache jeweils eine Datei.

Da die Dateien clientseitig installiert sind, kann rein theoretisch jeder Client zumindest diese Texte anpassen, ob das Sinn macht bleibt dahingestellt. Außerdem besteht die Gefahr die Datei, durch Tippfehler oder wenn man die ktd-Datei im falschen Zeichensatz bearbeitet, zu zerstören. Dann ist der Client nicht mehr startbar!

In dieser ktd-datei werden übrigens auch einige andere Dinge gesteuert. Zum Beispiel liefert in einem deutschen AX die Abfrage

if("a" == "ä")

immmer true zurück. Grund hierfür ist die nachstehende Passage im zur deutschen Sprache gehörigen axsysde-at.ktd

>#97
>TC_COLSEQ
>Definition of collating sequence mapping
>This table is used when sorting letters and strings
>First line is the letters to be mapped
>Second line is the corresponding letter to map to
AàáâãäÀÁÂÃÄBCçÇDEèéêëÈÉÊËFGHIìíîïÌÍÎÏJKLMNñÑOòóôõöÒÓÔÕÖPQRSTUùúûüÙÚÛÜVWXYýÝZæøåÆØÅ
aaaaaaaaaaabcccdeeeeeeeeefghiiiiiiiiijklmnnnooooooooooopqrstuuuuuuuuuvwxyyyz~¦Ç~¦Ç

 


 
 
Seiten « 1 ... 16 17 18 19 20 » 

 

 
 
 
Beiträge des aktuellen Monats
Mai 2024
MoDiMiDoFrSaSo
 12345
6789101112
13141516171819
20212223242526
2728293031 
 
© 2006-2024 Heinz Schweda | Impressum | Kontakt | English version | Mobile Version
Diese Webseite verwendet Cookies, um Benutzern einen besseren Service anzubieten. Wenn Sie weiterhin auf der Seite bleiben, stimmen Sie der Verwendung von Cookies zu.  Mehr dazu