<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2639161662922921717</id><updated>2012-01-21T21:42:14.695+01:00</updated><category term='x++ code formatting ReportRealControls'/><category term='getting field value on a common'/><category term='table records xml'/><category term='_ds.executeQuery _ds.Research'/><category term='Form data source debugging'/><category term='Dynamics AX begin'/><category term='Uses of Textbuffer'/><category term='extracting text from a label'/><category term='AliasFor property tablefield search keys'/><category term='Axapta (Dynamics AX) 3.0 overriding SysLastValues calling a report'/><category term='Runbase class field mandatory'/><category term='Dynamics AX 2009 labels'/><category term='Making a form modal'/><category term='Axapta / Dynamics AX Refreshing a calling form from the called object'/><category term='Dynamics AX Code Expression'/><category term='Dynamics AX x++ Code snippet'/><category term='Generating and running code RUNTIME.'/><category term='AOS instance'/><category term='Axapta 3.0 closing a form from a parent form'/><category term='Batch renaming item ids in AX 2009.'/><category term='Usefull debugging tip'/><category term='Overriding tabChange and user setup of a form'/><category term='Getting active company'/><category term='Application Layers and table maps'/><category term='DYNAMICS AX Import Export Tool advanced uses'/><category term='amounts fields'/><title type='text'>Dynamics AX - thoughts on application development</title><subtitle type='html'>My thoughts on Dynamics AX application development.

I have been working as a consultant with Microsoft ERP-technology since 1994.

Currently I work at Columbus Global Danmark.

My main focus is customization and application development.

This blog is merely my place to put stuff and tips and tricks that I want to remember.

If anybody can benefit from reading this, that's great :0).

Feel free to use any code snippets posted - but accept that you do this at your own risk.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>42</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-6328795482795573014</id><published>2011-11-16T14:47:00.001+01:00</published><updated>2011-11-16T15:03:01.342+01:00</updated><title type='text'>Project accounting 3 - Dynamics AX 2012 - indirect cost / burden</title><content type='html'>I was tasked with getting an indirect cost setup to work in project accounting 3, but encountered some problems.&lt;br /&gt;&lt;br /&gt;Having read the excellent set up guide at &lt;a href="http://www.dynamicscare.com/blog/index.php/applying-indirect-burden-costs-to-project-ax-2012-labor-actuals/comment-page-1#comment-3324"&gt;http://www.dynamicscare.com/blog/index.php/applying-indirect-burden-costs-to-project-ax-2012-labor-actuals/comment-page-1#comment-3324&lt;/a&gt;&amp;nbsp; (Thanks to Merrie Cosby for this)&amp;nbsp;I proceeded to make the set up according to this guide, but failed to get it working. :(&lt;br /&gt;&lt;br /&gt;After some debugging I found that there is an error in the calculation of indirect costs when you run Dynamics AX 2012 in other languages than english.&lt;br /&gt;&lt;br /&gt;When setting up Compounding Rules the “Base amount” that you chose, is actually hardcoded in the logic that makes the calculations.&lt;br /&gt;&lt;br /&gt;The error can be found in &lt;br /&gt;&lt;br /&gt;class PSAIndirectCostCalculation&lt;br /&gt;method calculate:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;#define.BaseComponent(‘Base amount’)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This could be corrected so that the define is &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;#define.BaseComponent(&lt;/span&gt;&lt;a href="mailto:“@SYS73028″"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;“@SYS73028″&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And the check for the BaseComponent &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;if (_sId == #BaseComponent)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;is changed to&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;if (_sId == strFmt(#BaseComponent))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Then at least it works in danish language. :0)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-6328795482795573014?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/6328795482795573014/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2011/11/proejct-accounting-3-dynamics-ax-2012.html#comment-form' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6328795482795573014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6328795482795573014'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2011/11/proejct-accounting-3-dynamics-ax-2012.html' title='Project accounting 3 - Dynamics AX 2012 - indirect cost / burden'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-8584086086557599091</id><published>2011-10-12T10:59:00.000+02:00</published><updated>2011-10-12T13:21:34.165+02:00</updated><title type='text'>Dynamics AX 2012 - how to delete a layer</title><content type='html'>With the advent of model management in Dynamics AX 2012, Microsoft has gotten rid of the ax&lt;layer&gt;.aod files which in previous versions of DAX constituted the layers.&lt;br /&gt;In DAX 2012 adjustments for the meta data model and code are stored in the modelstore in the database.&lt;br /&gt;&lt;br /&gt;In previous version deleting a layer containing adjustments to the standard application consisted of delete the ax&lt;layer&gt;.aod file and synchronizing and compiling.&lt;br /&gt;&lt;br /&gt;How is this done in DAX 2012 ?&lt;br /&gt;&lt;br /&gt;The answer is a command-line tool called AxUtil.&lt;br /&gt;&lt;br /&gt;To delete e.g. the usr-layer in the application do the following:&lt;br /&gt;&lt;br /&gt;1) Shut down all AOS-servers but one (applicable only if you have more than one AOS running).&lt;br /&gt;2) Go to command line interface on the server where the last AOS is running.&lt;br /&gt;3) Go to the folder where DAX's&amp;nbsp;management utilities are placed, e.g.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; C:\Program Files\Microsoft Dynamics AX\60\ManagementUtilities&lt;br /&gt;4) Run the Axutil like this:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Axutil delete /layer:&lt;layer&gt; /db:&lt;modelstoredb&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; To delete the usr-layer in the MicrosoftDynamicsAx database:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Axutil delete /layer:usr /db:MicrosoftDynamicsAx&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Below an example is shown:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://4.bp.blogspot.com/-4ZRwJwjwmZ0/TpVMyu0wn9I/AAAAAAAAABg/ZjW6TfzJ_vE/s1600/axutil.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" oda="true" src="http://4.bp.blogspot.com/-4ZRwJwjwmZ0/TpVMyu0wn9I/AAAAAAAAABg/ZjW6TfzJ_vE/s400/axutil.png" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;5) Restart the AOS&lt;br /&gt;6) Start the DAX client.&lt;br /&gt;7) In the process of starting up, DAX will detect that something has happened with the modelstore, and prompt you with:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-bdUl1wa27Yw/TpVNLRqbZZI/AAAAAAAAABo/vBExq7lcAfc/s1600/delusrlayerstartup.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="327" oda="true" src="http://4.bp.blogspot.com/-bdUl1wa27Yw/TpVNLRqbZZI/AAAAAAAAABo/vBExq7lcAfc/s400/delusrlayerstartup.png" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Choose the action appropriate for your situation.&lt;br /&gt;8) Start the remaining AOSes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-8584086086557599091?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/8584086086557599091/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2011/10/dynamics-ax-2012-how-to-delete-layer.html#comment-form' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8584086086557599091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8584086086557599091'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2011/10/dynamics-ax-2012-how-to-delete-layer.html' title='Dynamics AX 2012 - how to delete a layer'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-4ZRwJwjwmZ0/TpVMyu0wn9I/AAAAAAAAABg/ZjW6TfzJ_vE/s72-c/axutil.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-1374509716828602399</id><published>2011-09-13T15:29:00.001+02:00</published><updated>2011-09-13T15:29:23.874+02:00</updated><title type='text'>Dynamics AX 2012 SSRS report - "Report has no design."</title><content type='html'>I just helped a colleague fix a little problem in Dynamics AX 2012.&lt;br /&gt;&lt;br /&gt;He was going through a tutorial to make a (SSRS) report in Dynamics AX 2012.&lt;br /&gt;He had designed the report complete with a dataset getting SalesTable data from AX, and had deployed it to the Report Server.&lt;br /&gt;He had also made a menu item for the report and put that in the menu in AX.&lt;br /&gt;&lt;br /&gt;However when he clicked the menu item AX failed to run the report giving the error&lt;br /&gt;"Report has no design."&lt;br /&gt;&lt;br /&gt;We poked around using a breakpoint in the Info class, to find that the AX class failing was ReportRun.&lt;br /&gt;The method in ReportRun we ended up in expected to receive a designname.&lt;br /&gt;However as nearly all AX reports are gone and replaced with SSRS reports in Dynamics AX 2012, this lead me to believe that something was up with the menuitem.&lt;br /&gt;&lt;br /&gt;We examined the output menu item to find that the ObjectType property was set to "Report" which is a remnant of the old AX reporting system.&lt;br /&gt;We corrected this property to SSRSReport, and voila.&lt;br /&gt;Ax now ran the report with no problems.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-1374509716828602399?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/1374509716828602399/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2011/09/dynamics-ax-2012-ssrs-report-report-has.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1374509716828602399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1374509716828602399'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2011/09/dynamics-ax-2012-ssrs-report-report-has.html' title='Dynamics AX 2012 SSRS report - &quot;Report has no design.&quot;'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-8674679077849335012</id><published>2011-08-26T14:00:00.000+02:00</published><updated>2011-08-26T14:00:44.637+02:00</updated><title type='text'>RunBaseBatch inheritance and saving last values chosen in a query</title><content type='html'>&lt;br /&gt;Today I found a little hack that is useful.&lt;br /&gt;I have a (super) class extending RunBaseBatch.&lt;br /&gt;This class build a query on the fly.&lt;br /&gt;This class also implements a dialog, which of course have a select button, so you can input search ranges for the query the class uses.&lt;br /&gt;&lt;br /&gt;I have a second (sub) class extending the first (super) class.&lt;br /&gt;Of course the sub-class also uses a query object.&lt;br /&gt;&lt;br /&gt;The problem was that when the super class and the sub class instatiates a query on the fly the query is nameless, and therefor execution of the dialog for the query ranges, resulted in the savelast values for the query to become messed up, so that when you ran the sub-class you would get the query ranges from the super-class and vice versa.&lt;br /&gt;&lt;br /&gt;A simple solution exists to this problem:&lt;br /&gt;When you instatiate the query object in the and then the queryRun object, you can do:&lt;br /&gt;&lt;br /&gt;queryRun.name(this.name());&lt;br /&gt;&lt;br /&gt;giving the queryRun object the name of the object instatiated using the super- or subclass.&lt;br /&gt;This seems to keep the query ranges sys last values separate for the two classes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-8674679077849335012?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/8674679077849335012/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2011/08/runbasebatch-inheritance-and-saving.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8674679077849335012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8674679077849335012'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2011/08/runbasebatch-inheritance-and-saving.html' title='RunBaseBatch inheritance and saving last values chosen in a query'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-4361913051438742211</id><published>2011-07-25T11:49:00.001+02:00</published><updated>2011-07-25T11:56:40.893+02:00</updated><title type='text'>Videos: Developing in Dynamics 2012</title><content type='html'>Editor-demo:&lt;br /&gt;&lt;a href="http://www.youtube.com/watch?v=r4nnnf9WJjU"&gt;http://www.youtube.com/watch?v=r4nnnf9WJjU&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Report-programming:&lt;br /&gt;&lt;a href="http://www.youtube.com/watch?v=kXcQmGo6aOg"&gt;http://www.youtube.com/watch?v=kXcQmGo6aOg&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-4361913051438742211?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/4361913051438742211/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2011/07/video-demo-new-dax-2012-editor.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/4361913051438742211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/4361913051438742211'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2011/07/video-demo-new-dax-2012-editor.html' title='Videos: Developing in Dynamics 2012'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-9066531395030839029</id><published>2011-05-17T10:08:00.002+02:00</published><updated>2011-05-17T10:08:34.502+02:00</updated><title type='text'>Programmatically accessing a dimension field</title><content type='html'>&lt;div class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;span lang="EN-US" style="color: #333333; font-family: &amp;quot;Lucida Sans Typewriter&amp;quot;; font-size: 8.5pt; mso-ansi-language: EN-US;"&gt;The following snippet can be used (in a form) to programmatically toggle mandatory mode on a dimension field (in this case department).&lt;/span&gt;&lt;div class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;span lang="EN-US" style="color: #333333; font-family: &amp;quot;Lucida Sans Typewriter&amp;quot;; font-size: 8.5pt; mso-ansi-language: EN-US;"&gt;ledgerJournalTrans_DS.object(fieldId2Ext(fieldNum(LedgerJournalTrans,&lt;/span&gt;&lt;span style="color: #333333; font-family: &amp;quot;Lucida Sans Typewriter&amp;quot;; font-size: 8.5pt;"&gt;&lt;a href="javascript:void(0);" id="Y218162S1"&gt;&lt;span lang="EN-US" style="color: #666666; mso-ansi-language: EN-US;"&gt;Dimension&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span lang="EN-US" style="color: #333333; font-family: &amp;quot;Lucida Sans Typewriter&amp;quot;; font-size: 8.5pt; mso-ansi-language: EN-US;"&gt;),1)).mandatory(true);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-9066531395030839029?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/9066531395030839029/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2011/05/programmatically-accessing-dimension.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/9066531395030839029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/9066531395030839029'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2011/05/programmatically-accessing-dimension.html' title='Programmatically accessing a dimension field'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-7376218721163164430</id><published>2011-05-03T15:12:00.002+02:00</published><updated>2011-10-12T13:21:33.101+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='amounts fields'/><category scheme='http://www.blogger.com/atom/ns#' term='x++ code formatting ReportRealControls'/><title type='text'>Axapta &amp; Dynamics ax 4.0 &amp; 2009: Formatting real-controls i AX reports using x++ code PART II</title><content type='html'>&lt;div&gt;A classic problem with ERP-systems running in multinational enterprises is the formatting of amount fields in a report.&lt;br /&gt;&lt;br /&gt;One aspect of this is that the different currencies in which the different national companies of an enterprise operates can vary a lot with regards to number of digits in the amount.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;E.g. the exchange rate between a danish kroner and an indonesian rupiah is (at time of writing):&lt;br /&gt;&lt;br /&gt;1 DKK - 1524,75 IDR.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;This would for an amount of 1 million danish kroner yield an converted amount of 1,524,750,000.75 IDR. An amount of the size can result in the Dynamics AX core returning&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Today I was asked by a customer, to come up with a prototype for user enabling the setting of widths of fields on a report&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The class that formats Real fields can be found here: &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://www.fasor.dk/blogspotattachments/Class_ReportFieldControlFormatter.xpo"&gt;http://www.fasor.dk/blogspotattachments/Class_ReportFieldControlFormatter.xpo&lt;/a&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-7376218721163164430?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/7376218721163164430/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2011/05/formatting-real-controls-i-ax-reports.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/7376218721163164430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/7376218721163164430'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2011/05/formatting-real-controls-i-ax-reports.html' title='Axapta &amp; Dynamics ax 4.0 &amp; 2009: Formatting real-controls i AX reports using x++ code PART II'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-2948797831985877693</id><published>2011-05-03T15:09:00.002+02:00</published><updated>2011-05-03T15:12:06.535+02:00</updated><title type='text'>Recursively refreshing any calling forms with ONE method</title><content type='html'>CASE:&lt;br /&gt;In the project module you can create item requirements for a project (which are basically items you sell via the project). At a customer site, a customized table and form, has been added to the item requirements forms, so the customer is able to set up item specifications for each item requirement, consisting of records with different kinds of data which describes the item.&lt;br /&gt;&lt;br /&gt;A class bas been made to import a .csv-file to an set of intermediate tables where data which forms the basis of item requirements and item specifications are stored.&lt;br /&gt;&lt;br /&gt;On the item requirements form, you can call a form showing the contents of the intermediate tables and from this form you can then (via a menuitem button) call a class that facilitates population of the item requirements AND item specifications from the itermediate table. When populating the item requirements table based on the intermediate table, you deleted the contents of the intermediate table.&lt;br /&gt;&lt;br /&gt;So you have the&lt;br /&gt;&lt;br /&gt;Project form calling the&lt;br /&gt;Item Requirements form&lt;br /&gt;calling the Intermediate table form,&lt;br /&gt;&lt;br /&gt;from where you perform the population of item requirements and specification.&lt;br /&gt;&lt;br /&gt;PROBLEM:&lt;br /&gt;How do you refresh the Item requirements form, and the itermediate table form to show that data has been "moved" from the intermediate form to the item requirements form WITH ONE METHOD CALL.&lt;br /&gt;&lt;br /&gt;SOLUTION:&lt;br /&gt;On the class performing the population i added a method that recursively examines the args object to see if the caller is a form, and then call the executequery method on the form datasource:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;void doCallingFormsRefresh(Args _args)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FormDataSource fds;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Args prevLevelArgs;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // refresh calling form&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_args.caller() &amp;amp;&amp;amp; _args.dataset() &amp;amp;&amp;amp; _args.record().isFormDataSource())&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Previous level of args (args from caller's caller)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; prevLevelArgs = _args.caller().args();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fds = _args.record().dataSource();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; fds.executeQuery();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (prevLevelArgs &amp;amp;&amp;amp; prevLevelArgs.record().TableId != tablenum(ProjTable) &amp;amp;&amp;amp; prevLevelArgs.record().isFormDataSource())&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.doCallingFormsRefresh(prevLevelArgs);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;Notice that the Projtable form is NOT refreshed.&lt;br /&gt;This way I avoided all the tedious call back methods on the forms, that is normally done.&lt;/span&gt;&lt;br /&gt;:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-2948797831985877693?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/2948797831985877693/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2011/05/recursively-refreshing-any-calling.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/2948797831985877693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/2948797831985877693'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2011/05/recursively-refreshing-any-calling.html' title='Recursively refreshing any calling forms with ONE method'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-5889098786714642758</id><published>2011-04-04T10:03:00.000+02:00</published><updated>2011-04-04T10:03:42.064+02:00</updated><title type='text'>Methods of opening a browser</title><content type='html'>Mental note to self: Ways of programmatically opening a browser with a webpage in x++: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;infolog.urllookup('http://www.fasor.dk'); &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This will open the standard browser. &lt;br /&gt;Or &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WinAPI::shellExecute('iexplore.exe','http://www.fasor.dk');&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;This specifically opens internetexplorer. The last method can also be used for starting up 3rd party applications from Axapta.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-5889098786714642758?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/5889098786714642758/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2011/03/methods-of-opening-browser.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/5889098786714642758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/5889098786714642758'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2011/03/methods-of-opening-browser.html' title='Methods of opening a browser'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-2059309863876729597</id><published>2011-04-04T10:02:00.004+02:00</published><updated>2011-05-04T10:08:08.262+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='table records xml'/><title type='text'>A quick way of dumping records of a table in an xml-file.</title><content type='html'>A quick way of of dumping table records into a xml-file is to use the kernel method xml, which is present on all instances of a tablebuffer. However, the xml produced by this method is NOT well-formed.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Three problems exists:&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;No header info for the xml-document is written&lt;/li&gt;&lt;li&gt;No root node is written&lt;/li&gt;&lt;li&gt;The data within tags are not html escaped&lt;/li&gt;&lt;/ul&gt;When the xml-method is called a call to the GLOBAL class method XMLString method is made.&lt;br /&gt;With a little adjustment to this method we can make the XML data output&amp;nbsp;wellformed.&lt;br /&gt;&lt;br /&gt;But first you must add this method to the GLOBAL class: &lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;public static str escapeHTMLChars(str _in)&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;{ &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int x; &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; str out; &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(x=1;x&amp;lt;=strlen(_in);x++) &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((char2num(_in,x) &amp;lt; 32) &amp;amp;&amp;amp; (char2num(_in,x) &amp;gt; 126)) &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; out += '&amp;amp;#'+num2str(char2num(_in,x),0,0,0,0)+';'; &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; out += substr(_in,x,1); &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return out; &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;And now back to the global::XMLString method.&lt;br /&gt;The last code block in the method is a big switch case construct handling all data types in x++. In the string handler section: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;case Types::RSTRING:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;case Types::VARSTRING:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;case Types::STRING:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; r += legalXMLString(value);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Insert this code just before the break-statement:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;r = global::escapeHTMLChars(r);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To call the method mentioned above. &lt;br /&gt;So the code will look like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;case Types::RSTRING:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;case Types::VARSTRING:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;case Types::STRING: &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; r += legalXMLString(value);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; r = global::escapeHTMLChars(r);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now it is possible to write code that:&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;Writes an xml-header.&lt;/li&gt;&lt;li&gt;Writes a root node tag.&lt;/li&gt;&lt;li&gt;Iterates a table and calls the xml-method on the tablenbuffer.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Write the end for the root node tag.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;static void Job45(Args _args) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; query q; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; QueryRun qr; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AsciiIo f; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; f = new AsciiIo('\\\\axdev2\\e$\\CIT Files\\jas\\mcfly.xml','w');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!f) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw error("Argh ! File can not be created."); &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; f.writeRaw(''); &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Write root node &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; f.writeRaw('&lt;customer&gt;'); &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; q = new Query(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Get customer no. 0215&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; q.addDataSource(tablenum(CustTable)).addRange(fieldnum(CustTable,AccountNum)).value('0215'); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; qr = new QueryRun(q); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (qr.next()) { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; f.write(qr.get(tablenum(CustTable)).xml()); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; f.writeRaw('&lt;/customer&gt;'); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; f = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Show xml-file in browser &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; winapi::shellExecute('\\\\axdev2\\e$\\CIT Files\\jas\\mcfly.xml'); &lt;br /&gt;} &lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-2059309863876729597?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/2059309863876729597/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2011/04/quick-way-of-dumping-records-of-table.html#comment-form' title='2 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/2059309863876729597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/2059309863876729597'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2011/04/quick-way-of-dumping-records-of-table.html' title='A quick way of dumping records of a table in an xml-file.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-70193949895403796</id><published>2010-12-16T11:45:00.005+01:00</published><updated>2010-12-16T11:53:14.397+01:00</updated><title type='text'>Outlook WTF ?</title><content type='html'>&lt;a href="http://2.bp.blogspot.com/_9MpqRay9JI4/TQnutzzH2wI/AAAAAAAAABQ/AcbnGg27Bqs/s1600/outlookwtf.png"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 320px; FLOAT: left; HEIGHT: 298px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5551230486477003522" border="0" alt="" src="http://2.bp.blogspot.com/_9MpqRay9JI4/TQnutzzH2wI/AAAAAAAAABQ/AcbnGg27Bqs/s320/outlookwtf.png" /&gt;&lt;/a&gt; A quick None AX-related post regarding strange software behaviour.&lt;br /&gt;&lt;br /&gt;I was booking my wifes work in my calendar.&lt;br /&gt;She works nights right now at a hospital, and I needed this in my calendar, to be able to plan in project work for my studies.&lt;br /&gt;She works night shifts 7 days in a row starting tuesday evening ending monday morning the following week, and this every second week.&lt;br /&gt;&lt;br /&gt;I tried to book this using reoccurence, and got an extreme amount of hours.&lt;br /&gt;&lt;br /&gt;WTF? :0)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-70193949895403796?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/70193949895403796/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2010/12/outlook-wtf.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/70193949895403796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/70193949895403796'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2010/12/outlook-wtf.html' title='Outlook WTF ?'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_9MpqRay9JI4/TQnutzzH2wI/AAAAAAAAABQ/AcbnGg27Bqs/s72-c/outlookwtf.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-4614095230156786698</id><published>2010-11-17T18:05:00.003+01:00</published><updated>2010-11-17T18:30:11.332+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AliasFor property tablefield search keys'/><title type='text'>AliasFor property on a tablefield</title><content type='html'>Ever wonder what the AliasFor property on a table field is used for ?&lt;br /&gt;&lt;br /&gt;It is actually a pretty nifty little feature of the AX runtime.&lt;br /&gt;&lt;br /&gt;I was tasked with making a solution for the following problem:&lt;br /&gt;&lt;br /&gt;* Introduce a new field on the item table that can hold the EAN number of the item.&lt;br /&gt;* Enable the user to be able to type in either the item id OR the EAN number when searching for an item to put on e.g. a sales order line.&lt;br /&gt;* Make sure that the EAN number is shown in the look up lists&lt;br /&gt;&lt;br /&gt;This actually quite easy to do.&lt;br /&gt;&lt;br /&gt;First I created the EAN number field on the InventTable using a new extended datatype created for that purpose.&lt;br /&gt;&lt;br /&gt;Then I created a new index on the InventTable containing the new field. This of course makes for searching for EAN numbers effeciently, but it also makes the EAN number field appear in the lookup list.&lt;br /&gt;&lt;br /&gt;The final thing to do was to set the AliasFor property of the new EAN Number field to be an alias for ItemId, by assigning the value ItemId to the property.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_9MpqRay9JI4/TOQPM1Ub-7I/AAAAAAAAABI/ENe043RDW-4/s1600/aliasfor.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 217px; height: 320px;" src="http://1.bp.blogspot.com/_9MpqRay9JI4/TOQPM1Ub-7I/AAAAAAAAABI/ENe043RDW-4/s320/aliasfor.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5540570154718198706" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now "magically" the user is able to type in both item id and EAN number in the Item ID field of e.g. a sales order line, or an item journal etc. to get the item number.&lt;br /&gt;&lt;br /&gt;So the AliasFor property can be used to enable the user to use more fields as search keys when directly typing in keys in a field.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-4614095230156786698?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/4614095230156786698/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2010/11/aliasfor-property-on-tablefield.html#comment-form' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/4614095230156786698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/4614095230156786698'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2010/11/aliasfor-property-on-tablefield.html' title='AliasFor property on a tablefield'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_9MpqRay9JI4/TOQPM1Ub-7I/AAAAAAAAABI/ENe043RDW-4/s72-c/aliasfor.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-3965069156641915387</id><published>2010-11-02T20:11:00.004+01:00</published><updated>2010-11-02T20:19:21.174+01:00</updated><title type='text'>Dynanics AX - WTF ?</title><content type='html'>Try the following job in Dynamics AX:&lt;br /&gt;&lt;br /&gt;static void Job16(Args _args)&lt;br /&gt;{;&lt;br /&gt;    info(conPeek(new HeapCheck().createAContainer(), 4));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;I've tested it in Dynamics AX 2009 and Axapta 3.0, so I guess it would work in Dynamics AX 4.0 also.&lt;br /&gt;&lt;br /&gt;Translated from danish the result reads:&lt;br /&gt;&lt;br /&gt;"Hi mum, heres comes a buffer"&lt;br /&gt;&lt;br /&gt;An AX easter egg. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-3965069156641915387?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/3965069156641915387/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2010/11/dynanics-ax-wtf.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3965069156641915387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3965069156641915387'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2010/11/dynanics-ax-wtf.html' title='Dynanics AX - WTF ?'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-5678165691969788793</id><published>2010-06-17T11:24:00.004+02:00</published><updated>2010-06-17T11:47:51.298+02:00</updated><title type='text'>Finding differences in code layers between installation</title><content type='html'>When working with customizations in Dynamics AX I consider it best practice to have several installations for the same customer.&lt;br /&gt;&lt;br /&gt;At a minimum you should have a development environment, a development test environment, a test environment besides the production environment that the customer runs in daily business.&lt;br /&gt;&lt;br /&gt;DEV.&lt;br /&gt;The development environment is for hacking away, developing and doing research and experiments.&lt;br /&gt;&lt;br /&gt;DEV TEST.&lt;br /&gt;The development test environment is for testing the customizations (inhouse QA) before releasing it to the customer for test.&lt;br /&gt;The transfer of customizations between DEV and DEV TEST is done by exporting and &lt;br /&gt;importing .xpo-files.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;TEST.&lt;br /&gt;The TEST environment is where the customer makes acceptance test of customizations.&lt;br /&gt;The transfer of code to the TEST enviroment is preferably done by copying layer (.aod)-files from the DEV TEST to the TEST, allowing for release/build control.&lt;br /&gt;If successive deliveries must be done, this can be again be done by exporting importing code &lt;strong&gt;AS LONG AS YOU ENSURE EXPORTING AND IMPORTING IS DONE WITH ID'S AND LABELS&lt;/strong&gt; using an outer layer.&lt;br /&gt;&lt;br /&gt;By doing the above described, you avoid having ID-conflicts, when doing RELEASE-upgrades.&lt;br /&gt;A release/buld can the be delivered by copying the .aod and label-files from the DEV TEST to the TEST, and deleting outer layers where successive test-deliveries have been made. Thus when you deliver a release/build you have all customizations rolled up in the layer you use for release.&lt;br /&gt;&lt;br /&gt;PRODUCTION.&lt;br /&gt;When making a delivery to the production environment, this is preferably done by delivering layer-files. Again succesive deliveries for hotfixes can be done, by observing the above mentioned rules for the TEST environment (exporting / importing with ID'S and LABELS).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When working as a consultant you are sometimes challenged by having to take over a customer from someone else.&lt;br /&gt;It can become even more challenging, if your predecessors have not been taking the above best pratice rules in to consideration, and you have doubts if the environments TEST and PRODUCTION are in synchronization.&lt;br /&gt;Of course if recently deliveries have been made for test by the customer they wouldn't be. &lt;br /&gt;&lt;br /&gt;But some times hotfixes are made directly in the production, and not carried back to the DEV and DEV TEST environments thus leaving the risk that the hotfix will be overwritten by a new release from the DEV TEST to TEST and further on from TEST to PRODUCTION.&lt;br /&gt;&lt;br /&gt;I recently had this situation happen to me, and needed to get an overview of the differences between the layers in TEST and PRODUCTION.&lt;br /&gt;Best practice was not followed in this case, so no DEV and DEV TEST enviroments were present, and hotfixes had been made directly in the production.&lt;br /&gt;&lt;br /&gt;So I took the layers from the production environment and copied them to the appl / old folder under the TEST enviroment, and used a litte job to build a list of the differences.&lt;br /&gt;&lt;br /&gt;Using this list, I was able to pull the code from the PRODUCTION missing in the TEST environment to the TEST environment, so that a release from the test environment weas made.&lt;br /&gt;&lt;br /&gt;Se code below:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;static void UtilElementsFindDiffInLayers(Args _args)&lt;br /&gt;{&lt;br /&gt;    UtilElements    newElement;&lt;br /&gt;    UtilElements    uppElement;&lt;br /&gt;    UtilElementsOld oldElements;&lt;br /&gt;    UtilElements    delElement;&lt;br /&gt;    UtilElementType type;&lt;br /&gt;    UtilEntryLevel  level    = UtilEntryLevel::cus;&lt;br /&gt;    Container       types    = [UtilElementType::TableInstanceMethod, UtilElementType::TableStaticMethod, UtilElementType::ClassInstanceMethod, UtilElementType::ClassStaticMethod];&lt;br /&gt;    UtilElementId   uid      = 0; //ClassNum(SysTableBrowser); // init UID if running on specific element&lt;br /&gt;if running on specific element&lt;br /&gt;    boolean         testMode = false; // TRUE to only test&lt;br /&gt;    Counter i;&lt;br /&gt;&lt;br /&gt;    type = conpeek(types,i);&lt;br /&gt;    while select newElement&lt;br /&gt;        order by utilLevel&lt;br /&gt;        where newElement.utilLevel  &gt; UtilEntryLevel::dip &amp;&amp;&lt;br /&gt;             (newElement.parentId   == uid || !uid)&lt;br /&gt;        join oldElements&lt;br /&gt;            where oldElements.utilLevel  == newElement.utilLevel&lt;br /&gt;               &amp;&amp; oldElements.name       == newElement.name&lt;br /&gt;               &amp;&amp; oldElements.recordType == newElement.recordType&lt;br /&gt;               &amp;&amp; oldElements.parentId   == newElement.parentId&lt;br /&gt;    {&lt;br /&gt;        if (oldElements.source != newElement.source)&lt;br /&gt;        {&lt;br /&gt;            info(strfmt("Layer: %1 Difference: %2 %3.%4",enum2str(newElement.utilLevel),global::enum2Value(oldElements.recordType),xUtilElements::parentName(newElement),oldElements.name));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ATTENTION: As always - USE CODE AT OWN RISK.&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-5678165691969788793?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/5678165691969788793/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2010/06/finding-differences-in-code-layers.html#comment-form' title='2 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/5678165691969788793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/5678165691969788793'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2010/06/finding-differences-in-code-layers.html' title='Finding differences in code layers between installation'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-3358363271001799958</id><published>2010-05-06T14:08:00.007+02:00</published><updated>2010-06-17T12:23:42.361+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='x++ code formatting ReportRealControls'/><title type='text'>Formatting real-controls i AX reports using x++ code</title><content type='html'>I was asked by a (danish) client if Dynamics AX could format amount fields according to lanaguage code of the customer.&lt;br /&gt;&lt;br /&gt;The problem arises as the danish format for amounts is:&lt;br /&gt;999.999.999,99&lt;br /&gt;&lt;br /&gt;That is thousand separators are the dot-sign and decimal separator is the comma-sign,&lt;br /&gt;&lt;br /&gt;and the english format is&lt;br /&gt;999,999,999.99&lt;br /&gt;&lt;br /&gt;That is thousand separators are the comma-sign and decimal separator is the dot-sign.&lt;br /&gt;&lt;br /&gt;Now the Ax client is able to run in several language of course, but this also imposes the regional settings on any reports printed.&lt;br /&gt;Thus if you run the AX client with danish language and prints an invoice for an english customer, all amounts will be printed using danish formatting.&lt;br /&gt;&lt;br /&gt;I wrote a small class that builds a list of all real-controls in a report. You can then feed it a langauge code and it will traverse the list of controls and format them accordingly.&lt;br /&gt;&lt;br /&gt;Thus we can now batch invoice customers and get invoices printed where amounts are formatted according to the language code of the customer. :0)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-3358363271001799958?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/3358363271001799958/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2010/05/formatting-real-controls-i-ax-reports.html#comment-form' title='2 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3358363271001799958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3358363271001799958'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2010/05/formatting-real-controls-i-ax-reports.html' title='Formatting real-controls i AX reports using x++ code'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-8205808683153714322</id><published>2010-04-29T13:51:00.005+02:00</published><updated>2010-04-30T14:13:35.898+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Axapta / Dynamics AX Refreshing a calling form from the called object'/><title type='text'>Refreshing (executeQuery) a calling form from the called form.</title><content type='html'>A feature that you often need when you work with code that is called from a form and manipulates data, is to be able to refresh the calling form to reflect the changes made, when the code has been run.&lt;br /&gt;&lt;br /&gt;This could also be a form calling an other form, where data changes are made, in the called form, but the changes must be reflected in the calling form, when the called form is closed.&lt;br /&gt;&lt;br /&gt;I have seen it done by making call back to a method on the calling form, that does the refresh.&lt;br /&gt;&lt;br /&gt;You can however make the refresh from the CALLED form or code, using an args-object.&lt;br /&gt;&lt;br /&gt;When a form calls an other form it is typically done via a menu item, and thus automatically an args object is passed to the called form.&lt;br /&gt;&lt;br /&gt;The args object can carry a tablebuffer object that is acessed with the record method on the args object.&lt;br /&gt;&lt;br /&gt;You can determine if the tablebuffer object is a formDataSource, and if so, you can instantiate a formDataSource-object on which you call the executeQuery-metod.&lt;br /&gt;&lt;br /&gt;One example could be:&lt;br /&gt;&lt;br /&gt;Form SalesTable&lt;br /&gt;has a menuitembutton that calls Form SalesLine.&lt;br /&gt;&lt;br /&gt;Form SalesTable has a display method that sums up data manipulated in Form SalesLine.&lt;br /&gt;When closing form SalesLine we need Form SalesLine to re-execute the query in Form SalesTable and thus refreshing the data form SalesTable is showing.&lt;br /&gt;&lt;br /&gt;This can be done by overriding the close method on Form SalesLine and putting the following code into it:&lt;br /&gt;&lt;br /&gt;public void close()&lt;br /&gt;{&lt;br /&gt;    FormDataSource                  fds;         // Form data source object&lt;br /&gt;    SalesTable                      salesTable;  // tablebuffer passed in args object&lt;br /&gt;&lt;br /&gt;    super();&lt;br /&gt;    // Refresh calling form data source&lt;br /&gt;    salesTable = element.args().record();&lt;br /&gt;    if (salesTable.isFormDataSource())&lt;br /&gt;    {&lt;br /&gt;        fds = salesTable.dataSource();&lt;br /&gt;        if (fds)&lt;br /&gt;        {&lt;br /&gt;            fds.executeQuery();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;The above shown can also be used in a main-method on a class, so that code in the class that manipulates data shown in a form, where the class is called via a menu-button on the form.&lt;br /&gt;&lt;br /&gt;I thought of doing it with a common object, and putting the code in a method on the GLOBAL class, to make it useable everywhere from a single line of code, but the Axapta client (3.0) kept crashing when calling common.dataSource() :0(.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-8205808683153714322?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/8205808683153714322/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2010/04/refreshing-executequery-calling-form.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8205808683153714322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8205808683153714322'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2010/04/refreshing-executequery-calling-form.html' title='Refreshing (executeQuery) a calling form from the called form.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-4466828034562500185</id><published>2010-04-26T11:42:00.011+02:00</published><updated>2010-04-27T09:01:16.331+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Overriding tabChange and user setup of a form'/><title type='text'>Don't override the tabChange-method on a tab.</title><content type='html'>Working on a Dynmics AX 4.0, I learned today (from a &lt;a href="http://catb.org/jargon/html/W/wizard.html"&gt;wizard-level&lt;/a&gt; colleague), that overriding the tabChange-method on a tab in a form in Dynamic AX/Axapta, disallows the usersetup of the tab and all of it's children.&lt;br /&gt;&lt;br /&gt;My problem was that a customer complained that they were not able to make a user setup of the form and add fields to a tab and all tabpages below that tab on the PurchTable-form.&lt;br /&gt;&lt;br /&gt;The customization:&lt;br /&gt;&lt;br /&gt;public boolean  tabChange(int  fromTab)&lt;br /&gt;{&lt;br /&gt;    boolean ok;&lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;    ok = super(fromTab);&lt;br /&gt;&lt;br /&gt;    if (ok)&lt;br /&gt;        purchTable_ds.lastJournals();&lt;br /&gt;&lt;br /&gt;    return ok;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;had been added to the tab.&lt;br /&gt;&lt;br /&gt;Seing that the method call&lt;br /&gt;&lt;br /&gt;PurchTable_ds.lastJournals(); &lt;br /&gt;&lt;br /&gt;was present in &lt;br /&gt;pageActivated-method on the tabpage TabHeaderPostings in the SYS-layer (!),&lt;br /&gt;I decided to remove the above customization.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-4466828034562500185?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/4466828034562500185/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2010/04/dont-override-tabchange-method-on-tab.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/4466828034562500185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/4466828034562500185'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2010/04/dont-override-tabchange-method-on-tab.html' title='Don&apos;t override the tabChange-method on a tab.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-8469672992440442269</id><published>2010-04-21T08:55:00.001+02:00</published><updated>2010-04-27T09:02:05.771+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX x++ Code snippet'/><title type='text'>Useful function for left trimming 0's in a string.</title><content type='html'>A colleague of mine made this little function.&lt;br /&gt;It strips leading 0's in a string.&lt;br /&gt;The string may only be a 1000 characters long, but that can be modified by changing 1000 to an other value.&lt;br /&gt;&lt;br /&gt;static TempStr strLtrim0(TempStr txt,str 1 trim = '0') &lt;br /&gt;{ &lt;br /&gt;    int i = strNfind(txt,trim,1,1000); &lt;br /&gt;    return i ? subStr(txt,i,1000) : ''; &lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-8469672992440442269?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/8469672992440442269/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2010/04/useful-function-for-left-trimming-0s-in.html#comment-form' title='2 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8469672992440442269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8469672992440442269'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2010/04/useful-function-for-left-trimming-0s-in.html' title='Useful function for left trimming 0&apos;s in a string.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-1504955895208547238</id><published>2010-03-16T15:30:00.008+01:00</published><updated>2010-04-27T09:01:32.149+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Axapta 3.0 closing a form from a parent form'/><title type='text'>Having a caller form close a called form</title><content type='html'>&lt;div&gt;Today I was asked an interesting question by a colleague.&lt;br /&gt;&lt;br /&gt;If a form is opened from an other form, can we make Axapta (3.0) close the called form automatically when closing the caller form.&lt;br /&gt;&lt;br /&gt;I remembered some old code for making a form truly modal in Axapta, and thought that maybe we could use some of that.&lt;br /&gt;&lt;br /&gt;Now the solution presented here, is only good for one called form. but it should be quite easy to implement, that all opened forms open from a parent form, are closed when the parent form is closed, by changing the hwndchild reference to a list or a set of HWND-references, looping through that set or list, checking if each HWND-reference refers to an active window, and then and destroying each window.&lt;br /&gt;&lt;br /&gt;A small example code project can be downloaded&lt;br /&gt;&lt;a href="http://www.fasor.dk/axcodesnippets/xppCallerFormClosesCalledForm.xpo"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;The project contains two small forms and a display menu item.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;The parent form test, has a buttongroup where the menuitem (referring to the child form testchild) is included.&lt;/div&gt;&lt;br /&gt;&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;div&gt;When you open form test, and click the button, testchild opens.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Now when you give focus to the test (parent) form, and close it, the child form will automatically close.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;strong&gt;As always - USE AT OWN RISK.&lt;/strong&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-1504955895208547238?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/1504955895208547238/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2010/03/having-caller-form-close-called-form.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1504955895208547238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1504955895208547238'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2010/03/having-caller-form-close-called-form.html' title='Having a caller form close a called form'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-8412097319100355962</id><published>2010-01-14T10:54:00.004+01:00</published><updated>2010-01-20T11:20:32.240+01:00</updated><title type='text'>Mental note to self - disabling upgrade check list</title><content type='html'>Today I experienced that the Administration menu in AX 3.0 was very limited.&lt;br /&gt;This was due to a previous upgrade of the Payroll module, resulting in the upgrade check list was to be run.&lt;br /&gt;However the upgrade had been done in a dev/test- environment and been moved to a test/live environment. &lt;br /&gt;&lt;br /&gt;Thus the need to complete the full upgrade check list was nonscence.&lt;br /&gt;However we couldn't deactivate the upgrade check list via the menu, because the administration menu was limited to showing the Periodic menu node only.&lt;br /&gt;&lt;br /&gt;However we could access the AOT :).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Mental note to self:&lt;/strong&gt;&lt;br /&gt;If you want to disable the upgrade check list but for some reasone you have no access to the Administration menu item Administration/Setup/System/Checklists/Prevent startup of list you can activate the Action menu item SysCheckList_InitNoUpdate. :)&lt;br /&gt;&lt;br /&gt;Restart the AX client, and the Administration menu should be complete :).&lt;br /&gt;That was what I experienced anyhow.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;20\01\2010 - UPDATE&lt;/strong&gt;&lt;br /&gt;Well one more thing to mention about this little problem. Today we encountered the problem at a customer site, but with an additional twist. The twist being that we were not able to run the menuitem from the AOT, because of insufficient rights !!!&lt;br /&gt;&lt;br /&gt;Ouch ... then what to do ?&lt;br /&gt;&lt;br /&gt;Well I examined the class hierachy that among other things runs the upgrade check list and found the static method&lt;br /&gt;&lt;br /&gt;SysChecklist::initNoUpdate&lt;br /&gt;&lt;br /&gt;I copied the code in this method to a job (remembering the macro #SysCheckList in classdeclation of SysChecklist&lt;br /&gt;&lt;br /&gt;static void Job10(Args _args)&lt;br /&gt;{&lt;br /&gt;    #SysCheckList&lt;br /&gt;&lt;br /&gt;    ttsbegin;&lt;br /&gt;    SysSetupLog::saveEx(classstr(SysCheckListItem_Synchronize), '');          //Do not run Synchronize&lt;br /&gt;    SysSetupLog::saveEx(classstr(SysCheckListItem_SynchronizeUpgrade), '');   //same&lt;br /&gt;    SysSetupLog::saveEx(classstr(SysCheckList_Upgrade), #CheckListFinished);  //Do not run upgrade&lt;br /&gt;    SysSetupLog::saveEx(classstr(SysCheckListItem_Compile), '');              //Do not run compile&lt;br /&gt;    SysSetupLog::saveEx(classstr(SysCheckList_Setup), #CheckListFinished);    //Do not run setup&lt;br /&gt;    ttscommit;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Ran that and the check upgrade list didn't start up any more :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-8412097319100355962?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/8412097319100355962/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2010/01/mental-note-to-self-disabling-upgrade.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8412097319100355962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8412097319100355962'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2010/01/mental-note-to-self-disabling-upgrade.html' title='Mental note to self - disabling upgrade check list'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-1354560254429224287</id><published>2009-12-09T17:04:00.005+01:00</published><updated>2009-12-09T17:15:22.177+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Batch renaming item ids in AX 2009.'/><title type='text'>Batch-renaming a primary key.</title><content type='html'>For a programmer who has experienced the "terror" of having to batch-rename primary keys in Dynamics AX's predecessor XAL/C5, I was pleasantly surprised to find how easy it is in Dynamics AX 2009.&lt;br /&gt;&lt;br /&gt;Though not documented a method called renamePrimayKey exists on the kernel class xRecord which each table apparently inherits from.&lt;br /&gt;&lt;br /&gt;If you call this method after changing the primarykey field on a tablebuffer, this change will be cascaded to related tables. :0)&lt;br /&gt;&lt;br /&gt;I was given a task to perform renaming of Items in the InventTable.&lt;br /&gt;In an environment that is to go live - so &lt;strong&gt;THERE WERE NO TRANSACTIONS OG STOCK LEVELS&lt;/strong&gt;. If this has been the case we would have adviced the customer to live with it, as the renaming process potentially would have taken a very long time&lt;br /&gt;&lt;br /&gt;Nearly 75% of the item numbers were named with 4 digits, the rest with 5.&lt;br /&gt;The customer wanted only 5-digit item numbers.&lt;br /&gt;&lt;br /&gt;How to do this in one go ?&lt;br /&gt;A simple job is enough:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;static void Job7(Args _args)&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    InventTable inventTable;&lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;    ttsbegin;&lt;br /&gt;    while select forupdate inventTable&lt;br /&gt;        where inventTable.ItemId LIKE "????"&lt;br /&gt;    {&lt;br /&gt;        inventTable.ItemId = "0"+InventTable.ItemId;&lt;br /&gt;        inventTable.renamePrimaryKey();&lt;br /&gt;    }&lt;br /&gt;    ttscommit;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;As always &lt;strong&gt;USE AT OWN RISK&lt;/strong&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-1354560254429224287?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/1354560254429224287/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/12/batch-renaming-primary-key.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1354560254429224287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1354560254429224287'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/12/batch-renaming-primary-key.html' title='Batch-renaming a primary key.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-4114937615410607217</id><published>2009-12-09T12:52:00.006+01:00</published><updated>2009-12-21T13:17:28.813+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DYNAMICS AX Import Export Tool advanced uses'/><title type='text'>DYNAMICS AX Import Export Tool - digging a bit deeper.</title><content type='html'>Normally when I've used the export/import-tool in AX, it's because you want to dump data from a small database and import it in another environment, or if you want&lt;br /&gt;to install some sort of demonstration database in an environment.&lt;br /&gt;&lt;br /&gt;Up until now, if I've been presented with a task of importing data into a customers environment, i've always programmed some sort of class that handles the import.&lt;br /&gt;&lt;br /&gt;A couple of weeks ago, a colleague of mine showed me that the import/export tool, can be used for the same task - that is importing data, from e.g. a .csv-file, that your customer prepared in Excel.&lt;br /&gt;&lt;br /&gt;I was thrilled to discover that I do not actually always need to make a class to import data in a specific (or more specific) table(s).&lt;br /&gt;&lt;br /&gt;The procedure is:&lt;br /&gt;&lt;br /&gt;1) Create your own Definition group - make sure it is empty by removing all checkmarks on the Set up and include table groups tabs pages, and choose the type User defined.&lt;br /&gt;Save the def. group.&lt;br /&gt;&lt;br /&gt;2) Now click the Table setup button. Choose the table that you want to import data into. Choose the import status delete and import (if you want to clear the table of data before you import), or just import. Set up the file name of the file containing the data.&lt;br /&gt;&lt;br /&gt;3) On the general tab you can specify field delimiter (in my case ; for a .csv-file).&lt;br /&gt;&lt;br /&gt;4) On the Conversion tab you can actually write x++ code, that will be compiled and executed for each line in the file that is read in. In the method you get a table buffer of the table you choose in step 2, and a container containing all the fields read from the file.&lt;br /&gt;This means you can make custom transformation, and even create records in related tables if you want, while at the same time importing data in to the chosen table.&lt;br /&gt;You can let the compiler parse the code to verify syntax before saving the definition.&lt;br /&gt;&lt;br /&gt;5) Using the last tabpage on the form, you can have the first record read from the file and shown to you where the values read are mapped to the fields chosen in step 6.&lt;br /&gt;&lt;br /&gt;6) Using the button Field setup you can map the fields/values read from the file, to the fields of the table chosen in step 2.&lt;br /&gt;Even on the field level you can write conversion code similar to the code mentioned in step 4.&lt;br /&gt;&lt;br /&gt;All this works very nicely for importing data.&lt;br /&gt;&lt;br /&gt;Now I've used this for making imports in the supply chain modules, Invent locations, wms locations, planning data and Item coverage data, preparing the go-live at a customer site.&lt;br /&gt;This was done in a test environment.&lt;br /&gt;&lt;br /&gt;When the customer had verified the test data, we wanted to move the import templates created using the above steps, to the live production environment, to make the "real" import.&lt;br /&gt;&lt;br /&gt;How to be done ?&lt;br /&gt;&lt;br /&gt;Moving the import-definition between environments (test and production) is done by exporting data in the tables:&lt;br /&gt;&lt;br /&gt;SysExpImpGroup (which contains the definition group)&lt;br /&gt;SysExpImpTable (which contains the tables of the def. group)&lt;br /&gt;SysExpImpField (which contains the fields of the tables of the def. group)&lt;br /&gt;And maybe&lt;br /&gt;SysExpImpQuery (which contains any Export criteria - if used).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;One little problem&lt;/strong&gt; with the abovementiond procedure of moving the SysExpImp table.&lt;br /&gt;&lt;br /&gt;When you import the exported data, the code you write in the conversion tab pages will be messed up. The import process apparently strips all newlines in the code.&lt;br /&gt;&lt;br /&gt;You'll have to go through the conversion code and insert linebreaks after each semicolon, after import. &lt;strong&gt;Otherwise the import will not function correctly !!!&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-4114937615410607217?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/4114937615410607217/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/12/dynamics-ax-import-export-tool-digging.html#comment-form' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/4114937615410607217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/4114937615410607217'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/12/dynamics-ax-import-export-tool-digging.html' title='DYNAMICS AX Import Export Tool - digging a bit deeper.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-6047276659544826757</id><published>2009-12-02T22:12:00.005+01:00</published><updated>2010-04-27T09:00:13.451+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Application Layers and table maps'/><title type='text'>Weird experience with tablemaps and layers</title><content type='html'>Today we experienced something weird in AX2009.&lt;br /&gt;&lt;br /&gt;We have installed an application module in the AX in the VAR and VAP layers, and are making CUS-layer modifications that are customer specific.&lt;br /&gt;In the module a tablemap is used to be able to implement code once but for use on several tables.&lt;br /&gt;&lt;br /&gt;However we experienced a run-time error when we ran a form, that called the code on the table map. The kernel complained about a field having id 0.&lt;br /&gt;&lt;br /&gt;We searched high and low but couldn't find any reason for the run-time error that occurred. We then tried making a cus-layer edition of all the mappings on tablemap and voila, no more run time error.&lt;br /&gt;&lt;br /&gt;Weird. :0S&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-6047276659544826757?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/6047276659544826757/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/12/weird-experience.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6047276659544826757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6047276659544826757'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/12/weird-experience.html' title='Weird experience with tablemaps and layers'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-3277576944986809679</id><published>2009-11-30T10:07:00.002+01:00</published><updated>2009-11-30T10:09:37.219+01:00</updated><title type='text'>New job.</title><content type='html'>As of january 1st 2010, I am no longer employed by thy:data.&lt;br /&gt;I will be employed as a Senior System Consultant by Columbus IT Partner Denmark A/S situated at the office in Aalborg.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-3277576944986809679?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/3277576944986809679/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/11/new-job.html#comment-form' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3277576944986809679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3277576944986809679'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/11/new-job.html' title='New job.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-6089907223885107291</id><published>2009-10-23T11:16:00.003+02:00</published><updated>2009-10-23T11:21:01.179+02:00</updated><title type='text'>Check on which tier code is running.</title><content type='html'>A colleague of mine needed to determine (runtime) what ax-tier his code was running on.&lt;br /&gt;&lt;br /&gt;We digged around, and he came up with the solution:&lt;br /&gt;&lt;br /&gt;if (isRunningOnServer())&lt;br /&gt;{&lt;br /&gt;    // Server&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;    // Client&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;As a footnote he needed this check to make some code to refresh the AOS-code cache, when implementing quick-fixes to an environment running with multiple AOS-instances.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-6089907223885107291?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/6089907223885107291/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/10/check-on-which-tier-code-is-running.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6089907223885107291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6089907223885107291'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/10/check-on-which-tier-code-is-running.html' title='Check on which tier code is running.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-8138778230823708362</id><published>2009-10-19T14:30:00.001+02:00</published><updated>2009-10-19T14:34:18.424+02:00</updated><title type='text'>Merging code/elements in Layers</title><content type='html'>I've been assigned a task where the merge between VAR and CUS-layer of the application is necessary.&lt;br /&gt;&lt;br /&gt;I like to make my self a TO-do-list of elements to be processed, so I can check an item when it is done.&lt;br /&gt;&lt;br /&gt;I wrote a small job to identify elements in the application that were represented in both VAR and CUS-layers thus representing a &lt;strong&gt;potential&lt;/strong&gt; layer-conflict.&lt;br /&gt;&lt;br /&gt;The job produces an info-log with the potential conflicts that can be copied in to Excel to be used as a TO-DO-list.&lt;br /&gt;&lt;br /&gt;static void JSOVarVapAndCusConflictsJob9(Args _args)&lt;br /&gt;{&lt;br /&gt;    UtilIdElements  utilIdElements;&lt;br /&gt;    UtilIdElements  VarVapUtilIdElements;&lt;br /&gt;    Map             elemMap;&lt;br /&gt;    MapIterator     elemMI;&lt;br /&gt;    UtilElementType recType;&lt;br /&gt;    RecId           utilId;&lt;br /&gt;    int             pos;&lt;br /&gt;    str 60          elementName;&lt;br /&gt;&lt;br /&gt;    elemMap = new Map(Types::String,Types::String);&lt;br /&gt;    while select UtilIdElements&lt;br /&gt;        where (utilIdElements.utilLevel   == UtilEntryLevel::cus)&lt;br /&gt;           &amp;&amp; UtilIdElements.parentId     == 0&lt;br /&gt;    {&lt;br /&gt;        elemMap.insert(enum2str(UtilIdElements.recordType)+";"+num2str(UtilIdElements.recid,0,0,0,0),UtilIdElements.name);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    elemMI = new MapIterator(elemMap);&lt;br /&gt;    while (elemMi.more())&lt;br /&gt;    {&lt;br /&gt;        pos         = strscan(elemMI.key(),";",1,strlen(elemMi.key())-1);&lt;br /&gt;        recType     = str2enum(recType,substr(elemMI.key(),1,pos-1));&lt;br /&gt;//        utilId      = str2num(substr(elemMI.key(),pos+1,strlen(elemMI.key())-pos));&lt;br /&gt;        elementName = elemMi.value();&lt;br /&gt;&lt;br /&gt;        select firstonly VarVapUtilIdElements&lt;br /&gt;            where VarVapUtilIdElements.recordType   == recType&lt;br /&gt;               &amp;&amp; VarVapUtilIdElements.name         == elementName&lt;br /&gt;               &amp;&amp; (VarVapUtilIdElements.utilLevel   == UtilEntryLevel::var ||&lt;br /&gt;                   VarVapUtilIdElements.utilLevel   == UtilEntryLevel::vap);&lt;br /&gt;        if (VarVapUtilIdElements.RecId)&lt;br /&gt;        {&lt;br /&gt;            info("Potentiel conflict between CUS- og VAR/VAP-lag: "+enum2str(recType)+" "+elemMI.value());&lt;br /&gt;        }&lt;br /&gt;        elemMi.next();&lt;br /&gt;    }&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-8138778230823708362?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/8138778230823708362/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/10/merging-codeelements-in-layers.html#comment-form' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8138778230823708362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8138778230823708362'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/10/merging-codeelements-in-layers.html' title='Merging code/elements in Layers'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-2481638402030640903</id><published>2009-09-04T12:33:00.006+02:00</published><updated>2009-09-04T13:33:59.213+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX 2009 labels'/><title type='text'>Extracting labels from one labelfile to another</title><content type='html'>Recently I've had an assignment where we needed to "split up" a label file.&lt;br /&gt;&lt;br /&gt;The assignment was to:&lt;br /&gt;* read thorugh a label file.&lt;br /&gt;* If any labels were encountered with a number bigger then N these should be written to a new label file AND any references to these labels should be replaced in the code.&lt;br /&gt;&lt;br /&gt;So I exported all adjustments/code made to an .xpo file, and&lt;br /&gt;I took a copy of the label file.&lt;br /&gt;&lt;br /&gt;Then I wrote a class that did the "splitting up" of the label file and the search/replace of labels in the code (.xpo file).&lt;br /&gt;&lt;br /&gt;This made for use of an other entry in this blog, namely extracting text from a label, and for some interesting use of the TextBuffer object for search/replace.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.fasor.dk/blogspotattachments/Class_CreateNewLabelFile.xpo"&gt;Here you can download the code.&lt;/a&gt;&lt;br /&gt;Use at own risk !!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-2481638402030640903?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/2481638402030640903/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/09/extracting-labels-from-one-labelfile-to.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/2481638402030640903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/2481638402030640903'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/09/extracting-labels-from-one-labelfile-to.html' title='Extracting labels from one labelfile to another'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-463627882055686414</id><published>2009-07-20T13:01:00.000+02:00</published><updated>2009-07-20T13:12:44.073+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Making a form modal'/><title type='text'>Making a form modal i X++</title><content type='html'>Put the following code in the &lt;span style="font-family:courier new;"&gt;GLOBAL&lt;/span&gt; class in a new method called &lt;span style="font-family:courier new;"&gt;setFormModal&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;static void setFormModal(int _thisHWND, boolean _bModal)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DLL _winApiDLL;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DLLFunction _EnabledWindow;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DLLFunction _getTop;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DLLFunction _getNext;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DLLFunction _getParent;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void local_enableWHND(int _lHWND)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int lnextWnd;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lnextWnd = _getTop.call(_getParent.call(_lHWND));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while (lnextWnd)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (lnextWnd != _lHWND)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;enabledWindow.call(lnextWnd, (!_bModal));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lnextWnd = _getNext.call(lnextWnd, 2);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;; &lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_winApiDLL = new DLL('user32');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_getNext = new DLLFunction(_winApiDLL,"GetWindow");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_EnabledWindow = new DLLFunction(_winApiDLL,"EnableWindow");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_getTop = new DLLFunction(_winApiDLL,"GetTopWindow"); &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_getParent = new DLLFunction(_winApiDLL,"GetParent");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_getParent.returns(ExtTypes:: DWORD);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_getParent.arg(ExtTypes:: DWORD);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_EnabledWindow.returns(ExtTypes:: DWORD);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_EnabledWindow.arg(ExtTypes:: DWORD, ExtTypes:: DWORD); &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_getTop.returns(ExtTypes:: DWORD);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_getTop.arg(ExtTypes:: DWORD);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_getNext.returns(ExtTypes:: DWORD);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_getNext.arg(ExtTypes:: DWORD, ExtTypes:: DWORD);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;local_enableWHND(_thisHWND);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the form the following methods are overridden with calls to the &lt;span style="font-family:courier new;"&gt;Global::SetformModal&lt;/span&gt; method:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void run()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Global::setFormModal(this.hWnd(), true);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void close()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Global::setFormModal(this.hWnd(), false);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;} &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-463627882055686414?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/463627882055686414/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/making-form-modal-i-x.html#comment-form' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/463627882055686414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/463627882055686414'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/making-form-modal-i-x.html' title='Making a form modal i X++'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-1963788022827633767</id><published>2009-07-20T12:58:00.000+02:00</published><updated>2009-07-20T13:01:14.531+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Usefull debugging tip'/><title type='text'>Usefull debugging tip.</title><content type='html'>Useful debugging tip for tracking down the point where an exception is thrown.&lt;br /&gt;&lt;br /&gt;Some times it can be difficult to determine where an exception is thrown.&lt;br /&gt;Is it e.g. the validatefield method on a data source field on a form that throws the exception,&lt;br /&gt;or is it the validatewrite method on the data source or even the validatewrite method on the table it self.&lt;br /&gt;&lt;br /&gt;A useful trick to establish the point in the code where the exception is thrown, is to set a break point in line 11 in&lt;br /&gt;the method add in the class Info.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_9MpqRay9JI4/SmRORaRHLdI/AAAAAAAAAAw/HV9nPIi6mns/s1600-h/dynaxbreakpoint.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5360495517493571026" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 320px; CURSOR: hand; HEIGHT: 258px" alt="" src="http://3.bp.blogspot.com/_9MpqRay9JI4/SmRORaRHLdI/AAAAAAAAAAw/HV9nPIi6mns/s320/dynaxbreakpoint.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You can find the Info class at the bottom at the class subtree in the AOT.&lt;br /&gt;&lt;br /&gt;This will stop execution and activate the debugger each time something is added to the infolog which is normally done when an exception is thrown.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-1963788022827633767?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/1963788022827633767/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/usefull-debugging-tip.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1963788022827633767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1963788022827633767'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/usefull-debugging-tip.html' title='Usefull debugging tip.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_9MpqRay9JI4/SmRORaRHLdI/AAAAAAAAAAw/HV9nPIi6mns/s72-c/dynaxbreakpoint.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-8818811013340949995</id><published>2009-07-20T12:55:00.000+02:00</published><updated>2009-07-20T12:58:34.370+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Generating and running code RUNTIME.'/><title type='text'>Generating and running code RUNTIME.</title><content type='html'>How to create, compile and run code at RUNTIME.&lt;br /&gt;&lt;br /&gt;In some situations the need for making "generic" code arises.&lt;br /&gt;&lt;br /&gt;This is a little example that generates, compiles and runs code to delete the contents of table PBACustGroup.&lt;br /&gt;&lt;br /&gt;The code is made as a job, but transforming this code into a method on a class, and calling this method with parameters that allows it to identify the table, suddenly makes us able to delete several selected tables with very little code.&lt;br /&gt;It also allows for USER CONTROLLED actions, for example letting the user build a liste of tables he would like to delete, and then calling the code for each of these tables.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;static void TestGenericCode(Args _args)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XppCompiler XppCompiler;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;str code;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;str tableName = "PBACustGroup"; // Here we define the name of the table&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// A compile object is created&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XppCompiler = new XppCompiler();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Here the code to delete the tabel is created&lt;br /&gt;code = "void x() {"+tableName+" "+tablename+"; ttsbegin; delete_from "+tableName+"; ttscommit; }";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// And compiled&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (XppCompiler.compile(code))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// If the compiler was satisfied with the code we run it&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XppCompiler.execute();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// And inform the user that we deleted data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info("Deleted all record in table "+tableName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Otherwise the compiler lets us know the code was errorneous&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(XppCompiler.errorText());&lt;br /&gt;info("fejl !!");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;} &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-8818811013340949995?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/8818811013340949995/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/generating-and-running-code-runtime.html#comment-form' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8818811013340949995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/8818811013340949995'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/generating-and-running-code-runtime.html' title='Generating and running code RUNTIME.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-3291780014200044551</id><published>2009-07-20T12:54:00.001+02:00</published><updated>2009-07-20T12:55:29.179+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='extracting text from a label'/><title type='text'>Extracting text from a label.</title><content type='html'>How to extract label text.&lt;br /&gt;&lt;br /&gt;This code shows how to get the text of a specific label for a specific module, for a specific language.&lt;br /&gt;&lt;br /&gt;This might come in handy when constructing a text to be printed on a report, that will more than one label text.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// This code allows you to extract the label text of a specific label, for a specific module,&lt;br /&gt;// for a specific language&lt;br /&gt;//&lt;br /&gt;// Handy when constructing text fields containing many values and labels for printing&lt;br /&gt;//&lt;br /&gt;// str = labeltxt("gls",element.design().languageId(),200);&lt;br /&gt;&lt;br /&gt;str labeltxt(str _labelModule,LanguageId _languageId, LabelIdNum _labelNo)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Label l;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;l = new label(_languageId);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return l.extractString(l.name(_labelModule,_labelNo));&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-3291780014200044551?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/3291780014200044551/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/extracting-text-from-label.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3291780014200044551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3291780014200044551'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/extracting-text-from-label.html' title='Extracting text from a label.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-6826398727260578446</id><published>2009-07-20T12:49:00.000+02:00</published><updated>2009-07-20T12:53:27.431+02:00</updated><title type='text'>Getting field values of more than one data source when calling a menu item</title><content type='html'>When a form has called another form (the user has opened a form by clicking a button in another form), you sometimes need to get information from the calling form.&lt;br /&gt;&lt;br /&gt;The traditional way is to use element.args().record(); but this construction only allows for transferring ONE datasource at a time.&lt;br /&gt;&lt;br /&gt;Sometimes it would be nice to be able to transfer more than one datasource.&lt;br /&gt;This is an example of how that can be done.&lt;br /&gt;&lt;br /&gt;The code must be implemented in the&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;init&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;-method of the CALLED form:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SysSetupFormRun s;&lt;br /&gt;APMObjectTable apmObjectTable;&lt;br /&gt;int dataSourceNo;&lt;br /&gt;&lt;br /&gt;// Determine value of fields APMProductId and APMModelId of APMObjectTable record&lt;br /&gt;// which might have been active at the time of pressing CTRL+F4 in the previous form&lt;br /&gt;// (CTRL+F4 on model field in form APMCustOverview)&lt;br /&gt;s = element.args().caller();&lt;br /&gt;if (s)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (datasourceNo = 1; dataSourceNo &lt;= s.dataSourceCount(); dataSourceNo++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (s.dataSource(dataSourceNo).cursor().TableId == tableNum(APMObjectTable))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;apmObjectTable = s.dataSource(dataSourceNo).cursor();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;} &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-6826398727260578446?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/6826398727260578446/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/getting-field-values-of-more-than-one.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6826398727260578446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6826398727260578446'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/getting-field-values-of-more-than-one.html' title='Getting field values of more than one data source when calling a menu item'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-3046643848395034635</id><published>2009-07-20T12:48:00.001+02:00</published><updated>2010-04-27T09:09:32.433+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX x++ Code snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='Uses of Textbuffer'/><title type='text'>Tokenizing a string</title><content type='html'>How to tokenize a string.&lt;br /&gt;&lt;br /&gt;In Java you can use an object of the stringTokenizer class to break up a string in to tokens.&lt;br /&gt;Dynamics AX has a handy class called TextBuffer with which you can achieve a similar effect.&lt;br /&gt;This example shows how (the code is written as a job):&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;static void Job7(Args _args)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TextBuffer t;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t = new TextBuffer();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t.ignoreCase(true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t.regularExpressions(false);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Set the text to break in to tokens&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t.setText("When I find myself in times of trouble, mother Mary comes to me, speaking words of wisdom, let it be. And in my hour of darkness she is standing right in front of me, speaking words of wisdom, let it be.");&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// The delimiter to search for when finding tokens is space&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while (t.nextToken(false," "))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(t.token());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;} &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-3046643848395034635?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/3046643848395034635/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/tokenizing-string.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3046643848395034635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3046643848395034635'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/tokenizing-string.html' title='Tokenizing a string'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-7648773615676504678</id><published>2009-07-20T12:44:00.001+02:00</published><updated>2010-04-27T09:07:42.397+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='getting field value on a common'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX x++ Code snippet'/><title type='text'>Dynamics AX - Getting the value of a given field regardless of tablebuffer</title><content type='html'>How to get the value of a given field regardless of which tablebuffer is active.&lt;br /&gt;&lt;br /&gt;Foreign keys in Dynamics AX are scattered throughout the tables of the system, connecting the modules to each other.&lt;br /&gt;&lt;br /&gt;For example ItemId fields store the item identification in a lot of tables, for storing information related to the item in question.&lt;br /&gt;&lt;br /&gt;This example shows how you can write a generic method that gets the value of the field ItemId regardless of which table is active at runtime.&lt;br /&gt;&lt;br /&gt;The example was originally implemented as a method on a form.&lt;br /&gt;&lt;br /&gt;The method was able to return the value of the field ItemId regardless of which tablebuffer was active, when the form was called (&lt;span style="font-family:courier new;"&gt;element.args().record()&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public ItemId getFormItemId()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;common table; // Generic table buffer&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DictTable dt; // Dictionary object for handling table information&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Get the table in question&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;table = element.args().record();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Make DictTable object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dt = new DictTable(table.TableId);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return table.(dt.fieldName2Id('ItemId'));&lt;br /&gt;} &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-7648773615676504678?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/7648773615676504678/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/dynamics-ax-getting-value-of-given.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/7648773615676504678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/7648773615676504678'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/dynamics-ax-getting-value-of-given.html' title='Dynamics AX - Getting the value of a given field regardless of tablebuffer'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-7934214397742601387</id><published>2009-07-20T12:41:00.001+02:00</published><updated>2009-07-20T12:44:31.747+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Form data source debugging'/><title type='text'>Debugging and inspecting values of the fields in a form datasource</title><content type='html'>For debugging purposes code that can inspect the values of the fields in a datasource in a form or a report can be quite handy.&lt;br /&gt;&lt;br /&gt;This is how it can be done in e.g. the&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;strong&gt;active&lt;span &gt; &lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span &gt;&lt;br /&gt;method of the datasource :&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;QueryBuildDataSource qbds;&lt;br /&gt;QueryBuildRange qbr;&lt;br /&gt;int dsc,dsi,rc,ri;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// Get the number of datasource on the query&lt;br /&gt;dsc = queryRun.query().dataSourceCount();&lt;br /&gt;// Loop over datasources&lt;br /&gt;for (dsi=1;dsi&lt;=dsc;dsi++)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qbds = queryRun.query().dataSourceNo(dsi);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info("Table: "+tableid2name(qbds.table()));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rc = qbds.rangeCount();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Loop over fields&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (ri=1;ri&lt;=rc;ri++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qbr = qbds.range(ri);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info(fieldid2name(qbds.table(),qbr.field())+" value: "+qbr.value());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-7934214397742601387?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/7934214397742601387/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/debugging-and-inspecting-values-of.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/7934214397742601387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/7934214397742601387'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/debugging-and-inspecting-values-of.html' title='Debugging and inspecting values of the fields in a form datasource'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-3769123553676538245</id><published>2009-07-20T12:16:00.000+02:00</published><updated>2009-07-20T12:38:57.563+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Axapta (Dynamics AX) 3.0 overriding SysLastValues calling a report'/><title type='text'>Overriding SysLastValue Dynamics AX 3.0</title><content type='html'>This is an old blog entry from my old blog.&lt;br /&gt;&lt;br /&gt;Today I solved a problem, that has long puzzled me.&lt;br /&gt;&lt;br /&gt;From Axapta 3.0 (or was it 2.5 can't quite remember) it became best pratice to wrap reports in runbase-report classes.&lt;br /&gt;&lt;br /&gt;For a long time it has irritated me, that if you called your report class from something else than the menu, you were having trouble overriding syslastvalue, without clearing all saved last value completely.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;You have a report called from a runbasereport class.For the class you naturally have a output menuitem, that is attached to the menu. So when you call this report, and make selections in the ranges of the query of the report, they are shown in the report dialog, and saved, so that the next time you call your report, the last used selections is being restored for you in the dialog for reuse.&lt;br /&gt;&lt;br /&gt;However sometime you experience, that the report can be called from BOTH the menu and somewhere else like a form.&lt;br /&gt;When you call the report from a form, it is customary to synchronize certain ranges in the query of the report with values found on the particular record the cursor has been placed in the form.&lt;br /&gt;&lt;br /&gt;Then what about syslastvalue in this case. Normally they would be saved as the last used values destroying the values saved when the report was called from the menu.&lt;br /&gt;&lt;br /&gt;So how do we make the report function normally saving queryvalues etc as syslastvalues when calling it from the menu, and avoid doing so when calling the report from e.g. a form.&lt;br /&gt;&lt;br /&gt;The solution is actually fairly simple, and does not require a whole lot of work:&lt;br /&gt;&lt;br /&gt;If you make an extra output menuitem for your report class, which includes a parameter indicating that this has NOT been called from the menu, by putting a value in e.g. the PARM property and test for this it is quite easy.&lt;br /&gt;&lt;br /&gt;First you need a parameter method to set and return a flag indicating if or if not the class has been called from the menu:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;boolean calledromMenu(boolean _calledFromMenu = calledFromMenu)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;calledFromMenu = _calledFromMenu;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return calledFromMenu;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;Of course you must have a class member of the boolean type called calledFromMenu.&lt;br /&gt;&lt;br /&gt;In your&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;main&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;method in the runbasereport class you would have:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;MyRunBaseReportObject myRunBaseReportObject;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;myRunBaseReportObjec = new myRunBaseReportObject();&lt;br /&gt;if (_args.parm() != '')&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myRunBaseReportObject.calledFromMenu(false);&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myRunBaseReportObject.calledFromMenu(true);&lt;br /&gt;}&lt;br /&gt;if (myRunBaseReportObject.prompt())&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myRunBaseReportObject.run();&lt;br /&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;getLast&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;method on your wrapper class (extending RunBaseReport) must be overwritten:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void getLast()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getLastCalled = true;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inGetSaveLast = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (this.calledFromMenu()) // Do not save last value if not called from menu&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xSysLastValue::getLast(this);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.initParmDefault();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inGetSaveLast = false;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In this case the &lt;span style="font-family:courier new;"&gt;calledFromMenu()&lt;/span&gt; method returns either true or false according to the parameter passed from the menuitem, which indicates that the report is called from the menu.&lt;br /&gt;&lt;br /&gt;If it has been called from the menu, we want everything to function as normal, so we get the syslastvalues. Otherwise, we call initParmDefault to setup report with query and queryRun objects etc.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;It is important that super() is NOT called.&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;The other method to overwrite is:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void saveLast()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (this.calledFromMenu()) // Only save last value if called from menu&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inGetSaveLast = true;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xSysLastValue::saveLast(this);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inGetSaveLast = false;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;Actually the overwriting this method with the above code, just makes saving syslastvalues dependant on the calledFromMenu, thus NOT saving anything if the report was not called from the menu.&lt;br /&gt;&lt;br /&gt;That's it. Now your report will function as normally saving syslastvalues when called from the menu, but not doing so when you call it using the other menuitem which indicates a call from somewhere else than the menu.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-3769123553676538245?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/3769123553676538245/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/overriding-syslastvalue-dynamics-ax-30.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3769123553676538245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/3769123553676538245'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/overriding-syslastvalue-dynamics-ax-30.html' title='Overriding SysLastValue Dynamics AX 3.0'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-2641361118802660886</id><published>2009-07-20T12:12:00.000+02:00</published><updated>2009-07-20T12:15:32.090+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='_ds.executeQuery _ds.Research'/><title type='text'>Subtle but important difference between _ds.executeQuery() and ds.Research()</title><content type='html'>This is actually an old entry.&lt;br /&gt;&lt;br /&gt;Been tumbling with a problem for the last few days.&lt;br /&gt;&lt;br /&gt;A form in our Dynamics AX module for Preventive Maintenance Control was not behaving.&lt;br /&gt;&lt;br /&gt;The form has "explicit" filter fields that the user can see without having to activate the form filter (CTRL+F3), for setting up filters most commonly used in an easy way.&lt;br /&gt;&lt;br /&gt;And this is working ok. However at this customer site, the form has been adjusted so that the user can have the form refreshed automatically periodically, and when the users at the customer site were making use of the "explicit" filter combined with the AX's normal filtering (CTRL+F3), the form simply threw away the normal form filtering.&lt;br /&gt;&lt;br /&gt;I discovered a subtle but very important difference between writing&lt;br /&gt;&lt;br /&gt;&lt;formtable&gt;&lt;span style="font-family:courier new;"&gt;_ds.executeQuery(); &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(which was the way our code was doing it)&lt;br /&gt;&lt;br /&gt;and&lt;br /&gt;&lt;br /&gt;&lt;formtable&gt;&lt;span style="font-family:courier new;"&gt;_ds.Research(); &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The difference is that &lt;span style="font-family:courier new;"&gt;_ds.Research()&lt;/span&gt; will retain the filter ranges in the forms query as they are right now.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;_ds.executeQuery()&lt;/span&gt; will NOT.&lt;br /&gt;&lt;br /&gt;It is mentioned in the Developer's Guide, but I guess the responsible programmer hadn't noticed that one.&lt;br /&gt;&lt;br /&gt;Developer's guide states:&lt;br /&gt;&lt;br /&gt;"research vs. executeQuery&lt;br /&gt;&lt;br /&gt;If you want to refresh the form with records that were inserted in a method or job that was called, then you should use research.&lt;br /&gt;&lt;br /&gt;If you want to change the query to show other records, perhaps based on a modified filter, then you should use executeQuery."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-2641361118802660886?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/2641361118802660886/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/subtle-but-important-difference-between.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/2641361118802660886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/2641361118802660886'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/subtle-but-important-difference-between.html' title='Subtle but important difference between _ds.executeQuery() and ds.Research()'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-1924196147161871845</id><published>2009-07-20T12:09:00.000+02:00</published><updated>2009-07-20T12:11:04.666+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AOS instance'/><title type='text'>Dynamics AX 4.0 - showing AOS instance</title><content type='html'>I Dynamics AX version 4.0 the information about on what AOS you are currently running your code, has been removed.&lt;br /&gt;In version 3.0 (3-tier) the client showed the AOS instance info. With a development, a test and a production environment at a site, the missing info can be of great annoyance when you are working with clients started in multiple environments. Today I found that other developers and consultants have the same problem, and one developer even solved the problem, with the very usefull hack:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://coolhake.wordpress.com/2008/07/22/configuration-in-title-bar/"&gt;http://coolhake.wordpress.com/2008/07/22/configuration-in-title-bar/&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Oh yay, saved my day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-1924196147161871845?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/1924196147161871845/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/dynamics-ax-40-showing-aos-instance.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1924196147161871845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1924196147161871845'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/dynamics-ax-40-showing-aos-instance.html' title='Dynamics AX 4.0 - showing AOS instance'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-6215879173762632358</id><published>2009-07-20T12:03:00.000+02:00</published><updated>2009-07-20T12:07:38.495+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Runbase class field mandatory'/><title type='text'>Indicating mandatory field in a dialog (RunBase) class.</title><content type='html'>&lt;div&gt;A classical problem is indicating that a field is mandatory in a dialog, when the field is not bound to a datasource/field in a datasource.&lt;br /&gt;&lt;br /&gt;Normally fellow developers will tell you that, that is not possible.&lt;br /&gt;&lt;br /&gt;I found a way to do this.&lt;br /&gt;&lt;br /&gt;In your Runbase-based class you can implement the putToDialog-method e.g like this:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier new"&gt;protected void putToDialog()&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;{&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;    super();&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;    fieldMask.fieldControl().mandatory(true);&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;}&lt;/font&gt; &lt;/div&gt;&lt;br /&gt;&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;div&gt;where fieldMask is a DialogField object in your dialog.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;This will make the field act like it was a mandatory field from a datasource in a form, showing a red-wavy line under the field, and requiring the field to have a value.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;font size="4"&gt;&lt;strong&gt;Attention:&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Your class has to run on the client.If you set your class to run on the server, you get a run-time error, when the fieldMask.FieldControl()-call is made.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-6215879173762632358?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/6215879173762632358/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/indicating-mandatory-field-in-dialog.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6215879173762632358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6215879173762632358'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/indicating-mandatory-field-in-dialog.html' title='Indicating mandatory field in a dialog (RunBase) class.'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-1103563023267252491</id><published>2009-07-20T11:59:00.001+02:00</published><updated>2009-07-20T12:08:48.520+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Getting active company'/><title type='text'>Getting the active company accounts programmatically</title><content type='html'>&lt;div&gt;While working on a client case where custom made data export was needed,&lt;br /&gt;I coded some classes to make the export.&lt;br /&gt;&lt;br /&gt;While working with the code, I decided it would be a good idea to make the currently chosen company id a part of the file name when exporting, as the customer have several company accounts, and we need to export from all of them.&lt;br /&gt;&lt;br /&gt;I spent a little time to find out how to get the current selected company account id and I came up with:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier new"&gt;static void Job77(Args _args)&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;{&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;    ;&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;    info(appl.company().ext());&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;}&lt;br /&gt;&lt;/font&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;So I made a function for constructing the file name and put the&lt;/div&gt;&lt;br /&gt;&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;font face="courier new"&gt;appl.company().ext()&lt;/font&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;font face="Courier New"&gt;&lt;/font&gt; &lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;font face=""&gt;bit in that.&lt;/font&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-1103563023267252491?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/1103563023267252491/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/while-working-on-client-case-where.html#comment-form' title='1 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1103563023267252491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/1103563023267252491'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/while-working-on-client-case-where.html' title='Getting the active company accounts programmatically'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-6102231098741589853</id><published>2009-07-20T11:34:00.000+02:00</published><updated>2009-07-20T11:58:16.634+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX Code Expression'/><title type='text'>How to programmatically (X++) calculate a mathematical expression i Dynamics AX</title><content type='html'>This code snippet shows how to calculate a mathematical expression and get the result in X++ code (the shown code is made as a job):&lt;br /&gt;&lt;br /&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;static void calc(Args _args)&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="PADDING-LEFT: 20px; font-family:courier new;" &gt;XppCompiler x;&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="PADDING-LEFT: 20px;; font-family:courier new;" &gt;// In str s we write the expression that we want to evaluate&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="PADDING-LEFT: 20px; font-family:courier new;" &gt;Str s = "1+2*(8+4)*cos(25)";&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="PADDING-LEFT: 20px; font-family:courier new;" &gt;Str result;&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="PADDING-LEFT: 20px;font-family:courier new;" &gt;;&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;PADDING-LEFT: 20px; "&gt;x = new XppCompiler();&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;PADDING-LEFT: 20px;"&gt;if (x.compileExpr(s))&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;PADDING-LEFT: 20px; "&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;PADDING-LEFT: 40px; "&gt;result = x.execute();&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;PADDING-LEFT: 20px;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;PADDING-LEFT: 20px; "&gt;else&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;PADDING-LEFT: 20px; "&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;PADDING-LEFT: 40px; "&gt;result = "Error in formula";&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;PADDING-LEFT: 20px;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;PADDING-LEFT: 20px;"&gt;info(result);&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div align="left"&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-6102231098741589853?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/6102231098741589853/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/how-to-programmatically-x-calculate.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6102231098741589853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/6102231098741589853'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/how-to-programmatically-x-calculate.html' title='How to programmatically (X++) calculate a mathematical expression i Dynamics AX'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2639161662922921717.post-5079039897194743433</id><published>2009-07-20T11:12:00.001+02:00</published><updated>2010-04-27T09:08:50.064+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX begin'/><title type='text'>Let there be light ...</title><content type='html'>Let there be sound ....&lt;br /&gt;Let there be ... :)&lt;br /&gt;&lt;br /&gt;Just created a blog to put all my dax thoughts in.&lt;br /&gt;&lt;br /&gt;Chose this blog-system because my own ISP's&lt;br /&gt;blog-software suxxx.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2639161662922921717-5079039897194743433?l=gotdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gotdax.blogspot.com/feeds/5079039897194743433/comments/default' title='Kommentarer til indlægget'/><link rel='replies' type='text/html' href='http://gotdax.blogspot.com/2009/07/let-there-be-light.html#comment-form' title='0 kommentarer'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/5079039897194743433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2639161662922921717/posts/default/5079039897194743433'/><link rel='alternate' type='text/html' href='http://gotdax.blogspot.com/2009/07/let-there-be-light.html' title='Let there be light ...'/><author><name>Jacob</name><uri>http://www.blogger.com/profile/12247943635241923896</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/_9MpqRay9JI4/SmQ32d7y34I/AAAAAAAAAAM/stUwatqsEoc/S220/me.jpg'/></author><thr:total>0</thr:total></entry></feed>
