Dynamics AX Blog - Beiträge von 2010 - Seite 3
Palette verlagern per X++Folgend etwas X++ Code, mit dessen Hilfe man eine Palette verlagern kann, also genau das, was die Schaltfläche "Palette verlagern" in Formular Palette tut. WMSPalletMove wmsPalletMove = new wmsPalletMove();
wmsPalletMove.parmWMSPalletId('00000022_117'); wmsPalletMove.parmToInventLocationId('300'); wmsPalletMove.parmToLocationId('01'); if(wmsPalletMove.validate()) { wmsPalletMove.run(); }
|
Liste aller Felder einer Tabelle ausgeben
24.07.2010Microsoft Dynamics AX (Axapta)
Unlängst benötigte ich eine Liste aller Felder einer Tabelle mit deren Datentypen. Dafür habe ich mir den folgenden Job - im Beispiel für die Tabelle custGroup - geschrieben:
static void listAllFields4Table(Args _args)
{
dictTable dictTable = new dictTable(tableNum(custGroup));
int currFieldId = 0;
counter c = 0;
dictField dictField;
counter a = 0;
common common;
str enumName;
;
common = DictTable.makeRecord();
setPrefix(strFmt("Fields of table %1", tableId2name(common.TableId)));
currFieldId = 0;
c = 0;
do
{
currFieldId = dictTable.fieldNext(currFieldId);
if(currFieldId != 0)
{
dictField = new dictField(common.TableId, currFieldId);
if(dictField.arraySize() == 1)
{
info( strFmt("%1: %2 [%3%4]",
dictTable.fieldName(currFieldId),
dictField.label(),
dictField.baseType(),
dictField.enumId() ? strFmt(" %1", enumId2Name(dictField.enumId())) : "")
);
}
else if(dictField.arraySize() > 1)
{
for(a=1;a<=dictField.arraySize();a++)
{
info( strFmt("%1 [%2]: %3 [%4]",
dictTable.fieldName(currFieldId),
a,
dictField.label(),
dictField.baseType())
);
}
}
}
c++;
}
while (c < dictTable.fieldCnt());
}
|
Prüfungen durchführen beim/vor dem Schliessen eines Formulares
20.07.2010Microsoft Dynamics AX (Axapta)
Möchte/muß man beim bzw. vor dem Schliessen eines Formulares etwas tun, z.B. Prüfungen durchführen, so stellt Dynamics AX dafür einige Methoden zur Verfügung, die in einer bestimmten Reihenfolge abgearbeitet werden. Da ich selbst mir diese Reihenfolge nicht merke, habe ich sie hier kurz notiert. Beim Schliessen eines Formulares über einen OK-Commandbutton:
Beim Schliessen eines Formulares über einen CANCEL-Commandbutton:
Beim Schliessen eines Formulares über "das rote X" bzw. der ESC-Taste:
|
Feldwert eines aufrufenden Objektes ermitteln
19.07.2010Microsoft Dynamics AX (Axapta)
In vielen Objekten sieht man Kontrukte wie das folgende, die dazu dienen, einen Wert aus dem aufrufenden Datensatz zu ermitteln.
if (element.args() && element.args().record())
{
switch (element.args().dataset())
{
case tablenum(PurchLine) :
itemIdCaller = element.args().record().(fieldNum(purchLine, ItemId));
break;
case tablenum(SalesLine) :
itemIdCaller = element.args().record().(fieldNum(SalesLine, ItemId));
break;
case tablenum(SalesQuotationLine) :
itemIdCaller = element.args().record().(fieldNum(SalesQuotationLine, ItemId));
break;
}
}
Einfacher geht’s mit unten dem stehenden Stückchen Code! Der grosse Vorteil von diesem ist, daß wann immer man das Objekt von einem Datensatz aus aufruft, der ein Feld namens itemId enthält, die Logik abgearbeitet wird ohne daß man jede Tabelle einzeln im switch-Statement berücksichtigen muss. |
Ansprechen der seriellen Schnittstelle unter Dynamics AX 2009
24.06.2010Microsoft Dynamics AX (Axapta)
Mithilfe der Klasse SerialPorts aus dem .net-Framework kann man unter Dynamics AX 2009 recht bequem auf die serielle Schnittstelle zugreifen. Nachstehend dazu ein kurzes Code-Beispiel, wie man ein Display, wie man es z.B. von Kassensystemen kennt, ansteuern kann. static void sendText2SerialPort(Args _args)
{ System.IO.Ports.SerialPort SerialPort; str deleteDisplay = num2char(hex2int("0C")); ; SerialPort = new System.IO.Ports.SerialPort('com4'); SerialPort.Open(); if(SerialPort.get_IsOpen()) { SerialPort.Write(deleteDisplay); SerialPort.Write('Welcome World!'); SerialPort.Close(); } }
|
Eine von RunBasebatch abgeleitete Klasse ist nicht im Stapel lauffähig
10.06.2010Microsoft Dynamics AX (Axapta)
Vor kurzem hatte ich die Aufgabenstellung, eine Klasse die bereits von RunBase abgeleitet worden war, stapelfähig zu gestalten. So weit so einfach, dachte ich mir und habe in der ClassDeclaration der Klasse extends runBase durch extends runBaseBatch ersetzt. Ich hatte danach zwar den entsprechenden Register im Dialog, die Klasse wurde aber dennoch immer sofort ausgeführt :-( Nach etwas herumprobieren hatte ich schlussendlich in der Methode getFromDialog den Fehler entdeckt: Diese war so programmiert, daß sie per return true immer true retouniert, das runBaseBatch-Framework benötigt an dieser Stelle allerdings ein return super(). Kleine Ursache, grosse Wirkung. |
|
|
|
|
|
|
In einem früheren Beitrag habe ich ja hier schon einen Job veröffentlicht, mit dessen Hilfe man sich per X++ ein Shared Project erstellen kann. Basierend auf der neu entdeckten Funktion selectMultiple habe ich diesen nun etwas erweitert, der Benutzer hat mit dessen Hilfe nun die Möglichkeit, ein Shared Project zu erstellen und dabei für die aktuell benötigten Datentypen eigene Gruppenknoten innerhalb dieses Projektes zu erstellen.
{
DictEnum DictEnum;
container conValues;
container conSelectedValues;
container conSelectMultiple;
int i;
projectNode projectNode;
projectGroupNode projectGroupNode;
projectNode myProjectNode;
treeNodeName nameOfProject;
groupNodeType groupNodeType;
treeNodeName groupNodeName;
dialog dialog;
dialogField dfProjectName;
#AOTExport
;
// Create dialog
dialog = new dialog();
dfProjectName = dialog.addFieldValue(typeId(treeNodeName), "NameOfproject", "Name of project");
if( !dialog.run())
{
return;
}
nameOfProject = dfProjectName.value() ? dfProjectName.value() : "Unknown";
// Add available values to container
DictEnum = new DictEnum(enumName2Id(identifierStr(GroupNodeType)));
for(i=1;i<DictEnum.values();i++)
{
conValues = conIns(conValues, conLen(conValues)+1, [DictEnum.index2Label(i), i, false]);
}
// Call selectMultiple
conSelectMultiple = selectMultiple("Please select", "Please select the needed project-groups", conValues);
conSelectedValues = conPeek(conSelectMultiple, 2);
if( !conPeek(conSelectMultiple, 1))
{
return;
}
// Create shared project
projectNode = infolog.projectRootNode();
projectNode = projectNode.AOTfindChild(#expProjectShared);
myProjectNode = projectNode.AOTfindChild(nameOfProject);
if( !myProjectNode)
{
myProjectNode = projectNode.AOTadd(nameOfProject);
myProjectNode.AOTsave();
}
myProjectNode = myProjectNode.getRunNode();
if(conPeek(conSelectMultiple, 1))
{
for (i=1; i<=conLen(conSelectedValues); i++)
{
groupNodeName = DictEnum.index2Label(conPeek(conSelectedValues, i));
projectGroupNode = myProjectNode.AOTfindChild(groupNodeName);
if( !projectGroupNode)
{
myProjectNode.AOTadd(groupNodeName);
projectGroupNode = myProjectNode.AOTfindChild(groupNodeName);
projectGroupNode.projectGroupType(DictEnum.name2Value(groupNodeName));
myProjectNode.AOTsave();
}
}
}
projectGroupNode.AOTsave();
myProjectNode.AOTsave();
myProjectNode.AOTrefresh();
myProjectNode.AOTrun();
}
Obiger Code funktioniert meines Wissens nach in Dynamics AX 4.0 und Dynamics AX 2009.