<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/css" href="http://www.schweda.net/style_feed.css" ?>

<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:atom="http://www.w3.org/2005/Atom"	
	xmlns:dc="http://purl.org/dc/elements/1.1/" > 
<channel>
    <title>Heinz Schweda</title>
    <link>http://www.schweda.net/</link>
    <description>Meine Blog-Eintraege</description>
    <language>de-at</language>
    <copyright>Copyright 2006-2012</copyright>
    <generator>schweda.net</generator>
    <managingEditor>heinz.schweda@schweda.net</managingEditor>
    <webMaster>heinz.schweda@schweda.net</webMaster>
    <category>Blog</category>
	<atom:link href="http://www.schweda.net/blog_rss.php?" rel="self" type="application/rss+xml" />
<item>
<title>AX 2012: Standardfinanzdimension eines Datensatzes setzen</title>
<description><![CDATA[
<p>Der nachstehende Code soll zeigen, wie man in Dynamics AX 2012 bei einem Datensatz - im Beispiel handelt es sich um einen Debitor - die Standardfinanzdimensionen per X++ bef&uuml;llen kann.
</p>

<p>Im Beispiel werden mehrere Dimensionen mit Werten bef&uuml;llt. Bitte beachtet, da&szlig; die angef&uuml;hrten Dimensionen m&ouml;glicherweise in Euren AX-Installationen nicht vorhanden sind.
</p>

<div style="padding: 5px; width: 460px; height: 300px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void setDefaultDimension4CustTable(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; CustTable custTable;<br />
<br />
&nbsp;&nbsp;&nbsp; RecId getDefaultDimension(container _c)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionAttribute dimensionAttribute;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionAttributeValue dimensionAttributeValue;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionAttributeValueSetStorage dimensionAttributeValueSetStorage;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; container dimensionCon;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Name dimensionName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str 255 dimensionValue;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValueSetStorage = new&nbsp; DimensionAttributeValueSetStorage();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i=1;i&lt;=conLen(_c);i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionCon = conPeek(_c, i);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionName&nbsp; = conPeek(dimensionCon, 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionValue = conPeek(dimensionCon, 2);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select dimensionAttribute<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where dimensionAttribute.Name == dimensionName;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(dimensionAttribute)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute, dimensionValue, false, true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValueSetStorage.addItem(dimensionAttributeValue);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return dimensionAttributeValueSetStorage.save();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; ;<br />
<br />
&nbsp;&nbsp;&nbsp; try<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ttsbegin;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; custTable = CustTable::find('9101', true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; custTable.DefaultDimension =<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getDefaultDimension([<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [&quot;Department&quot;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '100'],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [&quot;Debitor&quot;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '3010'],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [&quot;CustomerGroup&quot;,&nbsp;&nbsp; '80'],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [&quot;ParentProject&quot;,&nbsp;&nbsp; '2000'],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [&quot;CostCenter&quot;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '07']<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ]);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; custTable.update();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ttscommit;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(&quot;Update custtable.defaultDimension sucessfull.&quot;);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; catch<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw error(&quot;Error occured&quot;);<br />
&nbsp;&nbsp;&nbsp; }<br />
}
</div>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Sat, 19 May 2012 10:55:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=427</link>
<comments>http://www.schweda.net/blog_ax.php?bid=427</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=427</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=427</wfw:commentRss>
</item>
<item>
<title>AX 2012: Standardfinanzdimension eines Datensatzes auslesen und Inhalt prüfen</title>
<description><![CDATA[
<p>Der folgende Job demonstriert, wie man den Inhalt&nbsp;der Standardfinanzdimensionen eines Datensatzes&nbsp;-&nbsp;im Beispiel jene eines Debitoren - per X++ pr&uuml;ft.
</p>

<p>Im Beispiel werden die Dimensionen namens <em>CustomerGroup</em>, <em>Debitor </em>und <em>NonExistingDimension </em>als zu pr&uuml;fen angegeben. Bitte beachtet, da&szlig; nicht alle Dimensionen in jeder AX-Instanz vorhanden sind. Vor allem letztere dient lediglich zur Demonstration, wie sich der Code verh&auml;lt, wenn eine Dimensionen ausgelesen werden soll, die es gar nicht gibt.
</p>

<div style="padding: 5px; width: 460px; height: 300px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void validateDefaultDimensionValues(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; CustTable custTable = CustTable::find('9101', true);<br />
&nbsp;&nbsp;&nbsp; container validateCon;<br />
&nbsp;&nbsp;&nbsp; container helpCon;<br />
&nbsp;&nbsp;&nbsp; int ii;<br />
<br />
&nbsp;&nbsp;&nbsp; container getDimensionValue(RecId _dimensionAttributeValueSetRecId, container _c)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionAttributeValueSetItem dimensionAttributeValueSetItem;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionAttributeValue dimensionAttributeValue;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionAttribute dimensionAttribute;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Common dimensionValueEntity;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Name dimensionName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str 255 dimensionValue;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; container retCon;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i=1;i&lt;=conLen(_c);i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionName&nbsp; = conPeek(_c, i);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( !DimensionAttribute::findByName(dimensionName))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; error(strFmt(&quot;Dimension %1 not found&quot;, dimensionName));<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while select dimensionAttributeValueSetItem<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where&nbsp;&nbsp; dimensionAttributeValueSetItem.DimensionAttributeValueSet&nbsp;&nbsp; == _dimensionAttributeValueSetRecId<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Find the dimension 'value' (DimensionAttributeValue) that the set item points to.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValue = DimensionAttributeValue::find(dimensionAttributeValueSetItem.DimensionAttributeValue);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Find the underlying attribute.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttribute = DimensionAttribute::find(dimensionAttributeValue.DimensionAttribute);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Use the helper class to obtain a reference to the underlying entity (can be anything)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionValueEntity = DimensionDefaultingControllerBase::findBackingEntityInstance(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curext(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttribute,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValue.EntityInstance);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(dimensionAttribute.Name == dimensionName)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; retCon = conIns(retCon, conLen(retCon)+1, [dimensionAttribute.Name, dimensionAttributeValue.getValue()]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return retCon;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; ;<br />
<br />
&nbsp;&nbsp;&nbsp; validateCon = getDimensionValue(custTable.DefaultDimension, [&quot;CustomerGroup&quot;, &quot;Debitor&quot;, &quot;NonExistingDimension&quot;]);<br />
&nbsp;&nbsp;&nbsp; for (ii=1;ii&lt;=conLen(validateCon);ii++)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; helpCon = conPeek(validateCon, ii);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(conPeek(helpCon, 1) == &quot;CustomerGroup&quot; &amp;&amp; conPeek(helpCon, 2) != custTable.CustGroup)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; warning(strFmt(&quot;Dimension %1 should be %2.&quot;, conPeek(helpCon, 1), conPeek(helpCon, 2)));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(conPeek(helpCon, 1) == &quot;Debitor&quot; &amp;&amp; conPeek(helpCon, 2) != custTable.AccountNum)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; warning(strFmt(&quot;Dimension %1 should be %2.&quot;, conPeek(helpCon, 1), conPeek(helpCon, 2)));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(conPeek(helpCon, 1) == &quot;NonExistingDimension&quot; &amp;&amp; conPeek(helpCon, 2) != custTable.AccountNum)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; warning(strFmt(&quot;Dimension %1 should be %2.&quot;, conPeek(helpCon, 1), conPeek(helpCon, 2)));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
}
</div>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Wed, 16 May 2012 21:22:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=430</link>
<comments>http://www.schweda.net/blog_ax.php?bid=430</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=430</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=430</wfw:commentRss>
</item>
<item>
<title>AX 2012: Benutzerdefinierte Finanzdimension anlegen</title>
<description><![CDATA[
<p>MIt Hilfe des folgenden Jobs kann in Dynamics AX 2012 ein neuer Eintrag f&uuml;r eine benutzerdefinierte Finanzdimension erstellt werden. Im Beispiel ist der Name der Dimension <em>ParentProject </em>und der einzuf&uuml;gende Wert ist <em>4600</em>.
</p>

<div style="padding: 5px; width: 460px; height: 240px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void createCustomDimensionValue(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; DimensionValueService dimensionValueService;<br />
&nbsp;&nbsp;&nbsp; DimensionValueContract dimensionValueContract;<br />
<br />
&nbsp;&nbsp;&nbsp; dimensionValueService = new DimensionValueService();<br />
&nbsp;&nbsp;&nbsp; dimensionValueContract = new DimensionValueContract();<br />
&nbsp;&nbsp;&nbsp; dimensionValueContract.parmDescription('Project 4500');<br />
&nbsp;&nbsp;&nbsp; dimensionValueContract.parmValue('4600');<br />
&nbsp;&nbsp;&nbsp; dimensionValueContract.parmDimensionAttribute('ParentProject');<br />
&nbsp;&nbsp;&nbsp; if(dimensionValueService.createDimensionValue(dimensionValueContract))<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(strFmt(&quot;Dimension value %1 for dimension %2 created&quot;, dimensionValueContract.parmValue(), dimensionValueContract.parmDimensionAttribute()));<br />
&nbsp;&nbsp;&nbsp; }<br />
}
</div>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Mon, 14 May 2012 12:53:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=428</link>
<comments>http://www.schweda.net/blog_ax.php?bid=428</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=428</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=428</wfw:commentRss>
</item>
<item>
<title>AX 2012: Werte einer Finanzdimension auslesen</title>
<description><![CDATA[
<p>Der folgende Job demonstriert, wie man sich die Werte einer Finanzdimension - im Beispiel&nbsp; <em>Department </em>- per X++ ausgeben lassen kann.
</p>

<div style="padding: 5px; width: 460px; height: 300px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void getValues4Dimension(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; DimensionValueService dimensionValueService;<br />
&nbsp;&nbsp;&nbsp; DimensionContract dimensionContract;<br />
&nbsp;&nbsp;&nbsp; List dimensionValueContractList;<br />
&nbsp;&nbsp;&nbsp; ListEnumerator listEnumerator ;<br />
&nbsp;&nbsp;&nbsp; DimensionValueContract dimensionValueContract;<br />
&nbsp;&nbsp;&nbsp; DimensionValue dimensionValue;<br />
<br />
&nbsp;&nbsp;&nbsp; dimensionValueService = new DimensionValueService();<br />
&nbsp;&nbsp;&nbsp; dimensionContract = new DimensionContract();<br />
&nbsp;&nbsp;&nbsp; dimensionContract.parmDimensionName('Department');<br />
&nbsp;&nbsp;&nbsp; dimensionValueContractList = dimensionValueService.getDimensionValues(dimensionContract);<br />
&nbsp;&nbsp;&nbsp; listEnumerator = dimensionValueContractList.getEnumerator();<br />
<br />
&nbsp;&nbsp;&nbsp; setPrefix(strFmt(&quot;Dimension %1: &quot;, dimensionContract.parmDimensionName()));<br />
&nbsp;&nbsp;&nbsp; while(listEnumerator.moveNext())<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionValueContract = listEnumerator.current();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionValue = dimensionValueContract.parmValue();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(dimensionValue);<br />
&nbsp;&nbsp;&nbsp; }<br />
}
</div>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Sun, 13 May 2012 20:45:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=431</link>
<comments>http://www.schweda.net/blog_ax.php?bid=431</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=431</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=431</wfw:commentRss>
</item>
<item>
<title>AX 2012: Kontostruktur eines Hauptkontos ermitteln</title>
<description><![CDATA[
<p>M&ouml;chte man f&uuml;r das Hauptkonto einer Position einer Allgemeinen Erfassung ermitteln, kann man dies mit Hilfe des nachstehenden Codes tun.
</p>

<div style="padding: 5px; width: 460px; height: 140px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void getAccountStructureFromLedgerDimension(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; ledgerJournalTrans ledgerJournalTrans;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; select ledgerJournalTrans<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where ledgerJournalTrans.JournalNum == '000151_010';&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; info(DimensionStorage::getAccountStructureFromLedgerDimension(ledgerJournalTrans.LedgerDimension).Name);<br />
}
</div>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Fri, 11 May 2012 11:02:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=433</link>
<comments>http://www.schweda.net/blog_ax.php?bid=433</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=433</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=433</wfw:commentRss>
</item>
<item>
<title>AX 2012: Standardfinanzdimension eines Datensatzes auslesen und ausgeben</title>
<description><![CDATA[
<p>Im folgenden Job werden die eingetragenen Standardfinanzdimensionen eines Datensatzes - im konkreten Fall die eines bestimmten Debitoren - ausgegeben.
</p>

<div style="padding: 5px; width: 460px; height: 300px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void getDimensionsFromDefaultDimension(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; DimensionAttributeValueSet dimensionAttributeValueSet;<br />
&nbsp;&nbsp;&nbsp; DimensionAttributeValueSetItem dimensionAttributeValueSetItem;<br />
&nbsp;&nbsp;&nbsp; DimensionAttributeValue&nbsp;dimensionAttributeValue;<br />
&nbsp;&nbsp;&nbsp; DimensionAttribute dimensionAttribute;<br />
&nbsp;&nbsp;&nbsp; Common dimensionValueEntity;<br />
<br />
&nbsp;&nbsp;&nbsp; dimensionAttributeValueSet = DimensionAttributeValueSet::find(CustTable::find('9101').DefaultDimension);<br />
<br />
&nbsp;&nbsp;&nbsp; // Find all of the 'value set items' linked against the 'value set'<br />
&nbsp;&nbsp;&nbsp; while select dimensionAttributeValueSetItem<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where&nbsp;&nbsp; dimensionAttributeValueSetItem.DimensionAttributeValueSet&nbsp;== dimensionAttributeValueSet.RecId<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Find the dimension 'value' (DimensionAttributeValue) that the set item points to.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValue = DimensionAttributeValue::find(dimensionAttributeValueSetItem.DimensionAttributeValue);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Find the underlying attribute.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttribute = DimensionAttribute::find(dimensionAttributeValue.DimensionAttribute);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Use the helper class to obtain a reference to the underlying entity (can be anything)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionValueEntity = DimensionDefaultingControllerBase::findBackingEntityInstance(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curext(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttribute,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValue.EntityInstance);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(strFmt(&quot;%1: %2&quot;, dimensionAttribute.Name, dimensionAttributeValue.getValue()));<br />
&nbsp;&nbsp;&nbsp; }<br />
}
</div>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Wed, 09 May 2012 20:00:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=432</link>
<comments>http://www.schweda.net/blog_ax.php?bid=432</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=432</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=432</wfw:commentRss>
</item>
<item>
<title>AX 2012: Dimensionen einer Position einer Allgemeines Erfassung per X++ auslesen</title>
<description><![CDATA[
<p>Wenn man bei einer Position einer Allgemeinen Erfassung, welche gegen ein Sachkonto/Hauptkonto bucht, per X++ die eingetragenen Dimensionen auslesen m&ouml;chte, kann der folgende Code m&ouml;glicherweise hilfreich sein.
</p>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/ax2012_ledgerjournaltrans_ledgeraccount.JPG"><img width="465" height="289" title="Position einer Allgemeinen Erfassung" alt="Position einer Allgemeinen Erfassung" border="0" src="http://www.schweda.net/pictures/blogpics/tb_ax2012_ledgerjournaltrans_ledgeraccount.JPG" /></a>
</p>


<div style="padding: 5px; width: 460px; height: 300px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void getLedgerDimensionData(Args _args) <br />
{ <br />
&nbsp;&nbsp;&nbsp; LedgerJournalTrans ledgerJournalTrans; <br />
<br />
&nbsp;&nbsp;&nbsp; void getDimensionsFromDefaultDimension(RecId _dimensionrecid) <br />
&nbsp;&nbsp;&nbsp; { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionAttributeValueSet dimensionAttributeValueSet; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionAttributeValueSetItem dimensionAttributeValueSetItem; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionAttributeValue&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValue; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionAttribute dimensionAttribute; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Common dimensionValueEntity; <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValueSet = DimensionAttributeValueSet::find(_dimensionrecid); <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Find all of the 'value set items' linked against the 'value set' <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while select dimensionAttributeValueSetItem <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where&nbsp;&nbsp; dimensionAttributeValueSetItem.DimensionAttributeValueSet == dimensionAttributeValueSet.RecId <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Find the dimension 'value' (DimensionAttributeValue) that the set item points to. <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValue = DimensionAttributeValue::find(dimensionAttributeValueSetItem.DimensionAttributeValue); <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Find the underlying attribute. <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttribute = DimensionAttribute::find(dimensionAttributeValue.DimensionAttribute); <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Use the helper class to obtain a reference to the underlying entity (can be anything) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionValueEntity = DimensionDefaultingControllerBase::findBackingEntityInstance( <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curext(), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttribute, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValue.EntityInstance); <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(strFmt(&quot;%1: %2 - %3&quot;, dimensionAttribute.Name, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValue.getValue(), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimensionAttributeValue.getName() <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; ; <br />
<br />
&nbsp;&nbsp;&nbsp; while select ledgerJournalTrans <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where ledgerJournalTrans.JournalNum == '000151_010' <br />
&nbsp;&nbsp;&nbsp; { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Get main account data <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(strFmt(&quot;Main account display value: %1&quot;, DimensionAttributeValueCombination::find(ledgerJournalTrans.LedgerDimension).DisplayValue)); <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(MainAccount::find(DimensionAttributeValueCombination::find(ledgerJournalTrans.LedgerDimension).MainAccount)) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(strFmt(&quot;Main account: %1 - %2&quot;, MainAccount::find(DimensionAttributeValueCombination::find(ledgerJournalTrans.LedgerDimension).MainAccount).MainAccountId, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MainAccount::find(DimensionAttributeValueCombination::find(ledgerJournalTrans.LedgerDimension).MainAccount).Name)); <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(strFmt(&quot;Account structure: %1&quot;, DimensionStorage::getAccountStructureFromLedgerDimension(ledgerJournalTrans.LedgerDimension).Name)); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Get dimension values <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setPrefix(&quot;Dimension values&quot;); <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getDimensionsFromDefaultDimension(DimensionStorage::getDefaultDimensionFromLedgerDimension(ledgerJournalTrans.LedgerDimension)); <br />
&nbsp;&nbsp;&nbsp; } <br />
}
</div>

<p>Als Ergebnis des obigen Jobs wird ein Infolog ausgegeben.
</p>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/ax2012_ledgerjournaltrans_ledgeraccount_infolog.JPG"><img width="465" height="239" title="Infolog" alt="Infolog" border="0" src="http://www.schweda.net/pictures/blogpics/tb_ax2012_ledgerjournaltrans_ledgeraccount_infolog.JPG" /></a>
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Wed, 09 May 2012 09:28:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=435</link>
<comments>http://www.schweda.net/blog_ax.php?bid=435</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=435</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=435</wfw:commentRss>
</item>
<item>
<title>AX 2012: Datensätze mit einer bestimmten Dimension ausgeben</title>
<description><![CDATA[
<p>Der folgende Job listet alle Debitoren auf, bei welchen in der Dimension <em>CustomerGroup </em>der Wert <em>80 </em>eingetragen ist.
</p>

<p>Der interessante Teil des Jobs ist die Methode <em><strong>addDimensionAttributeRange </strong></em>der Klasse <em>SysQuery</em>, da diese sich um das&nbsp;Verkn&uuml;pfen der ben&ouml;tigten Datenquellen k&uuml;mmert.
</p>

<div style="padding: 5px; width: 460px; height: 300px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void getRecords4DimensionValue(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; Query query;<br />
&nbsp;&nbsp;&nbsp; QueryBuildDataSource queryBuildDataSource;<br />
&nbsp;&nbsp;&nbsp; QueryBuildRange queryBuildRange;<br />
&nbsp;&nbsp;&nbsp; QueryRun queryRun;<br />
&nbsp;&nbsp;&nbsp; CustTable custTable;<br />
<br />
&nbsp;&nbsp;&nbsp; query = new Query();<br />
&nbsp;&nbsp;&nbsp; queryBuildDataSource = query.addDataSource(tableNum(CustTable));<br />
<br />
&nbsp;&nbsp;&nbsp; queryBuildRange = SysQuery::addDimensionAttributeRange( query,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; queryBuildDataSource.name(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;DefaultDimension&quot;,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DimensionComponent::DimensionAttribute,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; queryValue(&quot;80&quot;),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;CustomerGroup&quot;);<br />
<br />
&nbsp;&nbsp;&nbsp; queryRun = new QueryRun(query);<br />
&nbsp;&nbsp;&nbsp; while(queryRun.next())<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; custTable = queryRun.get(tableNum(CustTable));<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(custTable.name());<br />
&nbsp;&nbsp;&nbsp; }<br />
}
</div>

<p>Die Klasse SysQuery stellt &uuml;brigens zahlreiche weitere &auml;hnliche Funktionen zur Verf&uuml;gung, um mit Dimensionswerten zu arbeiten.
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Tue, 08 May 2012 18:06:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=434</link>
<comments>http://www.schweda.net/blog_ax.php?bid=434</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=434</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=434</wfw:commentRss>
</item>
<item>
<title>AX 2012: ID, LegacyID und Origin</title>
<description><![CDATA[
<p>&nbsp;
</p>

<table>
    <tbody>
        <tr valign="top">
            
<td><strong>ID</strong>
</td>
            
<td>
            
<p>Ist eine sogenannte installations-spezifische ID,  d.h. ein und dasselbe Objekt kann in unterschiedlichen Umgebungen eine andere ID  aufweisen.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</p>
            
<p>Die ID wird u.a. zum Zeitpunkt des Importes eines  Model per AXUTIL vergeben Somit ist die ID aus Entwicklersicht zu  vernachl&auml;ssigen.
</p>
            
<p>Ein Model-File enth&auml;lt z.B. keine IDs! Auch per  Export/Import-Funktion erstellte Exportfiles mit Daten enthalten keine IDs  (lediglich GUIDs)
</p>
            
</td>
        </tr>
        <tr valign="top">
            
<td><strong>LegacyID</strong>
</td>
            
<td>
            
<p>Ist nur bei &quot;alten&quot; Objekten gesetzt, die es schon  in fr&uuml;heren Versionen von Dynamics AX gab. Bei neuen Elementen wird dieses  LegacyID nicht mehr vergeben.
</p>
            
<p>Somit ist diese LegacyID f&uuml;r einen Entwickler nicht relevant.
</p>
            
</td>
        </tr>
        <tr valign="top">
            
<td><strong>Origin</strong>
</td>
            
<td>
            
<p>Ist eine GUID, die beim Erstellen eines Elementes  zugewiesen wird und nicht mehr ver&auml;ndert wird.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</p>
            
<p>Diese dient dazu, ein Objekt eindeutig zu  identifizieren, weil die ID in unterschiedlichen Umgebungen (Entwicklungsumgebung vs. Produktivumgebung) ja  eine andere sein kann.
</p>
            
<p>Angenommen in AX7 w&uuml;rde eine in AX 2012 bereits  vorhandene Klasse umbenannt werden, k&ouml;nnte sie weder &uuml;ber die ID noch &uuml;ber den  Namen als das selbe Objekt erkannt werden, deshalb wurde diese GUID  eingef&uuml;hrt.
</p>
            
<p>Bei Tests innerhalb einer Windows-Dom&auml;ne habe ich  festgestellt, da&szlig; die Origin auch beim Import von Models/XPOs mit neuen Objekten  von der Quell- in die Zielumgebung &uuml;bernommen wird (hingegen sich die ID  ver&auml;ndert hat).&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</p>
            
<p><em>Wichtig</em>: &Uuml;ber die Funktion Export/Import erstellte  Export-Dateien enthalten GUIDs, keine Ids (im Gegensatz zu z.B. AX  2009)
</p>
            
</td>
        </tr>
    </tbody>

</table>

<p>Ein Must-Read zu dem Thema ist freilich: <a href="http://blogs.msdn.com/b/mfp/archive/2011/07/11/the-solution-to-the-element-id-problem.aspx">http://blogs.msdn.com/b/mfp/archive/2011/07/11/the-solution-to-the-element-id-problem.aspx</a>
</p>

<p>&nbsp;
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Tue, 08 May 2012 15:57:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=425</link>
<comments>http://www.schweda.net/blog_ax.php?bid=425</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=425</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=425</wfw:commentRss>
</item>
<item>
<title>Formular als Dialog verwenden</title>
<description><![CDATA[
<p>Im AOT befinden sich einige tutorial-Objekte, die dem Entwickler dabei helfen k&ouml;nnen, die eine oder andere Anforderung zu l&ouml;sen. Eine dieser Klassen ist die Klasse <em>tutorial_RunbaseForm</em>, die erkl&auml;rt wie man statt einem Dialog ein eigens erstelltes Formular als Dialog verwendet.
</p>

<p>Auf Basis dieses Turorials habe ich in Dynamics AX 2012 eine Anforderung wie folgt gel&ouml;st:
</p>


<p>In der Klasse <em>wmsArrivalStart </em>- das ist jene Klasse, die aus der Wareneingangs&uuml;bersicht aus aufgerufen werden kann und Wareneingangsjournale erstellt - eine neue Methode <em>MyDialog </em>eingebaut, die ein Formular namens <em>MyWMSArravialStart </em>als Dialog aufruft. Diesem Formular wird eine tempor&auml;re Tabelle <em>wmsArrivalDetailTmp </em>&uuml;bergeben und in einem Grid dargestellt.
</p>

<p>Das Formular baut auf Basis dieser Tabelle <em>wmsArrivalDetailTmp </em>eine weitere tempor&auml;re Tabelle namens <em>TmpWMSArrivalStartReturn </em>auf und retourniert diese an die Klasse <em>WMSArrivalStart</em>.
</p>

<p>Die Methode <em>MyDialog </em>wird von der <em>run</em>-Methode der Klasse <em>WMSArrivalStart </em>aus aufgerufen und &ouml;ffnet das Formular <em>MyWMSArrivalStart</em>. Dabei wird diesem Formular &uuml;ber eine entsprechende Parameter-Methode&nbsp; die Tabelle <em>wmsArrivalDetailTmp </em>&uuml;bergeben.&nbsp;Auf Basis dieser Tabelle wird im Formular eine tempor&auml;re Tabelle <em>TmpWMSArrivalStart </em>aufgebaut und in einem Grid angezeigt. Hat der Benutzer in diesem Grid seine Eingaben gemacht,&nbsp; wird diese tempor&auml;re Tabelle &uuml;ber die Methode <em>getTmpWMSArrivalStart </em>an die Klasse retourniert.
</p>

<div style="padding: 5px; width: 460px; height: 300px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public static client boolean MyDialog(wmsArrivalDetailTmp _wmsArrivalDetailTmp)<br />
{<br />
&nbsp;&nbsp;&nbsp; DialogRunbase DialogRunbase;<br />
&nbsp;&nbsp;&nbsp; Object formRun;<br />
&nbsp;&nbsp;&nbsp; wmsArrivalDetailTmp wmsArrivalDetailTmpLocal;<br />
&nbsp;&nbsp;&nbsp; TmpWMSArrivalStart TmpWMSArrivalStartReturn;<br />
<br />
&nbsp;&nbsp;&nbsp; wmsArrivalDetailTmpLocal.setTmpData(_wmsArrivalDetailTmp);<br />
<br />
&nbsp;&nbsp;&nbsp; DialogRunbase = Dialog::newFormnameRunbase(formstr(MyWMSArrivalStart),null);<br />
<br />
&nbsp;&nbsp;&nbsp; DialogRunbase.run(false);<br />
<br />
&nbsp;&nbsp;&nbsp; if(DialogRunbase.formRun() &amp;&amp; sysFormRun::hasMethod(DialogRunbase.formRun(), identifierStr(&quot;parmWmsArrivalDetailTmp&quot;)))<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; formRun = DialogRunbase.formRun();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; formRun.parmWmsArrivalDetailTmp(wmsArrivalDetailTmpLocal);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw error(error::wrongUseOfFunction(funcName()));<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; DialogRunbase.run();<br />
<br />
&nbsp;&nbsp;&nbsp; DialogRunbase.wait();&nbsp;&nbsp; // Waits for user-input<br />
<br />
&nbsp;&nbsp;&nbsp; if(formRun &amp;&amp; sysFormRun::hasMethod(formRun, identifierStr(&quot;getTmpWMSArrivalStart&quot;)))<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TmpWMSArrivalStartReturn = formRun.getTmpWMSArrivalStart();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; while select TmpWMSArrivalStartReturn<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // do something...<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; return DialogRunbase.closedOk();<br />
}
</div>

<p>Aufruf der Methode aus der <em>run</em>-Methode der Klasse <em>wmsStartArrival</em>
</p>

<div style="padding: 5px; width: 460px; height: 160px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">protected WMSJournalId run()<br />
{<br />
&nbsp;&nbsp;&nbsp; //...code...<br />
&nbsp;&nbsp;&nbsp; if (!WMSArrivalStart::MyDialog(wmsArrivalDetailTmp))<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &quot;&quot;;&nbsp;&nbsp;&nbsp; // Empty WMSJournalId<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; //...code...<br />
}
</div>

<p>In der <em>run</em>-Methode des Formulares wird die Methode <em>fillTables </em>aufgerufen, welche die von der Klasse &uuml;bergebenen Daten verarbeitet (&uuml;ber die Methode <em>parmWmsArrivalDetailTmp</em>)
</p>

<div style="padding: 5px; width: 460px; height: 120px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public void run()<br />
{<br />
&nbsp;&nbsp;&nbsp; this.fillTables();<br />
<br />
&nbsp;&nbsp;&nbsp; super();<br />
}
</div>

<p>Die Methode <em>parmWmsArrivalDetailTmp </em>dient zum &Uuml;bergeben der Datens&auml;tze der Tabelle <em>WmsArrivalDetailTmp</em>
</p>

<div style="padding: 5px; width: 460px; height: 120px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public wmsArrivalDetailTmp parmWmsArrivalDetailTmp(WmsArrivalDetailTmp _wmsArrivalDetailTmp = wmsArrivalDetailTmp)<br />
{<br />
&nbsp;&nbsp;&nbsp; wmsArrivalDetailTmp = _wmsArrivalDetailTmp;<br />
<br />
&nbsp;&nbsp;&nbsp; return wmsArrivalDetailTmp;<br />
}
</div>

<p>Die Methode <em>fillTables </em>baut auf Basis der Tabelle <em>WmsArrivalDetailTmp </em>eine weitere Tabelle auf. Diese Tabelle dient gleichzeitig als DataSource des Formulares und wird in einem Grid dargestellt.
</p>

<div style="padding: 5px; width: 460px; height: 120px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">private void fillTables()<br />
{<br />
&nbsp;&nbsp;&nbsp; while select WMSArrivalDetailTmp<br />
&nbsp;&nbsp;&nbsp; where WMSArrivalDetailTmp.Selected&nbsp;&nbsp; == NoYes::Yes<br />
&nbsp;&nbsp;&nbsp; &amp;&amp;&nbsp;&nbsp;&nbsp; WMSArrivalDetailTmp.InventQty&nbsp; &gt;&nbsp; 0<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TmpWMSArrivalStartReturn.itemid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = WMSArrivalDetailTmp.ItemId;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TmpWMSArrivalStartReturn.InventTransId&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = WMSArrivalDetailTmp.InventTransId;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TmpWMSArrivalStartReturn.WMSStandardPalletQuantity&nbsp;&nbsp;&nbsp; = InventTable::find(TmpWMSArrivalStartReturn.itemid).standardPalletQuantity;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TmpWMSArrivalStartReturn.WMSPalletCount&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = WMSArrivalDetailTmp.NoOfPallets;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TmpWMSArrivalStartReturn.insert();<br />
&nbsp;&nbsp;&nbsp; }<br />

<p>&nbsp;&nbsp;&nbsp; TmpWMSArrivalStart.setTmpData(TmpWMSArrivalStartReturn);<br />
<br />
&nbsp;&nbsp;&nbsp; TmpWMSArrivalStart_ds.executeQuery();<br />
}
</p>

</div>

<p>Klickt der Benutzer auf den OK-Button des Formulares wird &uuml;ber die Methode <em>getTmpWMSArrivalStart </em>der Inhalt der Tabelle <em>TmpWMSArrivalStart </em>an die Klasse retourniert.
</p>

<div style="padding: 5px; width: 460px; height: 80px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public TmpWMSArrivalStart getTmpWMSArrivalStart()<br />
{<br />
&nbsp;&nbsp;&nbsp; return TmpWMSArrivalStartReturn;<br />
}
</div>

<p>Abschliessend noch ein paar Anmerkungen zum Formular selbst:
</p>

<ul>
    
<li>Die Form muss eine Gruppe namens <em>dialogStartGrp </em>enthalten
</li>
    
<li>Die Form ben&ouml;tigt auch die entsprechenden Buttons (daf&uuml;r am besten die gesamte Gruppe <em>BottomButtonGrp </em>des Formulares<em> tutorial_RunbaseForm</em> &uuml;bernehmen
</li>

</ul>

<p>Das Beispiel funktioniert prinzipiell in AX 2009 genauso wie in AX 2012.
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Fri, 06 Apr 2012 22:37:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=350</link>
<comments>http://www.schweda.net/blog_ax.php?bid=350</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=350</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=350</wfw:commentRss>
</item>
<item>
<title>Event-Handling in Dynamics AX 2012</title>
<description><![CDATA[
<p>Eine wichtige Neuerung von AX 2012 sind die sogenannten <strong>Event-Handler</strong>. Diese Event-Handler sind eine elegante M&ouml;glichkeit, die Funktionalit&auml;t von AX 2012 zu erweitern, ohne dabei den Standardcode zu ver&auml;ndern. Dies soll vor allem sp&auml;tere Releaseupdates von Dynamics AX 2012 erheblich erleichtern.
</p>

<p>Prinzipiell unterscheidet man dabei zwischen Event-Handler die vor (PRE) bzw. nach (POST) dem Originalcode ausgef&uuml;hrt werden sollen, wobei jede der beiden Varianten ihre eigenen M&ouml;glichkeiten bieten. Pre-Event-Handler k&ouml;nnen die Original-Parameter der ausl&ouml;senden Methode ver&auml;ndern wogegen Post-Event-Handler den R&uuml;ckgabewert der ausl&ouml;senden Methode ver&auml;ndern k&ouml;nnen.
</p>

<p>Die folgenden drei Beispiele sollen die Verwendung dieser Event-Handler verdeutlichen.
</p>

<p><strong><em>Beispiel 1:</em></strong><em> Es soll der Inhalt des Feldes Suchbegriff der Artikeldetails dahingehend gepr&uuml;ft werden, da&szlig; zumindest 5 Zeichen eingegeben wurden.</em>
</p>


<p>In fr&uuml;heren Versionen von Dynamics AX h&auml;tte man f&uuml;r eine solche Pr&uuml;fung &uuml;blicherweise die <em>validateWrite </em>der Tabelle <em>inventTable </em>ver&auml;ndert - in AX 2012 erstellen wir statt dessen eine Klasse <em>MyInventTableEventHandler </em>mit einer Methode <em>inventTableValidateWritePostEventHandler </em>und verkn&uuml;pfen die Methode mit der <em>validateWrite</em>.
</p>

<p title="gotodetail">&nbsp;<a href="http://www.schweda.net/pictures/blogpics/ax2012_myinventtableeventhandler.jpg" target="_blank"><img width="339" border="0" height="53" src="http://www.schweda.net/pictures/blogpics/ax2012_myinventtableeventhandler.jpg" alt="Screenshot MyInventTableEventHandler" title="Screenshot MyInventTableEventHandler" /></a>
</p>

<p><u>Schritt 1: Erstellen der Klasse und Methode</u>
</p>

<div style="padding: 5px; width: 460px; height: 300px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">class MyInventTableEventHandler <br />
{ <br />
} <br />
<br />
public static void inventTableValidateWritePostEventHandler(XppPrePostArgs _args) <br />
{ <br />
&nbsp;&nbsp;&nbsp; inventTable inventTable; <br />
<br />
&nbsp;&nbsp;&nbsp; inventTable = _args.getThis(); <br />
<br />
&nbsp;&nbsp;&nbsp; if (strLen(inventTable.NameAlias) &lt; 5) <br />
&nbsp;&nbsp;&nbsp; { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; warning(strFmt('Field &quot;%1&quot; should contain at least 5 characters.', fieldPName(inventTable, NameAlias))); <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Set return value of the original method <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _args.setReturnValue(false); <br />
&nbsp;&nbsp;&nbsp; } <br />
}
</div>

<p><br />
<br />
<u>Schritt 2: Verkn&uuml;pfen der Methode mit der Tabelle</u>
</p>

<p>Per Drag &amp; Drop ziehen wir die Methode <em>inventTableValidateWritePostEventHandler </em>auf die <em>validateWrite </em>der <em>inventTable</em>.
</p>

<p><a href="http://www.schweda.net/pictures/blogpics/ax2012_myinventtableeventhandler_subscription.jpg" target="_blank"><img width="248" border="0" height="36" src="http://www.schweda.net/pictures/blogpics/ax2012_myinventtableeventhandler_subscription.jpg" title="Screenshot Subscription" alt="" /></a>
</p>

<p>Nun m&uuml;ssen wir noch festlegen, wann dieses Event ausgef&uuml;hrt werden soll, in unserem Fall w&auml;hlen wir die Variante Post.
</p>

<p><a href="http://www.schweda.net/pictures/blogpics/ax2012_myinventtableeventhandler_properties.jpg" target="_blank"><img width="465" border="0" height="152" src="http://www.schweda.net/pictures/blogpics/ax2012_myinventtableeventhandler_properties_small.jpg" alt="Screenshot Properties" title="Screenshot Properties" /></a>&nbsp;
</p>

<p>&nbsp;
</p>

<p><br />
<strong><em>Beispiel 2:</em></strong><em> Auch in diesem Beispiel soll der Inhalt des Feldes Suchbegriff der Artikeldetails gepr&uuml;ft werden, allerdings nicht erst beim Speichern des Datensatzes sondern gleich nach der Eingabe. </em>
</p>

<p>In fr&uuml;heren Versionen von Dynamics AX h&auml;tten wir hierf&uuml;r die Methode <em>validateField</em> entspechend angepasst, in meinem Beispiel verwende ich die Methode <em>validateField</em> als Ausl&ouml;ser des Events.
</p>

<p>Im Gegensatz zum Beispiel 1 verf&uuml;gt die Methode <em>validateField </em>&uuml;ber zwei Paramter, die selbstverst&auml;ndlich auch durch Event-Handler genutzt werden k&ouml;nnen. Auch dieses Mal handelt es sich um einen Post-Event-Handler.
</p>

<p><u>Schritt 1: Erstellen der Klasse und Methode</u>
</p>

<div style="padding: 5px; width: 460px; height: 300px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">class MyInventTableEventHandler <br />
{ <br />
} <br />
<br />
public static void inventTableValidateFieldPostEventHandler(XppPrePostArgs _args) <br />
{ <br />
&nbsp;&nbsp;&nbsp; inventTable inventTable; <br />
&nbsp;&nbsp;&nbsp; FieldName fieldName; <br />
&nbsp;&nbsp;&nbsp; int arrayIndex; <br />
<br />
&nbsp;&nbsp;&nbsp; if(_args.getCalledWhen() != XppEventHandlerCalledWhen::Post) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw error(error::wrongUseOfFunction(funcName())); <br />
<br />
&nbsp;&nbsp;&nbsp; inventTable = _args.getThis(); <br />
<br />
&nbsp;&nbsp;&nbsp; // First parm _fieldName of the original method <br />
&nbsp;&nbsp;&nbsp; fieldName = _args.args().valueIndex(1); <br />
<br />
&nbsp;&nbsp;&nbsp; // Second parm _arrayIndex of the original method <br />
&nbsp;&nbsp;&nbsp; arrayIndex = _args.args().valueIndex(2); <br />
<br />
&nbsp;&nbsp;&nbsp; switch(fieldName) <br />
&nbsp;&nbsp;&nbsp; { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case fieldStr(InventTable, NameAlias): <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (strLen(inventTable.NameAlias) &lt; 5) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; warning(strFmt('Field &quot;%1&quot; should contain at least 5 characters.', fieldPName(inventTable, NameAlias))); <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Set return value of the original method <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _args.setReturnValue(false); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; <br />
&nbsp;&nbsp;&nbsp; } <br />
}
</div>

<p><br />
<u>Schritt 2: Verkn&uuml;pfen der Methode mit der Tabelle</u>
</p>

<p>Per Drag &amp; Drop ziehen wir die Methode <em>inventTableValidateFieldPostEventHandler </em>auf die <em>validateField </em>der <em>inventTable</em>. Nun m&uuml;ssen wir noch festlegen, wann dieses Event ausgef&uuml;hrt werden soll, in unserem Fall w&auml;hlen wir die Variante Post.
</p>

<p>Hinweis: Alternativ zu _args.args().valueIndex() kann man die Parameter der Original-Methode auch wie folgt abfragen:
</p>

<div style="padding: 5px; width: 460px; height: 100px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">&nbsp;&nbsp;&nbsp; // First parm _fieldName of the original method <br />
&nbsp;&nbsp;&nbsp; fieldName = _args.getArg(identifierStr(_fieldName)); <br />
&nbsp;&nbsp;&nbsp; // Second parm _arrayIndex of the original method <br />
&nbsp;&nbsp;&nbsp; arrayIndex = _args.getArg(identifierStr(_ArrayIndex));
</div>

<p>&nbsp;
</p>

<p><br />
<strong><em>Beispiel 3: </em></strong><em>Bei Aktualisieren eines Datensatzes in den Artikeldetails soll das Feld Suchbegriff mit der Artikelnummer gef&uuml;llt werden, wenn das Feld Suchbegriff leer ist. </em>
</p>

<p>In Versionen vor Dynamics AX 2012 h&auml;tten wir gewohnterweise die <em>update</em>-Methode ver&auml;ndert, in dieser Version verwenden wir Sie als Ausl&ouml;ser des Events.<br />
<br />
<u>Schritt 1: Erstellen der Klasse und Methode</u>
</p>

<div style="padding: 5px; width: 460px; height: 300px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">class MyInventTableEventHandler <br />
{ <br />
} <br />
<br />
public static void inventTableUpdatePreEventHandler(XppPrePostArgs _args) <br />
{ <br />
&nbsp;&nbsp;&nbsp; inventTable inventTable; <br />
<br />
&nbsp;&nbsp;&nbsp; if(_args.getCalledWhen() != XppEventHandlerCalledWhen::Pre) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw error(error::wrongUseOfFunction(funcName())); <br />
<br />
&nbsp;&nbsp;&nbsp; inventTable = _args.getThis(); <br />
<br />
&nbsp;&nbsp;&nbsp; if( !inventTable.NameAlias) <br />
&nbsp;&nbsp;&nbsp; { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inventTable.NameAlias = inventTable.ItemId; <br />
&nbsp;&nbsp;&nbsp; } <br />
}
</div>

<p><br />
<u>Schritt 2: Verkn&uuml;pfen der Methode mit der Tabelle</u><br />
<br />
Per Drag &amp; Drop ziehen wir die Methode <em>inventTableUpdatePreEventHandler </em>auf die update der inventTable. Nun m&uuml;ssen wir noch festlegen, wann dieses Event ausgef&uuml;hrt werden soll, in unserem Fall w&auml;hlen wir die Variante Pre.
</p>

<p>&nbsp;
</p>

<p><em><strong>Weitere Hinweise</strong></em>
</p>

<p>Selbstverst&auml;ndlich kann eine Klasse mehrere Methoden enthalten die als Event-Handler benutzt werden, so k&ouml;nnten wir also alle drei oben beschriebenen Methoden in nur einer Klasse kombinieren.
</p>

<p>Weiters ist es nat&uuml;rlich auch m&ouml;glich, eine Event-Handler-Methode derart zu programmieren, als da&szlig; sie sowohl als Pre- als auch als Post-Event-Handler verwendet werden kann. Abgefragt werden kann dies - wie in den obigen Beispielen ansatzweise dargestellt &uuml;ber die Abfrage von <em>getCalledWhen </em>der <em>XppPrePostArgs</em>.<br />
Auch k&ouml;nnen wir mehrere Event-Handler mit eine Methode verkn&uuml;pfen, die Reihenfolge der Ausf&uuml;hrung ist allerdings nicht steuerbar.
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Sun, 25 Mar 2012 20:49:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=424</link>
<comments>http://www.schweda.net/blog_ax.php?bid=424</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=424</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=424</wfw:commentRss>
</item>
<item>
<title>Abfragen der aktiven Lagerungsdimensionen</title>
<description><![CDATA[
<p>Um f&uuml;r einen Artikel &uuml;ber X++ zu ermitteln, ob eine bestimmte Lagerungsdimension verwendet wird, gibt es abh&auml;ngig von der verwendeten AX-Version verschiedene Ans&auml;tze. In den beiden Beispielen wird ermittelt, ob die Dimension Palettennummer aktiv ist:
</p>

<p><strong>Dynamics AX 2009</strong>
</p>

<div style="padding: 5px; width: 460px; height: 60px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">inventDimSetup::find(inventTable::find(_itemId).DimGroupId, <br />
&nbsp;&nbsp;&nbsp; fieldnum(InventDim, wmsPalletId)).Active
</div>

<p><strong>Dynamics AX 2012</strong>
</p>

<div style="padding: 5px; width: 460px; height: 60px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">EcoResDimensionGroupSetup::isInventoryDimensionActiveForItem(<br />
&nbsp;&nbsp;&nbsp; _itemId, fieldNum(InventDim, wmsPalletId))
</div>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Fri, 16 Mar 2012 18:47:00 +0100</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=423</link>
<comments>http://www.schweda.net/blog_ax.php?bid=423</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=423</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=423</wfw:commentRss>
</item>
<item>
<title>Funktion num2expstr</title>
<description><![CDATA[
<p>Vor kurzem lief mir eine Fehlermeldung in Dynamics AX &uuml;ber den Weg die vermuten lies, da&szlig; in einer Tabelle Werte mit mehr Nachkommastellen gespeichert waren, als Dynamics AX dort erwartet h&auml;tte. Leider sieht man &uuml;ber den Table-Browser solche Nachkommastellen oft nicht, deshalb musste ich mir mit einem Job und der Funktion <strong>num2expstr </strong>helfen, letztere zeigt die Werte detailierter als z.B. der Table-Browser an.
</p>

<div style="padding: 5px; width: 460px; height: 180px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void num2expstrTest(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; ledgerTrans ledgerTrans;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; while select ledgerTrans&nbsp;<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(strFmt(&quot;%1&nbsp; %2&quot;, num2expstr(ledgerTrans.AmountMST), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ledgerTrans.AmountMST));<br />
&nbsp;&nbsp;&nbsp; }<br />
}
</div>

<p>&nbsp;
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Sat, 10 Mar 2012 19:32:00 +0100</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=413</link>
<comments>http://www.schweda.net/blog_ax.php?bid=413</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=413</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=413</wfw:commentRss>
</item>
<item>
<title>AX 2012: Relations, Surrogate Foreign Keys</title>
<description><![CDATA[
<p>Mit dem Release von Dynamics AX 2012 konfrontiert Microsoft den erfahrenen AX-Entwickler mit zahlreichen Neuerungen. Einige davon betreffen das Herstellen von Beziehungen (Relations) zwischen Tabellen.
</p>

<p>Hatte man in AX 2009 noch die M&ouml;glichkeit, die Relations auf einem Extended Datatyp (EDT) festzulegen, so muss dies nun direkt auf den Tabellen erfolgen. Ausserdem sind die Tabellen nun meist so aufgebaut, da&szlig; Relations &uuml;ber die sogenannten Surrogate Foreign Keys erfolgen.<br />
&nbsp;<br />
Als <strong>Surrogate Foreign Key</strong> bezeichnet man ein einzelnes Feld, &uuml;ber das sich ein Datensatz eindeutig identifizieren l&auml;sst. In vielen Datenbanksystemen ist dies eine vom System generierte Nummer die in der jeweiligen Benutzeroberfl&auml;che oft gar nicht angezeigt wird, in AX w&auml;re dies beispielsweise die RecId. Schon in fr&uuml;heren Versionen von Dynamics AX wurde dieses Feld dazu verwendet, Beziehungen zwischen Tabellen herzustellen, mit Dynamics AX 2012 sollen s&auml;mtliche Relations &uuml;ber die RecId abgebildet werden.
</p>


<p>Neben den Surrogate Foreign Keys gibt es die <strong>Natural Foreign Keys</strong>, &uuml;ber&nbsp; die&nbsp; sich ein Datensatz ebenfalls eindeutig identifizieren l&auml;sst, allerdings in einer auch f&uuml;r den Benutzer lesbaren Form. Ausserdem kann ein Natural Foreign Key mehrere Felder beinhalten.<br />
&nbsp;<br />
Da sowohl der SurrogateForeign&nbsp; Key als auch der Natural Foreign Key einen Datensatz eindeutig identifizieren, k&ouml;nnen beide als <strong>Primary Key </strong>verwendet werden. Die neue Eigenschaft <strong>ReplacementKey </strong>von Tabellen steuert die Anzeige im AX-Client, unabh&auml;ngig vom tats&auml;chlichen Primary Key.
</p>

<p>&nbsp;
</p>

<p>Um die Verwendung dieser Keys zu verdeutlichen, m&ouml;chte ich in Dynamics AX 2012 beispielsweise zwei Tabellen erstellen, in welchen Autohersteller und deren Modelle gespeichert werden sollen.
</p>

<p>Die erste Tabelle <em>DmoCarManufacturer </em>enth&auml;lt<em> </em>nur zwei Felder:
</p>

<ul>
    
<li>ManufacturerID (Abgeleitet von einem eigens erstellten EDT vom Typ String mit dem Label Hersteller)
</li>
    
<li>Name (Abgeleitet vom EDT Name)
</li>

</ul>

<p><a href="http://www.schweda.net/pictures/blogpics/ax2012_dmocar_2.jpg" target="_blank"><img width="202" border="0" height="308" src="http://www.schweda.net/pictures/blogpics/ax2012_dmocar_2.jpg" alt="" title="Screenshot" /></a>
</p>

<p>Wenn man sich die Eigenschaften der Tabelle nach der Erstellung ansieht, erkennt man da&szlig; AX die Eigenschaft <em>CreateRecIdIndex </em>auf YES gesetzt und als <em>Primary Key </em>und <em>Clustered Index</em>&nbsp;den Wert <em>SurrogateKey </em>eingetragen hat.
</p>

<p><img border="0" src="http://www.schweda.net/pictures/blogpics/ax2012_dmocar_4.jpg" alt="" />
</p>

<p>Nun erstellt man einen neuen eindeutigen Index &uuml;ber das Feld <em>ManufacturerId </em>und legt diesen &uuml;ber die gleichnamige Eigenschaft als <strong>AlternateKey </strong>fest. <br />
Danach ist dieser Key auf Tabellenebene als <em>ReplacementKey </em>einzustellen wodurch dieses Feld automatisch der FieldGroup <em>AutoIdentification </em>hinzugef&uuml;gt wird.
</p>

<p><img border="0" src="http://www.schweda.net/pictures/blogpics/ax2012_dmocar_5.jpg" alt="" />&nbsp;
</p>

<p>Zus&auml;tzlich habe ich noch die Felder <em>ManufacturerId </em>und <em>Name </em>als <em>TitleFields </em>der Tabelle definiert, dies hat aber f&uuml;r die Relaton selbst keine Auswirkung, lediglich das sp&auml;tere Lookup-Formular wird dadurch benutzerfreundlicher.
</p>

<p>Der n&auml;chste Schritt ist die Erstellung der zweiten Tabelle <em>DmoCarModel</em>.
</p>

<p style="text-align: left;"><a href="http://www.schweda.net/pictures/blogpics/ax2012_dmocar_1.jpg" target="_blank"><img width="457" border="0" height="290" src="http://www.schweda.net/pictures/blogpics/ax2012_dmocar_1.jpg" alt="" title="Screenshot" /></a>
</p>

<p style="text-align: left;">Um nun eine Beziehung zur Tabelle <em>DmoCarManufacturer </em>zu erstellen w&auml;hlt man im Kontextmen&uuml; des Knoten Relations <em>Neue Relation </em>und tr&auml;gt als Tabelle die <em>DmoCarManufacturer </em>ein. Nun kann man &uuml;ber das Kontextmen&uuml; dieser neuen Relation <em>Neu &gt; ForeignKey &gt; PrimaryKey-basiert </em>ausw&auml;hlen. Dadurch erstellt AX ein neues Feld mit dem Namen <em>DmoCarManufacturer</em>, abgeleitet vom EDT <em>RefRecId</em>.
</p>

<p>Das zweite Feld <em>ModelId </em>lege ich manuell an und soll sp&auml;ter die Modellbezeichnung eines Autos beinhalten.
</p>

<p>Um nun die Auswirkung dieser Einstellungen darzustellen, erstelle ich auf Basis der Formular-Vorlage <em>Simple List </em>ein Formular f&uuml;r die Tabelle <em>DmoCarModel </em>und ziehe per Drag &amp; Drop das Feld <em>DmoCarManufacturer </em>in ein Grid des Designs. Dadurch wird innerhalb des Grids eine sogenannte <em>ReferenceGroup </em>erstellt. Auch das zweite Feld der Tabelle <em>ModelId </em>ziehe ich per Drag &amp; Drop ins Grid.
</p>

<p><a href="http://www.schweda.net/pictures/blogpics/ax2012_dmocar_3.jpg" target="_blank"><img border="0" src="http://www.schweda.net/pictures/blogpics/ax2012_dmocar_3.jpg" alt="" title="Screenshot" /></a>&nbsp;
</p>

<p>&Ouml;ffne ich nun dieses Formular und erstelle ich einen neuen Datensatz, sieht man da&szlig; im Lookup des Feldes <em>DmoCarManufacturer </em>nicht die <em>RecId </em>- welche ja in der Datenbank gespeichert wird - angezeigt wird, sondern die sprechenden Felder <em>Hersteller </em>und <em>Name</em>.
</p>

<p><a href="http://www.schweda.net/pictures/blogpics/ax2012_dmocar_6.jpg" target="_blank"><img width="465" border="0" height="375" src="http://www.schweda.net/pictures/blogpics/tb_ax2012_dmocar_6.jpg" alt="" title="Screenshot" /></a>&nbsp;
</p>

<p>&Ouml;ffnet man hingegen die Tabelle <em>DmoCarModel </em>&uuml;ber den TableBrowser, wird der Lookup das Feldes <em>DmoCarManufacturer </em>insoferne etwas anders dargestellt, als da&szlig; man hier auch die <em>RecId </em>sieht.
</p>

<p><a href="http://www.schweda.net/pictures/blogpics/ax2012_dmocar_7.jpg" target="_blank"><img width="465" border="0" height="376" src="http://www.schweda.net/pictures/blogpics/tb_ax2012_dmocar_7.jpg" alt="" title="Screenshot" /></a>&nbsp;
</p>

<p>Informationen dazu sind nat&uuml;rlich&nbsp;in der MSDN (<a href="http://msdn.microsoft.com/en-us/library/aa556809.aspx">http://msdn.microsoft.com/en-us/library/aa556809.aspx</a>) zu finden.&nbsp;
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Fri, 02 Mar 2012 17:39:00 +0100</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=421</link>
<comments>http://www.schweda.net/blog_ax.php?bid=421</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=421</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=421</wfw:commentRss>
</item>
<item>
<title>AX 2012: Eigene Lookups mit Hilfe der Klasse SysLookupMultiSelectCtrl erstellen</title>
<description><![CDATA[
<p>In AX 2012 gibt es &uuml;ber die Klasse <strong>SysLookupMultiSelectCtrl </strong>eine neue M&ouml;glichkeit, um bei einem Formularfeld, welches weder an eine DataSource noch an einen Extended Datatyp gebunden ist, dem Benutzer ein Lookup-Formular anzubieten.
</p>

<p>Diese Klasse hat gegen&uuml;ber der Klasse <strong>SysTableLookup</strong>, die es schon in Dynamics AX 2009 gegeben hat, sowohl einige Vorteile aber&nbsp;auch ein paar Nachteile:
</p>

<p><strong>Vorteile</strong>
</p>

<ul>
    
<li>Aufruf aus der <em>init</em>-Methode eines Formulares aus m&ouml;glich (d.h. es muss die <em>lookup</em>-Methode des jeweiligen Feldes nicht &uuml;berschrieben werden)
</li>
    
<li>Mehrfachauswahl von Werten ist m&ouml;glich
</li>

</ul>

<p><strong>Nachteile</strong>
</p>

<ul>
    
<li>Es k&ouml;nnen keine (Display-)Methoden in den Lookup eingebunden werden
</li>
    
<li>Man muss den Lookup verwenden um einen Wert auszuw&auml;hlen, eine &quot;freie&quot; Eingabe ist nicht m&ouml;glich
</li>

</ul>


<p>Hier ein einfaches Anwendungsbeispiel:
</p>

<p>Es soll bei dem FormStringControl namens <em>LookupStingEdit </em>eine Lookup-M&ouml;glichkeit auf die Debitorengruppen geschaffen werden. Es sollen aber nur bestimmte Gruppen angezeigt werden (realisiert &uuml;ber einen QueryBuildRange auf&nbsp;einen Query) und es soll der Name der Debitorengruppe retourniert werden (realisiert &uuml;ber den 5 Parameter der Methode <em>SysLookupMultiSelectCtrl::constructWithQuery</em>).
</p>

<div style="padding: 5px; width: 460px; height: 160px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public void init()<br />
{<br />
&nbsp;&nbsp;&nbsp; Query query;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; super();<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; query = new query();<br />
&nbsp;&nbsp;&nbsp; query.addDataSource(tableNum(CustGroup));<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; SysQuery::findOrCreateRange(query.dataSourceTable(tableNum(CustGroup)), fieldNum(CustGroup, Name)).value(&quot;*inter*&quot;);<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; SysLookupMultiSelectCtrl::constructWithQuery(this, LookupStringEdit, query, false, [tableNum(CustGroup), fieldNum(CustGroup, Name)]);<br />
}
</div>

<p><a href="http://www.schweda.net/pictures/blogpics/ax2012_SysLookupMultiSelectCtrl_1.jpg" target="_blank"><img width="465" border="0" height="157" src="http://www.schweda.net/pictures/blogpics/tb_ax2012_SysLookupMultiSelectCtrl_1.jpg" alt="" title="Screenshot" /></a>
</p>

<p>Diese&nbsp;neue Klasse&nbsp;kann man auch f&uuml;r Dialog-Felder verwenden, beispielsweise innerhalb eines Jobs:
</p>

<div style="padding: 5px; width: 460px; height: 160px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void dialogAddCustomLookup(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; Dialog dialog;<br />
&nbsp;&nbsp;&nbsp; DialogField dialogField;<br />
&nbsp;&nbsp;&nbsp; Query query;<br />
&nbsp;&nbsp;&nbsp; ;<br />
&nbsp;&nbsp;&nbsp; // Build dialog&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; dialog = new Dialog();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; dialogField = dialog.addField((&quot;name&quot;));<br />
<br />
&nbsp;&nbsp;&nbsp; // Build query for lookup<br />
&nbsp;&nbsp;&nbsp; query = new Query();<br />
&nbsp;&nbsp;&nbsp; query.addDataSource(tableNum(CustGroup));<br />
&nbsp;&nbsp;&nbsp; SysQuery::findOrCreateRange(query.dataSourceTable(tableNum(CustGroup)), fieldNum(CustGroup, Name)).value(&quot;*inter*&quot;);<br />
<br />
&nbsp;&nbsp;&nbsp; // Run dialog<br />
&nbsp;&nbsp;&nbsp; dialog.run(true);<br />
<br />
&nbsp;&nbsp;&nbsp; // Add lookup to dialogfield<br />
&nbsp;&nbsp;&nbsp; SysLookupMultiSelectCtrl::constructWithQuery(dialog.formRun(), dialogField.control(), query, false, [tableNum(CustGroup), fieldNum(CustGroup, Name)]);<br />
<br />
&nbsp;&nbsp;&nbsp; dialog.wait();<br />
<br />
&nbsp;&nbsp;&nbsp; // Get values from dialog<br />
&nbsp;&nbsp;&nbsp; if(dialog.closedOk())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(dialogField.value());<br />
}
</div>

<p>F&uuml;hrt man den Job aus, &ouml;ffnet sich der Dialog wie folgt:
</p>

<p><a href="http://www.schweda.net/pictures/blogpics/ax2012_SysLookupMultiSelectCtrl_1.jpg" target="_blank"><img width="305" border="0" height="170" src="http://www.schweda.net/pictures/blogpics/ax2012_SysLookupMultiSelectCtrl_3.jpg" alt="" title="Screenshot" /></a>
</p>

<p>Auch innerhalb einer von <em>RunBasebatch </em>abgeleiteten Klasse kann der Dialog um einen Lookup erweitert werden. Daf&uuml;r m&uuml;ssen die Methoden <em>dialog </em>und <em>dialogPostRun </em>angepasst werden. Im Beispiel wird ein Lookup auf die Debitoren erm&ouml;glicht, wobei auch Informationen aus der jeweiligen Debitorengruppe angezeigt werden:
</p>

<div style="padding: 5px; width: 460px; height: 160px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public Object dialog()<br />
{<br />
&nbsp;&nbsp;&nbsp; DialogRunbase&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dialog = super();<br />
&nbsp;&nbsp;&nbsp; queryBuildDataSource qbds;<br />
&nbsp;&nbsp;&nbsp; #resAppl<br />
&nbsp;&nbsp;&nbsp; ;<br />
&nbsp;&nbsp;&nbsp; dialogField = dialog.addField((&quot;name&quot;));<br />
<br />
&nbsp;&nbsp;&nbsp; // Build query for lookup<br />
&nbsp;&nbsp;&nbsp; query = new Query();<br />
&nbsp;&nbsp;&nbsp; qbds = query.addDataSource(tableNum(custTable));<br />
&nbsp;&nbsp;&nbsp; qbds.fields().clearFieldList();<br />
&nbsp;&nbsp;&nbsp; qbds.addSelectionField(fieldNum(CustTable, AccountNum));<br />
&nbsp;&nbsp;&nbsp; qbds.addSelectionField(fieldNum(CustTable, segmentId));<br />
&nbsp;&nbsp;&nbsp; qbds = qbds.addDataSource(tableNum(custGroup));<br />
&nbsp;&nbsp;&nbsp; qbds.fields().clearFieldList();<br />
&nbsp;&nbsp;&nbsp; qbds.addSelectionField(fieldNum(CustGroup, CustGroup));<br />
&nbsp;&nbsp;&nbsp; qbds.addSelectionField(fieldNum(CustGroup, name));<br />
&nbsp;&nbsp;&nbsp; qbds.joinMode(JoinMode::InnerJoin);<br />
&nbsp;&nbsp;&nbsp; qbds.relations(true);<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; SysQuery::findOrCreateRange(query.dataSourceTable(tableNum(CustGroup)), fieldNum(CustGroup, Name)).value(&quot;*inter*&quot;);<br />
<br />
&nbsp;&nbsp;&nbsp; return dialog;<br />
}
</div>

<p>&nbsp;
</p>

<div style="padding: 5px; width: 460px; height: 140px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public void dialogPostRun(DialogRunbase dialog)<br />
{<br />
&nbsp;&nbsp;&nbsp; ;<br />
&nbsp;&nbsp;&nbsp; // Add lookup to dialogfield<br />
&nbsp;&nbsp;&nbsp; SysLookupMultiSelectCtrl::constructWithQuery(dialog.formRun(), dialogField.control(), query, false, [tableNum(custTable), fieldNum(custTable, segmentId)]); <br />
<br />
&nbsp;&nbsp;&nbsp; super(dialog);<br />
}
</div>

<p><a href="http://www.schweda.net/pictures/blogpics/ax2012_SysLookupMultiSelectCtrl_2.jpg" target="_blank"><img width="465" border="0" height="234" src="http://www.schweda.net/pictures/blogpics/tb_ax2012_SysLookupMultiSelectCtrl_2.jpg" alt="" title="Screenshot" /></a>
</p>

<p><strong>Hinweis</strong>: Wenn innerhalb des Lookups mehrere Tabellen verjoint werden, k&ouml;nnen nur Werte aus der &quot;Haupttabelle&quot; des Queries retourniert werden. Wichtig ist weiters, da&szlig; nur jene Felder der Tabelle retourniert werden k&ouml;nnen, die auch im Lookup angezeigt werden.
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Tue, 21 Feb 2012 19:19:00 +0100</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=419</link>
<comments>http://www.schweda.net/blog_ax.php?bid=419</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=419</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=419</wfw:commentRss>
</item>
<item>
<title>Eigenes Lookup-Formular mit Hilfe der Klasse SysTableLookup gestalten</title>
<description><![CDATA[
<p>Ab und an kommt man als Entwickler in die Verlegenheit, ein Formularfeld, welches weder an eine Datenquelle (DataSource) oder einen Extended Datatyp gebunden ist, um ein Lookup-Formular zu erweitern. Daf&uuml;r stellt Dynamics AX die Klasse <strong>SysTableLookup </strong>zur Seite, die man in die <em>lookup</em>-Methode des jeweiligen Feldes einbinden kann.
</p>

<p>Hier ein einfaches Beispiel unter Verwendung eines Queries, bei dem prinzipiell ein Lookup auf die Kundengruppen m&ouml;glich sein soll, aber nur bestimmte angezeigt werden sollen. Diese Einschr&auml;nkung kann &uuml;ber <em>sysQuery::findOrCreateRange</em> abgebildet werden.
</p>

<p>Das Beispiel funktioniert &uuml;brigens sowohl in Dynamics AX 2009 als auch AX 2012.
</p>

<div style="padding: 5px; width: 460px; height: 160px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public void lookup()<br />
{<br />
&nbsp;&nbsp;&nbsp; sysTableLookup sysTableLookup;<br />
&nbsp;&nbsp;&nbsp; query query;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; super();<br />
<br />
&nbsp;&nbsp;&nbsp; query = new query();<br />
&nbsp;&nbsp;&nbsp; query.addDataSource(tableNum(custGroup));<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; sysQuery::findOrCreateRange(query.dataSourceTable(tableNum(custGroup)), fieldNum(custGroup, name)).value(&quot;*inter*&quot;);<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; sysTableLookup = sysTableLookup::newParameters(tableNum(custGroup), this);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.parmQuery(query);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupfield(fieldNum(custGroup, custGroup));<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupfield(fieldNum(custGroup, name));<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.performFormLookup();<br />
}
</div>


<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/ax_SysTableLookup_6.jpg"><img width="297" height="103" title="Screenshot" alt="" border="0" src="http://www.schweda.net/pictures/blogpics/ax_SysTableLookup_6.jpg" /></a>
</p>

<p>Im n&auml;chsten Beispiel sollen nur Kundengruppen angezeigt werden, wo es auch Kunden/Debitoren dazu gibt, dies wurde &uuml;ber einen <em>ExistsJoin </em>mit der Tabelle <em>CustTable </em>realisiert.
</p>

<p>Weiteres werden die im Lookup angezeigten Spalten die Labels &uuml;ber die Methode <em>setLabel </em>ge&auml;ndert und es wird nicht - wie es standardm&auml;ssig der Fall ist - die erste Spalte als zu retournierender Wert angegeben sondern die Spalte mit dem Namen der Kundengruppe (daf&uuml;r wird der zweite, boolsche Parameter der Methode <em>addLookupfield </em>verwendet):
</p>

<div style="padding: 5px; width: 460px; height: 160px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public void lookup()<br />
{<br />
&nbsp;&nbsp;&nbsp; sysTableLookup sysTableLookup;<br />
&nbsp;&nbsp;&nbsp; query query;<br />
&nbsp;&nbsp;&nbsp; queryBuildDataSource qbds_custGroup;<br />
&nbsp;&nbsp;&nbsp; queryBuildDataSource qbds_custTable;<br />
<br />
&nbsp;&nbsp;&nbsp; super();<br />
<br />
&nbsp;&nbsp;&nbsp; query = new query();<br />
&nbsp;&nbsp;&nbsp; qbds_custGroup = query.addDataSource(tableNum(custGroup));<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; qbds_custTable = qbds_custGroup.addDataSource(tableNum(custTable));<br />
&nbsp;&nbsp;&nbsp; qbds_custTable.joinMode(joinMode::ExistsJoin);<br />
&nbsp;&nbsp;&nbsp; qbds_custTable.relations(true);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup = sysTableLookup::newParameters(tableNum(CustGroup), this);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.parmQuery(query);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupfield(fieldNum(custGroup, custGroup));<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.setLabel(&quot;Custgroup ID&quot;);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupfield(fieldNum(custGroup, name), true);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.setLabel(&quot;Name of custgroup&quot;);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.performFormLookup();<br />
}
</div>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/ax_SysTableLookup_5.jpg"><img width="297" height="188" title="Screenshot" alt="" border="0" src="http://www.schweda.net/pictures/blogpics/ax_SysTableLookup_5.jpg" /></a>
</p>

<p>Auch dieses Beispiel funktioniert sowohl in Dynamics AX 2009 als auch AX 2012.
</p>

<p>Zus&auml;tzlich zu den oben beschriebenen M&ouml;glichkeiten k&ouml;nnen auch <strong>Display-Methoden</strong> von Tabellen eingebunden werden. Wichtig dabei ist lediglich, da&szlig; s&auml;mtliche Felder, die von der anzuzeigenden Display-Methode ben&ouml;tigt werden, auch im Lookup angezeigt werden. Im Beispiel wird die Methode <em>bankAccountNum </em>eingebunden, diese ben&ouml;tigt die Werte aus den Feldern <em>accountNum </em>und <em>bankAccount </em>der Tabelle <em>custTable</em>:
</p>

<div style="padding: 5px; width: 460px; height: 160px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public void lookup()<br />
{<br />
&nbsp;&nbsp;&nbsp; sysTableLookup sysTableLookup;<br />
<br />
&nbsp;&nbsp;&nbsp; super();<br />
<br />
&nbsp;&nbsp;&nbsp; sysTableLookup = sysTableLookup::newParameters(tableNum(custTable), this, true);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupfield(fieldNum(custTable, accountNum));<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupMethod(tableMethodStr(custTable, name));<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupfield(fieldNum(custTable, bankaccount));<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupMethod(tableMethodStr(custTable, bankAccountNum));<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.performFormLookup();<br />
}
</div>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/ax_SysTableLookup_4.jpg"><img width="465" height="187" title="Screenshot" alt="" border="0" src="http://www.schweda.net/pictures/blogpics/tb_ax_SysTableLookup_4.jpg" /></a>
</p>

<p>Im folgenden Beispiel gehe ich noch einen Schritt weiter und bef&uuml;lle zuerst eine <strong>tempor&auml;re Tabelle</strong>, aus der anschlie&szlig;end die Daten angezeigt werden. Ganz konkret werden s&auml;mtliche Kundengruppen inkl. einer Anzahl der zugewiesenen Kunden.
</p>

<p><em>Notiz:</em>Als tempor&auml;re Tabelle habe ich im Beispiel die <em>TmpJobSelect </em>verwendet, sch&ouml;ner w&auml;re nat&uuml;rlich eine eigene Tabelle. Auch bin ich mir dar&uuml;ber im klaren, da&szlig; das kontruierte Beispiel auch ohne tempor&auml;re Tabelle l&ouml;sbar gewesen w&auml;re.
</p>

<div style="padding: 5px; width: 460px; height: 160px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public void lookup()<br />
{<br />
&nbsp;&nbsp;&nbsp; sysTableLookup sysTableLookup;<br />
&nbsp;&nbsp;&nbsp; query query;<br />
&nbsp;&nbsp;&nbsp; TmpJobSelect TmpJobSelect;<br />
&nbsp;&nbsp;&nbsp; custGroup custGroup;<br />
<br />
&nbsp;&nbsp;&nbsp; super();<br />
<br />
&nbsp;&nbsp;&nbsp; // Fill temp-table&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; while select custGroup<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TmpJobSelect.ClassName = custGroup.CustGroup;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TmpJobSelect.ClassDescription = custGroup.name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TmpJobSelect.id = (select count(recId) from CustTable where custtable.CustGroup == custGroup.CustGroup).recid;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TmpJobSelect.insert();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; query = new query();<br />
&nbsp;&nbsp;&nbsp; query.addDataSource(tableNum(TmpJobSelect));<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; sysTableLookup = sysTableLookup::newParameters(tableNum(TmpJobSelect), this);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.parmTmpBuffer(TmpJobSelect);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.parmQuery(query);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupfield(fieldNum(TmpJobSelect, ClassName));<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.setLabel(&quot;Custgroup&quot;);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupfield(fieldNum(TmpJobSelect, ClassDescription));<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.setLabel(&quot;Name&quot;);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.addLookupfield(fieldNum(TmpJobSelect, id));<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.setLabel(&quot;Count of customers&quot;);<br />
&nbsp;&nbsp;&nbsp; sysTableLookup.performFormLookup();<br />
}
</div>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/ax_SysTableLookup_7.jpg"><img width="389" height="212" title="Screenshot" alt="" border="0" src="http://www.schweda.net/pictures/blogpics/ax_SysTableLookup_7.jpg" /></a>
</p>

<p>Auch dieses Beispiel funktioniert sowohl in Dynamics AX 2009 als auch AX 2012.
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Mon, 20 Feb 2012 14:23:00 +0100</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=420</link>
<comments>http://www.schweda.net/blog_ax.php?bid=420</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=420</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=420</wfw:commentRss>
</item>
<item>
<title>Windows 7: Als anderer Benutzer ausführen</title>
<description><![CDATA[
<p>Als Entwickler muss ich Dynamics AX immer wieder mal mit einem anderen Windows-Login starten, als dem eigenen. Deshalb habe ich in Windows 7 die Option <strong>Als anderer Benutzer ausf&uuml;hren</strong> im Kontext-Men&uuml; schmerzlich vermisst und statt dessen&nbsp; immer <a title="Dynamics AX mit einem bestimmten Windowslogin starten" target="_self" href="http://www.schweda.net/blog_ax.php?nid=runas1">Batch-Dateien</a> daf&uuml;r verwendet.
</p>

<p>&Uuml;ber einen Blog-Eintrag bin ich aber auf einen wertvollen Tip gestossen: Wenn man die [SHIFT]-Taste h&auml;lt, w&auml;hrend man &uuml;ber die rechte Maustaste das Kontext-Men&uuml; einer Applikation aufruft, steht die Option <strong>Als anderer Benutzer ausf&uuml;hren</strong> wieder zur Verf&uuml;gung.
</p>

<p><img border="0" align="left" width="334" height="161" title="Als anderer Benutzer ausf&uuml;hren" alt="Als anderer Benutzer ausf&uuml;hren" src="http://www.schweda.net/pictures/blogpics/dynamics_ax_runas_shift.jpg" />
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Fri, 02 Dec 2011 23:01:00 +0100</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=418</link>
<comments>http://www.schweda.net/blog_ax.php?bid=418</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=418</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=418</wfw:commentRss>
</item>
<item>
<title>AX 2012: Einen Bericht mit den SQL Reporting Services erstellen</title>
<description><![CDATA[
<p>Mit der Version Dynamics AX 2012 halten die SQL Reporting Services (SSRS) nun endg&uuml;ltig Einzug im Leben eines jeden AX-Entwicklers. Zeit also, sich mit diesem Thema etwas intensiver zu besch&auml;ftigen. Die Ergebnisse meiner ersten Gehversuche mit den SSRS pr&auml;sentiere ich Euch nun in diesem Beitrag.
</p>

<p>Szenario: Es soll ein Bericht erstellt werden, bei welchem der Umsatz pro Verkaufsgruppe ausgewertet werden kann.
</p>

<p>&nbsp;
</p>

<h2>Schritt 1: Erstellen eines Queries in Dynamics AX
</h2>

<table width="100%" cellspacing="1" cellpadding="1" border="0">
    <tbody>
        <tr>
            
<td valign="top" align="left">Ich gehe davon aus, da&szlig; der geneigte Leser schon einmal einen Query  erstellt hat, deshalb werde ich darauf nur sehr oberfl&auml;chlich eingehen.<br />
            <br />
            Basis-Tabellen meines Queries sind die Tabellen<br />
            
<ul>
                
<li>CustInvoiceTrans
</li>
                
<li>CustInvoiceJour
</li>
                
<li>CommissionSalesGroup
</li>
            
</ul>
            
<p>Die Tabelle <em>CustInvoiceTrans </em>wird per InnerJoin mit der <em>CustInvoiceJour </em>&uuml;ber die im Screenshot gezeigten Felder verkn&uuml;pft, die Tabelle <em>CommissionSalesGroup </em>wird per OuterJoin &uuml;ber das Feld <em>SalesGroup </em>verkn&uuml;pft.
</p>
            
</td>
            
<td valign="top">&nbsp;
</td>
            
<td valign="top" style="text-align: right;"><a target="_blank" href="http://www.schweda.net/pictures/blogpics/ax_query.jpg"><img width="232" align="right" height="179" title="Query" alt="Query" src="http://www.schweda.net/pictures/blogpics/ax_query_small.jpg" /></a>
</td>
        </tr>
    </tbody>

</table>

<p>Seit AX 2012 muss die Eigenschaft <em>Dynamic</em> der Fields-Gruppe aller beteiligten Tabellen entsprechend gesetzt werden, im einfachsten Fall wird diese auf <em>Yes </em>gesetzt, um im Visual Studio sp&auml;ter alle Felder der Tabellen verwenden zu k&ouml;nnen.
</p>


<p>&nbsp;
</p>

<h2>Schritt 2: Erstellen eines Projektes im Visual Studio
</h2>

<table width="100%" cellspacing="1" cellpadding="1" border="0">
    <tbody>
        <tr>
            
<td valign="top">&Uuml;ber <em>File &gt; New &gt; Project</em> das Template Microsoft Dynamics AX  ausw&auml;hlen, Report Model ausw&auml;hlen und einen Namen und Speicherort  angeben.
</td>
            
<td valign="top">&nbsp;
</td>
            
<td valign="top"><a target="_blank" href="http://www.schweda.net/pictures/blogpics/vs_solutionexplorer_project.jpg"><img width="216" height="115" title="Solution Explorer" alt="Solution Explorer" src="http://www.schweda.net/pictures/blogpics/vs_solutionexplorer_project_small.jpg" /></a>
</td>
        </tr>
    </tbody>

</table>

<p>&nbsp;
</p>

<h2>Schritt 3: Erzeugen eines DataSets
</h2>

<table width="100%" cellspacing="1" cellpadding="1" border="0">
    <tbody>
        <tr>
            
<td><a target="_blank" href="http://www.schweda.net/pictures/blogpics/vs_dataset_fields.jpg"><img width="191" height="316" title="DataSet" alt="DataSet" src="http://www.schweda.net/pictures/blogpics/vs_dataset_fields_small.jpg" /></a>
</td>
            
<td>
            
<p>Innerhalb dieses Reports ist nun ein neues DataSet zu erstellen.  Diesem geben wir den Namen <strong>CustInvoiceDataSet </strong>und tragen als Query den  zuvor in Dynamics AX erstellten ein. Letzteres erfolgt &uuml;ber einen Dialog  wo auch jene Felder oder Methoden gew&auml;hlt werden k&ouml;nnen, die im Bericht  ausgegeben werden sollen.
</p>
            
<p>In unserem Fall sind dies:
</p>
            
<p>Aus der Tabelle <em>CustInvoiceTrans </em>die Felder
</p>
            
<ul>
                
<li>InvocieId
</li>
                
<li>InvocieDate
</li>
                
<li>ItemId
</li>
                
<li>SalesGroup
</li>
                
<li>LineAmountMST
</li>
            
</ul>
            
<p>und die Methode
</p>
            
<ul>
                
<li>itemName()
</li>
            
</ul>
            
<p>Aus der Tabelle <em>CommissionSalesGroup</em> ben&ouml;tige ich das Feld
</p>
            
<ul>
                
<li>Name
</li>
            
</ul>
            
<p>Gleichzeitig habe ich das DataSet &uuml;ber die Properties auf <strong>CustInvoiceDataSet </strong>umbenannt.
</p>
            
</td>
        </tr>
    </tbody>

</table>

<p>Die Eigenschaften des DataSet stellen sich nach Abschlu&szlig; des Dialoges wie folgt dar:
</p>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/vs_dataset_properties.jpg"><img width="465" height="177" title="DataSet Properties" alt="DataSet Properties" src="http://www.schweda.net/pictures/blogpics/vs_dataset_properties_small.jpg" /></a>
</p>

<p>&nbsp;
</p>

<h2>Schritt 4: Erzeugen eines Designs
</h2>

<p>Nun kann das DataSet per Drag &amp; Drop in den Knoten <strong>Designs </strong>gezogen werden. Dadurch wird ein neues Design namens <strong>AutoDesign1 </strong>erstellt.
</p>

<p>Nun gilt es einige Eigenschaften dieses Designs anzupassen. Dazu z&auml;hlen das Seitenformat, Bezeichnungen (<em>Title</em>) des Berichtes aber auch das Layout (<em>LayoutTemplate</em>), im Beispiel habe ich als Seitenformat die Einstellungen f&uuml;r DIN-A4 eingetragen.
</p>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/vs_design_properties.jpg"><img width="465" height="263" title="Properties" alt="Properties" src="http://www.schweda.net/pictures/blogpics/vs_design_properties_small.jpg" /></a>&nbsp;
</p>

<p>Der automatisch generierten Tabelle <strong>CustInvoiceDataSetTable </strong>weisen wir ebenfalls &uuml;ber die Eigenschaft <em>StyleTemplate </em>ein Layout zu. Im Beispiel habe ich das Layout so gew&auml;hlt, da&szlig; die einzelnen Zeilen sp&auml;ter abwechselnd grau oder wei&szlig; unterlegt werden.
</p>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/vs_design_dataset_properties.jpg"><img width="465" height="327" alt="" src="http://www.schweda.net/pictures/blogpics/vs_design_dataset_properties_small.jpg" /></a>
</p>

<p>&nbsp;
</p>

<h2>Schritt 5:Gruppierung einrichten
</h2>

<table width="100%" cellspacing="1" cellpadding="1" border="0">
    <tbody>
        <tr>
            
<td><a href="http://www.schweda.net/pictures/blogpics/vs_design_groupings.jpg" target="_blank"><img width="213" height="400" src="http://www.schweda.net/pictures/blogpics/vs_design_groupings_small.jpg" alt="Gruppierung" title="Gruppierung" /></a>
</td>
            
<td valign="top" align="left">Nun gilt es, die geforderte Gruppierung nach der Verkaufsgruppe (Feld <em> SalesGroup</em>) abzubilden. Hierzu muss im Knoten Groupings der <strong> CustInvoiceDataSetTable</strong> benannten Tabelle ein neuer Knoten erstellt  werden. Diesen nennen wir <strong>SalesGroupGrouping </strong>und vergeben im einen  sprechenden Label, z.B. Verkaufsgruppe.<br />
            <br />
            In diesem Knoten k&ouml;nnen wir nun einen Unterknoten erstellen, in  dessen Expression wir das Feld <em>SalesGroup </em>eintragen. Dieser Knoten  bekommt nun noch den Namen <strong>SalesGroup</strong>.<br />
            <br />
            Danach erstellen wir jeweils einen neuen Knoten im Header und  Footer-Bereich. Auch diese bekommen einen m&ouml;glichst selbstsprechenden  Namen (<strong>SalesGroupHeader </strong>bzw. <strong>SalesGroupFooter</strong>).<br />
            <br />
            Im <strong>SalesGroupHeader </strong>erzeugen wir zwei Unterknoten. Beim Ersten tragen  wir in der Eigenschaft <em>Expression </em>das Feld <em>SalesGroup</em> ein, beim Zweiten  das Feld <em>Name</em>.
</td>
        </tr>
    </tbody>

</table>

<p>Im <strong>SalesGroupFooter </strong>erzeugen wie nun in Summe sieben Unterknoten. Nur beim siebenten tragen wir &uuml;ber die Eigenschaft <em>Expression </em>einen Wert ein, die anderen taufen wir <strong>Dummy1 </strong>bis <strong>Dummy6</strong>.
</p>

<p><a href="http://www.schweda.net/pictures/blogpics/vs_data_dummy_properties.jpg" target="_blank"><img width="465" height="177" src="http://www.schweda.net/pictures/blogpics/vs_data_dummy_properties_small.jpg" alt="Properties" title="Properties" /></a>
</p>

<p>Damit diese Summe je Verkaufsgruppe korrekt formatiert wird, passen wir die Eigenschaften entsprechend an:
</p>

<p><a href="http://www.schweda.net/pictures/blogpics/vs_groupsum_properties.jpg" target="_blank"><img width="465" height="252" src="http://www.schweda.net/pictures/blogpics/vs_groupsum_properties_small.jpg" alt="Properties" title="Properties" /></a>
</p>

<p>Hintergrund der Dummy-Felder ist, da&szlig; Visual-Studio die Spalten im Footer automatisch unter den Spalten im Data-Bereich versucht auszurichten. W&uuml;rden wir diese Dummy-Felder nicht erstellen, w&uuml;rde die Summe unterhalb der ersten Spalte&nbsp; angedruckt.
</p>

<p>In fr&uuml;heren Versionen von Dynamics AX h&auml;tten wir einfach die Eigenschaft <em>ModelFieldName </em>f&uuml;r solcherart Positionierung herangezogen, eine solche Eigenschaft scheint es aber in Visual Studio nicht zu geben.
</p>

<p>&nbsp;
</p>

<h2>Schritt 6: Reihenfolge der Spalten und Detail-Eigenschaften anpassen
</h2>

<p><a href="http://www.schweda.net/pictures/blogpics/vs_sorting_salesgroup_properties.jpg" target="_blank"><img width="465" height="118" src="http://www.schweda.net/pictures/blogpics/vs_sorting_salesgroup_properties_small.jpg" alt="Properties" title="Properties" /></a>
</p>

<p>Damit die Daten in einer bestimmten Reihenfolge sortiert angedruckt werden, erstellen wir im Sorting-Knoten entsprechende Unterknoten und tragen &uuml;ber deren Eigenschaft <em>SortBy </em>das jeweilige Feld ein. Wir sortieren nach Verkaufsgruppe, Rechnungsnummer und Rechnungsdatum.
</p>

<p>Abschlie&szlig;end pr&uuml;fen bzw. &auml;ndern wir die Reihenfolge der anzudruckenden Felder im Data-Bereich und passen &uuml;ber die jeweiligen Eigenschaften Spaltenbreiten und ggf. die Bezeichnungen an. So w&auml;hle ich zum Beispiel f&uuml;r die Spalte <em>LineAmountMST </em>als Bezeichnung <em>Betrag </em>statt dem vom Visual Studio vorgeschlagenen Label.
</p>

<p>&nbsp;
</p>

<h2>Schritt 7: Spalte Betrag einf&auml;rben
</h2>

<p>Damit Gutschriften bzw. Rechnungen mit negativen Werten rot dargestellt  werden, &auml;ndern wir die Eigenschaft <em>Style &gt; Font &gt; Color</em> &uuml;ber eine  entsprechende Expression:
</p>

<p><a href="http://www.schweda.net/pictures/blogpics/vs_data_lineamountmst_fontcolor_expression.jpg" target="_blank"><img width="465" height="377" src="http://www.schweda.net/pictures/blogpics/vs_data_lineamountmst_fontcolor_expression_small.jpg" alt="Expression" title="Expression" /></a>&nbsp;
</p>

<p>Diese &Auml;nderung bewirkt, da&szlig; im Bericht negative Betr&auml;ge sp&auml;ter wie folgt dargestellt werden:
</p>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/ax_report_colored_lines.jpg"><img width="465" height="52" title="Bericht mit eingef&auml;rbten Werten" alt="Bericht mit eingef&auml;rbten Werten" src="http://www.schweda.net/pictures/blogpics/ax_report_colored_lines_small.jpg" /></a>
</p>

<p>&nbsp;
</p>

<h2>Schritt 8: MenuItem in Dynamics AX erzeugen
</h2>

<table width="100%" cellspacing="1" cellpadding="1" border="0">
    <tbody>
        <tr>
            
<td valign="top">Abschlie&szlig;end erstellen wir in Dynamics AX ein neues MenuItem, verkn&uuml;pfen  dieses mit einem Men&uuml; um den Bericht aus Dynamics AX heraus starten zu k&ouml;nnen.<br />
            <br />
            AX erzeugt - wie schon in fr&uuml;heren Versionen - automatisch einen  Dialog, wo man die anzuzeigenden Daten filtern kann.
</td>
            
<td>&nbsp;
</td>
            
<td><a href="http://www.schweda.net/pictures/blogpics/ax_menuitem.jpg" target="_blank"><img width="232" height="118" src="http://www.schweda.net/pictures/blogpics/ax_menuitem_small.jpg" alt="Menuitem" title="Menuitem" /></a>
</td>
        </tr>
    </tbody>

</table>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/ax_dialog.jpg"><img title="Dialog" alt="Dialog" src="http://www.schweda.net/pictures/blogpics/ax_dialog_small.jpg" /></a>&nbsp;
</p>

<p>&nbsp;
</p>

<h2>Schritt 9: Aufrufen des Berichtes aus Dynamics AX heraus - Fertig
</h2>

<p><a target="_blank" href="http://www.schweda.net/pictures/blogpics/ax_report_examplepage.jpg"><img width="465" height="266" title="Bericht" alt="Bericht" src="http://www.schweda.net/pictures/blogpics/ax_report_examplepage_small.jpg" /></a>&nbsp;
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Fri, 04 Nov 2011 19:06:00 +0100</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=417</link>
<comments>http://www.schweda.net/blog_ax.php?bid=417</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=417</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=417</wfw:commentRss>
</item>
<item>
<title>SID für einen Active-Directory-User auslesen</title>
<description><![CDATA[
<p>Wer schon einmal eine Applikation inkl. Datenbank von einer Netzwerk-Dom&auml;ne in eine andere &uuml;bertragen hat, der kennt vielleicht die Situation. Man hat die Applikation und die Datenbank eingerichtet, kann sich in Dynamics AX aber nicht anmelden und erh&auml;lt die Fehlermeldung:
</p>

<blockquote>

<p>You are not recognized user of Dynamics AX. Please contact your system administrator
</p>

</blockquote>

<p>Die Ursache daf&uuml;r ist, da&szlig; in der Tabelle <strong>UserInfo </strong>- das ist jene Tabelle wo die AD-Benutzer verwaltet werden - nat&uuml;rlich noch die Benutzer der Ursprungsdom&auml;ne hinterlegt sind. Im einfachsten Fall &auml;ndert man in dieser Tabelle den Eintrag f&uuml;r den Administrator, indem man die Felder <em>NetworkDomain</em>, <em>NetworkAlias </em>und <em>SID </em>entsprechend &auml;ndert. <em>NetworkDomain </em>und <em>NetworkAlias </em>sind selbsterkl&auml;rend, woher bekommt man aber die <em>SID</em>?
</p>

<p>Eine einfache Internet-Recherche nach &quot;GET SID&quot; liefert einige M&ouml;glichkeiten, weniger bekannt ist aber, da&szlig; auch Dynamics AX 2009 selbst eine Methode zur Verf&uuml;gung stellt, um die SID f&uuml;r einen Benutzer auszulesen.
</p>

<p>Jetzt braucht man also nur noch ein anderes, bereits lauff&auml;higes AX, wo man sich anmelden und den Job absetzen kann ;-)
</p>

<div style="padding: 5px; width: 460px; height: 100px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void getUserSid(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; ;<br />
&nbsp;&nbsp;&nbsp; info(new xAxaptaUsermanager().getUserSid('h.schweda', 'schweda.net'));<br />
}
</div>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Tue, 27 Sep 2011 21:33:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=416</link>
<comments>http://www.schweda.net/blog_ax.php?bid=416</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=416</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=416</wfw:commentRss>
</item>
<item>
<title>Bearbeiten von Formularfeldern beschränken II</title>
<description><![CDATA[
<p>Sollen in einem Formular nur bestimmte Felder zur Bearbeitung freigegeben sein, kann man die Eigenschaft <em>allowEdit </em>s&auml;mtlicher Felder der DataSource der Tabelle entsprechend umsetzen.
</p>

<p>Einfacher geht&rsquo;s mit folgendem Codebeispiel, welches in der <em>init</em>-Methode der DataSource eingebunden wurde und - im konkreten Fall in der Tabelle <em>SalesLine </em>- nur bei einem einzigen Feld die Bearbeitung erlaubt.
</p>

<p>Im Gegensatz zu einem <a title="Bearbeiten von Formularfeldern beschr&auml;nken" target="_self" href="http://www.schweda.net/blog_ax.php?nid=allowedit1">fr&uuml;her ver&ouml;ffentlichten Beitrag</a> mit dem gleichen Thema werden bei diesem Codebeispiel auch Array-Felder korrekt ber&uuml;cksichtigt.
</p>

<div style="padding: 5px; width: 460px; height: 290px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">public void init()<br />
{<br />
&nbsp;&nbsp;&nbsp; FormDataObject&nbsp; fdo;<br />
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f;<br />
&nbsp;&nbsp;&nbsp; SysDictTable&nbsp;&nbsp;&nbsp; sysDictTable;<br />
&nbsp;&nbsp;&nbsp; MapEnumerator&nbsp;&nbsp; fdoMapEnumerator;<br />
&nbsp;&nbsp;&nbsp; ; <br />
&nbsp;&nbsp;&nbsp; sysDictTable = new SysDictTable(tablenum(SalesLine));<br />
&nbsp;&nbsp;&nbsp; for(f=1;f&lt;=sysDictTable.fieldCnt();f++)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fdoMapEnumerator = new MapEnumerator(formDataSourceArrayFieldExtObjects(salesLine_ds, sysDictTable.fieldCnt2Id(f)));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (fdoMapEnumerator.moveNext())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fdo = fdoMapEnumerator.currentValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(fdo)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fdo.allowEdit(false);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; fdo = salesLine_ds.object(fieldnum(SalesLine, QtyOrdered));<br />
&nbsp;&nbsp;&nbsp; fdo.allowEdit(true);<br />
}
</div>

<p>Getestet in Dynamics AX 2009
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Sun, 21 Aug 2011 19:34:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=415</link>
<comments>http://www.schweda.net/blog_ax.php?bid=415</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=415</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=415</wfw:commentRss>
</item>
<item>
<title>Datensatzvorlagen ermitteln</title>
<description><![CDATA[
<p>Wer einmal in die Verlegenheit kommt, ermitteln zu m&uuml;ssen ob f&uuml;r eine bestimmte Tabelle Datensatzvorlagen vorhanden sind, f&uuml;r den kann folgendes Code-Beispiel hilfreich sein.
</p>

<p>Im Beispiel wird ermittelt, wieviele Benutzer- bzw. Unternehmensvorlagen es f&uuml;r die Tabelle <em>InventTable </em>gibt und ob der aktuelle Benutzer sich den Vorlagendialog anzeigen l&auml;sst, wenn er/sie einen neuen Artikel anlegt.
</p>

<div style="padding: 5px; width: 460px; height: 260px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void SysRecordTemplatesActive(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; tableId tableId = tableNum(inventTable);<br />
&nbsp;&nbsp;&nbsp; common common = new sysdictTable(tableId).makeRecord();<br />
&nbsp;&nbsp;&nbsp; SysRecordTemplateStorageUser storageUser&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = SysRecordTemplateStorage::newCommon(common, SysRecordTemplateType::User);<br />
&nbsp;&nbsp;&nbsp; SysRecordTemplateStorageCompany storageCompany = SysRecordTemplateStorage::newCommon(common, SysRecordTemplateType::Company);<br />
&nbsp;&nbsp;&nbsp; sysRecordTemplateSelect sysRecordTemplateSelect;<br />
&nbsp;&nbsp;&nbsp; container userTemplates;<br />
&nbsp;&nbsp;&nbsp; container companyTemplates;<br />
&nbsp;&nbsp;&nbsp; ;<br />
&nbsp;&nbsp;&nbsp; // Liste der Vorlagen<br />
&nbsp;&nbsp;&nbsp; userTemplates = storageUser.get();<br />
&nbsp;&nbsp;&nbsp; info(strFmt(&quot;Anzahl Benutzervorlagen f&uuml;r Tabelle %1: %2&quot;, new sysdictTable(tableId).label(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conLen(userTemplates)));<br />
<br />
&nbsp;&nbsp;&nbsp; companyTemplates = storageCompany.get();<br />
&nbsp;&nbsp;&nbsp; info(strFmt(&quot;Anzahl Unternehmensvorlagen f&uuml;r Tabelle %1: %2&quot;, new sysdictTable(tableId).label(), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conLen(companyTemplates)));<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; // Soll der aktive Benutzer nach Vorlagen gefragt werden?<br />
&nbsp;&nbsp;&nbsp; sysRecordTemplateSelect = SysRecordTemplateSelect::newTableId(tableId);<br />
&nbsp;&nbsp;&nbsp; sysRecordTemplateSelect.load();<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; info(strFmt(&quot;Datensatzvorlagen f&uuml;r die Tabelle %1 in Verwendung: %2&quot;, new sysdictTable(tableId).label(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum2str(sysRecordTemplateSelect.parmPrompt()))); <br />
}
</div>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Fri, 12 Aug 2011 20:08:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=414</link>
<comments>http://www.schweda.net/blog_ax.php?bid=414</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=414</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=414</wfw:commentRss>
</item>
<item>
<title>Berichte lassen sich nicht über die Stapelverarbeitung ausführen</title>
<description><![CDATA[
<p>Wenn bei einem Benutzer der Register Stapel beim Aufruf eines Berichtes nicht angezeigt wird, kann dies u.U. daran liegen, da&szlig; der Benutzer keine oder unzureichende&nbsp;Berechtigung f&uuml;r den Sicherheitsschl&uuml;ssel <em>Stapelverarbeitungsbericht</em> (SecurityKey <em>BatchReport</em>) hat.
</p>

<p><img width="465" height="206" border="0" alt="" title="Screenshot" src="http://www.schweda.net/pictures/blogpics/axReportBatchTab.jpg" />
</p>

<p><br />
&nbsp;
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Wed, 06 Jul 2011 19:24:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=411</link>
<comments>http://www.schweda.net/blog_ax.php?bid=411</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=411</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=411</wfw:commentRss>
</item>
<item>
<title>Projekte nach einem bestimmten Objekt durchsuchen</title>
<description><![CDATA[
<p>Nachstehender Job durchsucht alle Projekte nach einem bestimmten Element des AOT.
</p>

<p>Daf&uuml;r wird ein Dialog verwendet, wo man lediglich den Namen und den Typ des zu suchenden Elementes angeben muss. Au&szlig;erdem kann man noch einstellen, ob auch die privaten Projektknoten durchsucht werden sollen.
</p>

<div style="padding: 5px; width: 460px; height: 260px; color: rgb(0, 0, 0); overflow: scroll; font-family: courier new,helvetica; font-size: 12px; white-space: nowrap; background-color: rgb(255, 255, 204);">static void findObjectWithinProjects(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; UtilElementType utilElementType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = UtilElementType::Table;<br />
&nbsp;&nbsp;&nbsp; Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objectName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 'custTable';<br />
&nbsp;&nbsp;&nbsp; boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; includePrivateProjects = false;<br />
&nbsp;&nbsp;&nbsp; Dialog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dialog;<br />
&nbsp;&nbsp;&nbsp; DialogField&nbsp;&nbsp;&nbsp;&nbsp; df_objectName;<br />
&nbsp;&nbsp;&nbsp; DialogField&nbsp;&nbsp;&nbsp;&nbsp; df_utilElementType;<br />
&nbsp;&nbsp;&nbsp; DialogField&nbsp;&nbsp;&nbsp;&nbsp; df_privateProjects;<br />
&nbsp;&nbsp;&nbsp; container&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conProjects;<br />
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c;<br />
&nbsp;&nbsp;&nbsp; TreeNode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeNodeRoot;<br />
&nbsp;&nbsp;&nbsp; SysOperationProgress&nbsp;&nbsp;&nbsp; sysOperationProgress;<br />
&nbsp;&nbsp;&nbsp; UtilElementType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; utilElementTypeSelection;&nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp;&nbsp; #Aot<br />
&nbsp;&nbsp;&nbsp; #TreeNodeSysNodeType<br />
&nbsp;&nbsp;&nbsp; #AviFiles<br />
&nbsp;&nbsp;&nbsp; #define.objectNameField(&quot;Name of object&quot;)<br />
&nbsp;&nbsp;&nbsp; #define.utilElementTypeField(&quot;Type of object&quot;)<br />
<br />
&nbsp;&nbsp;&nbsp; void findChildNodes(TreeNode _treeNodeParent, ProjectNode _projectNode, str _objectName)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TreeNode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeNode;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TreeNodeIterator&nbsp;&nbsp;&nbsp; treeNodeIterator;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeNodeIterator = _treeNodeParent.AOTiterator();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeNode = treeNodeIterator.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (treeNode)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (treeNode.AOTgetNodeType() == #NT_PROJECT_GROUP)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; findChildNodes(treeNode, _projectNode, _objectName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (treeNode.AOTname() like _objectName)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; utilElementTypeSelection = str2enum(utilElementTypeSelection, enum2str(utilElementType)); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!utilElementType || treeNode.applObjectType() == utilElementTypeSelection)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!confind(conProjects, _projectNode.AOTname()))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conProjects = conins(conProjects, conlen(conProjects)+1, _projectNode.AOTname());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeNode.treeNodeRelease();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeNode = treeNodeIterator.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; void loopProjectsNode(TreeNode _treeNode)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProjectNode projectNode;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TreeNode treeNodeProject; <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (_treeNode)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeNodeProject = _treeNode.AOTfirstChild();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (treeNodeProject)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; projectNode = treeNodeProject; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sysOperationProgress.setText(projectNode.name()); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; findChildNodes(projectNode.loadForInspection(), treeNodeProject, objectName); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeNodeProject = treeNodeProject.AOTnextSibling();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; ; <br />
&nbsp;&nbsp;&nbsp; dialog = new Dialog();<br />
&nbsp;&nbsp;&nbsp; dialog.caption(&quot;Find projects containing specific object&quot;);<br />
&nbsp;&nbsp;&nbsp; df_objectName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = dialog.addField(Types::String, #objectNameField);<br />
&nbsp;&nbsp;&nbsp; df_utilElementType = dialog.addField(typeid(UtilElementType), #utilElementTypeField);<br />
&nbsp;&nbsp;&nbsp; df_privateProjects = dialog.addField(typeid(NoYesId), &quot;Include Private projects&quot;); <br />
&nbsp;&nbsp;&nbsp; df_objectName.value(objectName);<br />
&nbsp;&nbsp;&nbsp; df_utilElementType.value(utilElementType);<br />
&nbsp;&nbsp;&nbsp; df_privateProjects.value(includePrivateProjects); <br />
&nbsp;&nbsp;&nbsp; if( !dialog.run())<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; objectName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = df_objectName.value();<br />
&nbsp;&nbsp;&nbsp; utilElementType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = df_utilElementType.value();<br />
&nbsp;&nbsp;&nbsp; includePrivateProjects = df_privateProjects.value(); <br />
&nbsp;&nbsp;&nbsp; if (objectName == '*' || objectName == '')<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw error(strfmt(&quot;@SYS26332&quot;, #objectNameField));<br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; setprefix(strfmt(&quot;Projects containing %1 '%2'&quot;, utilElementType, objectName)); <br />
<br />
&nbsp;&nbsp;&nbsp; startLengthyOperation(); <br />
<br />
&nbsp;&nbsp;&nbsp; sysOperationProgress = new SysOperationProgress();<br />
&nbsp;&nbsp;&nbsp; sysOperationProgress.setCaption(&quot;Searching&quot;);<br />
&nbsp;&nbsp;&nbsp; sysOperationProgress.setAnimation(#AviSearch); <br />
<br />
&nbsp;&nbsp;&nbsp; // Private projects<br />
&nbsp;&nbsp;&nbsp; if(includePrivateProjects)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loopProjectsNode(SysTreeNode::getPrivateProject());<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; // Shared projects<br />
&nbsp;&nbsp;&nbsp; loopProjectsNode(SysTreeNode::getSharedProject()); <br />
&nbsp;&nbsp;&nbsp; sysOperationProgress.kill();<br />
&nbsp;&nbsp;&nbsp; endLengthyOperation(); <br />
<br />
&nbsp;&nbsp;&nbsp; // List projects<br />
&nbsp;&nbsp;&nbsp; for(c=1;c&lt;=conlen(conProjects);c++)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info(conpeek(conProjects, c));<br />
&nbsp;&nbsp;&nbsp; }<br />
}
</div>

<p>Wer eine etwas komfortablere M&ouml;glichkeit vorzieht, der kann sich bei Firma Loncar Technologies Inc. ein entsprechendes XPO herunterladen und ins AX einspielen. AUf Basis dieses XPOs ist auch obiger Job entstanden.
</p>

<p><a href="https://www.loncartechnologies.com/download.php">https://www.loncartechnologies.com/download.php</a>
</p>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Wed, 29 Jun 2011 19:36:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=343</link>
<comments>http://www.schweda.net/blog_ax.php?bid=343</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=343</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=343</wfw:commentRss>
</item>
<item>
<title>Berechtigung eines Benutzers für einen Sicherheitsschlüssel abfragen</title>
<description><![CDATA[
<p>Mit diesem St&uuml;ckchen Code kann man in Dynamics AX pr&uuml;fen, welche Berechtigung ein Benutzer f&uuml;r einen bestimmten Sicherheitsschl&uuml;ssel (Securitykey) hat.
</p>

<div style="padding: 5px; background-color: rgb(255, 255, 204); width: 460px; font-family: courier new,helvetica; white-space: nowrap; height: 260px; color: rgb(0, 0, 0); font-size: 12px; overflow: scroll;">static void GetSecurityKeyAccess4User(Args _args)<br />
{<br />
&nbsp;&nbsp;&nbsp; Dictionary&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dictionary = new Dictionary();<br />
&nbsp;&nbsp;&nbsp; securityKeyId&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; securityKeyId;<br />
&nbsp;&nbsp;&nbsp; SecurityKeySet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; securityKeySet = new SecurityKeySet();<br />
&nbsp;&nbsp;&nbsp; UserId&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; userId = 'user1';<br />
&nbsp;&nbsp;&nbsp; SelectableDataArea&nbsp; dataArea = 'ceu';<br />
&nbsp;&nbsp;&nbsp; AccessType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; accessType;<br />
&nbsp;&nbsp;&nbsp; ;<br />
<br />
&nbsp;&nbsp;&nbsp; securityKeyId = Dictionary.securityKeyName2Id(&quot;BatchReport&quot;);<br />
<br />
&nbsp;&nbsp;&nbsp; securityKeySet.loadUserRights(userId, dataArea);<br />
<br />
&nbsp;&nbsp;&nbsp; AccessType = securityKeySet.access(securityKeyId);<br />
<br />
&nbsp;&nbsp;&nbsp; info(enum2str(AccessType));<br />
}
</div>]]></description>
<category>Microsoft Dynamics AX (Axapta)</category>
<pubDate>Fri, 24 Jun 2011 20:49:00 +0200</pubDate>
<link>http://www.schweda.net/blog_ax.php?bid=410</link>
<comments>http://www.schweda.net/blog_ax.php?bid=410</comments>
<guid isPermaLink="true">http://www.schweda.net/blog_ax.php?bid=410</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog_ax.php?bid=410</wfw:commentRss>
</item>
<item>
<title>HDC-350: Kopieren der Aufnahmen von einer auf die andere Festplatte</title>
<description><![CDATA[
<p>Wer einmal die am Kabelreceiver <strong>HDC-350</strong> angeschlossene Festplatte gegen ein gr&ouml;ssere auszutauschen m&ouml;chte, der wird m&ouml;glicherweise vor der gleichen Frage stehen wie ich: Wie kopiere ich meine Aufnahmen von der alten auf die neue Festplatte?<br />
<br />
<a target="_blank" href="http://www.schweda.net/pictures/blogpics/pc2box21.jpg"><img width="160" height="139" border="0" align="right" alt="PC2Box 2.1" src="http://www.schweda.net/pictures/blogpics/pc2box21_small.jpg" style="padding-left: 10px; padding-bottom: 5px;" /></a>Erste Anlaufstelle war das Programm <strong>PC2Box </strong>in der Version 2.0. Leider stellt dieses Programm offenbar nur die M&ouml;glichkeit zur Verf&uuml;gung, die Aufnahmen auf dem PC zu sichern. In die umgekehrte Richtung scheint dies nicht vorgesehen zu sein. <br />
<br />
&Uuml;ber einen <a target="_blank" href="http://www.mgdjs.de/mgdjs/22/08/2010/pc2box-filme-vom-externen-speicher-des-dr-hd-201-auf-den-pc-kopieren-auf-cddvd-brennen-oder-anschauen/">Blogbeitrag</a> bin ich aber auf eine <a target="_blank" href="http://developer.berlios.de/forum/forum.php?forum_id=35951">die Version 2.1</a> des Programmes gestossen, welches u.a. genau diese M&ouml;glichkeit bietet. Und diese k&ouml;nnte einfacher nicht sein, daher im folgenden also eine kurze Anleitung, wie man die Aufnahmen von einer auf die andere Festplatte &uuml;bertr&auml;gt:
</p>

<ol>
    
<li>Sichern der Aufnahmen der alten Festplatte &uuml;ber die Schaltfl&auml;che &quot;speichere rec-Dateien&quot; in einem Verzeichnis seiner Wahl
</li>
    
<li>&Uuml;bertragen der gesicherten Aufnahmen &uuml;ber die Schaltfl&auml;che &quot;&uuml;bertrage rec-Dateien&quot; auf die neue Festplatte
</li>

</ol>

<p>Jetzt nur noch die neue Festplatte am Receiver anschliessen und schon kann man sich seine Aufnahmen ansehen. Super!
</p>

<p>Ein paar kleine Bugs beim Zur&uuml;ckschreiben der Aufnahmen auf die Festplatte sind mir dann aber doch aufgefallen:
</p>

<p>Zum einen bekommen die Aufnahmen einen neuen Namen, dieser scheinbar aus dem urspr&uuml;nglichen und dem jeweiligen Sicherungslaufwerk zusammengesetzt sind. Da man &uuml;ber PC2Box die Aufnahmen auch umbenennen kann ist dies aber kein wirkliches Problem. Ausserdem k&ouml;nnen aber u.U. die Sicherungen der Aufnahmen nicht immer zur&uuml;ckgespielt werden. Ich hatte z.b. mit einer Aufnahme die Sonderzeichen im Namen enthalten hat Schwierigkeiten. Erst als ich die Aufnahme im Verzeichnis des PCs entsprechend umbenannt habe, konnte ich die Aufnahme zur&uuml;ckspielen.
</p>

<p>Ein weiterer Sch&ouml;nheitsfehler war auch die Anzeige der L&auml;nge der Aufnahmen. Lt. Anzeige in PC2Box aber auch im Men&uuml; der DVB-C-Receivers wurde eine wesentlich k&uuml;rzere Laufzeit angezeigt. Beim Abspielen dieser Aufnahmen wurde aber dennoch die gesamt Laufzeit problemlos abgespielt.
</p>]]></description>
<category>Dies und Das</category>
<pubDate>Sun, 19 Jun 2011 15:50:00 +0200</pubDate>
<link>http://www.schweda.net/blog.php?bid=409</link>
<comments>http://www.schweda.net/blog.php?bid=409</comments>
<guid isPermaLink="true">http://www.schweda.net/blog.php?bid=409</guid>
<author>heinz.schweda@schweda.net (Heinz Schweda)</author><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Heinz Schweda</dc:creator><wfw:commentRss>http://www.schweda.net/blog.php?bid=409</wfw:commentRss>
</item>
</channel>
</rss>	



