Dynamics AX Blog - Dynamics AX 2009 - Seite 13

RSS-Feed dieser Version
Zertifizierungsprüfung Microsoft Dynamics AX 2009 Trade & Logistics
07.12.2009In eigener Sache
Heute morgen habe ich eine weitere Microsoft Zertifizierungsprüfung - der genaue Titel lautete Microsoft Dynamics AX 2009 Trade & Logistics - erfolgreich abgelegt. |
PageFooter sind nicht immer dort, wo sie sein sollten
04.12.2009Microsoft Dynamics AX (Axapta)
Ich kenne kein einziges AX-Projekt, in dem nicht zumindest einer der Berichte Auftragsbestätigung, Ausgangslieferschein oder Ausgangsrechnung angepasst worden sind. Und deshalb stolpere ich auch immer wieder über das selbe Problem: Man erweitert einen Bericht (Report) um einen PageFooter, der aber nicht auf jeder Seite angedruckt werden soll. |
Vorsicht beim Mandanten duplizierenDaß man einen Mandanten/Unternehmen duplizieren kann, ist bekannt. Die Erfahrung der vergangenen Wochen hat mich in dem Zusammenhang folgendes gelehrt:
Um sicherzustellen, daß man der einzige Benutzer im System ist, sollte man alle anderen deaktivieren. Außerdem sollte man vor dem Kopiervorgang ein Datenbank-Backup anlegen und nach der erfolgten Aktion den Quell- und Zielmandant hinsichltich doppelter Datensätze vergleichen. Hierfür kann man sich der Funktion "Anzahl der Datensätze" bedienen. |
Alle Felder einer Tabelle auflisten
22.11.2009Microsoft Dynamics AX (Axapta)
Kurzes Codebeispiel, wie man alle Felder einer Tabelle auflistet: static void ListFieldOfTable(Args _args)
{ dictTable dictTable; int currFieldId = 0; counter c = 0; ; dictTable = new dictTable(tableNum(custtable)); do { currFieldId = dictTable.fieldNext(currFieldId); info(dictTable.fieldName(currFieldId)); c++; } while (c < dictTable.fieldCnt()); }
|
Arbeiten mit dem aufrufenden Objekt einer Form (Caller)Nachstehende Methode enthält einige Snippets, die in einem Formular verwendet werden können, um in Dynamics AX diverse Funktionen/Methoden des Aufrufenden Objektes aufzurufen. Ändert man element.args() auf z.b. _args und übergibt der Methode diese als Parameter, kann die selbe Logik auch aus einer Klasse heraus verwendet werden. void workWithCallingRecord() { common common; object object; formDataSource formDataSource; formRun formRun; inventDim inventDim; salesTable salesTable; int i; ; // Call method from calling record if( element.args() && element.args().record() ) { common = element.args().record(); if(common.isFormDataSource()) { info(tableId2Name(common.TableId)); if(formDataSourceHasMethod(common.dataSource(), identifierStr("someMethod"))) { object = common.dataSource(); object.someMethod(); } } } // Call method from calling form if(element.args() && element.args().caller() && element.args().caller().handle() == className2Id('formRun')) { formRun = element.args().caller(); if(sysFormRun::hasMethod(formRun, identifierStr("someFormMethod"))) { object = formRun; object.someFormMethod(); } } // Get value from calling record if( element.args() && element.args().record() ) { common = element.args().record(); if(common.TableId == tableNum(salesTable)) { info(common.(fieldNum(salesTable, salesId))); } } // Get value from calling datasource (form with multiple datasources) if(element.args() && element.args().caller() && element.args().caller().handle() == className2Id('formRun')) { formRun = element.args().caller(); for (i = 0; i <= formRun.dataSourceCount(); i++) { formDataSource = formRun.datasource(i); if (formDataSource && formDataSource.table() == tablenum(inventDim)) // Search for specific table { inventDim = formDataSource.cursor(); break; } } if(inventDim) { info(inventDim.InventLocationId); } } // Change data in calling datasource if(element.args() && element.args().caller() && element.args().caller().handle() == className2Id('formRun')) { formRun = element.args().caller(); for (i = 0; i <= formRun.dataSourceCount(); i++) { formDataSource = formRun.datasource(i); if (formDataSource && formDataSource.table() == tablenum(salesTable)) // Search for specific table { salesTable = formDataSource.cursor(); break; } } if(salesTable) { // Update data salesTable.PurchOrderFormNum = "Some value"; salesTable.update(); } } // Refresh calling datasource if( element.args() && element.args().record() ) { common = element.args().record(); if(common.isFormDataSource()) { formDataSource = common.dataSource(); formDataSource.research(true); } } } |
Dynamics AX mit einem bestimmten Windowslogin starten
08.11.2009Microsoft Dynamics AX (Axapta)
Gegenüber früheren Versionen von Dynamics AX hat man - dank Integration des Active Directories - in AX 2009 kaum Möglichkeiten, die Anwendung als ein bestimmter Benutzer zu starten. Gerade dies ist aber notwendig, wenn man z.B. Änderungen in den Sicherheitseinstellungen/Berechtigungen überprüfen möchte. Für solche Fälle habe ich mir eine Batch-Datei (*.bat) geschrieben, die mir eine lokale AX-Installation mit einem bestimmten Windows-Login startet. Diese Batch-Datei öffnet ein Windows-Kommandozeilen-Fenster in welchem man zur Eingabe des Windows-Passworts aufgefordert wird. runas /user:domain\username "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe "C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc"" Wenn man diese Befehlszeile direkt in der Eingabeaufforderung eingeben will, muss man den Befehl wie folgt leicht abwandeln: runas /user:domain\username "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe \"C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc\"" Muss man ausser der Konfigurationsdatei noch weitere Parameter übergeben, kann man die Batch-Datei wie folgt erweitern: runas /user:domain\username "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe "C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc" -aol=var -aolcode=j+eA4566458bsZReSO1Q==" Der selbe Befehl sähe, wenn man ihn über die Eingabeaufforderung eingeben wollte, wie folgt aus: runas /user:domain\username "C:\Programme\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe \"C:\Programme\Microsoft Dynamics AX\50\MyConfigurationfile.axc\" -aol=var -aolcode=j+eA4566458bsZReSO1Q==" Alternativ dazu kann man sich auch der hier beschriebenen Lösung bedienen. Übrigens: Sollte die Konfigurationsdatei auf einem Netzlaufwerk liegen, so sollte man bei der Angabe des Dateipfades nicht dessen Laufwerksbuchstaben verwenden, sondern den vollen UNC-Pfad. Denn möglicherweise hat der Benutzer, mit dem ich die Applikation starten möchte, den einzelnen Netzwerklaufwerken andere Laufwerksbuchstaben zugewiesen als man selbst ;-) |
|
|
|
|
|
|
Nachstehend Beispiele für den Zugriff auf die AX-Datenbank per SQL-Statement, diese Zugriffe müssen im übrigen immer serverseitig erfolgen (runOn-Property).
Beispiel für ein SELECT-Statement
Übrigens: Wenn folgender Fehler beim Abfragen des resultSets auftritt, kann die Ursache ein ungültiges SQL-Statement sein!