Monday, March 11, 2024

D365 - Filter RefRecId Grid column for NULL Value

A client wanted to filter a column for blank values, and it wasn't working.  I tried all sort of query syntax tricks with no avail.  Is Exactly "", Is Not ?*, Is Exactly 0, Does Not Contain *, etc... The issue was that the field was a refRecId with a lookup against a related table. Here is what worked:

Use the 'Matches' option with the following value: (InventTable.FieldNameRefRecId == 0)

Include the parenthesis and change the field name to the field you are filtering on.

Tuesday, May 23, 2023

D365 F&O - Override System Fields on Data Entity Insert

 During data migration, you may find it necessary to overwrite system fields like 'createdBy' or 'createdDateTime'. In this case, my client has a custom table that stores user comments and relies on these two fields to give context to who and when the comment was created.  

1. Create two custom fields on the data entity

    1. CreatedByMigrated
    2. CreatedDateTimeMigrated

2. Update the Staging Table from the Data Entity so that the new fields are added to the staging table
3. Override (or extend) the insertEntityDatasource() method of your entity

public boolean insertEntityDataSource(DataEntityRuntimeContext _entityCtx, DataEntityDataSourceRuntimeContext _dataSourceCtx)
    {
        boolean ret;
 
        ARWSpecSheetComments comments;
 
        if(_dataSourceCtx.name() == dataEntityDataSourceStr(ARWSpecSheetCommentsEntity, ARWSpecSheetComments))
        {
            comments = _dataSourceCtx.getBuffer() as ARWSpecSheetComments;
            comments.overwriteSystemfields(true);
            comments.(fieldNum(ARWSpecSheetComments, CreatedBy)) = this.CreatedByMigrated;
            comments.(fieldNum(ARWSpecSheetComments, CreatedDateTime)) = this.CreatedDateTimeMigrated;
            _dataSourceCtx.setBuffer(comments);
        }
   
        ret = super(_entityCtx, _dataSourceCtx);
   
        return ret;
    

3. When importing your entity in data management, make sure the 'createdByMigrated' fields are set in the source to staging mapping, and you will also need to uncheck 'Validate Field' in the target mapping.

Thursday, July 18, 2019

Making a Dialog Form Stay on Top

I am working on a project that requires me to lock a parent form when a dialog is executed from a 'submit' button click on the parent form.  If the parent form is not locked, the user could continually push the button and execute multiple dialog boxes, which would not be good.  While exploring the Dialog class I found an easy solution, the IsModal variable. Simply set the isModal variable using the parmIsModal() method before calling Dialog.Run().  Like this.



Now, the user must close the Dialog before they can use any other AX form. Perfect!

Wednesday, June 12, 2019

Renaming a Dialog's 'Ok' Button

Some of our users tend to be a bit 'click happy' when it comes to pop-ups.  Reading a complete sentence or two in a prompt can be a laborious task, and the 'ok' button seems to be viewed as the easy way out. I have often wanted to rename a dialog's 'ok' button in the past in order to give a more descriptive text of what would happen next, but I always resorted to just creating a form with custom buttons.  Today, I decided to figure it out.   I was tasked with prompting the user to send an email to a customer, and I did not want them to just click through this prompt.  Renaming the button 'Send' will make them think twice before clicking away... I hope.

Here is my original prompt with the boring old 'Ok' button.



A few lines of extra code...


and...

Beautiful!



Friday, June 7, 2019

SFTP File Upload via x++

I recently had a requirement to create a batch job that would upload a file to an SFTP server daily.  AX 2012 was not capable of doing this directly from X++.  I chose to create a C# class that references a ssh.net dll and then call that class from x++. Here is how I did it.

1. Create a new C# Class Library project in Visual Studio. I named mine 'CompanyToolbox' so I could add other helper classes to it in the future.
2. Add Project to AOT
3. Install the SSH.Net NuGet Package

4. Create the 'SFTPHelper' class, and the UploadFile method. 

5. Set the Deploy to Client and Deploy to Server Properties of the project.

6. Add Project to AOT & Deploy
7. Once you Deploy, you should see the 'CompanyToolbox' DLL in the Server and Client Bin folders.

8. Unfortunately, I could not get the referenced renci.sshnet.dll to be automatically deployed to the client and server bins, so I had to manually drop them in.  You can copy the Renci.sshnet.dll from this location -      'C:\Users\(yourUsername)\AppData\Local\Temp\2\Microsoft Dynamics AX\C Sharp Projects\CompanyToolbox\bin\Debug'.  Paste the dll into the both the client and server bin folders. 

9. Restart the AOS if hot swapping is not enabled.
10. Call the method from x++.   


      Done!