Tuesday, March 15, 2011

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

One of the great features of Dynamics AX is the rich integration with other applications or services. The Dynamics AX client is for example exchanging data with Microsoft Office applications like Microsoft Office Excel or Microsoft Office Outlook. Some of these interactions are performed using COM. When the Dynamics AX Client is using COM for the data exchange in certain situation it can happen you are getting confronted with one of the following error message:
  • Error executing code: The method has been called with an invalid number of parameters
  • The number of arguments provided is different from the number of arguments accepted by the method
Certain situations means, that you are not always getting this error message but only sometimes and the error is not reproducible. The chance of getting this error message is higher when you continue to work in other applications while the Dynamics AX client is performing the COM operation.
One reason for running into this issue can be if the Windows Operating System is replacing the Dynamics AX application window by a ghost window.
When Dynamics AX starts a lengthy COM operation, it is not responding to messages sent by the Windows Operating System in time. So Windows supposes Dynamics AX has stopped responding. When this happens the Dynamics AX application window is replaced by a ghost window until Dynamics AX resumes. Window ghosting is a nice feature that allows the user to minimize, move or close the main window even if the application is not responding. You can easily identify a ghost window as it shows (Not responding) in the window title.
Unfortunately the replacement of the Dynamics AX application window by the ghost window can interfere the COM operation and result in the above error message.
Therefore it can be helpful to turn window ghosting for the Dynamics AX Client off:
  1. Locate the Dynamics AX shortcut in the Windows Start Menu
  2. Click with the right mouse button on the shortcut and select Properties
  3. Go to the Compatibility tab
  4. Enable the checkbox Run this program in Compatibility mode for and select Windows XP (Service Pack 2)
Please note:
  • We have seen this issue most on Windows Vista and Windows Server 2008 but this issue is not limited to those two
  • Window ghosting is not the only cause of this issue, so you might continue to see the error message even if window ghosting was turned off
But sometime there exists several possibilities resulting in this situation and disabling Window Ghosting has proven as workaround in some of those. By now we have found some other workarounds as well. But so far there is no once for all solution.
Here are the workarounds we know so far...

Workaround 1: Disable Window Ghosting as described in this post.

Workaround 2: Debug the X++ code down to the line that is causing the error. Once identified, insert one line before this statement a call to the yield method of the xInfo class.
  Example:  infolog.yield();
  namespace = outlook.getNamespace(#mapidef);


Workaround 3: Debug the X++ code down to the line that is causing the error. Once identified, place the statement inside a try / catch block. In the catch block simply retry the operation.
  Example:  int retryCount = 3;
  //...

  try
  {
     namespace = outlook.getNamespace(#mapidef);
  }
  catch(Exception::Error)
  {
     retryCount--;

     if(retryCount > 0)
        retry;
     else
        throw(Exception::Error);
  }




Monday, March 7, 2011

Dynamics AX - code to Read/Write data to excel

Writing Data to Excel file
How it works
1. Use SysExcelApplication class to create excel file.
2. Use SysExcelWorkbooks and SysExcelWorkbook to create a blank workbook(by default 3 worksheets will be available).
3. Use SysExcelWorkSheets to select worksheet for writing data.
4. SysExcelCells to select the cells in the excel for writing the data.
5. SysExcelCell to write the data in the selected cells.
6. Once you done with write operation use SysExcelApplication.visible to open
file.

static void Write2ExcelFile(Args _args)
{
InventTable inventTable;
SysExcelApplication application;
SysExcelWorkbooks workbooks;
SysExcelWorkbook workbook;
SysExcelWorksheets worksheets;
SysExcelWorksheet worksheet;
SysExcelCells cells;
SysExcelCell cell;
int row;
;
application = SysExcelApplication::construct();
workbooks = application.workbooks();
workbook = workbooks.add();
worksheets = workbook.worksheets();
worksheet = worksheets.itemFromNum(1);
cells = worksheet.cells();
cells.range('A:A').numberFormat('@');
cell = cells.item(1,1);
cell.value("Item");
cell = cells.item(1,2);
cell.value("Name");
row = 1;
while select inventTable
{
row++;
cell = cells.item(row, 1);
cell.value(inventTable.ItemId);
cell = cells.item(row, 2);
cell.value(inventTable.ItemName);
}
application.visible(true);
}

Reading Data from Excel File

static void ReadExcel(Args _args)
{
SysExcelApplication application;
SysExcelWorkbooks workbooks;
SysExcelWorkbook workbook;
SysExcelWorksheets worksheets;
SysExcelWorksheet worksheet;
SysExcelCells cells;
COMVariantType type;
int row;
ItemId itemid;
Name name;
FileName filename;
;
application = SysExcelApplication::construct();
workbooks = application.workbooks();
//specify the file path that you want to read
filename = "C:\\item.xls";
try
{
workbooks.open(filename);
}
catch (Exception::Error)
{
throw error("File cannot be opened.");
}
workbook = workbooks.item(1);
worksheets = workbook.worksheets();
worksheet = worksheets.itemFromNum(1);
cells = worksheet.cells();
do
{
row++;
itemId = cells.item(row, 1).value().bStr();
name = cells.item(row, 2).value().bStr();
info(strfmt('%1 - %2', itemId, name));
type = cells.item(row+1, 1).value().variantType();
}
while (type != COMVariantType::VT_EMPTY);
application.quit();
}