woensdag 21 december 2011
maandag 24 oktober 2011
dinsdag 27 september 2011
Global::allowEditFieldsOnFormDS_W
Set allowEdit property on every field in a form DataSource.
client static public void allowEditFieldsOnFormDS_W(FormDataSource _dataSource, boolean _allowEdit)
{
DictTable dictTable = new DictTable(_dataSource.table());
DictField dictField;
FormDataObject dataObject;
int cx, idx;
for(cx = 1; cx <= dictTable.fieldCnt(); cx ++)
{
dictField = dictTable.fieldObject(dictTable.fieldCnt2Id(cx));
if(! dictField.isSystem())
{
for(idx = 1; idx <= dictField.arraySize(); idx++)
{
dataObject = _dataSource.object(fieldId2Ext(dictField.id(), idx));
if (dataObject)
{
dataObject.allowEdit(_allowEdit);
}
}
}
}
}
maandag 26 september 2011
How to extend your editor in Axapta
EditorScripts class.
See http://www.fourone.se/blog/2007/12/13/how-to-extend-your-editor-in-axapta/
donderdag 9 juni 2011
donderdag 26 mei 2011
Joins: InnerJoin / OuterJoin combined ?
SELECT STATEMENT
Consider this statement:
while
select *
from prodTable
where prodTable.ADUProdClusterId == "CL00000001"
join *
from clusterTable
where clusterTable.ClusterId == prodTable.ADUProdClusterId
outer join *
from prodTableRef
where prodTableRef.ProdId == prodTable.CollectRefProdId
It results in an error:
Cannot select a record in Works orders (ProdTable).
The join does not contain any link between the joined tables in the WHERE clause.
The cause is that we use a combination of inner join and outer join on the same source (prodTable)
Axapta doesn’t seem to be able to handle this.
The solution is to use all inner or all outer joins.
In our case, we changed the inner join to an outer join, and the query ran fine.
QUERY OBJECT
We also tried to replicate this query in a Query object.
(click pictures to enlarge)
ADUProdClusterTable properties:
We found that AX ignores the inner join when combined with an outer join (ProdTableRef enabled)
When we disabled ProdTableRef, effectively making this an inner join between just 2 tables, AX took the join into account correctly.
See the queries AX builds when executing through the Query object:
ProdTableRef ENABLED
ProdTable: SELECT * FROM ProdTable
WHERE ((ADUProdClusterId = N'CL00000001'))
ADUProdClusterTable: SELECT * FROM ADUProdClusterTable
WHERE ProdTable.ADUProdClusterId = ADUProdClusterTable.ClusterId
ProdTableRef: SELECT *
FROM ProdTable
WHERE ProdTable.CollectRefProdId = ProdTable.ProdId
ProdTableRef DISABLED
ProdTable: SELECT * FROM ProdTable
WHERE ((ADUProdClusterId = N'CL00000001'))
JOIN * FROM ADUProdClusterTable
WHERE ProdTable.ADUProdClusterId = ADUProdClusterTable.ClusterId
ADUProdClusterTable: SELECT * FROM ADUProdClusterTable
WHERE ProdTable.ADUProdClusterId = ADUProdClusterTable.ClusterId
ProdTableRef: (ignored)
Changing the ADUProdClusterTable JoinMode property to OuterJoin doesn’t seem to make a difference:
ProdTableRef ENABLED
ProdTable: SELECT * FROM ProdTable
WHERE ((ADUProdClusterId = N'CL00000001'))
ADUProdClusterTable: SELECT * FROM ADUProdClusterTable
WHERE ProdTable.ADUProdClusterId = ADUProdClusterTable.ClusterId
ProdTableRef: SELECT *
FROM ProdTable
WHERE ProdTable.CollectRefProdId = ProdTable.ProdId
ProdTableRef DISABLED
ProdTable: SELECT * FROM ProdTable
WHERE ((ADUProdClusterId = N'CL00000001'))
OUTER JOIN * FROM ADUProdClusterTable
WHERE ProdTable.ADUProdClusterId = ADUProdClusterTable.ClusterId
ADUProdClusterTable: SELECT * FROM ADUProdClusterTable
WHERE ProdTable.ADUProdClusterId = ADUProdClusterTable.ClusterId
ProdTableRef: (ignored)
CONCLUSION:
- The select statement in X++ will work as long as you don’t mix inner and outer joins.
- The select statement cannot be built with a Query object, since the resulting select statements are wrong,
regardless of whether or not you mix inner and outer joins.
Form Splitters
woensdag 25 mei 2011
vrijdag 20 mei 2011
Convert Set to Container
Put this method in the Global class.
public static container set2Con(Set _set)
{;
return condel(_set.pack(),1,3);
}
adding a DynaLink through code
example:
public void init() //on form datasource reqPO
{
QueryBuildDatasource QBDSReqPO;
;
super();
QBDSreqPO = this.query().dataSourceTable(tablenum(reqPO));
QBDSreqPO.clearDynalinks();
QBDSreqPO.addDynalink( fieldnum(reqPO,ADUcollectrefid), ADUQRMWipTable, fieldnum(ADUQRMWipTable,refid));
QBDSreqPO.addRange(fieldnum(reqpo,reqplanid)).value(reqparameters::find().CurrentReqPlanIdSchedStatic);
}
woensdag 18 mei 2011
Form DataSource Query: show Select statements
Add these 2 methods to the Global Class:
public static void showFormQueries(FormRun _fr)
{
Counter dsCount = _fr.dataSourceCount();
Counter c;
Name frName = _fr.name();
;
setPrefix(strfmt("@SYS76681", "@SYS6890", frName, strfmt("@SYS76498", dsCount, strlwr(dsCount==1?"@SYS56294":"@SYS26774"))));
for (c=1; c <= dsCount; c++)
showFormDataSourceQuery(_fr.dataSource(c));
}
public static void showFormDataSourceQuery(FormDataSource _fds)
{
Name fdsName = _fds.name();
Name tableName = tableId2Name(_fds.table());
;
setPrefix(strfmt("%1%2", fdsName, (fdsName!=tableName)?strfmt(" (%1: %2)", "@SYS8868", tableName):""));
info(_fds.query().dataSourceNo(1).toString());
}
As an example, we can use it in the form SalesTable.run method:
void run()
{
int designatedTabNo = 1;
;
if (!advanced)
{
designatedTabNo = 2;
}
else if (this.isCalledFromListPage())
{
designatedTabNo = 3;
}
SysListPageHelper::handleRunPreSuper(element, tabHeader, designatedTabNo, designatedTabNo);
super();
SysListPageHelper::handleRunPostSuper(element, tabHeader);
global::aduShowFormQueries(element);
}
Which yields:
Form SalesTable (11 data sources)
SalesTable
SELECT * FROM SalesTable USING INDEX SalesIdx WHERE ((NOT (ReturnStatus = 4) AND NOT (ReturnStatus = 1)))
SalesLine
SELECT * FROM SalesLine USING INDEX SalesLineIdx WHERE ((((SalesLine.ReturnStatus != 1) || (SalesLine.ExpectedRetQty < 0)&&(SalesLine.ReturnStatus == 1)))) AND SalesTable.SalesId=SalesLine.SalesId JOIN * FROM InventDim WHERE SalesLine.InventDimId = InventDim.inventDimId
InventDim
SELECT * FROM SalesLine USING INDEX SalesLineIdx WHERE ((((SalesLine.ReturnStatus != 1) || (SalesLine.ExpectedRetQty < 0)&&(SalesLine.ReturnStatus == 1)))) AND SalesTable.SalesId=SalesLine.SalesId JOIN * FROM InventDim WHERE SalesLine.InventDimId = InventDim.inventDimId
InterCompanyPurchSalesReference
SELECT * FROM InterCompanyPurchSalesReference WHERE SalesTable.SalesId=InterCompanyPurchSalesReference.SalesId JOIN * FROM PurchTable WHERE InterCompanyPurchSalesReference.PurchId = PurchTable.PurchId
PurchTable_Reference (Table: PurchTable)
SELECT * FROM InterCompanyPurchSalesReference WHERE SalesTable.SalesId=InterCompanyPurchSalesReference.SalesId JOIN * FROM PurchTable WHERE InterCompanyPurchSalesReference.PurchId = PurchTable.PurchId
SalesTable_Reference (Table: SalesTable)
SELECT * FROM SalesTable WHERE ((SalesId = N'PO000024'))
ShipCarrierAddress (Table: Address)
SELECT FIRSTONLY * FROM Address USING INDEX TypeIdx WHERE ((type = 11)) AND SalesTable.RecId=Address.AddrRecId AND SalesTable.TableId=Address.AddrTableId
ShipCarrierAddressInLine (Table: Address)
SELECT FIRSTONLY * FROM Address USING INDEX TypeIdx WHERE ((type = 11)) AND SalesLine.RecId=Address.AddrRecId AND SalesLine.TableId=Address.AddrTableId
DPInventSum (Table: InventSum)
DPInventDim (Table: InventDim)
ADUPriceDiscDetail1 (Table: ADUPriceDiscDetail)
SELECT * FROM ADUPriceDiscDetail WHERE SalesLine.ADUPriceDiscDetailId=ADUPriceDiscDetail.ADUPriceDiscDetailId
woensdag 4 mei 2011
dinsdag 3 mei 2011
Relations and DeleteActions
Relations
To be placed on Child table, or defined on EDT.
Indicates a Foreign Key relation: Child table uses data defined in Master table
DeleteActions
To be placed on Master table.
Indicates what should happen to Child records when the Master record is deleted.
Restricted = don’t delete Master record if Child records still exist.
Cascade = delete Child records when Master record is deleted.
maandag 2 mei 2011
woensdag 20 april 2011
dinsdag 19 april 2011
Yellow Lock in Dynamics–Form setup
Solution = use pageActivated on the tab instead.
See http://dynamics-ax.blogspot.com/2007/06/yellow-lock-in-dynamics-ax-401.html
dinsdag 5 april 2011
MICROSOFT DYNAMICS AX RECORDED WEBCASTS
See http://www.advancedsystemsintegration.com/innerCategory.aspx?menu_id=38&id=1388
Got this link from http://axhelper.blogspot.com/ (DynamicsAX Links & Blogs)
maandag 4 april 2011
Common Report Methods
Source: http://www.lulu.com/items/volume_49/340000/340213/3/print/340213.pdf (page 222)
Report Runbase Framework active
When making modifications to a report, you are either overriding existing methods,
or adding new methods which are called from the overridden methods.
The following methods are executed in listed order when a report is loaded as shown here:
init() ► dialog() ► run() ► fetch() ► send() ► print()
1. Init() and dialog() are triggered when the report is loaded.
2. Run() is triggered when the OK button is pressed in the dialog.
3. Fetch() is looping through the query and for each record found send() is triggered.
4. Finally, print() is triggered.
These methods are the most important within a report, and are the ones you will override most often.
Typical customizations include adding controls to a dialog, manipulating the output from the query before it is printed,
or adjusting the output by executing a programmable section which must be printed within the report body section.
The above listed execution order is used when the report runbase framework is in effect.
Report Runbase Framework not active
If you call your report directly from the AOT without using a menu item,
the execution order of the methods is slightly different as shown here:
init() ► run() ► prompt() ► fetch() ► send() ► print()
Notice that dialog() will not be triggered.
RunBaseReportStd controls the dialogs of the report and when the “runbase framework is not active” prompt() is used.
donderdag 31 maart 2011
Display methods on Form Datasource
See http://msdn.microsoft.com/en-us/library/aa595058.aspx
To create a display method, place the display keyword immediately in front of the method’s return type. For example:
display Amount amount()
display methods must have a return type. The return value is typically a calculated value (for example, a sum). For an example, see How to: Create Form Controls.
There should no parameters in a display method unless it is on a form data source where you must include the data source as a parameter.
For example:
display InventQty accumulated(InventBudgetInvent Budget)
You must use display on a form data source method when the return value is to be shown on a grid control. |
woensdag 9 maart 2011
dinsdag 8 maart 2011
vrijdag 25 februari 2011
real formatting–.NET style
public display String30 displayLabelQty()
{
String30 labelQty = System.String::Format("{0:.##}", tempTable.LabelQty);
;
return strfmt("@SYS76498", labelQty, InventTable::find(this.displayItemId()).inventUnitId());
}
refresh() - refreshEx() - reread() - research() - executeQuery()
refresh() will not reread the record from the database.
It basically just refreshes the screen with whatever is stored in the form cache.
refreshEx() will refresh the view of the records.
reread() will only re-read the CURRENT record from the DB so you should not use it to refresh the form data if you have added/removed records.
It's often used if you change some values in the current record in some code, and commit them to the database using .update() on the table, instead of through the form datasource.
In this case .reread() will make those changes appear on the form.
research() will rerun the existing form query against the datasource, therefore updating the list with new/removed records as well as updating existing ones.
This will honour any existing filters and sorting on the form.
executeQuery() is another useful one. It should be used if you have modified the query in your code and need to refresh the form.
It's like .research() except it takes query changes into account.
Source: http://www.mail-archive.com/axapta-knowledge-village@yahoogroups.com/msg19026.html
See also http://kashperuk.blogspot.com/2010/03/tutorial-reread-refresh-research.html for detailed explanation.
Use Pack/Unpack on Form
See http://daxguy.blogspot.com/2006/12/use-packunpack-on-form.html
Example on \Forms\AddressZipCodeLookup
Example with pack/unpack of printJobSettings on \Forms\SysTableForm