Periodic Processing in Microsoft Dynamics AX, Part II

 
    引用自: http://msdn.microsoft.com/en-us/library/bb456475.aspx

Patrick G. Hodo
Chief Technical Officer
Red Maple Press, Inc.
Red Maple Technologies, Inc.

September 2006

Applies to:
   Microsoft Dynamics™ AX

Summary: This article describes advanced periodic (job-based) processing within Microsoft Dynamics AX. It is the second of two articles about processing. To read the first article, see Period Processing in Axapta, Part I. (16 printed pages)

The reader should be a beginning to midlevel X++ programmer, and be familiar with the Runbase and RunbaseBatch classes. Programmers in general should have some X++ training and be familiar with programming concepts such as inheritance and object-oriented programming (OOP). Knowledge of Microsoft Dynamics AX is assumed.

Contents

Introduction
Overview of Periodic Processing
Advanced Periodic Processing in Microsoft Dynamics AX
   Creating an Advanced Query in a Runbase Class
   Advanced Techniques for Dialog Boxes
Best Practices within Period Processes
Conclusion

Introduction

This article shows you advanced topics regarding periodic processing within Dynamics AX. In particular, after you read this article, you will be able to create:

  • Runtime queries
  • Advanced dialog box features

Download a blank template to help you create your own periodic classes from http://download.microsoft.com/download/3/f/5/3f570978-2b8c-412f-b6a5-364104d7e2e4/axp_PerProcessingP1.exe.

In Periodic Processing in Microsoft Business Solutions—Axapta, Part I, you received an introduction about periodic processes. It covered how to use the Runbase and RunbaseBatch classes and explored how to gather input from users, interpret data and process that data.

Note   To use the example code, you must select Configuration Key "Commissions." The strings are in English rather than label IDs (for example, "Commission" rather than "@SYS71025") to make the code more readable.

Overview of Periodic Processing

After you have been programming on periodic processes, it becomes apparent that there is much more functionality available than only taking user input and processing data. You might have noticed that some other periodic process classes are more advanced in their use of gathering user input, processing data, or performing other tasks. With advanced functionality, however, come frustrations and difficulties.

This article will help you take advantage of that advanced functionality. As an additional benefit, you can use much of the advanced functionality elsewhere in Microsoft Dynamics AX. Some, but not all, of the advanced functionality covered in this article stays within the context of the Runbase and RunbaseBatch classes.

Advanced Periodic Processing in Microsoft Dynamics AX

This article shows you how to create advanced functionality in the following areas:

  • Custom queries within a Runbase class
  • Advanced techniques for dialog boxes
  • Best practices within those classes

Creating an Advanced Query in a Runbase Class

In Part I of this article, you used a query to retrieve data based on the user’s input. That input was dependent on the user clicking Select on the form. After clicking Select, a query dialog box is displayed that enables the user to input specific criteria.

The query that was displayed was based on the New method and is specified in the line:

queryRun = new QueryRun(querystr(inventTable));

The line created a query called InventTable that is already defined in the Application Object Tree (AOT). Creating pre-existing queries is very quick and convenient. At times, however, using a pre-existing query can be limiting. Creating your own query at runtime will give your class flexibility and less dependency on other objects.

To create a runtime query:

  1. Declare two additional variables in the ClassDeclaration method of your class.
      Query      q;             //Query for advanced  functionality
      QueryBuildRange   qbr;   //Used for additional parameters later
  2. Replace the queryRun code in the New method with the following lines:
    q = new Query();
    q.addDataSource(tablenum(inventTable));

    At this point, you are changing the way that the class gathers data. Instead of relying on a standard query that is defined in the AOT and that is run automatically by using the queryRun object, a query written in X++ is created. This query needs additional definition, which you must provide. The overall functionality of the class has not changed. In fact, it runs the same as before.

    Because the queryRun object is not actually run until the method queryRun.next() is called, you can continue to add to the query until the method is called. For example, if your query includes default parameters (something you can do in a standard AOT query), you can also add parameters in the New method.

  3. Update this line in the New method:
    Qbr=q.addDataSource(tablenum(inventTable)).addRange(inventTable,itemType));

    There are more elaborate ways to create a range in a query. However, for now you are simply adding a filter to the query, which is called a “range” within a query. All that remains to complete the query is for you to insert the value for this range.

  4. You can enable the user to enter data that is actually not a part of the standard query. In other words, you may want to translate an entered parameter into something more meaningful. For instance, in this example, you may want to enter a check box that enables the user to select all items that are not BOM items.

    In a standard query, the user would have to either enter Item and Service into the ItemType field in the query, or !BOM. This is not very user friendly. Instead, you can create a checkbox that enables the user to select the functionality, which is more efficient for the user.

    To add a value to the range that you defined in the New method, add a user input field. Most of the instructions for adding an input field and a new dialog box are covered in Part I of this article and will not be repeated here. In this example, you add a new check box in the Exclude BOMs dialog box. In the example below, that value is stored in a variable called NoBOM.

    In the Run method, take the input from the user and add it to the query. Add this line:

    If (noBOM == NoYes::Yes)
    {
    Qbr.value(enum2str(ItemType::Item) + “,” +   enum2str(ItemType::Service));
    }

You have now added default parameters. The code examines the value of the dialog box to determine whether the parameter is selected. If it is, values are added to the range that you added in step 3. If it is not selected, the code ignores the range and returns all the values in the query.

Because the possible choices within a query are extensive, this article cannot account for them all. However, with some work, your periodic class can return a sophisticated dataset with very little programming.

Advanced Techniques for Dialog Boxes

The first article in this series covered how to collect data from the user. This article extends this to include dialog boxes that display fields and groups that organize the parameters from a user. These fields and groups are relatively easy to create.

Creating dialog boxes

Dialog boxes inherit their methods and properties from the DialogRunBase class. You may have noticed in the first article that the dialog method instantiated this class to create its properties:

DialogRunBase   dialog = super();

Two things happen here:

  • You declare and instantiate the DialogRunBase class, which opens some methods and properties.
  • You instantiate that class within the RunBase framework. You can now add fields to the DialogRunBase class and have those fields be a part of your periodic process.
Best practices for adding groups and fields

Best practices for periodic processes are:

  • When you create more than one logical set of fields, always create a group of dialog box fields. Even if you create two separate fields, as you did in the first article, the RunBase class automatically enforces best practices by grouping the fields under the Parameters heading. However, it is best to create your own groups to ensure that the organization is clear.
  • Separate groups of fields by function. By presenting groups of fields to users, you enable them to more easily find a particular field.

To create groups of fields within a periodic process, modify the dialog method by using the following steps:

  1. Add a semicolon under the declaration in the class:
    DialogRunBase   dialog = super();
    ;

    This may seem very detailed and unnecessary. However, if you do not add this semicolon, the remainder of the code in this section does not compile. By using the separating semicolon, you can save yourself many frustrating hours hunting through code.

  2. Add the following code to create a dialog group:
    Dialog.addGroup(“Properties”);

    Unless you create a new group, all fields that follow this statement are part of the group that you just created.

  3. Add the following code under the dialogNewField line:
    Dialog.addGroup(“BOM’s”);
    dialogNoBOM = dialog.addField(typeId(NoYes), “No BOM’s”, “Select to exclude BOM’s from the SPIFF”);

    This code simply adds another group for you to use. Notice that you use the Label and Help text properties to make it easier for users to understand what you are trying to accomplish. Therefore, another best practice is:

  • Always include Label and Help text information for users.
Adding other items to the dialog box

You do not have to stop at dialog groups and fields within your periodic process. You can add other helpful objects such as:

  • Menu items: Sometimes it is useful to add a menu item to take the user to a screen for reference. In this example, it would be helpful for the user to be able to view commission items as a group in order to see what already exists. To enable the user to do this, you can add a Commission Item Group button by adding the following code:
    Dialog.addMenuItemButton(MenuItemType::Display, “CommissionItemGroup”, “View commission items”, 
       “Use for quick lookup”);

    The code here defines what type of menu item (button) that you are creating, the name of that menu item, and its description. When you open the periodic process, you should see the button in the dialog box under the Select button.

  • Text items: Adding text to a dialog box can be useful when you need to convey information to the user. In many cases, the text box creates a way to provide clarification on a form. For example, you can create a text area that states Click OK to update the information in the tables listed. To add this text to the dialog box, type the following code:
    Dialog.addText(“Click Ok to update the information in the tables listed:”);
Removing the Select button

When a dialog box opens from your periodic process, there is a Select button on the right side of the form. Sometimes, you do not want users to alter the query that you have created. In these cases, modify the showQueryValues method to the following:

Return false;

This code informs the RunBase class that the query should be static.

Clearing selections and setting defaults

You may want to enable users to click a button to clear all their choices or to set a number of defaults that you define. In both cases, you simply add each of these methods to the class to enable the behavior described:

protected Boolean showClearButton()
{
  return true;
}

- or -

protected Boolean showDefaultButton()
{
  return true;
}

In both cases, a button appears in the dialog box. However, this is only half of what is required. To capture the results of the button that is being clicked, you must also add the following methods:

public void dialogClear()
{
   // Add code to perform your clearing mechanism
super();
}
public void dialogDefault()
{
  super();
}

By adding your own code, you can clear or populate the dialog boxes that you previously created.

Best Practices within Periodic Processes

When you manipulate data within a periodic process, it is a best practice to inform your users what is happening. If you do not inform them, they may think that nothing is happening.

Microsoft Dynamics AX has two ways to convey information to users while they are performing tasks:

  • The startLengthyOperation and endLengthyOperation methods
  • The Progress class

With each of these, you can convey information to the user that something is happening during the process.

Hourglass

By using the startLengthyOperation and endLengthyOperation methods, you can control how the cursor displays to the user. The startLengthyOperation method turns the cursor into an hourglass. The hourglass conveys to the user that a process is occurring and that they must wait for it to complete. Without it, the user may see a typical cursor while your process runs. When a system is unresponsive and the hourglass does not display, the user may conclude that the system is not responding and try to reboot. This can compromise incomplete processes.

To use these methods, insert them at the beginning and end of the run method in your class:

..
startLengthyOperation();
..
endLengthyOperation();
..

In both cases, the methods are part of ClassFactory in Microsoft Dynamics AX and therefore do not need to be instantiated to work.

Progress class

Although it is easy to use, new Microsoft Dynamics AX users often do not take advantage of the Progress class. The Progress class enables you to display a progress meter to users. In many cases, the meter also enables you to include additional text. This text can help the user understand what the process is doing and how much longer they need to wait for the process to complete.

To use the Progress class:

  1. Add the following code to the declaration section of the method that you are using:
    #AviFiles
      SysOperationProgress  progress = new SysOperationProgress();

    The #AviFiles code is a macro that defines variables for you. The SysOperationProgress class is a Microsoft Dynamics AX tool.

  2. To begin to use the class in your method, you have two options:
    • Include a caption that indicates to the user what is happening. To add a caption, add the following code. For <caption text>, substitute the text that you want to include:
      progress.setCaption("<caption text>");
    • Indicate to the user how many records your periodic process will process. You do this by setting a total. The total can be records, items, or the number of steps that your class must perform. To add a total to the progress meter, add the following code. For N, substitute the number of steps that you want to include:
      //N Steps to perform
      progress.setTotal(N);
  3. After you have added a total, you can indicate progress by incrementing the number to reach your total. To indicate this progress, add the following code:
    Progress.incCount();

    In many cases, this method is called within a loop or a While statement so that the increment is apparent. You can also do this manually by adding the following code:

    Progress.setCount(2);
  4. Finally, you can continue to update your user by using a caption, substituting a caption such as "Still working" for <caption text> below.
    Progress.setCaption("<caption text>");

By experimenting with this method, you will find other methods that may make for a more user-friendly experience when a user works with your periodic process.

Conclusion

This article has shown you advanced techniques that you can use when you write periodic classes using the Runbase and Runbasebatch classes. Periodic processing provides advanced functionality to users in a standard format. As a result, when users ask for functionality that requires some input and updates a range of data, periodic processing classes provide great functionality.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值