Dynamics AX Blog - Dynamics AX 2009 - Seite 20

RSS-Feed dieser Version
Dynamics AX: Notizen zu Labelfiles
22.04.2008Microsoft Dynamics AX (Axapta)
Es gibt vier verschiedene Dateien, in welchen serverseitig Informationen zu Labels gespeichert werden:
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:
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~¦Ç~¦Ç
| ||||||||||||||||||||||||||
Dynamics AX: Rechnungen per Code druckenÜber nachstehenden Code kann ganz einfach jederzeit eine Verkaufsrechnung nachträglich ausgedruckt werden. Durch leichte Modifikationen des Codes gilt dies auch für sämtliche anderen verkaufs- und einkaufsseitigen Dokumente. Hier ein kurzes Beispiel unter AX 2009 static void PrintSalesInvoice(Args _args) { custInvoiceJour custInvoiceJour; SalesFormLetter salesFormLetter = SalesFormLetter::construct(DocumentStatus::Invoice, false); PrintJobSettings printJobSettings = new PrintJobSettings(); Args args = new Args(); boolean prompt = true; boolean printIt = true; ; if (prompt) { // Auswahl des Benutzers über Dialog printIt = printJobSettings.printerSettings('SysPrintForm'); } else { // Printjobsettings per Code steuern printJobSettings.setTarget(PrintMedium::File); printJobSettings.format(PrintFormat::PDF); printJobSettings.fileName(@'c:\temp\myfile.pdf'); } if (!printIt) { return; // Benutzerabbruch } salesFormLetter.updatePrinterSettingsFormLetter(printJobSettings.packPrintJobSettings()); select firstOnly custInvoiceJour where custInvoiceJour.salesid == '100001'; args.record(custInvoiceJour); args.caller(salesFormLetter); new MenuFunction(menuitemoutputstr(SalesInvoice), MenuItemType::Output).run(args); } Nachstehend ein Code-Beispiel unter AX 4.0 static void PrintSalesInvoice(Args _args) { custInvoiceJour custInvoiceJour; SalesFormLetter salesFormLetter = SalesFormLetter::construct(DocumentStatus::Invoice, false); PrintJobSettings printJobSettings = new PrintJobSettings(); Args args = new Args(); boolean prompt = true; boolean printIt = true; salesPrintSetup salesPrintSetup; ; if (prompt) { // Auswahl des Benutzers über Dialog printJobSettings = new PrintJobSettings(salesPrintSetup.PrintJobSettings); printIt = printJobSettings.printerSettings('SysPrintForm'); salesPrintSetup.PrintJobSettings = printJobSettings.packPrintJobSettings(); } else { // Printjobsettings per Code steuern printJobSettings.setTarget(PrintMedium::File); printJobSettings.format(PrintFormat::PDF); printJobSettings.fileName(@'c:\temp\myfile.pdf'); } if (!printIt) { return; // Benutzerabbruch } salesFormLetter.updatePrinterSettingsFormLetter(printJobSettings.packPrintJobSettings()); select firstOnly custInvoiceJour where custInvoiceJour.salesid == '100001'; args.record(custInvoiceJour); args.caller(salesFormLetter); new MenuFunction(menuitemoutputstr(SalesInvoice), MenuItemType::Output).run(args); } |
CSV-Datei und Zeilenumbrüche
10.03.2008Microsoft Dynamics AX (Axapta)
Wenn man aus AX Daten in eine CSV-Datei exportieren muss, gibt es immer wieder Probleme mit Zeilenumbrüchen in mehrzeiligen AX-Feldern. Um diese zu umgehen, müssen lediglich folgende Punkte beachtet werden:
static void Export_CSV(Args _args) { TextIO textFile; CustTable CustTable; str csv(str _str) { _str = strReplace(_str, """, """"); return """ + _str + """; } ; textFile = new TextIO("c:\temp\csv_test.csv","W",0); textFile.outFieldDelimiter(";"); textFile.outRecordDelimiter(num2char(10)); // Wichtig wegen Zeilenumbrüchen!!! while select CustTable { textFile.write( csv(CustTable.Name) + ";" + csv(CustTable.Address) + ";" ); } textFile = null; } |
Fehlermeldungen in AX aussagekräftiger gestalten
10.12.2007Microsoft Dynamics AX (Axapta)
Info, warning und error sind das täglich Brot des AX-Entwicklers. Schließlich kann er über diese Befehle dem Benutzer mitteilen, was er getan hat, zu tun hat oder nicht hätte tun sollen. Und dies erfolgt in der Regel mit einer mehr oder weniger aussagekräftigen Fehlermeldung. Unterstützen kann man diese auf einfache Art und Weise mit dem zusätzlichen Parameter sysInfoAction. Anbei einige Beispiele, wie man diesen einsetzen kann: static void InfoWarningErrorExamples(Args _args) { query query; CustTable CustTable; sysInfoAction_MenuFunction sysInfoAction_MenuFunction; ; // Öffnet ein Formular mit einer Auswahl an Datensätzen (über eine Query) // Zusätzlich kann man hier ein FormControl angeben, welches nach dem öffnen den Fokus erhält query = new query(); query.addDataSource(tableNum(CustTable)).addRange(fieldNum(CustTable, AccountNum)).value('401*'); info( 'Bitte überprüfen Sie, ob bei allen betroffenen Debitoren die selbe Debitorengruppe eingetragen ist', 'APPLDOC://Tables/CustTable/CustGroup', sysInfoAction_FormRunQuery::newFormnameControlnameQuery(formStr(CustTable),'Posting_CustGroup', query)); // Öffnet nur das Formular ohne einen bestimmten Datensatz auszuwählen, man kann aber den Names // eines FormControl angeben, welches den Fokus zu öffnenden Formular erhalten soll warning( 'Bitte überprüfen Sie die Einstellungen der am Debitoren hinterlegten Debitorengruppe', 'APPLDOC://Tables/CustTable/CustGroup', sysInfoAction_FormRun::newFormnameControlnameDesc( formStr(CustTable), 'Posting_CustGroup' 'Debitorengruppe anzeigen')); // Öffnet das Formular mit einem bestimmten Datensatz und setzt den Fokus auf ein bestimmtes Feld CustTable = CustTable::find('4011'); error( 'Bitte überprüfen Sie die Einstellungen der am Debitoren hinterlegten Debitorengruppe', 'APPLDOC://Tables/CustTable/CustGroup', sysInfoAction_TableField::newBufferField(CustTable, fieldNum(CustTable, custGroup))); // Öffnet ein Formular über die Angabe des entsprechenden MenuItems // Dabei kann ein Datensatz ausgewählt werden, welcher angezeigt werden soll // ACHTUNG: Funktioniert nicht bei allen Formularen (Tabellenrelationen werden benötigt) sysInfoAction_MenuFunction = new sysInfoAction_MenuFunction(); sysInfoAction_MenuFunction.parmDataAreaId(curext()); sysInfoAction_MenuFunction.parmMenuItemType(MenuItemType::Display); sysInfoAction_MenuFunction.parmMenuItemName(identifierStr(CustTable)); sysInfoAction_MenuFunction.parmCallerBuffer(CustTable::find('4011')); info('Bitte überprüfen Sie die Stammdaten des Debitoren', '', sysInfoAction_MenuFunction); } Nachstehend die äquivalenten Befehle in AX 3.0. static void InfoWarningErrorExamples(Args _args) { query query; CustTable CustTable; sysInfoAction_FormRunQuery sysInfoAction_FormRunQuery; sysInfoAction_FormRun sysInfoAction_FormRun; sysInfoAction_TableField sysInfoAction_TableField; ; // Öffnet ein Formular mit einer Auswahl an Datensätzen (über eine Query) // Zusätzlich kann man hier ein FormControl angeben, welches nach dem öffnen den Fokus erhält query = new query(); query.addDataSource(tableNum(CustTable)).addRange(fieldNum(CustTable, AccountNum)).value('401*'); sysInfoAction_FormRunQuery = new sysInfoAction_FormRunQuery(formStr(CustTable),'Posting_CustGroup', query); info( 'Bitte überprüfen Sie, ob bei allen betroffenen Debitoren die selbe Debitorengruppe eingetragen ist', 'APPLDOC://Tables/CustTable/CustGroup', sysInfoAction_FormRunQuery); // Öffnet nur das Formular ohne einen bestimmten Datensatz auszuwählen, man kann aber den Names // eines FormControl angeben, welches den Fokus zu öffnenden Formular erhalten soll sysInfoAction_FormRun = new sysInfoAction_FormRun(formStr(CustTable), 'Posting_CustGroup', 'Debitorengruppe anzeigen'); warning( 'Bitte überprüfen Sie die Einstellungen der am Debitoren hinterlegten Debitorengruppe', 'APPLDOC://Tables/CustTable/CustGroup', sysInfoAction_FormRun); // Öffnet das Formular mit einem bestimmten Datensatz und setzt den Fokus auf ein bestimmtes Feld CustTable = CustTable::find('4011'); sysInfoAction_TableField = new sysInfoAction_TableField(CustTable, fieldNum(CustTable, custGroup)); error( 'Bitte überprüfen Sie die Einstellungen der am Debitoren hinterlegten Debitorengruppe', 'APPLDOC://Tables/CustTable/CustGroup', sysInfoAction_TableField); } Aussehen tun solche Fehlermeldungen dann zum Beispiel wie folgt |
|
|
|
|
|
|
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).