Quantcast
Channel: Dynamics AX – ErpCoder
Viewing all 49 articles
Browse latest View live

Item Journal Approval Workflow

$
0
0

I’ve create an Item Journal Approval Workflow. It can be used to change the default order settings for a journal of items as part of a workflow. The Workflow contains three approval steps, for purchase, inventory management and sales. Each approval sets or clears the stopped flag in the default order settings in the corresponding tab.

ItemJournalApprovalWF

 

Watch the Video at YouTube:

Item Journal Approval Workflow for Dynamics AX 2009

 

Download the Source at Axaptapedia



Color Rows in Enterprise Portal AxGridView

$
0
0

image

  1. Create a new display method webBackgroundColor at InventTable

    public display Color webBackgroundColor()
    {;
        switch(this.ItemType)
        {
            case ItemType::BOM:     return "Red";
            case ItemType::Item:    return "Green";
            case ItemType::Service: return "Blue";
            default: return "White";
        }
    }

  2. Create a new Dataset and add InventTable as DataSource
  3. Create or open a new Dynamcis Ax web project in Visual Studio
  4. Create or open an AxWebUserControl and add an AxDataSource using InventTable data set from AX
  5. Add an AxGridView and link it with the AxDataSource
  6. Add webBackroungColor**, ItemId and ItemName to the grid
    image
  7. Select the AxGridView, change to events and modify the RowDataBound event

    protected void AxGridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        string axColor = e.Row.Cells[0].Text.ToLower();
       
        if(axColor.Equals("red"))
            e.Row.BackColor = System.Drawing.Color.Red;
        else if(axColor.Equals("green"))
            e.Row.BackColor = System.Drawing.Color.Green;
        else if(axColor.Equals("blue"))
            e.Row.BackColor = System.Drawing.Color.Blue;       
    }

  8. Load the user control in an enterprise portal site

Use an Extended Datatype (Color instead of str) for the display method, otherwise you may experience strange behaviour in your ASP.NET application.


Enterprise Portal Custom Filter Error after a short time

$
0
0

Again I experienced a strange behavior within Dynamics AX 2009 Enterprise Portal. I’ve created a AxGridView using an AxDataSource connected to a DataSet in Dynamics AX. The DataSet holds a setFilter method to set values on some QueryBuildRanges. Moreover I’ve create a button in my AxUserControl Webpart that invokes the setFilter method with some values.

protected void SearchButton_Click(object sender, EventArgs e)
{
   string value1 = TextBox1.Text;
   string value2 = TextBox2.Text;
   AxDataSourceMyTable.GetDataSet().DataSetRun.AxaptaObjectAdapter.Call  
    (“setFilter”,value1,value2);
}

public void setFilter(str _value1, str value2)
{;
   qbrSomeField.value(_value1);
   qbrAnotherField.value(_value2);
   MyTable_DS.executeQuery();
}

This implementation worked fine the first time using the webpart. However, after a very short time I got an error telling me that no Business Connector Session was found.

Microsoft.Dynamics.Framework.BusinessConnector.Session.Exceptions.NoKernelSessionException

First I thought of some kind of timeout and played with IIS settings. But Google found this discussion where it is explained that Dynamics AX deletes the QueryBuildRange objects after a very short time, and therefore the call fails. The solution is to use SysQuery::findOrCreateRange .

public void setFilter(str _value1, str value2)
{
   QueryBuildDataSource qbds;
   ; 
   qbds = MyTable_DS.query().dataSourceTable(tableNum(MyTable))
   SysQuery::findOrCreateRange(qbds,fieldNum(MyTable,Field1)).value(_value1);
   SysQuery::findOrCreateRange(qbds,fieldNum(MyTable,Field2)).value(_value2);
   MyTable_DS.executeQuery();
}


Add Sound to Infolog

$
0
0

I’ve been asked by a colleague if it is possible to let the Infolog make a noise depending on the log type, e.g. a *beep* for an info, a *pling* for a warning and an evil noise for an error. Fortunately we can use .NET in AX 2009. The System.Media.SystemSound class already provides access to the typical system sounds. I’ve modified the Info class in AX this way:

Exception add(
    Exception _exception,
    str _txt,
    str _helpUrl = ”,
    SysInfoAction _sysInfoAction = null,
    boolean buildprefix = true)
{

    int numOfLines,i;
    int actionClassId;
    container packedAction;
    xSession session;   

    System.Media.SystemSound sound;
    InteropPermission permission;

    ;

// default infolog code here …

    permission = new InteropPermission(Interopkind::ClrInterop);
    permission.assert();
   
switch(_exception)
    {
        case(Exception::Info):
        sound = System.Media.SystemSounds::get_Asterisk();
        break;
        case(Exception::Warning):
        sound = System.Media.SystemSounds::get_Hand();
        break;
        case(Exception::Error):
        sound = System.Media.SystemSounds::get_Exclamation();
        break;
    }    
    if(sound!=null)
        sound.Play();

    CodeAccessPermission::revertAssert();

    return super(_exception, (buildprefix?getprefix():”)+_txt);
}


Extend SalesTable2Line Framework

$
0
0

Dynamics AX provides a Framework for updating changes made on SalesTable fields to SalesLine fields. The update method can be configured within Dynamics AX at Accounts Receivable > Setup > Parameters > Updates > “Update order Line”. This form is used to configure if and how changes made to the SalesTable are written to the lines. This framework can be extended to update your own fields, like a “Notes” field in the example below.

Dynamics AX 2009 Update Order Lines

  1. Create a new field called "SalesNotes” in the SalesTable and SalesLine
  2. Add the SalesTable.SalesNotes field to the Field Group HeaderToLineUpdate at the SalesTable
    Put Sales Notes field HeaderToLineUpdate group in the SalesTable
  3. Display the new fields in the SalesTable form e.g. in the General tab
  4. Open the SalesTable2LineParameters table in the table browser and remove all records. Don’t worry, these data will be populated automatically and is the basis for the “Update order line” form.
  5. Add the following line to the SalesTable2LineField.lineUpdateDescription method

    case fieldnum(SalesTable, SalesNote):
        return fieldid2pname(tableNum(SalesLine), fieldNum(SalesLine, SalesNote));

    Modify the SalesTable2LineField.lineUpdateDescription method

     

  6. Add a parameter method for the SalesNote field to the AxSalesTable class

    public SalesNote parmSalesNote(SalesNote _salesNote = ”)
    {
        if (!prmisdefault(_salesNote))
        {
            this.setField(fieldnum(SalesTable, SalesNote), _salesNote);
        }

        return salesTable.SalesNote;
    }

  7. Add a parameter method for the salesNote field to the AxSalesLine class

    public SalesNote parmSalesNote(SalesNote _salesNote = ”)
    {
        if (!prmisdefault(_salesNote))
        {
            this.setField(fieldnum(SalesLine, SalesNote), _salesNote);
        }

        return salesLine.SalesNote;
    }

  8. Create a setSalesNote method on the AxSalesLine class

    protected void setSalesNote()
    {
        if (this.isMethodExecuted(funcname(), fieldnum(SalesLine, SalesNote)))
        {
            return;
        }

        this.setAxSalesTableFields();

        if (this.isAxSalesTableFieldsSet() || this.axSalesTable().isFieldModified(fieldnum(SalesTable, SalesNote)))
        {
            this.parmSalesNote(this.axSalesTable().parmSalesNote());
        }
    }

  9. Modify the setTableFields method to call the setSalesNote method
    Call the setSalesNote method
    Test your modification. Open the “Update order line” form and set the update method for Sales Notes to “Prompt”. Open the sales order details form, go to your new field, modify the text and save. A dialog will appear and ask your to update the Note fields. Click OK, and review the Sales Notes in the SalesLines.

Modify the SalesNote value in a sales order

Review the update on the sales line


@Dynamics AX Technical Conference

$
0
0

You can find me at the Dynamics AX Technical Conference in Nice


Use Fulltext Index in AX 2012 to search in RSS feeds

$
0
0

Here is a simple example how to use the fulltext index capability in Dynamics AX 2012. This example downloads RSS postings into a table with fulltext index and runs a query to identify those with specific words.

Create the RssFeedTable

  1. Create a new String Extended Datatype called RssFeedId
  2. Create a new table called RssFeedTable and add the RssFeedId, Name and Uri
  3. Create a primary index based on the RssFeedId
  4. Set the RssFeedTable as Reference at the RssFeedId Extended
  5. Populate the table with data e.g.
    FeedId = technet
    Name = “Technet Austria”
    Uri = http://feeds.feedburner.com/TechnetTeamBlogAustria?format=xml

Create the RssContentTable

  1. Create a new Table called RssContentTable
  2. Add the RssFeedId, Description255 and rename it as Title and a Memo field
  3. Create a fulltext index for the memo field

image image

    Create the RSS Reader Class in C#

    1. Create a new Visual C# class library project for .NET 4.0 in Visual Studio
    2. Add the project to AOT
    3. Copy this code

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel.Syndication;
    using System.Xml;
    using System.Text.RegularExpressions;

    namespace ErpCoder.RssFeed
    {
        public class Reader
        {
            private string xmlAddress = String.Empty;
            private IEnumerator<SyndicationItem> enumerator;

            public Reader(string address)
            {
                xmlAddress = address;
            }

            public void Load()
            {
                var reader = new XmlTextReader(xmlAddress);
                var feed = SyndicationFeed.Load(reader);
                enumerator = feed.Items.GetEnumerator();
            }

            public bool Read()
            {
                return enumerator.MoveNext();
            }

            public string GetTitle()
            {
                return enumerator.Current.Title.Text;
            }

            public string GetDescription()
            {
                string text = Regex.Replace(enumerator.Current.Summary.Text,
                                             "<(.|n)*?>", String.Empty);
                return text;
            }       
        }
    }

    1. Set the Deployment Target at the project to Client: Yes and deploy

    Populate the RssContentTable

    1. Create a find method on the RssFeedTable
    2. Copy this code and substitute the parameter in the find method with one of yours

    static void populateFeedTable(Args _args)
    {
        System.Exception ex;
        RssFeedTable feedTable = RssFeedTable::find("techat");
        RssFeedContent content; 
        ErpCoder.RssFeed.Reader reader;
        InteropPermission permission;
     
        permission = new InteropPermission(InteropKind::ClrInterop);    
        permission.assert();

        try
        {
            reader = new ErpCoder.RssFeed.Reader(feedTable.Uri);
            reader.Load();

            while(reader.Read())
            {
                content.clear();
                content.Title = reader.GetTitle();
                content.Text = reader.GetDescription();
                content.FeedId = feedTable.FeedId;
                content.insert();
            }
        }
        catch(Exception::CLRError)
        {
            ex = CLRInterop::getLastException();
            error(ex.get_Message());
        }

        CodeAccessPermission::revertAssert();
    }

    Create a job to test the fulltext index

    1. Create a new job and copy this code

      static void queryFullText(Args _args)
      {
          RssFeedContent feedContent;
          Query query = new Query();

          QueryBuildDataSource qbdsContent =
           query.addDataSource(tableNum(RssFeedContent));

          QueryBuildRange rangeText =
           qbdsContent.addRange(fieldNum(RssFeedContent,Text),
                                1,QueryRangeType::FullText);
          QueryRun queryRun;
          rangeText.value("Office Hyper-V");

          queryRun = new QueryRun(query);
          while(queryRun.next())
          {
              feedContent = queryRun.get(tableNum(RssFeedContent));
              info(feedContent.Text);
          }
      }

    2. Subsitute the value of the fulltext range value with yours
    3. Test the query

    image


    SSRS: Error when opening design of duplicated report

    $
    0
    0

    When you duplicate an SSRS Dynamics AX 2012 report in Visual Studio, and you try to open the design node you may get an error message like “object instance not set to an object”. The reason is that the data set parameters contain the name of the report e.g. SalesQuotation. Now that you have duplicated the report its name is CopyOfSalesQuotation and the report is broken.

    Broken parameter in duplicated SSRS report

    Compiling the report project brings up a list of errors.

    Errors when compiling a duplicated report

    Navigate to each data set parameter and change the name of the report to match the new name e.g. CopyOfSalesQuotation instead fo SalesQuotation

    Broken parameter in duplicated report

    The fixed parameter should look like this

    Dynamics AX 2012 duplicated report data set parameter

    Finally the report designer is working

    Dynamics AX 2012 duplicated report in report designer



    MCTS: 70-573 SharePoint 2010 Application Development

    $
    0
    0

    image

    On Friday 13th Smiley I was certified for SharePoint 2010 Application Development. Since every Dynamics AX Silver+ Partner need at least on SharePoint guy, I’m the one for InsideAx. I’m already experienced in maintaining SharePoint 2012 (mainly Foundation) for those of our Customers running Rolecenter in AX 2009. Furthermore I’ve upgraded and developed Enterprise Portal applications in the last two years. However, EP development and classic SharePoint development does diverge. Everybody who ever tried to modify EP using SharePoint designer knows what I’m taking about.

    I don’t want to say that all the cool SharePoint features cannot be used to extend Dynamics AX (e.g. I’ve built a web based appointment app using SharePoint and its lists and calendars to visualize the schedules). All those who are now forced to get in touch with SharePoint may experience that it can be used in may cases to provide cool solutions for their customers. But I’d like Microsoft to strengthen the web / enterprise portal development aspect of Dynamics AX by extending the development course materials and provide an Enterprise Portal Certification.


    Dynamics AX 2009: FTP Adapter for AIF

    $
    0
    0

    The Application Integration Framework in Dynamics AX is an extensible framework for data transportation and reception. It support the separation of transport technology (e.g. MSMQ, XML/SOAP Webservices, Filesystem Share) security aspects (services, permissions, transported data) and data manipulation. Creating new adapters to support other transport technologies is simple. Here is an example to support FTP.

    Develop AIF FTP Adapter

    • First, create a new parameter table AifFTPParameters to store FTP server name, user, password and directory (4 strings). Next create a setup form for the AifFTPParameters table and a display menu item. Add an OK command button. Add this code to the buttons clicked event:

      void clicked()
      {;
          super();
          // use the server name as selected value 
          element.closeSelect(Setup_ServerName.text());
      }

      FTP Parameters setup

    • Create a new AifFTPSendAdapter class that implementes the AifSendAdapter interface. You may create empty implementations for begin(), commit(), initialize(), rollback() and terminate(). But you really need to implement the sendMessage() method. I’m using the System.Net Classes to implement the FTP transfer.
       

      public void sendMessage(AifGatewayMessage gatewayMessage)
      {
          System.Text.Encoding encoding;
          System.Byte[] bytes;
          str requestStr = "";
          object ftpo;
          System.Net.FtpWebRequest ftpRequest;
          System.Net.NetworkCredential credential;
          str ftpUser;
          str ftpPass;
          System.IO.Stream requestStream;
          InteropPermission clrPermission =
           new InteropPermission(InteropKind::ClrInterop);
          ;

          clrPermission.assert();

          switch(gatewayMessage.parmEncoding())
          {
              case ‘UTF-8′:
                  encoding = System.Text.Encoding::get_UTF8();
                  break;
              default:
                  throw error("Unsupported Encoding");
          }
          bytes = encoding.GetBytes(gatewayMessage.parmMessageXml());

          requestStr = strfmt(‘ftp://%1′,AifFTPParameters::find().ServerName);
          if(AifFTPParameters::find().Directory)
          {
              requestStr = strfmt(‘%1/%2′,
                                   requestStr,
                                   AifFTPParameters::find().Directory);
          }

          requestStr = strfmt(‘%1/%2%3′,
                                requestStr,
                                gatewayMessage.parmMessageId(),
                                ’.xml’);

          ftpo =  System.Net.WebRequest::Create(requestStr);
          ftpRequest = ftpo;

          ftpUser = AifFTPParameters::find().UserName;
          ftpPass = AifFTPParameters::find().Password;
          //BP deviation documented
          credential = new System.Net.NetworkCredential(ftpUser,ftpPass);
          ftpRequest.set_Credentials(credential);
          ftpRequest.set_ContentLength(bytes.get_Length());
          ftpRequest.set_Method(‘STOR’);

          requestStream = ftpRequest.GetRequestStream();
          requestStream.Write(bytes,0,bytes.get_Length());
          requestStream.Close();

          CodeAccessPermission::revertAssert();
      }

    • Create a new AifFTPAdapter class that implements AifIntegrationAdapter. This class is used by the AIF configuration interface in Dynamics AX to identify an outbound adapter and its configuration form.

      public AifIntegrationAdapterType getAdapterType()
      {;
          return AifIntegrationAdapterType::SendOnly;
      }

      public MenuItemNameDisplay getAddressDisplayMenuItem()
      {;
          // the AifFTPParameter forms display menu items name
          return ‘AifFTPParameters’;
      }

      public AifTransportAddress getCanonicalTransportAddress(AifTransportAddress transportAddress)
      {;
          return transportAddress;
      }

      public MenuItemNameDisplay getConfigurationDisplayMenuItem()
      {;
          return ”;
      }

      public LabelString getLabel()
      {;
          return "AIF FTP Adapter";
      }

      public AifReceiveAdapter getReceiveAdapter()
      {;
          return null;
      }

      public AifSendAdapter getSendAdapter()
      {;
          return new AifFTPSendAdapter();
      }

      public boolean isHosted()
      {;
          return true;
      }

      public void validateConfiguration(AifTransportAddress transportAddress,
                                        AifChannelDirection channelDirection)
      {;
          //TODO:Check or throw error
      }

        1. Register FTP Adapter and configure AIF

      1. Go to Basics > Setup > Application Integration Framework.
      2. In Local Endpoints make sure you have an endpoint configured
      3. In Transport Adapters create a new record, select AifFTPAdapter and mark it as active.
      4. In Channels, create a new outbound FTP Channel, provide server name and credentials.
        Mark the channel as active.
        Configure AIF FTP Adapter 
      5. In Services activate the SalesSalesInvoiceService
        Activate SalesSalesInvoiceService 
      6. In Endpoints create a new endpoint. Set the outbound channel to your FTP channel and set the local endpoint. Go to the Constraints tab and set “No Constraints” flag. Mark the endpoint as active.
        Create an endpoint with outbound FTP

        Click the Action Policies button and add the SalesSalesInvoiceService.read method
        Activate SalesSalesInvoiceService.read

        Click the Data Policies button and use the set button to enable all data fields for transportation.
        Set data policies for invoice

      7. Go to Basic > Inquiries > Batch jobs. Make sure to run a batch job that processes the AIF message send and receive tasks: AIFInboundProcessingService, AIFOutboundProcessingService, AIFGatewaySendService and AIFGatewayReceiveService.
        Setup AIF processing batch jobs
      8. Go to Accounts Receivable > Inquiries > Journals > Invoice. Select an invoice and use the Send Electronically button to put it in the transportation queue.
        Send invoice electronically using AIF
      9. Wait a few miniutes and take a look at your FTP space. There you should see the transmitted invoices as xml file.
        Invoice successfully uploaded

      Send SSRS Report as Email

      $
      0
      0

      The SSRS Report Viewer in AX 2012 does not have a built in Email function. However, there are some implementations available to add an email button in SharePoint or ASP.NET pages, e.g. Codeproject . The idea is simple, save the report as PDF, open outlook email and add the PDF file as attachment. Follow these steps to implement an Email button for Dynamics AX.

      In the AOT add a reference to the Microsoft.Reporting.WinForms DLL. It contains the SRS Report Viewer class. The DLL can be found here: C:\Program Files (x86)\Microsoft Visual Studio 10.0\ReportViewer. Make sure you are using the corresponding assembly version as your SQL Server.

      Open the SrsReportViewer Form in the AOT, and add a button to the ButtonGroup. Call it “SendReport”.

      image

      Add the following Code to the clicked method:

      void clicked()
      {
          Microsoft.Dynamics.AX.Frameworks.Controls.ReportViewer.AxReportViewer axviewer;
          Microsoft.Reporting.WinForms.ReportViewer nviewer;
          Microsoft.Reporting.WinForms.LocalReport report;
          System.Exception ex;
          System.Array bytear;
          System.Object no;
          System.IO.File file;
          str tmpPath;
          System.IO.FileStream fs;
          SmmOutlookEmail smmOutlookEmail = new SmmOutlookEmail();
          super();

          axviewer = AxReportViewer.control();
          nviewer = axviewer.get_ReportViewerControl();
          try
          {
        
              //render as PDF
              report = nviewer.get_ServerReport();
              bytear = report.Render("PDF");
              no = bytear;

              //path to temp. files
              tmpPath = System.IO.Path::GetTempPath();
              tmpPath = tmpPath + "report.pdf";


              //save to file
              fs = System.IO.File::Create(tmpPath);
              fs.Write(no,0,bytear.get_Length());
              fs.Flush();
              fs.Close();

              //open outlook email
              if (smmOutlookEmail.createMailItem())
              {
                  smmOutlookEmail.isHTML(true);
                  smmOutlookEmail.addFileAsAttachment(tmpPath);
                  smmOutlookEmail.sendEMail(smmSaveCopyofEmail::No);
              }

          }
          catch(Exception::CLRError)
          {
              ex = CLRInterop::getLastException();
              info(ex.ToString());
          }
      }

      Save, Compile and open a report. Enlarge the “Options” and you’ll see the new Email button.

      image

      By clicking the Email button, the report is rendered as PDF, stored locally in your temp. files and attached to a new outlook email.

      image

      This is a very simple implementation. You may add more customizations, e.g. take the report parameters into account to initialize the TO and CC Email fields.


      Windows Mobile & CE

      $
      0
      0

      They say Windows Mobile is dead. I agree, its dead on the mobile phone market. However Mobile and CE legacy OS’ are still relevant to develop mobile applications on barcode reader and RFID reader / writer devices. Just to mention Smiley ..

      scanner


      Metadata Service Exception: Option with ID -1 unknown

      $
      0
      0

      A colleague started to develop a report in Visual Studio and experienced a strange exception when selecting a query as dataset. It said that an exception occurred in the metadata service >SOMEFIELD option with ID -1 was not recognized

      image

      A look at the table being part of the query reveled the reason for this problem. The filed on the table is based on an extended datatype, but this datatype was deleted a while ago. However on a first look the field looks okay.

      image

      The table does compile without errors and incremental IL succeeds(!)

      image

      As soon as your select the fields enum property in the property window, you’ll see that the datatype is missing.

      image

      Set the compiler level up to 4 in order to get best practice errors displayed. It tells your that the field has an unknown type (BP:100) and that each field should be defined using a type.

      image


      Create a PowerPivot BI Application for AX Project Postings

      $
      0
      0

      PowerPivot is a great extension for Excel to realize BI applications in very short. For Excel 2010 download and install the free PowerPivot extension. PowerPivot ist built in with Excel 2013. To activate PowerPivot go to File > Options > Addins > Choose COM Addins > activate PowerPivot.

      PowerPivot Tab in Excel 2010

      Load Data

      Open PowerPivot Window > External Data > SQL Server. Provide Credentials to access Dynamics AX database. Select PROJTABLE, PROJJOURNALTRANS, HCMWORKER and DIRPARTYTABLE. For each table open the preview and select the following fields.

      ProjTable ProjId Name DataAreaId        
      ProjJournalTrans ProjId CategoryId Txt Qty Transdate Worker DataAreaId
      HcmWorker Person RecId          
      DirPartytable Name RecId          

      In the import wizard set a filter on the DataAreaId for PROJTABLE and PROJJOURNALTRANS on CEU

      PowerPivot Data Import

      After the tables have been imported, create relations between these tables. Back in the PowerPivot window > Relations > Manage Relations create these relations.

      • ProjJournalTrans[PROJID] to ProjTable[PROJID]
      • ProjJournaltrans[WORKER] to HcmWorker[RECID]
      • HcmWorker[PERSON] to DirPartytable[RECID]
        Data Model in PowerPivot
        In the PowerPivot window select PROJJOURNALTRANS table and on the right side after the last column select the new empty column. Write =YEAR(‘PROJJOURNALTRANS’[TRANSDATE]) in the formula text field. Rename the new calculated field to YEAR. Add a second calculated column =MONTH(‘PROJJOURNALTRANS’[TRANSDATE]) and rename to MONTH

      Calculated Field in PowerPivot

      Create the first pivot table

      Close the PowerPivot windows and return to Excel. From the PowerPivot tab create new pivot table. Place the PROJJOURNALTRANS[QTY] field in the right lower Values box. Place PROJTABLE[NAME] and PROJJOURNALTRANS[CATEGORYID] in the rows box. Place PROJTABLE[NAME] and PROJJOURNALTRANS[CATEGORYID] in the vertical slicer box. Place PROJJOURNALTRANS[YEAR] and PROJJOURNALTRANS[MONTH] in the columns box and horizontal slicer.

      Pivot Table based on Dynamics AX Data

      Create charts

      From the PowerPivot tab open the PowerPivot table dropdown, select 2 charts vertical and place them in a new sheet. For both charts place the PROJJOURNALTRANS[QTY] in the lower right values box. For the first diagram place the PROJTABLE[NAME] field in the columns box. In the second diagram place the DIRPARTYTABLE[NAME] in the rows box. Now there are two diagrams, postings per employee and postings per project. Place PROJTABLE[NAME], PROJJOURNALTRANS[CATEGORYID] and DIRPARTYTABLE[NAME] in the vertical slicer. Place PROJJOURNALTRANS[YEAR] and PROJJOURNALTRANS[MONTH] in the horizontal slicer.

      Dynamics AX Project Postings per Project and per Employee

      Connect Slicer to other sheets

      Select the YEAR slicer, from the context menu open the pivot table connections. Connect the slicer to the other pivot table created earlier. By connecting the slicer a selection made on one sheet also effects the other sheet.

      PowerPivot Slicer

      Create Measures and define a KPI

      From the PowerPivot tab, PowerPivot table dropdown create a new simple pivot table on a new sheet. Place the DIRPARTYTABLE[NAME] field in the rows box. Place the PROJJOURNALTRANS[YEAR] in the horizontal slicer On the fieldlist select the PROJJOURNALTRANS table and create a new measure from the PowerPivot tab. Call the measure M_TOTAL and use the formula  =sum(PROJJOURNALTRANS[QTY])

      PowerPivot Measure posted Qty

      Create a second measure on the PROJJOURNALTRANS table called M_ABSENCE. This will be the sum of all postings made on project HOLIDAY (PROJID 50002) and ILLNESS (PROJID 50003). Use the formula
      =CALCULATE(sum([QTY]);PROJJOURNALTRANS[PROJID] = "50002" || PROJJOURNALTRANS[PROJID] = "50003") .

      PowerPivot Measure posted Qty on Holiday or Illness

      On the fieldlist, select the measure M_ABSENCE in the PROJJOURNALTRANS table. From the PowerPivot tab, create a new Key Performance Indicator (KPI) based on the M_ABSENCE Measure. Select the M_TOTAL as target. Choose green > yellow > red color schema. Define green to be from 0 – 5 percent, yellow from 5 to 10 percent and red to all above.

      PowerPivot KPI

      The pivot table with KPI should look like this

      PowerPivot table with KPI


      UserSessionService/GetPartitionKey

      $
      0
      0

      When you upgrade from Dynamics AX 2012 RTM / FP to R2 and start upgrade your reports in Visual Studio, your might run into an error telling you that the GetPartitionKey action was not found in the UserSessionService.

      GetPartitionKey action not found

      Partitions were introduced in R2 and therefore the UserSessionService has changed and got new methods. However, the WSDL interface definition is the old one and you need to update the interface description.

      AifUserSessionService in AX 2012 RTM and FP AifUserSessionService in AX 2012 R2
      AX 2012 FP AX 2012 R2

      If you want to check the actual interface description you might want to look at the WSDL itself. The URL can be found at AX > System Administration > Services and AIF > Inbound Ports > User Session Service > WSDL URI

      UserSessionService in Dynamics AX 2012 R2

      You might open the XML and go all the way through the files until you got the operations, or just feed the URL to Visual Studio. Create a new C# console application, add a service reference and provide the URL. If your WSDL definition is out of date your service reference looks like this.

      Check the UserSessionService WSDL in Visual Studio

      Go back to Dynamics AX development environment. Compile the AifUserSessionService class in X++ and incremental IL. Make sure there are no errors in your application. Go to the services node in the AOT and select the AifUserSessionService. From the context menu click Add Ins > Register Service. Go to the service group node in the AOT. Select the UserSessionService group. From the context menu click Deploy Service Group. You will see the infolog popping up telling you that the .NET artifacts have been generated and deployed.

      Deploy the UserSessionService group

      Go back to Visual Studio and refresh the service reference. The service has the same WSDL URL as before but the inferface has changed. Now you should see more methods including the GetPartitionKey.

      Check the UserSessionService WSDL in Visual Studio



      Enterprise Portal Installation fails due not enough memory

      $
      0
      0

      A typical Dynamics AX 2012 (R2) installation requires lot of RAM to work properly. Especially SharePoint, the basis for Role Center and Enterprise Portal want’s lot of it. I came across an issue where EP installation failed. The DynamicsSetupLog.txt revealed the issue; an exception at the SecurityTokenService.

      The service ‘/SecurityTokenServiceApplication/securitytoken.svc’ cannot be activated due to an exception during compilation.The exception message is: Memory gates checking failed because the free memory (723009536 bytes) is less than 5% of total memory

      There are some blogs regarding this issue: Restart NodeRunner, Set the App Domain, Configure minFreeMemoryPercentageToActivateService . The simplest solution however is to provide more memory Smiley


      Create a PowerPivot BI Application for AX Project Postings (Update)

      $
      0
      0

      This is an update on the first posting how to create a PowerPivot Application for Dynamics AX. These are the changes and updates:

      • Excel 2013
      • XML Data Feeds instead of SQL
      • Timeline Filter instead of calculated fields

        Create and Publish Data Access Services

        You can publish Dynamics AX queries as open data feed. In contrast to direct SQL access it gives you more control on what is published because the builtin Dynamics AX security layer is used. Furthermore the data is delivered as XML and can easily be processed by other applications  Create three queries using these datasources and fields:

        Datasource            
        ProjTable ProjId Name        
        ProjJournalTrans ProjId CategoryId Txt Qty Transdate Worker
        HCMWoker join
        DirPerson
        Person RecId from HCMWorker Name      

      HcmWorker join DirPerson

      Go to Organization Administration > Setup > Document Management > Document data sources. For each of the queries create a new entry using Module “Project” and Type “Query Reference”. Choose your query from the dropdown and activate them.

      Document Data Sources

      You can check your services by opening the ODataService URL in your Browser. Depending on the name of the Server and Ports it might look like this http://localhost:8101/DynamicsAx/Services/ODataQueryService. You should see three available data services.

      ODataFeed collections

      You can load the data by adding /COLLECTION_NAME to the URL. For example http://localhost:8101/DynamicsAx/Services/ODataQueryService/ERPProjTable to view the data from the ERPProjTable collection based on the ERPProjTable query.

      Projtable ODataFeed

      Build the Data Model

      PowerPivot and PowerView reports are builtin with Excel 2013. However, these addins need to be activated manually. Go to File > Options > Addins > Dropdown COM Addins. Activate PowerPivot and PowerView.

      Active PowerPivot and PowerView

      Go to PowerPivot Tab > Manage > Get External Data From Data Service. In the wizard copy the data service URL (without collection name) and click next. Select the data feed collections and finish the import

      Import Dynamics AX ODataFeed in Excel

      Switch to the Diagram View using the small button on the right bottom. Create the relations between the tables by drag and dropping the related fields. ProjTable.ProjId on ProjJournalTrans.ProjId and ProjJournalTrans.Worker on HcmWorker.RecId

      PowerPivot 2013 Relations

      Switch back to Excel. From the PowerPivot tab, select Calculated Fields and create 2 new calculated fields. One for the Qty sum and another sum of postings on project Holiday and Illness.

      • sum(ERPProjJournalTrans[ProjJournalTrans_Qty])
      • CALCULATE(sum(ERPProjJournalTrans[ProjJournalTrans_Qty]);
        ERPProjTable[ProjTable_ProjId] = "50002" || ERPProjTable[ProjTable_ProjId] = "50003")

       image

      Create a KPI to visualize Absence vs. Productive

      In the PowerPivot Tab, create a new KPI. Use the C_Absence as base value and the C_Total as Target value. Change the color scheme to Gree-Yellow-Red and set the sliders to 5% and 10%.

      image

      Go to Insert Tab, from the Tables Group select PowerPivot Table. In the Dialog select “External Datasource”. Switch to Tables and use Workbook Data Model.

      image

      Select the ERPWorker and drag the DirPers_Name field in the rows. Select the ERPProjJournalTrans and drag the C_Total calculated field in the Values box. Expand the C_Absence KPI. Drag the Value(C_Absence) and the Status in the values box.

      image

      Go to the Analyze Tab (only visible if the pivot table is selected), from the group Filter, create a new Timeline Filter and select the ProjJournalTrans_TransDate field. Place the Filter above the table (or wherever your want)

      image


      BI Service Error: SSASFrameworkService not generated, Instance of ‘SysSecRole’ could not be created

      $
      0
      0

      I recently faced another problem with SSRS reports. The BI Service (Administration > Setup > AIF > Incoming Ports) was down and could not be activated. Trying to re-activate the service resulted in an error telling me that the SSASFrameworkService could not be generated because an instance of service class “SysSecRole” could not be generated. AOS restart and Full IL Compilation didn’t solve the problem.

      However, the solution was to re-deploy the AIF Service Group: AOT > Service Groups > BI Service > Context Menu > Deploy Service Group. Afterwards the BI Service could be activated and reports were working again.


      Use .NET Assemblies in Dynamics AX 3.0 via COM

      $
      0
      0

      Dynamics AX 3.0 Axapta.NET is great and since version 4.0 it can be used in Dynamics AX. However, some customers may still run an older version like 3.0 which makes it difficult to integrate AX with other applications. To use .NET assemblies in Dynamics AX 3.0 they have to be COM visible. There are good tutorials online like Mikes Odds and Ends. This article follows the steps presented by Mike to integrate a C# class library that creates HTML code in AX 3.0 SP6.

      Code in Visual Studio / C#

      1. Create a new project in Visual Studio
      2. Create a public interface called IHTMLHelper and add a method createHeader(int size,string text)

        namespace ERPCoder
        {
            public interface IHTMLHelper
            {
                string createHeader(int size, string text);
            }
        }

      3. Create a new class and name it HTMLHelper that implements IHTMLHelper
      4. Add a public empty constructor
      5. Add the namespace System.Runtime.InteropServices
      6. Mark the class as [ClassInterface(ClassInterfaceType.None)]
      7. Mark the class and createHeader() method as [ComVisible(true)]

        using System;
        using System.Collections.Generic;
        using System.Text;
        using System.Runtime.InteropServices;

        namespace ERPCoder
        {
            /// <summary>
            /// HTML Helper class
            /// </summary> 
         
            [ClassInterface(ClassInterfaceType.None)]
            [ComVisible(true)]

            public class HTMLHelper : IHTMLHelper
            {
                public HTMLHelper()
                {
                }

                /// <summary>
                /// Creates a HHTML header line
                /// </summary>
                /// <param name="size">Header size between 1 and 6</param>
                /// <param name="text">Header text</param>
                /// <returns>HTML header line</returns>
                [ComVisible(true)]
                public string createHeader(int size, string text)
                {
                    if (size < 1 || size > 6)
                        size = 6;

                    return String.Format("<H{0}>{1}</H{0}>", size, text);
                }
            }
        }

       

      Modify the Visual Studio Project properties

      1. In Visual Studio open the projects properties from the context menu on the project node in the solution explorer
      2. In the Application Tab open the Assembly Information Dialog enable the COM Visible Property
        Make assembly COM visible
      3. In the Build Tab change the architecture to x86 and enable the Register for COM Interop property
        set x86 and register for COM
      4. In the Build Event add the regasm call as Post-Build event
        %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\regasm $(TargetFileName) /tlb:$(TargetName).lib
      5. Build the project

       

      Include COM in Dynamics AX 3.0

      1. In Dynamics AX 3.0 open from the Menu > Tools > Development Tools > Wizards > COM Class Wrapper Wizard
      2. Click on Browse Button and navigate to the Visual Studio Build Directory
      3. Select the .tlb File and click Next
        Select .TLB in Axapta COM Wrapper Wizard 
      4. Provide a Prefix e.g. ERP
        Provide Prefix in Axapta COM Wrapper Wizard
      5. AX creates two classes to wrap the Interface and implementation class
        Generated COM Wrapper classes in Axapta

      Test COM Object

      Create a new job, that uses the wrapper class and call the createHeader() method
      Test COM Wrapper in X++


      Visualize geographic distribution of sales and animate over time in Excel 2013

      $
      0
      0

      Excel provides great BI features for end users and professionals. Loading, transforming and presenting data can easily be done with PowerView and PowerMap. This is an example to visualize Dynamics AX sales data.

      Dynamics AX sales data in PowerMap

      Prerequisites

      Provide Data via ODataFeed

      1. Open Dynamics AX 2012 R2 development workspace
      2. Create a new Query called ERPCustInvoiceJour
      3. Add the CustInvoiceJour as datasource, set the Fields Dynamic property to false
      4. Add InvoiceAmount, InvoiceDate and CustGroup to the field list
      5. Add the LogisticsPostalAddress
      6. Add the CountryRegionId and City to the field list
      7. Set the Relations property to No
      8. Add a new relation manually, clear the Field and Related Field property but select InvoicePostalAddress_FK

      image

      In Dynamics AX Application workspace go to Organisation Administration > Setup > Document Management > Document Data Sources. Create a new record for module “Sales and Marketing”, type Query Reference for ERPCustInvoiceJour query. Enable the data source.

      image

      Open the ODataFeed in a browser, depending on the server name and AOS Port it should look like this http://localhost:8101/DynamicsAx/Services/ODataQueryService/ERPCustInvoiceJour

      image

      Enable PlugIns

      1. Open Excel and go to File > Options > Add Ins > COM Add-ins > Go…
      2. Enable PowerPivot, PowerView and PowerMap

      image

              Create Map

            In Excel go to DATA > From other sources > Data Feed > provide the URL from Dynamics AX data feed. Load the data in Excel. go to INSERT > Map. Set the LogisticsPostalAddress_City as Geography field and click next.

          image

          Leave the Type as Column. Set the CustInvoiceJour_InvoiceAmount as Height for the Column. Set the CustInvoiceJour_CustGroup as Category and CustInvoiceJour_InvoiceDate as Time.

          image

          Run the map time line and watch where and when sales takes place. Watch the implementation in this short video


          Viewing all 49 articles
          Browse latest View live