How to insert into a table field with a dynamic string? - axapta

Im working in AX 2012.
I try to make code where i count all sales for each month and insert them into fields in a table.
These fields are called Sales1, Sales2, Sales3 etc... representing the months in a year.
is there a way i can select these fields and insert into them in a while select like this example below?
while select myTable where myTable.date >= startDate && myTable.date <= endDate
{
MyTable.("Sales" +MthOfYear(MyTable.Date)) += MyTable.SalesQty;
}
myTable.insert();
it's a stupid example, but it should show what i want to achieve... any ideas?
Regards
Kent

I think your main question is how to access a field by having its name in a string variable?
If that's the case then please see the following two links:
How to convert field name to its ID
How to access a table field by ID
In short: First of all you have to convert your field name to the corresponding field ID by using fieldName2Id. After that, you can access this field by using the syntax myTable.(fieldId).
To put it all together for your case:
myTable.(fieldName2Id(myTable.TableId, strfmt("%1%2", "Sales", mthofyr(myTable.Date)))) += myTable.SalesQty
If you have any problems or questions don't hesitate to ask via a comment.

While the fieldName2Id may save your day, it is an AX anti-pattern to have fields named Sales1, Sales2 ... Sales17. Why? Because AX supports arrays in tables (albeit only of a fixed size).
To use that, define a new extended data type SalesAmountMonth exending SalesAmount (or whatever).
Label the it "January". Then in the node "Array Elements" add an new array element for "February", "Marts" up till "December". See How to Define an Extended Data Type as an Array.
Then add the extended data type to your table.
Your field access is then quite simple:
myTable.Sales[mthofyr(myTable.Date)] += myTable.SalesQty;
I prefer using the intvNo function for date indexing like this, as it has more flexibility:
myTable.Sales[intvNo(myTable.date, startDate, IntvScale::YearMonth) + 1] += myTable.SalesQty;
By changing the IntvScale enumeration you can group by month, week, quarter or whatever it supports.

Related

How to take value from combo box table microsoft dynamics ax 2012 x++ while select

I have table like
(1st photo)
table
What I should do to take this value to while select in x++?
(2c photo)
value
The short answer is you would need to take the return from the lookup, find the value in the table via the returned value (key), and take the Name field.
So this would be the data in your case for the first result:
InventLocation::find('11').Name
This is what's called a lookup. When you do a lookup, there are multiple methods that AX will determine what values to display. The one you're looking at is a lookup based upon the Extended Data Type relation.
EDT - In this case \Data Dictionary\Extended Data Types\InventLocationId
Table - which has a reference table of \Data Dictionary\Tables\InventLocation
Primary Key - which has an alternate primary key of \Data Dictionary\Tables\InventLocation\Indexes\InventLocationIdx, which I believe in this case determines the return value
AutoLookup - and the AutoLookup located at \Data Dictionary\Tables\InventLocation\Field Groups\AutoLookup determines which fields are displayed to the user as information.
If you want a custom lookup to return the InventLocation.Name field, you should look at the different methods available to you. This blog post is an excellent start to see different methods: https://kashperuk.blogspot.com/2009/04/lookup-methods-tutorial-custom-list.html

Axapta 2012 - Ax Views and GETDATE()

I'm trying to make a date range in a view work relative to today. But I'm not find any function to set in the query range to make it dynamic.
Example:
Creates:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[MYCUSTINVOICETABLEVIEW] AS
SELECT T1.INVOICEID AS INVOICEID,T1.DATAAREAID AS DATAAREAID,T1.PARTITION AS PARTITION,T1.RECID AS RECID
FROM CUSTINVOICETABLE T1
WHERE (INVOICEDATE<={ts '2017-07-18 00:00:00.000'})
GO
But instead of looking relative to last synchronization date, I want to look compared to today.
SELECT ... FROM CUSTINVOICETABLE T1
WHERE (INVOICEDATE<=GETDATE())
Any ideas how I can setup the query ranges for this?
Tried so far:
..GetDate()
..today()
..currentDate()
lessThanDate(0)
"< GETDATE()"
< currentSessionDateTime()
According to How to refresh/Synch View based on a Query with dynamic range?, it's not possible (for UserID()). I want to double check if that's the same case for dates. The view is being consumed by a other application on the same box (not an Ax form).
This isn't pretty and I still imagine there might be a better way, but here is a solution that I just tested. Obviously there are much better ways of doing this in x++, forms, and reports, but the result of the below can be queried externally from AX and will still return dynamic results.
You have a Query > View > Query > View structure, with the top level view being your consumable view.
The first view has the data you need and a computed date column, populated by the following code to get the dynamic date:
public server static str today()
{
return 'CONVERT (date, GETDATE())';
}
You then make a query of that view, and put an extended query range on it to check your field vs the dynamic GETDATE() column. You then have a view built on top of that query that your external application can consume.
In the example below, all field lists are set to dynamic yes. Obviously you would carry the relevant data from the root query all the way up.
The example in the picture results in the following view definitions:
CREATE VIEW "DBO".TESTVIEW AS SELECT T1.SALESID AS SALESID,
T1.RECEIPTDATEREQUESTED AS RECEIPTDATEREQUESTED,
T1.DATAAREAID AS DATAAREAID,T1.PARTITION AS PARTITION,T1.RECID AS RECID,
(CAST ((CONVERT (date, GETDATE())) AS DATETIME)) AS CURRENTDATE
FROM SALESTABLE T1
CREATE VIEW "DBO".TESTCONSUMABLEVIEW AS
SELECT T1.CURRENTDATE AS CURRENTDATE,T1.RECEIPTDATEREQUESTED AS RECEIPTDATEREQUESTED,
T1.SALESID AS SALESID,T1.DATAAREAID AS DATAAREAID,T1.PARTITION AS PARTITION,
T1.RECID AS RECID
FROM TESTVIEW T1 WHERE (RECEIPTDATEREQUESTED<CURRENTDATE)
My answer is based off #Spencer Kershaw's answer. So credit for his work, but I want to provide a more succinct answer that doesn't require a query and hopefully is clearer for others trying to accomplish the task.
To accomplish what you want, you need to do 3 things.
Create static method to use for computed column
Add a computed column to your view
Correctly put in the range by using some random field
1. Add this method to your view:
public server static str today()
{
return 'CONVERT (date, GETDATE())';
}
2. Right click on the fields node and click New>Date Computed Column. On the properties set ViewMethod = today.
3. Add a range. Choose dataAreaId for the field (this is arbitrary). Set the Value property equal to ("YourComparisonField" < "today"). The syntax can be important here.
This produces:
CREATE VIEW [dbo].[AAATESTVIEW]
AS
SELECT T1.ADDRESS AS ADDRESS
,T1.MODIFIEDDATETIME AS MODIFIEDDATETIME1
,T1.RECID AS RECID1
,T1.PARTITION AS PARTITION
,T1.RECID AS RECID
,(CAST((CONVERT(DATE, GETDATE())) AS DATETIME)) AS TODAY
FROM LOGISTICSPOSTALADDRESS T1
WHERE (N'modifiedDateTime1' < N'today')
GO

How to update DATETIME field with existing data from same table

I have an sqlite database which currently holds an integer field called Year which currently only stores the year. In future versions I want to store a full date and time.
I updated my table to include a FullDate field using alter table.
> ALTER TABLE Files ADD COLUMN UploadDate DATETIME DEFAULT 0;
Next, I want to migrate all the existing year fields to the new field. So I'm looking for something like:
> UPDATE Files SET UploadDate = (DATETIME('%Y-%m-%d', Year, 1, 1));
Unfortunately this doesn't seem to work as the result is empty. I also tried the date and strftime functions but they either result in incorrect data or empty data.
What's the proper way to update a DATETIME field with existing data in the same table?
The DATE and DATETIME functions don't have a format parameter.
For more: http://sqlite.org/lang_datefunc.html
The main catch is that SQLite does not have any date or time types, so that you might as well populate your field with:
UPDATE Files SET UploadDate = Year || '-01-01';
And that will do the exact same thing. Dates are not stored as typed, but can be evaluated as such against the date and time functions.

Need advice on ASP.NET localization - strings stored in a database & displayed in a gridview

I am looking for some advice on localization. I have an app that has been localized in the usual fashion (i.e., .resx files), which handles about 95% of the strings. However, I still need to localize some strings for category names that are stored in the database.
I'd like to avoid adding 15 new columns named categoryname_ES, categoryname_FR, etc, and then pulling the right column dynamically. If there would be some way to pull the data, and then do a substitution in the code, I think that would be a little less messy. Maybe along the lines of:
go through gridview row by row
if the language selected isn't english, look for this text value in a global resources file and replace it.
Anyone have a good idea of how to accomplish this? Or is adding a lot of categoryname columns for each language just the way to go (ewww).
I use the resource file method that you describe.
Add a CategoryName.resx file with a row for each category. Make sure the "Name" matches your database value exactly. Put the translation in the "Value".
Get the string in code via the resx's generated code file. (sorry for the C#)
Resources.CategoryName.ResourceManager.GetString(categoryName, new CultureInfo("fr"));
If you're binding to custom class, just make another property and bind to that property instead.
If you're binding to a DataSet, you might want to use the RowDataBound event to do the substitution.
You can do it with four database columns:
ID (unique primary key)
CultureCode
ProductID
ProductName
I presume that you are selecting your products from the database. Pass in the UI culture as part of the stored proc, then when you select from your product table join to the Culture table on the product ID and UICulture. You would phrase your SELECT something like this:
SELECT ProductID
,another field
,IsNull(Culture.ProductName, Product.ProductName)
,etc
FROM Product
LEFT JOIN Culture
ON Product.ProductID = Culture.ProductID
AND Culture.CultureCode = #UICulture
you get the idea. You could even check the UICulture for a hyphen (eg: fr-CA), split it into another variable, then do two joins to the Culture table - one for the exact culture, and one for the fallback culture, so in this example the first join would be for fr-CA and the second join would just fallback to fr. If all your culture joins fail (eg. because you don't have Zulu in the culture table), then the IsNull uses just the ordinary ProductName (which is probably in english).
You could create three tables:
Category
Category_ID (identity)
Category_Name (string)
Language
Language_ID (identity)
Language_Name (string)
CategoryLanguage
Category_ID (FK)
Language_ID (FK)
Translation (string)
The category table would have the names in English. The language table would have the languages that your application supports. The association table would then be able to provide the translated category name based on the selected language, if it exists. If it doesn't exist, then simply display the English version as the default.

L2Entities, stored procedure and mapping

Finally checked out L2E framework and ran into problems almost instantly.
Yeah, i know... i should read some books before.
Situation:
entity with props -> id and name.
entity is mapped to table, which has id and name columns.
sproc, which returns ONLY id column.
Problem:
ObjectResult<MyProp> result = _container.MyStoredProcedure(uberParameter);
Calling this will cause an error
[guilty method goes here] threw exception:
System.Data.EntityCommandExecutionException: The data reader is incompatible with the specified 'DataBase.MyPropTableObject'. A member of the type, 'name', does not have a corresponding column in the data reader with the same name..
Problem #2:
Can`t "just return" that field, cause that column has XML data type, but sproc uses fancy select statements, which causes:
Msg 421, Level 16, State 1, Line 1
The xml data type cannot be selected as DISTINCT because it is not comparable.
Question:
Is it possible to exclusively turn off mapping for this entity prop only for this one sproc?
Problem 1 is due to the proc not having the columns to populate the entity. You don't really need the proc if you have mapped the table, just select the field you want from it using linq
var result = MyEntities.EntityIMapped.First(r => r.id = uberParameter).Name;
Would give you the value from the Name column of the table for the given id. You don't need to use a stored proc for this.
Problem 2 sounds like it is in the proc, I would think that distinct on an xml data column would give a lot of results, but I'm only guessing as I don't know your solution.
This is not a direct answer for your question but, hopefully it will point you in the right direction.

Resources