Wednesday, July 27, 2011

strRem Function - Delete a Character from String - AX 2009

The following code searches a specified string character and deletes it. The cool thing about this function is that it is case sensitive.


str strRem(str text1, str text2)
text1  The string from which to remove characters.
text2 The characters to exclude from the output string.

For example:

strRem("MynameIs","is"); //Returns the string "MynameI".

Tuesday, July 26, 2011

Wednesday, July 20, 2011

Create Electronic Invoice to Text File Format - Ax 2009 -

 The following code is to create a company country specific requirement. In addition, the logic is specific to the needs of my customer, but I'm sure you will be able to find great examples on how to create directories with WinApi and manipulate text files with the TextIO function.

The project flow is as follow:

1- The user posts an invoice
2- After the invoice has been posted, the KMN_eInvoiceCreation class is called with parameters  (This call is not posted here)
3- The class has several methods from creating the path file name, to writing a very specific logic into a text file.
4- The class saves the file into a specific location

The project produces the following text file contents:

DC|3.0|||15/07/2011|Pago en una sola exhibición||150.22|||||270.02||I
EM|KIE9512187VA|Compania de Ventanas S.A.

DF|Juytyu|130|Piso 7 y 8, Desp.801|Lostre|||MiguelHidalgo|DF|Mexico|999
RC|TORE621221HP9|Elizabeth Araya Reyes
DM|Teaneck|308||Warrrr|||Guadalupe|NL|Mexico|986589

CN|1.00|||Libro de Respuestas 3A/2A/A|25.00|25.00
CN|1.00|||Diploma de Finalización 7A|2.61|2.61
CN|1.00|||Diploma de Finalización 6A|2.61|2.61
CN|1.00|||Flashcards 1-50|120.00|120.00
IA|102433660003476|08/10/2010|Laredo
IT|IVA|33.80|16.00
TI||33.80


This project uses a custom table to store all the SalesParmTable data as we needed to provide a way for the user to re-run a posted invoice.

The following are the base enums I'm using.

Friday, July 15, 2011

SubStr function - Axapta

str SubStr (str _text, int _position, int _chars)

SubStr("MyString",20,3);  // Returns ""
SubStr("MyString ",4,50);  // Returns "tring"

Monday, July 11, 2011

Create loop from an AX form DataSet - Ax 2009

Sometimes we need to loop through values at the form level. The following code loops (for loop) the SalesParmTable in the CloseOk() Form method.        


        //Create Lines
        for (localSalesParmTable = salesParmTable_ds.getFirst();
              localSalesParmTable;
              localSalesParmTable = salesParmTable_ds.getNext())
        {

              ....Implementation....
        }

Code to check for "garbage" in the ReleaseUpdateScripts table - AX 2009

ReleaseUpdateScripts    releaseUpdateScripts;
Counter                 total;
Counter                 invalid;
;
while select ClassID
    from    releaseUpdateScripts
    group by ClassID
{
    total++;
    if (classid2name(releaseUpdateScripts.ClassID) == '')
    {
        info(int2str(releaseUpdateScripts.ClassID));
        invalid++;
    }
}
info(strfmt(@"Found %1 invalid classIds out of %2", invalid, total));

Wednesday, July 6, 2011

Workaround to Exception::CLRError using System.IO.StreamWriter

In one of my projects I was using the System.IO.StreamWriter to write data into a text file in X++. Everything went well until I started testing for exception in order to handle them (the System.IO is a .Net class that allows us to maniluplate file operations, including folders. So, I though in catching the exception with the Exception::CLRError one. )

The problem I was having was that when an exception was raised by a problem creating the file (Incorrect file name), the operation will not fall into the Exception::CRLError exception, Instead, it would just crash and I wasn't able to properly handle the exception.

The reason for this is that when using an AX class that runs on the server, the exception never comes back to the client and therefore cannot be handled correctly. I'm using the SalesFormLetter class main method to call my own class after an invoice is generated, and this class (SalesFormLetter) is (1) an abstract class and (2) runs on the server and I really did not want to do this.

A workaorund is to use the TextIO class in AX along with the FileIoPermission. For example, when using the TextIo to create (and/or overwrite) a file, we get a null value when the file could not be created (and/or overwritten). Then, we can throw an exception when the object is null.

In my case I have a central class that handles all errors, so when the TextIO object is null, I call this class and I throw an error, then the error comes back to my method and falls into the Exception::Error exception.

The following is the code

Wednesday, June 15, 2011

Mark Customer Invoices for settlement with AX 2009 - Mark Invoices

After creating a payment journal (http://axwonders.blogspot.com/2011/06/create-axapta-payment-journal.html ), you might want to mark the invoices for settlement. This task is done by looping through the just created Payment Journal and then by querying the CustTransOpen Table and instantiating the CustTrans table from the CustTransOpen.CustTrans() method.


The following is the code to mark invoices. Also, the code loops through each payment journal transaction.

Also, the logic behind it is that the SpecTrans table needs to have two records in order to offset an open invoice with a transaction. So the code below inserts two records to the SpecTrans table. One is for all the open transactions (invoices - Sales) and the other is for all the payment transactions (paymet - Payment)

For example:

select firstonly invCustTrans where invCustTrans.AccountNum == custTable.AccountNum
            && invCustTrans.TransType == LedgerTransType::Sales
            && !invCustTrans.LastSettleDate;


the code above will select all the customer transactions with a TransType of Sales.

On the other hand, the code below will select all the customer transaction with a TransType of Payment.

select firstonly payCustTrans where payCustTrans.AccountNum == custTable.AccountNum
            && payCustTrans.TransType == LedgerTransType::Payment
            && !payCustTrans.LastSettleDate;


Then we need to insert the two instances of CustTrans into the SpecTrans table:

specOffsetVoucher.insert(invCustTrans.dataAreaId, invCustTrans.TableId, invCustTrans.RecId, invCustTrans.AmountCur, invCustTrans.CurrencyCode, NoYes::No);

specOffsetVoucher.insert(payCustTrans.dataAreaId, payCustTrans.TableId, payCustTrans.RecId, payCustTrans.AmountCur, payCustTrans.CurrencyCode, true);
The following is the whole code:

Monday, June 13, 2011

Create Axapta Payment Journal

The following code creates a payment journal in AX.

public void PaymentJournalLineCreation()
{
    boolean                     ret;
    CustTable                   custTable;
    LedgerJournalName           LedgerJournalName;
    LedgerJournalTable          ledgerJournalTable;
    LedgerJournalTrans          ledgerJournalTrans;
    LedgerJournalCheckPost      ledgerJournalCheckPost;
    NumberSeq numberseq;

    ;

    //Get customer account
    this.getCustomerAccount();

    //Get currency
    this.setCurrency();

    //Set JournalNameId
    this.setJournalNameId(LedgerJournalACType::Bank);

    //Get table buffer
    custTable = CustTable::find(customerAccount, false);

    // Find a ledgerJournalName record
    select firstonly LedgerJournalName
    where LedgerJournalName.JournalName == journalNameId;


    //Get next available voucher number
    numberseq = NumberSeq::newGetVoucherFromCode(LedgerJournalName.VoucherSeries);
    ledgerJournalTrans.Voucher = numberseq.voucher();

    //Generate the transaction line
    ledgerJournalTrans.JournalNum = ledgerJournalId;
    ledgerJournalTrans.CurrencyCode = currencyCode;
    ledgerJournalTrans.ExchRate = Currency::exchRate(ledgerJournalTrans.CurrencyCode);

    ledgerJournalTrans.AccountNum = customerAccount;
    ledgerJournalTrans.accountName();
    ledgerJournalTrans.AccountType = LedgerJournalACType::Cust;

    ledgerJournalTrans.Dimension[1] = custTable.Dimension[1];
    LedgerJournalTrans.KUMTeamDescription();
    ledgerJournalTrans.Dimension[2] = custTable.Dimension[2];
    ledgerJournalTrans.KUMDetailDescription();
    ledgerJournalTrans.Dimension[3] = custTable.Dimension[3];
    ledgerJournalTrans.KUMEventDescription();

    ledgerJournalTrans.AmountCurCredit = paymentAmount;
    ledgerJournalTrans.TransDate = PaymentDate;
    ledgerJournalTrans.Txt = '@COL1576'; //Payment, Thank you
    ledgerJournalTrans.PaymMode = custTable.PaymMode;
    ledgerJournalTrans.PostingProfile = 'DFLT';
    ledgerJournalTrans.BankTransType = 'Chck-rcpt';
    ledgerJournalTrans.Payment = custTable.PaymTermId;
    ledgerJournalTrans.CustVendBankAccountId = this.GetCustomerBankAccountID(customerAccount);
    ledgerJournalTrans.SettleVoucher = SettlementType::OpenTransact;
    ledgerJournalTrans.TransactionType = LedgerTransType::Payment;
    ledgerJournalTrans.Approved = NoYes::Yes;
    ledgerJournalTrans.ApprovedBy = curUserId();
    ledgerJournalTrans.Due = systemdateget();
    ledgerJournalTrans.TaxGroup = 'DFLT';

    ledgerJournalTrans.OffsetAccount = bankAccount;
    ledgerJournalTrans.OffsetAccountType = LedgerJournalACType::Bank;
    ledgerJournalTrans.offsetAccountName();

    ledgerJournalTrans.PaymentStatus = CustVendPaymStatus::None;
    ledgerJournalTrans.insert();

}
There are some methods calls in the previous code. These are the following:
//Find customer account based on Customer Reference Number
public CustAccount getCustomerAccount()
{
    CustAccount     custAccount;
    CustBankAccount custBankAccount;
    int             countRecords = 0;
    ;

    switch (JournalFormatType)
    {
        case KMN_CustPaymentJournalFormatType::Mexico:
            select * from custBankAccount where custBankAccount.MsgToBank == customerReference;
            custAccount = custBankAccount.CustAccount;
            this.parmCustAccount(custAccount);
            break;
    }

    return custAccount;
}

//Sets the currency value to the property
public void setCurrency()
{
    ;
    //Set property
    this.parmCurrencyCode(CompanyInfo::standardCurrency());
}

public void setJournalNameId(LedgerJournalACType _journalType)
{
    LedgerJournalNameId _journalNameId;
    ;
    switch(_journalType)
    {
        case LedgerJournalACType::Bank:
            _journalNameId = 'CR';
            break;

    }

    this.parmLedgerJournalNameId(_journalNameId);
}

NOTE: I'm using accessory methods for most of the variables in this code (this is a class), so remember to declare them in the classDeclaration and create your own properties.

Tuesday, June 7, 2011

Using Args for Output and Display Menuitems - AX 2009

public static void main(Args args)
{
    VendPurchOrderJour      vendPurchOrderJour;
    PurchTable              purchTable;
    ;
    if(args.dataset() == tablenum(VendPurchOrderJour))
    {
        vendPurchOrderJour = args.record();
        select purchTable where purchTable.PurchId == vendPurchOrderJour.PurchId;
        if(purchTable.CustomsImportOrder_IN == noYes::Yes)
            new MenuFunction(menuitemoutputstr(TestPurch), MenuItemType::Output).run(args);
        else
            new MenuFunction(menuitemoutputstr(TestS), MenuItemType::Output).run(args);
    }
}

RAID in AX 2009 - AX 2009

With an ERP system such as Microsoft Dynamics AX 2009, the database server generally stores a very large amount of important data for the business. If this data is unavailable for any length of time, the business could experience
significant financial losses.


Using a Redundant Array of Independent Disks (RAID) can help reduce the possibility of this loss occurring. Another important aspect for a database server is fine tuning for optimal performance. A RAID disk subsystem can also be used to help achieve this goal.

RAID refers to a group of two or more disks managed as a single unit to store the data together with additional, or redundant, information to provide recovery if there is a disk failure.

Usually a failed disk in a RAID system can be replaced while the server is still running. This is one benefit of RAID.

Managing Multiple AOS Instances - AX 2009

When multiple instances are installed, use the Microsoft Dynamics AX Server Configuration utility to manage all AOS instances. Use the Server Configuration utility to verify that the AOS connects to the correct database and application file server.

1. Open the Server Configuration utility (Start > Administrative Tools > Microsoft Dynamics AX Server Configuration).

2. Click Manage, click Create configuration, and then enter a name for the configuration. Then determine whether to copy it from the active or original configuration.

3. On the Application Object Server tab, validate that the Application file location is correct.

4. In the TCP/IP port field, note which port the AOS is running on.This information is needed to connect to the AOS.

5. On the Database tab, validate that the AOS is connected to the correct database. If not, change it.

6. Click OK to exit the configuration utility

Connect to a new AOS Instance - AX 2009

Follow these steps to connect a client to a new AOS instance:

1. Open the Microsoft Dynamics AX Client Configuration utility
(Start > Control Panel > Administrative Tools > Microsoft Dynamics AX Configuration Utility).

2. In the Configuration target list, select Local client.

3. Click Manage, click Create configuration, and then enter a name for the configuration. Then determine whether to copy it from the active or original configuration.

4. On the Connection tab, click New. Enter the Server name, Instance name, and TCP/IP port of the AOS instance to connect to, and then click OK and exit the configuration utility.

Create a Proxy Business Connector Account in active directory - AX 2009

Create the proxy account in Active Directory as follows:

1. Create a unique user in Active Directory in the form domain\username, for example, domain\bcproxy. This user must not have the same name as an existing Microsoft Dynamics AX user. For the procedure to add a new user, see the Active Directory documentation.

2. Assign a password to the user.

3. Select the Password does not expire option.

4. Select the No interactive logon rights option.

5. Close Active Directory

Macros in AX 2009 - AX 2009

Macros are constants, or pieces of code, that are being taken care of by the compiler before the rest of the code to replace the code where the macro is used with the content of the macro.

There are three different types of macros: stand alone macros, local macros, and macro libraries.

Macros are typically constant values that are only changed by developers. They are used so that developers don't have to hardcode these kind of values in the X++ code, but rather refer to the macro.

Inheritance in AX - AX 2009

One of the central concepts of object-oriented programming is the possibility to inherit functionality defined at a higher level in the system. This can be done by having a class hierarchy where a method in a subclass overrides a method in the super class (higher level).

The method in the subclass can still use the functionality in the same method in the super class by using the super function as in this example:

Friday, May 13, 2011

Deploy AX 2009 from Terminal Services with the AX configuration - AX 2009

In my company we were trying to deploy AX 2009 from terminal services and we encountered profiles issues when other users (other than the server admin or domain admin) were trying to access the application.

This was strange as we did install the client on a public share, and we also imported the correct configuration for the AX 2009 client.

Anyway, I need to give full credit to my company's System Manager. His name is Rohan Robinson and he is truly a master when it comes to Terminal Services and Citrix. His email is rrobinson@argointl.com in case you have questions for him.

So, Rohan came up with the following solution:


1- He installed the AX client on a public share
2- Imported the correct configuration for the client. In here make sure that the configuration file has the correct path as shown below:



3- Moved the configuration file to the bin folder (E:\Program Files (x86)\Microsoft Dynamics AX\50\Client\Bin)



4- Modified the properties in terminal services to point to the axc file instead of the AX32.exe file. The process is as follow:

*Right-Click on the AX remote App on the Terminal Services UI as shown:


*Then change the path with the configuration file name (which is already in E:\Program Files (x86)\Microsoft Dynamics AX\50\Client\Bin) instead of the AX32.exe one as shown below:




At this point, everybody can access the application through terminal services. Rohan also mentioned that the same process can be used in Citrix (XenApp 6.0).

Thanks!

Friday, May 6, 2011

Error while trying to access Active Directory - AX 2009 -

Today I was trying to add some users by using the Microsoft Dynamics AX 2009  Active Directory Import Wizard and I got the following error:



Error while trying to access Active Directory

I went into a code (Forms/SysUserADUserImportWizard/searchADUser) and I saw that the Active Directory searcher will break into this line:

searchResultCollection = directorySearcher.FindAll();

Tuesday, April 26, 2011

Best Practice Check execution - Multisite in AX 2009 - Specific Checks - Tables - Inventory dimension fields are handled by multisite activation

When upgrading from an older version to AX 2009, the multisite function is, by default, inactive. Ususally when you activate Multisites in AX 2009, you may have an error message saying:

"The Multisite wizard is not up-to date"

This means that some new InventDim fields have been added to some tables and the wizard cannot run. There are many ways to fix this, but I found that by executing a Best Practice Check is the best way to do this.

On the Microsoft white paper about multisites (http://www.ax-pact.com/downloads/Multisite%20Activation%20White%20Paper%20for%20Microsoft%20Dynamics%20AX%202009%20.pdf) they suggest doing this, but they don't tell you where to run the Best Practices Check from.

To do so follow the next steps:

Tuesday, April 19, 2011

Consume an Currency Exchange Rates Web Service from AX 2009 - WFC

Consuming web services from Ax 2009 is a sort of tricky task when the web service is not DAX 2009 "friendly".


Microsoft published a white paper on how to consume a web service to load currency exchange rates into the ExchRates Tables. The problem is that the web service provider's information is outdated. In addition, this white paper does not really explain the problem the developer will faced when the URL does not have the WSDL definition into it.


For example, in the white paper the web service URL is the following:

Tuesday, March 29, 2011

Lightswitch "How Do I?" Videos - Visual Studio Lightswitch

A few weeks ago I downloaded Visual Studio Lightswitch. I'm still getting to know the application and new features that are offered by Microsoft. You can have a full definition of Visual Studio Lightswitch here:

https://community.altiusconsulting.com/blogs/mikevinson/archive/2010/11/09/microsoft-visual-studio-lightswitch-what-is-it.aspx

I do have to say that the development of business applications has been taken to the next step. I think the most interesting aspect of Visual Studio Lightswitch is that we can now develop apps for the cloud. This is really interesting to me as I'm getting into SharePoint development and I just read that Microsoft will have the Office 365 available really soon.

Anyway the Silverlight team has some interesting tutorials about developing data-centered silverlight apps for the web by using Visual Studio LightSwitch. You can find it here:

http://team.silverlight.net/announcement/announcing-visual-studio-lightswitch-beta-2-is-available/


Also, the MSDN LightSwitch has some easy to understand How Do I videos around Visual Studio LightSwitch here:

http://msdn.microsoft.com/en-us/lightswitch/gg604823

Monday, March 28, 2011

Find AOT classes through X++

Today I needed to implement a job that existed my company's old version of AX into AX 2009. In the Old Axapta I went to Basic > Batch List to find the name of the job and/or the date it was created.

Then I went to the AOT > Data Dictionary > Tables > Batch and I opened the table by using the table browser and I saw that the Class ID for this particular Job was 40144.

Then I created a new job and I wrote the following code:


static void ClassNames(Args _args)
{
    DictClass   dictclass;
    ;
   
    dictclass = new DictClass(40144);
    info(dictclass.name());
}



The info log showed me the name of class that is run by the AX Job. From there I just created a new batch record to run it every night.



Wednesday, March 23, 2011

make friendly URL’s for your SharePoint 2010 site in 4 steps with IIS7 URL Rewrite module

I started developing an Internet facing site with the help of this book : http://www.amazon.com/Professional-SharePoint-Branding-Interface-Programmer/dp/0470584645/ref=sr_1_12?s=books&ie=UTF8&qid=1300888674&sr=1-12#_

However, for me SEO is critical nowadays and this book did not give me any information on how to make my Share Point 2010 Internet facing site URL friendly. Because I'm an ASP.NET developer, I knew that now we have the URL Rewrite module in IIS7 and I wondered if I could apply it to a Share Point site as well.

I found this great post that explains how to achieve Share Point 2010 friendly URL by using the II7 URL Rewrite module.

http://blog.mastykarz.nl/friendly-urls-sharepoint-site-4-steps-iis7-url-rewrite-module/

After following the steps stated in the above link, I was able to produce a friendly URL.

Saturday, March 19, 2011

SQL 2008R2 FULL TEXT INDEX SEARCH SETUP

In Microsoft SQL 2008 R2, the process of setting up full text search is done differently then in prior versions of SQL.


In earlier versions of SQL, we would have to right-click on the table we wanted to have full text index search capabilities by going to Design. Once in the table designer, we would choose Full Text Index and we would set the values in the window that would pop up.


In SQL 2008 R2, however, the process of setting up the full text index search is as follows:


The very first step is to create a new Catalog in our data base as follows (Let's not forget to click on the Data Base we want to setup the Full Text Index Search)


CREATE FULLTEXT CATALOG NameOfCatalog


Execute the stored procedure, which should be really quick and in where we should get a message like this:


Command(s) Completed Successfully


Then we go through the following steps:

Friday, March 18, 2011

SQL Injection: Defense in Depth -

SQL Injection happens when a developer accepts user input that is directly placed into a SQL Statement and doesn't properly filter out dangerous characters. This can allow an attacker to not only steal data from your database, but also modify and delete it.

Certain SQL Servers such as Microsoft SQL Server contain Stored and Extended Procedures (database server functions). If an attacker can obtain access to these Procedures it may be possible to compromise the entire machine.

In addition, attackers commonly insert single qoutes into a URL's query string, or into a forms input field to test for SQL Injection. If an attacker receives an error message like the one below there is a good chance that the application is vulnerable to SQL Injection.


Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near the
keyword 'or'



The following article talks about how to prevent SQL Injections. I thought it was pretty comprehensive and has good examples on how to achieve a good strategy to minimize these attacks.

http://www.simple-talk.com/sql/learn-sql-server/sql-injection-defense-in-depth/

You can also learn more about it here http://msdn.microsoft.com/en-us/library/ms161953.aspx

Also, there are a few videos that walk you through some of these issues here http://www.google.com/#q=sql+injections+tutorial&hl=en&sa=X&prmd=ivns&source=univ&tbs=vid:1&tbo=u&ei=DGCDTceeN6WY0QG8r7XkCA&ved=0CEcQqwQ&bav=on.2,or.r_gc.r_pw.&fp=3d8c1b5379a812ef

Thursday, March 17, 2011

Axapta: Validate Access to return value from display method - Ax 2009

I was working on a report today and after compiling it I saw that the compiler gave me some Best Practices errors.

Basically the error said : Validate Access to return value from display method.

Well, the compiler is smart enough to remind us that we need to consider if a specific user should have access to the data that you are returning from the function.

In addition, to check if a user has permissions to a specific field, we can use the hasFieldAccess function. There are other functions we can use as well such as hasMenuItemAccess, hasSecurityKeyAccess amd hasTableAccess.

An example is shown below:


//BP Deviation Documented
display vatNumJournal TaxExemptNum()
{
    if(!hasFieldAccess(tablenum(SalesTable), fieldnum(SalesTable, VatNum)))
        throw error("@SYS57330");

    if (SalesTable.VATNum)
        return SalesTable.VATNum;
    else
        return '';
}

The BP Deviation Documented comment line just above the function is to tell the compiler we have addressed the issue.

Thursday, March 10, 2011

Allowing Users to Copy of a Lost or Sent Quote - Microsoft Dynamics AX 2009

The default functionality of Microsoft Dynamics Ax 2009 does not allow to copy a quote when a quote's status is either Lost, Sent, Confirmed, or Canceled.

Today I was asked to allow the users to copy a quote when its status is Sent or Lost.

To copy a quote go to Sales Quotation Details, choose a record and then go to the header level buttons and click Function > CopyFromAll



The following are the steps to accomplish this very quick:

Email Invoices based on customer setup options - Microsoft Dynamics Ax 2009

Today I had a requirement that said to add a CheckBox control to the Customer Form to decide weather to print or email an invoice automatically.


NOTE: I will no go over the actual logic on how to email the invoice as I have already written a post about it, you can find it here http://axwonders.blogspot.com/2011/02/save-microsoft-dynamics-ax-2009-report_23.html


The following is the new control added to the CustTable form under the setup Tab:





 Now the logic is very simple. If the a customer account has this checkbox checked then set the Document destination value automatically to Email. Otherwise set the value of the control to Printer. In the picture above we can see that this specific customer has the checkbox checked.


Then the expected result will be to see the Document destination value to Email when a sales order record needs to be invoiced or acknowledged.


Please see the following sequence:

Tuesday, March 8, 2011

Languages in AX 2009 - Using a the LanguageTable form for Lookup building- AX 2009

Today I had a requirement to only show the following language across the whole application:
  • en-us
  • fr
  • it
At first I thought to create a custom lookup method as I did for another requirement last month (http://axwonders.blogspot.com/2011/03/filter-activity-form-contact-to-only.html), but then I thought .. Oh my .. this would mean to add a lookup method to several forms across the application, and what about if I need to change something in the future? It was a fact that the scalability of this change will be an issue.

Because the requirement said "Across the application" I decided to modify the LanguageTable form to be shown as a lookup in every instance of the LanguageID across the application.

The following are the steps I took:

WPF Training videos - Thanks Joe Stagner

The following is a list of WPF training videos. I found them extremely useful to what I'm doing right now.

http://www.msjoe.com/2011/03/wpf-3-5-training-videos/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+MSJoe+%28MSJoe%29

Enjoy!

114 windows forms tutorials - Thanks Joe Stagner

The following is a great resource on tutorial for win forms.

http://www.msjoe.com/2011/03/windows-forms-training-videos-114/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+MSJoe+%28MSJoe%29

Thursday, March 3, 2011

Filter the Activity Form contact to only existing records on a Business Relationship by creating a Lookup Dynamically- AX 2009

Today a user came to me and asked me if I would be able to show only the contacts related to a Business Relationship when choosing a contact in the Activity form.


The following is the form:



 The original setup would show all the contacts available table wise. This was a problem for the users as it will take a lot of time for them to find the right contact.

Set the Business Relationship Account in the Activities Form

Yesterday I had a requirement that said to pre-populate the Business Relationship Account in the Activities Form field Business Account upon creation of a new activity.

To do this I modified the InitValue() method within the smmActivities Data Source:

Forms > smmActivities > DataSources > smmActivities > Methods > InitValue


To do it I had to make sure that the element that was calling the form was the smmBusRelTable, then I assigned the element record to my smmBusRelTable variable. Finally, upon checking the validity of the record, I assigned the busRelTable.BusRelAccount to the busRelAccount in the smmActivities table.

The code is as follows:


THE FOLLOWING CODE GOES INTO THE FORM INIT METHOD
if (element.args().dataset() == tablenum(smmBusRelTable))
    {
        busRelTable = element.args().record();
        //businessRelationRange.value(smmBusRelTable.BusRelAccount);
    }

This Goes in the smmActivities data source initvalue().
    if(busRelTable.BusRelAccount)
    {
        smmActivities.smmBusRelAccount = busRelTable.BusRelAccount;
    }

Tuesday, March 1, 2011

Set the MarkupGroup from the SalesCreateQuotation Form - Microsoft Dynamics Ax 2009

Today I had a requirement to automatically set the MarkupGroup at the moment a user creates a new Sales Quote in AX.


In the past the user would have had to do this manually but with the following changes in my code this happens in the background.


The place where we want to change this is in the salesQuotationTable.writeCreateQuotation Method. This method can be accessed from:


SalesCreateQuotation Form > DataSources > SalesQuotationTable > Methods > Write



The code is as follows:

Monday, February 28, 2011

Creating a simple Pager user control with ASP.NET and C#

The following is a simple user control that will display a Pager functionality for any type of web page that deals with large amount of data that need to be segmented in pages.

This is part of a larger project and perhaps in the future I will present the finished project, but for now this user control can help us organize our data with a data list.

  1. Create a new web site project in Visual Studio
  2. Add a new Web User control named Pager.
  3. In Source View (Asp.Net) write the following code
  4. <%@ Control Language="C#" AutoEventWireup="true" CodeFile="Pager.ascx.cs" Inherits="UserControls_Pager" %>
    <p>
    Page
    <asp:Label ID="currentPageLabel" runat="server" />
    of
    <asp:Label ID="howManyPagesLabel" runat="server" />

    <asp:HyperLink ID="previousLink" runat="server">Previous</asp:HyperLink>

    <asp:Repeater ID="pagesRepeater" runat="server">
        <ItemTemplate>
            <asp:HyperLink ID="hyperlink" runat="server" Text='<%#Eval("Page") %>' NavigateUrl='<%#Eval("Url") %>' />
        </ItemTemplate>
    </asp:Repeater>
    <asp:HyperLink ID="nextLink" runat="server">Next</asp:HyperLink>
    </p>

Table methods using ValidateWrite() ValidateDelete() initValue() ModifiedField() - Microsoft Dynamics AX 2009

Table methods using ValidateWrite() ValidateDelete() initValue() ModifiedField()

initValue()This method file while creating new record to initialize a value, here I am assigning user id to the userID field.

public void initValue()
{
super();
this.UserId = curuserid();
}

Sunday, February 27, 2011

Schedule a Windows Task to call an ASP.NET web page - ASP.NET - VB.NET, Windows Task Scheduler

The following is how you can schedule a windows task that can call an ASP.NET web page. Usually we want to schedule task from Windows. I have seen lots of questions regarding this in the past.

The cool thing about Windows task is that you can execute custom jobs to be executed in the server without the need of a user to be logged in.

The following code can be used to call ASPX web pages to run a specific job that needs to execute some sort of logic. The script is written in VB.NET, but the web page can be written with C# as the vbscript only is used to create the call from the server to the page.

The steps are as follow:

Friday, February 25, 2011

Get Employee email with X++ - Microsoft Dynamics AX

The new way Microsoft Dynamics AX handles employee records is very different from the prior versions. For example, in AX 3.0 or 4.0 the employee table will have an email for a specific record, so you could just do something like this to retrieve an employee email:

EmplTable::find(emplId).email;

I needed to get the Employee ID for a custom functionality that sends a sales status confirmation email to a contact with copy to the employee that is handling that Sales Order.




In Microsot Dynamics AX 2009, however, the employee's information is handled diferently. For example, the Employee contact information is stored in a table called DirECommunicationAddress, and the Employee's address is stored in the Address table.

Wednesday, February 23, 2011

SalesCreateQuotation - Always set an Address when creating a new Sales Quotation - Microsoft Dynamics AX 2009

I was faced with a very weird problem today at work. When a user goes to Sales Quotations and clicks the New button, he/she gets the SalesCreateQuotation form (Show below). In our implementation of this form, a contact is required. So, the user always has to choose a contact that is related to the business relationship that it is being quoted.

Now, the issue is that when users create a contact, they only set basic data such as email, and more often than not, the address fields are left blank.

Save an Microsoft Dynamics AX 2009 report to a PDF file (Second Part) - Save the file to a network location

In this part of the article we'll continue to build our functionality to save an Axapta report to a PDF format, then save this file to a network location, and then send it as an attachment in outlook.

The firt part of this series in here http://axwonders.blogspot.com/2011/02/save-microsoft-dynamics-ax-2009-report.html

In the prior article I created a job to save an Axapta report to PDF into a local drive ... C:\. In this article, the code from the last article is integrated within the Run() method of a class I created called SalesConfirmReportEmail.

The SalesConfirmReportEmail class gets executed when a a user wants to send and post an Order Acknowledgement on a Sales Order. I will not discuss how the code works from the moment the user clicks ok in the SalesEditLines form, but I will point out the path that the code follows:

So, the user opens the Sales Order form, finds a record, goes to Posting > Acknowledgement , does whatever he/she needs to do and clicks OK.

In my implementation, the user can choose the output for the order confirmation report. This is, in the DocDestination drop down list he/she can choose Preview, Print, and/or Email. In this case the user wants to print the report.

Tuesday, February 22, 2011

Error executing code: The method has been called with an invalid number of parameters. - Microsoft Dynamics AX 2009

When trying to use the COM object to attach a file into Outlook I got the following error message:

Error executing code: The method has been called with an invalid number of parameters.

After setting a breakpoint into the SysInetOutlookMail class AddAttachment method, the code broke in the following line:

_outlookMailAttachments = _outlookMail.Attachments();

Save a Microsoft Dynamics AX 2009 report to a PDF file (First Part)

The following code saves an Axapta report to a PDF file. This is the first article of 3. The next article will show how to save the file into a network share and pass a Sales Order dynamically, and the last part will be about attaching the PDF to an Outlook instance and create a dynamic subject. So, the titles of the three articles will be the same foe exception of the text in parenthesis.

In my case, I'm having a lot of problems saving the file to a network file and then to attach it to Outlook. The code below saves the report to a local palce in your computer.

static void Job10(Args _args)
{
   custConfirmJour     custInvoiceJour;
  SalesFormLetter     salesFormLetter = SalesFormLetter::construct(DocumentStatus::Confirmation,  false);
   PrintJobSettings    printJobSettings = new PrintJobSettings();
   Args                args = new Args();
   boolean             prompt = false;
   boolean             printIt = true;
   ;

    printJobSettings.setTarget(PrintMedium::File);
    printJobSettings.format(PrintFormat::PDF);
    printJobSettings.fileName(@'c:\temp\myfile2.pdf');
  
   salesFormLetter.updatePrinterSettingsFormLetter(printJobSettings.packPrintJobSettings());

   select firstOnly custInvoiceJour
       where custInvoiceJour.salesid == '18-062467';

   args.record(custInvoiceJour);
   args.caller(salesFormLetter);

   new MenuFunction(menuitemoutputstr(SalesConfirmation), MenuItemType::Output).run(args);

}

Monday, February 21, 2011

Data List Control (.NET) - Create a fully dynamic user control that handles URL links and Css Classes - ASP.NET

A few days ago I wrote a post on how to create a fully dynamic Link class in C# that will return a full query string based on what a user is clicking within a page. In the following example I'll present the table design, Stored Procedure, C# class, CSS Class and ASP.NET user control I'm using to

Invoice Verification - Total Line Calculation from PurchParmTableTotals in PurchEditLine - Microsoft Dynamics AX 2009

Today I had to fulfill the following requirement:
  1. When the user clicks "Invoice Verification" from the Purch Order Form, place the follwing in the PurchEditLines Form
    • Invoice Balance
    • SalesTax
    • Line Discount
    • Balance
Usually you can see these values when clicking the Totals button from the PurchEditLines Form object in AX 2009.




When you clicked the Totals button the PurchParmTableTotals Form gets activated and the PurchTotals class gets instantiated. So I needed to basically replicate what this form is doing to present the values we see above in the PurchEditLines form as show below.

Saturday, February 19, 2011

Create a Link (URL) class for ASP.NET and C#

I was faced with a requirement last week to build a dynamic link generator to manage URL's in a site. The project owner did not want to build the URL in the presentation layer as the site has an ecommerce architecture where there are product categories and products department, which include a category in itself.

Of course, if you think about it, every time that the user clicks on a category or department, the site needs to create a dynamic URL like Catalog.aspx?DepartmentID=1". The Query string will be used to retrieve the value of DepartmentId, which in our example is equal to 1.

Thursday, February 17, 2011

In DCOMCnfg "Run application on this computer" is grayed out for my application on two Windows 7 machines, but it works fine on all other machines

I was having a problem sending an email through outlook in one of the dev machines at work this morning. After reading a few articles about the topic, I eneded up going to the Component Services to edit the Outlook Message Attachment Service component.

Went I got to the window (Start > Administrative tools >

Tuesday, February 15, 2011

Create a Custom Error Page in 4 steps - .NET - ASP.NET - C#

Visual Studio gives us the possibility to handle errors by using many different types of error handling functions. However, we know we need to tell the viewer that something went wrong when the application crashes, and for this we need to implement an Error page.

I remember seeing some custom error pages in the past that were implemented by using a class that will be called after an exception was thrown.

It worked well, but the implementation of an error page can be more efficient and faster by doing the following:

Monday, February 14, 2011

Choose to whom send what type of email from Outlook automatically in Microsoft Dynamics AX 2009

Ax 2009 came with many changes regarding addresses and contacts.

(If you want to learn more from it go here http://www.microsoft.com/downloads/en/details.aspx?FamilyID=052e9dda-667b-42bd-bd13-f8c5aa1bc0f0&displaylang=en)

Now the GAB (Global Address Book) allows you to have a centralized repository of contacts (person and/or organizations), these can be used in many different processes such as Business Relations, Leads, Sales Orders, ect.

Because of this, I came up with an idea to setup a place in the contacts table (and form) where the user can choose to whom send what type of email from Outlook automatically.

Monday, February 7, 2011

SysInfoAction Class - Go to a specific record from the Infolog - Microsoft Dynamics AX 2009

Today I had a requirement that would allow a user to go to a ContactPersonLookup form record from an infolog that would be showed when a user wants to send an email to a contac without an email address.

First I needed to get the ContactPersonId based on the contact's PartyID. The following method takes one parameter (PartyId) and goes trough a simple sql query to get the record I need: