Dynamics AX 2012 AOT Object Lookup - dynamics-ax-2012

Anyone have sample lookup code for AOT objects? (or know where to find the one they use for the AX properties window)
I need to replicate the functionality that you see in several fields in the properties window. The ExtendedDataType field is a good example. Type a few letters, hit the down arrow, and a filtered list of AOT ExtendedDataType objects appears.
I've been trying to use treeNode findChildren to build my custom lookup list, but it is very slow. Whatever method AX is using happens instantly.
Thanks

Try this:
Dictionary d = new Dictionary();
int i;
int cnt = d.tableCnt();
TableId tableId;
str nameForLookup;
for (i = 1; i <= cnt; i++)
{
tableId = d.tablecnt2id(i);
nameForLookup = tableid2name(tableId);
}
Queries to the Model/Util*Element tables will not be cached, and are relatively slow due to the number of records that they contain.
There may be other factors slowing down execution as well. If you are on 2012, for lookups, you may want to build a temp table with an XDS() method, which populates itself using the above code, then you can simply select from that table (and it will be cached for the session):
create a SQL Temp table (e.g. with a name like MyTableLookup), add a name column
add a method like this:
public RefreshFrequency XDS()
{
MyTableLookup tableLookup;
ttsbegin;
// Use the above code to insert records into tableLookup
ttscommit;
return RefreshFrequency::PerSession;
}
bind your form to MyLookupTable

You may develop an estándar EDT linked to the UtilElement Table properly filtered. This will show a list of objects and will have same functionality of all table-linked text fields.

Related

Inserting listview items individually into database as new entries

Tl:dr
I have a listview with items. I want each individual item inserted into my sqlite database as a new entry. Right now, I am only able to insert all items into the database as a single entry.
I am able to populate the list from my database correctly. If I manually input the items in the SqliteStudio. The added items will show up as an individual item.
Code settings up the list
private ObservableList listchosedescription;
listchosedescription = FXCollections.observableArrayList();
this.descriptionschosen.setItems(listchosedescription);
Code for populating the list
while (result.next()) {
listchosedescription.add(result.getString("description"));
}
descriptionschosen.setItems(listchosedescription);
Faulty code for adding listview items to the database
Connection conn = dbConnection.getConnection();
PreparedStatement statement2 = conn.prepareStatement(sqlDesInsert);
statement2.setString(1, String.valueOf(descriptionschosen.getItems()));
statement2.setInt(2, Integer.parseInt(labelidnew.getText()));
statement2.execute();
From looking online. I think that I need a for-loop counting the individual items in the list.
for(int i = listchosedescription.size(); i != 0; i--){
Then I need to add each individual entry to a batch and then execute the batch.
I also understand how to get a single item from the listview. So I feel a little stuck, hence I thought I would post for guidance.
for (int i = listchosedescription.size(); i != 0; i--) {
statement2.setString(1, String.valueOf(listchosedescription.subList(i - 1, i)));
statement2.setInt(2, Integer.parseInt(labelidnew.getText()));
statement2.addBatch();
}
statement2.executeBatch();
In this for-loop, I have three statements:
I create an integer (i) which counts the size() of my observableList.
I run the loop as long as the size() is not equal to 0 (should probably be as long as it is larger than zero).
I decrease my integer (i) by 1 each time the loop is run.
Inside the loop, I add my two statements as I normally would. But the values from the observableList are accessed by using its subList. I acess the location using my integer (i).
i-1 will make sure I reach the correct fromIndex.
i will make sure I reach the correct toIndex.
Lastly, I add to the batch inside the loop and execute the batch after the loop.

How to filter and sort by dynamically created fields in grid?

I am creating a form in a job using
Form form;
FormRun formRun;
FormBuildDesign formBuildDesign;
FormBuildDataSource formBuildDataSource;
form = new Form();.
formBuildDataSource = form.addDataSource("Table");
formBuildDesign = form.addDesign("Design");
formBuildDesign.widthMode(1);
formBuildDesign.heightMode(1);
form.design().caption("Caption");
I am adding a grid to the form by
formBuildGridControl = formBuildDesign.addControl(FormControlType::Grid,"Table Grid");
and than fields (they are named F1, F2, …) to this grid by
for(ii = 1; ii < 5; ii++)
{
formBuildGridControl.addDataField(formBuildDataSource.id(),fieldName2Id(tableName2id("Table"), strFmt("F%1",ii)));
}
Form is created, grid is added and visible but when I try to sort by a field I get
Invalid sort field type.
and I do not see filter function.
What I need to do to have sorting and filtering available?
I am doing it in Dynamics AX 2012 R2.
Are your fields of type String with size Memo?
Sorting by such fields raises exactly that error due to the fact that sorting by this data type is not possible.
Try setting one of this fields to a limited length e.g. 20 and try it again with this field.

How to filter on report?

I am working on a report in AX 2009. I want to filter data of InventSiteID on the basis of ExpDate.
I have 2 datasource in the query which is attached to report. Both the data source are same InventExpired. I have to show 4 fields in dialog i.e. SiteID, Exp Date for datasource1 and same for datasource 2 and then filter it out.
In your report, you can use
SysQuery::findOrCreateRange(this.queryRun().query().dataSourceNo(1),
fieldNum(InventExpired, ExpDate)
).value(SysQuery::value(yourFilterDate));
That will filter the first datasource with the date entered.
If you need to filter by dates greater than or less than the filter date, you can use
SysQuery::findOrCreateRange(...).value('>' + SysQuery::value(yourFilterDate));
or
SysQuery::findOrCreateRange(...).value('<' + SysQuery::value(yourFilterDate));
Do you know how to add the fields to the dialog?
If you don't, you should override the dialog() method, and in the dialog() method, after the call to super(), you should use:
Dialog d = ret;
expDateField = d.addField(typeid(yourDateEDT), "Expiry Date");
To get the values from the fields and use them in your report, you should use
expDateField.value()
I haven't tested this, but I've done similar things on numerous occasions so I'm fairly confident this will work. Let me know if you have any problems with this
If you want to specify a range here is how I accomplished it. Hope this helps somebody...
Method1:
qbds3 = qry.dataSourceTable(tableNum(DMxVehicleTable));
SysQuery::findOrCreateRange(qbds, fieldNum(DMxVehicleTable,VehicleMSRPRetails)).value(strFmt('(VehicleMSRPRetails >= %1) && (VehicleMSRPRetails <= %2)', queryValue(VehicleMinPrice), queryValue(VehicleMaxPrice)));
Method2:
qbds4 = qry.dataSourceTable(tableNum(DMxSysYearTable));
SysQuery::findOrCreateRange(qbds4, fieldNum(DMxSysYearTable,Year), 1, 1).value('>' + SysQuery::value(VehicleModelYearStart));
qbds4.addRange(fieldNum(DMxSysYearTable, Year)).value(strFmt('< %1', queryValue(VehicleModelYearEnd)));

AX 2009: Adjusting User Group Length

We're looking into refining our User Groups in Dynamics AX 2009 into more precise and fine-tuned groupings due to the wide range of variability between specific people within the same department. With this plan, it wouldn't be uncommon for majority of our users to fall user 5+ user groups.
Part of this would involve us expanding the default length of the User Group ID from 10 to 40 (as per Best Practice for naming conventions) since 10 characters don't give us enough room to adequately name each group as we would like (again, based on Best Practice Naming Conventions).
We have found that the main information seems to be obtained from the UserGroupInfo table, but that table isn't present under the Data Dictionary (it's under the System Documentation, so unavailable to be changed that way by my understanding). We've also found the UserGroupName EDT, but that is already set at 40 characters. The form itself doesn't seem to restricting the length of the field either. We've discussed changing the field on the SQL directly, but again my understanding is that if we do a full synchronization it would overwrite this change.
Where can we go to change this particular setting, or is it possible to change?
The size of the user group id is defined as as system extended data type (here \System Documentation\Types\userGroupId) and you cannot change any of the properties including the size 10 length.
You should live with that, don't try to fake the system using direct SQL changes. Even if you did that, AX would still believe that length is 10.
You could change the SysUserInfo form to show the group name only. The groupId might as well be assigned by a number sequence in your context.
I wrote a job to change the string size via X++ and it works for EDTs, but it can't seem to find the "userGroupId". From the general feel of AX I get, I'd be willing to guess that they just have it in a different location, but maybe not. I wonder if this could be tweaked to work:
static void Job9(Args _args)
{
#AOT
TreeNode treeNode;
Struct propertiesExt;
Map mapNewPropertyValues;
void setTreeNodePropertyExt(
Struct _propertiesExt,
Map _newProperties
)
{
Counter propertiesCount;
Array propertyInfoArray;
Struct propertyInfo;
str propertyValue;
int i;
;
_newProperties.insert('IsDefault', '0');
propertiesCount = _propertiesExt.value('Entries');
propertyInfoArray = _propertiesExt.value('PropertyInfo');
for (i = 1; i <= propertiesCount; i++)
{
propertyInfo = propertyInfoArray.value(i);
if (_newProperties.exists(propertyInfo.value('Name')))
{
propertyValue = _newProperties.lookup(propertyInfo.value('Name'));
propertyInfo.value('Value', propertyValue);
}
}
}
;
treeNode = TreeNode::findNode(#ExtendedDataTypesPath);
// This doesn't seem to be able to find the system type
//treeNode = treeNode.AOTfindChild('userGroupId');
treeNode = treeNode.AOTfindChild('AccountCategory');
propertiesExt = treeNode.AOTgetPropertiesExt();
mapNewPropertyValues = new Map(Types::String, Types::String);
mapNewPropertyValues.insert('StringSize', '30');
setTreeNodePropertyExt(propertiesExt, mapNewPropertyValues);
treeNode.AOTsetPropertiesExt(propertiesExt);
treeNode.AOTsave();
info("Done");
}

Flex - sorting a datagrid column by the row's label

I'm creating a table that displays information from a MySQL database, I'm using foreignkeys all over the place to cross-reference data.
Basically I have a datagrid with a column named 'system.' The system is an int that represents the id of an object in another table. I've used lableFunction to cross-reference the two and rename the column. But now sorting doesn't work, I understand that you have to create a custom sorting function. I have tried cross-referencing the two tables again, but that takes ~30sec to sort 1200 rows. Now I'm just clueless as to what I should try next.
Is there any way to access the columns field label inside the sort function?
public function order(a:Object,b:Object):int
{
var v1:String = a.sys;
var v2:String = b.sys;
if ( v1 < v2 ){
trace(-1);
return -1;
}else if ( v1 > v2 ){
trace(1);
return 1;
}else {
trace(0);
return 0;
}
}
One way to handle this is to go through the objects you received and add the label as a property on each of them based on the cross-referenced id. Then you can specify your label property to display in your data grid column instead of using a label function. That way you would get sorting as you'd expect rather than having to create your own sort function.
The way that DataGrids, and other list based classes work is by using itemRenderers. Renderers are only created for the data that is shown on screen. In most cases there is a lot more data in your dataProvider than what is seen on screen.
Trying to sort your data based on something displayed by the dataGrid will most likely not give you the results you want.
But, there is no reason you can't call the same label function on your data objects in the sortFunction.
One way is to use the itemToLabel function of the dataGrid:
var v1:String = dataGrid.itemToLabel(a);
var v2:String = dataGrid.itemToLabel(b);
A second way is to just call the labelFunction explicitly:
var v1:String = labelFunction(a);
var v2:String = = labelFunction(b);
In my experience I have found sorting to be extremely quick, however you're recordset is slightly larger than what I usually load in memory at a single time.

Resources