Navision Axapta
Axapta Developer's Guide (Part 1)
Columbus IT Partner Russia, ApS
Navision Axapta
Contents Introducing MorphX..................................................................................................................... 7 1. Getting Help............................................................................................................................. 8 Using the Developer's Guide Help ............................................................................ 8 Print a Help topic ....................................................................................................... 8 Use shortcut keys ...................................................................................................... 8 Modify the Help document....................................................................................... 12 2. Developing Axapta Applications......................................................................................... 14 2.1. The Seven Steps of Application Development .......................................................... 14 Conceptualization: understanding the problem....................................................... 14 Create Extended Data Types based on the primitive data types............................ 15 Create tables to hold your data ............................................................................... 15 Design classes for handling business procedures .................................................. 15 Create forms for interacting with the user ............................................................... 16 Create reports to extract information and present surveys ..................................... 16 Create menus and menu items for accessing the functionality in your application 16 3. Using MorphX ....................................................................................................................... 17 3.1. Working with the Application Object Tree.................................................................. 17 An overview of the commands in the AOT shortcut menu...................................... 18 Application Object Tree nodes: an overview........................................................... 19 Working with projects .............................................................................................. 21 Saving your work ..................................................................................................... 21 The MorphX property sheet..................................................................................... 21 MorphX concepts you need to know ....................................................................... 22 3.2. Application Object Layers .......................................................................................... 24 Using the top level version of an object at all times ................................................ 25 Layer benefits .......................................................................................................... 26 Additional patch layers ............................................................................................ 26 Viewing layers in the application during development ............................................ 27 Using the Layers command..................................................................................... 28 Setting the current layer .......................................................................................... 29 Exporting objects from a selected layer .................................................................. 29 Tips ................................................................................... 30 3.3. Working with projects................................................................................................. 31 Open a project ......................................................................................................... 31 Create a new project ............................................................................................... 32 Create a new ptoject using the project filter funtion ................................................ 33 Autogenerate a project group.................................................................................. 33 Project tips............................................................................................................... 34 3.4. Using the editor.......................................................................................................... 34 Editor color codes.................................................................................................... 35 Use editor shortcut keys.......................................................................................... 35 Editor lookup facilities.............................................................................................. 36 Printing your code ................................................................................................... 37 Editor scripts: What they are and how they work .................................................... 37 3.5. Using the Debugger ................................................................................................... 37 To activate the debugger automatically when code is compiled............................. 37 To set breakpoints ................................................................................................... 38 Use debugger shortcut keys.................................................................................... 38 Using debugger information .................................................................................... 39 3.6. Working with more languages ................................................................................... 40 Ladels: What they are and how they work .............................................................. 40 Creating a label ....................................................................................................... 41 The label dialog ....................................................................................................... 41 Line breaks in labels................................................................................................ 42 Creating a label file.................................................................................................. 42 3.7. Working in MorphX .................................................................................................... 43 System classes: What they are and how they work................................................ 43 Columbus IT Partner Russia, ApS
2
Navision Axapta Locking the datebase in a multiuser environment................................................... 44 Using the fundamental classes ............................................................................... 45 Using global variabies ............................................................................................. 46 WinAPI (Windows Application Programming Interface) .......................................... 48 3.8. Securing date............................................................................................................. 49 Feature keys: What they are and how they work .................................................... 50 Define and enable a feature key ............................................................................. 52 Disabling a datebase feature key............................................................................ 52 Creating a feature keys hierarchy ........................................................................... 53 Feature key organization......................................................................................... 53 3.9. Backup of Application Objects ................................................................................... 55 Using the application object export import facilities ................................................ 55 Export application objects ....................................................................................... 56 Import application objects........................................................................................ 56 A note about exporting tables and classes ............................................................. 57 3.10. Tips................................................................................................................ 57 Setting development options ................................................................................... 57 Easing your login procedure.................................................................................... 60 Using Windows Regional Settings .......................................................................... 62 How do I locate… .................................................................................................... 63 Add company logo to the Main menu...................................................................... 64 Executing commands on startup ............................................................................. 64 4. Working with MorphX Development Tools ........................................................................ 66 4.1. Using the Cross-Reference system ........................................................................... 67 Create a cross-reference system ............................................................................ 67 Using the cross-reference system........................................................................... 68 4.2. Generating an Application Hierachy Tree.................................................................. 70 Application Hierarchy Tree information ................................................................... 70 If information for a hierarchical view is not available............................................... 72 4.3. Using the MorphXplorer ............................................................................................. 72 Creating a tables relation diagram .......................................................................... 73 Include class and map information in a table relations diagram ............................. 74 Creating a classes diagram..................................................................................... 75 Including super and sub classes information in a class diagram ............................ 75 Opening, saving, and printing diagrams from the MorphXplorer ............................ 76 Arranging, zooming, and copying in the MorphXplorer ........................................... 76 Legend in the MorphXplorer.................................................................................... 77 4.4. Other Tools ................................................................................................................ 77 Using the application objects list ............................................................................. 77 4.5. Creating Wizards ....................................................................................................... 79 Create a wizard ....................................................................................................... 80 Guidelines for wizard development ......................................................................... 81 The wizard class...................................................................................................... 82 The wizard form....................................................................................................... 83 Wizard tips............................................................................................................... 83 4.6. Tips . ............................................................................................. 86 Searching on properties .......................................................................................... 86 5. Creating a Database ............................................................................................................. 88 5.1. Database Basics ........................................................................................................ 88 Databases and MorphX........................................................................................... 88 The MorphX Interface Layer.................................................................................... 88 5.2. Databases and Companies ....................................................................................... 89 Dividing a database into companies ....................................................................... 89 Working with companies ......................................................................................... 90 Creating table collections, virtual companies and companies ................................ 90 Who creates what.................................................................................................... 92 5.3. Extended Data Types ................................................................................................ 92 Basing one Extended Data Type on another .......................................................... 94 Defining Extended Data Types as arrays................................................................ 95 Creating Extended Data Types ............................................................................... 95 3
Columbus IT Partner Russia, ApS
Navision Axapta Customizing Extended Data Types ......................................................................... 96 Description of properties for Extended Data Types ................................................ 97 Adding dimensions .................................................................................................. 99 Complete these steps to add a dimension: ..................................................................... 100 5.4. Table Basics ............................................................................................................ 103 Creating tables ...................................................................................................... 106 Using keys in tables .............................................................................................. 107 5.5. Relationships ........................................................................................................... 108 Creating a relationship .......................................................................................... 109 Creating a relationship on an Extended Data Type .............................................. 110 Creating a condition on a relationship on an Extended Data Type....................... 110 Creating a relationship on a table ......................................................................... 111 Creating a condition on a relationship on a table .................................................. 112 Adding conditions to your relationships................................................................. 114 Validation and integrity .......................................................................................... 115 Using delete actions .............................................................................................. 116 5.6. Using Code in Tables............................................................................................... 117 Sequence of execution of methods....................................................................... 123 Defining and modifying methods in your tables .................................................... 123 5.7. Indexes . ............................................................................... 124 Deciding what to index .......................................................................................... 125 Creating an index .................................................................................................. 126 Description of properties for indexes..................................................................... 126 5.8. Ways to customize................................................................................................... 127 Customizing fields in a table.................................................................................. 131 Modifying tables that contain data......................................................................... 134 Temporary tables .................................................................................................. 135 Using maps............................................................................................................ 135 Creating a map...................................................................................................... 136 5.9. Tips . ........................................................................................ 137 Using Index and Order By in select statements .................................................... 137 Caching lookups .................................................................................................... 138 Browsing data........................................................................................................ 141 6. Creating forms .................................................................................................................... 143 6.1. Form basics ............................................................................................................. 143 What is a form and what is it used for? ................................................................. 143 The basic steps in defining a form ........................................................................ 143 What are controls and how do their properties relate to properties in their underlying fields? .......................................................................................................... 145 Access keys on forms ........................................................................................... 149 Using the graphical forms editor............................................................................ 150 Automatic reports on data in forms ....................................................................... 150 Guidelines for form design .................................................................................... 151 6.2. Ways to Customize Your Form................................................................................ 152 Add a picture to a form .......................................................................................... 152 Add a control to a form .......................................................................................... 152 Create a form with tabs ......................................................................................... 153 Bind an unbound control to a field......................................................................... 153 Change the tab order on a form ............................................................................ 154 Delete a control on a form ..................................................................................... 154 Format groups on your form.................................................................................. 154 Group controls on your form.................................................................................. 154 Use image lists for Tree controls and ListView controls ....................................... 154 Modify the shortcut menu on controls ................................................................... 156 Description of properties for controls .................................................................... 157 Description of properties for a form data source ................................................... 177 Description of properties for form design .............................................................. 179 Joining data sources on forms .............................................................................. 180 6.3. Designing Forms...................................................................................................... 183 Determining the opening view of a form................................................................ 183 Specify whether a form opens for modification and data entry ............................. 184 Columbus IT Partner Russia, ApS
4
Navision Axapta
6.4. 6.5.
6.6.
6.7. 6.8. 6.9.
Implicit forms variable declarations ....................................................................... 184 Validate or restrict data in forms............................................................................ 184 Order of evaluation for controls and fields ............................................................ 185 Auto-arrange principles in forms ........................................................................... 185 Sizeable forms....................................................................................................... 188 Toggling between different views on data............................................................. 188 Display a message box ......................................................................................... 189 Using display and edit method modifiers .............................................................. 190 The standard lookup form: what it consists of....................................................... 192 The lookup facility: creating you own lookup forms .............................................. 193 Creating a run-time lookup form............................................................................ 196 Tips ................................................................................... 198 Using ActiveX controls ............................................................................................. 199 Adding an ActiveX control to a form...................................................................... 199 Forms System Classes ............................................................................................ 201 Form control system classes................................................................................. 202 Constructing a form from your X++ code .............................................................. 202 Add a picture to a form using a system class........................................................ 203 Accessing the active query on a form ................................................................... 204 Events on forms ....................................................................................................... 206 Methods on a form ................................................................................................ 208 Methods on a form data source............................................................................. 211 Methods on form controls...................................................................................... 213 Forms: Examples ..................................................................................................... 225 An example: a typical form from the standard application .................................... 225 An additional benefit of creating relations................................................................ 230 An example of a Progress control ......................................................................... 231 An example of a Window control........................................................................... 233 Optimizing and Troubleshooting Forms................................................................... 234 Troubleshoot forms ............................................................................................... 234 Optimize form performance................................................................................... 234
7. Creating Queries................................................................................................................. 235 7.1. Quiries basics .......................................................................................................... 235 The standard QueryForm ...................................................................................... 235 Organization of queries ......................................................................................... 237 7.2. Creating a query ...................................................................................................... 238 Creating relations between embedded data sources............................................ 239 Setting properties and default options................................................................... 239 Using multiple tables in a query ............................................................................ 241 Sequencing of retrieved records ........................................................................... 242 7.3. Using queries from other application objects........................................................... 243 Using Run classes for Query objects .................................................................... 243 Using Build classes for Query objects................................................................... 244 Queries in forms and reports................................................................................. 246 7.4. Queries and methods............................................................................................... 246 8. Creating Reports................................................................................................................. 248 8.1. Reports basics ......................................................................................................... 248 Report components ............................................................................................... 248 Data source and visual layout ............................................................................... 249 8.2. Creating a report ...................................................................................................... 250 Creating a report by using a wizard ...................................................................... 250 Using report templates .......................................................................................... 251 Report sections ..................................................................................................... 252 Creating a new report template ............................................................................. 253 Creating a report based on a design specification ................................................ 254 Creating a report with a custom design................................................................. 256 Creating a report with multiple designs ................................................................. 256 Using controls to display information from the database ...................................... 257 Example showing how to use a display method ................................................... 257 Description of properties for the data source query .............................................. 258 5
Columbus IT Partner Russia, ApS
Navision Axapta Defining report orientation ..................................................................................... 258 8.3. Printing Reports ....................................................................................................... 259 Printing reports executed on the server ................................................................ 259 Choosing alternative report medium ..................................................................... 259 Disable printer selection ........................................................................................ 260 Fit to page.............................................................................................................. 262 8.4. Reports and methods............................................................................................... 262 Methods on a report .............................................................................................. 263 Overview of methods on a report .......................................................................... 263 The Fetch and Send methods ............................................................................... 265 Modifying the Fetch method on a report ............................................................... 265 Understanding the Send method on a report ........................................................ 266 Methods on the report design................................................................................ 266 Events on reports .................................................................................................. 266 Events caused by the Fetch method..................................................................... 267 8.5. Tips . ....................................................................................... 268 Overview of components in a report design.......................................................... 268 Printing headers for reports with many columns ................................................... 268 Sequencing of sections when printing a report ..................................................... 268 Setting font and font size....................................................................................... 269 Positioning sections relative paper edges............................................................. 269 Column headings and word wrap.......................................................................... 269 Missing bitmaps..................................................................................................... 270 9. Creating Menus................................................................................................................... 271 Creating a menu.................................................................................................... 271 Description of properties for menus ...................................................................... 271 Menu items: What they are and how they work .................................................... 272 Creating a menu item ............................................................................................ 272 Methods on a menu item....................................................................................... 273 Description of properties for menu items .............................................................. 273 Activating a menu item from your X++ code ......................................................... 274 Activating a class from a menu item ..................................................................... 276
Columbus IT Partner Russia, ApS
6
Navision Axapta
Introducing MorphX The development environment in Axapta is called MorphX. It is referred to as an Integrated Development Environment, or IDE, because it integrates many different functions such as designing, editing, compiling, and debugging within a common environment. In most traditional development tools, each of these functions would operate as a separate program, each with its own interface. In the Application Object Tree the developer can create new application objects by using drag-and-drop, and setting properties. To make the developer's job easier and faster, the system has auto settings for all application object properties. The concept of inheritance is central to the system. Inheritance means that what is defined at lower levels in the system is automatically inherited by higher levels. One illustration of the concept of inheritance is the way a developer may modify and augment the system functionality by writing his own methods. An Axapta application is flexible and easily modifiable on many levels. Typically you need to modify only a single parameter for the entire system inherit your change. If, for example, you change the length of a database field from ten characters to twenty, this is automatically reflected on all forms in the application that display this field. Axapta is not tied to a specific database platform but has been designed to be used on top of a relational database such as Microsoft SQL server. X++ uses object-oriented programming principles such as encapsulation, inheritance, classes, objects, methods, and properties. The language has Java-like syntax, and incorporates SQL data manipulation statements.
7
Columbus IT Partner Russia, ApS
Navision Axapta
1. Getting Help Using the Developer's Guide Help The Developer's Guide describes central concepts in MorphX and provides in-depth task oriented help to guide you through the development process. The book Using MorphX is a good place to begin if you want to learn about general system concepts and efficient ways to work in the system. When you are ready to begin developing your integrated enterprise solution or to customize the standard application, Developing Axapta Applications will guide you through the development process step by step. The Creating... books provide conceptual as well as task oriented help on designing Axapta application objects: tables, forms, queries, reports and menus. Securing a Database deals with all aspects of security in Axapta, from disabling features in the system to setting up users and user groups and monitoring database changes. Axapta includes a number of tutorials to demonstrate various form features. The Tutorials book holds brief desriptions of these tutorials. Axapta Language Reference is a reference guide to X++, the Axapta programming language. Axapta Application Development Standards holds information about the development standards that form the basis of the application. Design Patterns in Axapta Applications holds guideline for good programming practice in Axapta. The Axapta COM Connector book includes a basics book with examples and a reference guide.
In the development environment, reference help information is available on for example functions and classes. 1. Expand the System Documentation or the Application Developer Documentation node. 2. Locate the item you want help on and press F1. Alternatively, press F1 and click the Search button on the toolbar.
Print a Help topic 1. In the Help topic window, click the Printer icon on the toolbar. 2. Choose between printing the selected topic, or printing all topics in the selected heading. 3. Click OK.
The version and setup of Microsoft Internet Explorer determines the print functionality on your system
Use shortcut keys You can use shortcut keys (also called accelerator keys) for quick access to frequently used commands or operations. The topics below describe shortcut keys generally available in Axapta and those specific to MorphX.
Click Shortcut keys on Axapta's Help menu for a complete list of system shortcut keys.
Columbus IT Partner Russia, ApS
8
Navision Axapta
What do you want to do? Use global Axapta shortcut keys Printing and saving
Press
To save an application object
CTRL+S
To print an application object
CTRL+P
Cut, copy and paste
Press
To cut an application object
CTRL+X (SHIFT+DEL)
To copy an application object
CTRL+C (CRTL+INS)
To paste an application object
CTRL+V (SHIFT+INS)
Opening...
Press
To open the Application Object Tree
CTRL+D
Getting Help
Press
To get Help on an application object
F1
To display What's this? Help on an application object
SHIFT+F1
Getting Help
Press
To get Help on an application object
F1
Use shortcut keys in forms to locate records Filter functions
Press
To set up a filter
CTRL+F3
To clear a filter
CTRL+SHIFT+F3
Locating records
Press
To create a new record
CTRL+N
To find the first record
CTRL+HOME
To find the last record
CTRL+END
Deleting records To delete a record
ALT+F9
Use shortcut keys to navigate in forms
9
Columbus IT Partner Russia, ApS
Navision Axapta Field navigation
Press
To go to first field
CTRL-SHIFT-HOME
To go to last field
CTRL-SHIFT-END
To go to previous field
SHIFT-TAB
To go to previous tab
CTRL-SHIFT-TAB
To go to next tab
TAB
To go to previous group
CTRL-SHIFT-PAGE UP
To go to next group
CTRL-SHIFT-PAGE DOWN
Use shortcut keys in the Application Object Tree When you want ...
Press
To open an application object
CTRL+O
To compile an application object
F7
To go to the previous node
UP
To go to the next node
DOWN
To move the node up
ALT+UP
To move the node down
ALT+DOWN
To expand the current node
RIGHT
To collapse the current node
LEFT
To expand the current node as much as possible
*
To collapse the current node as much as possible
-
Use shortcut keys in the editor To make it easier and faster to use the editor, use these shortcut keys: When you want to...
Press
Indent selection
TAB
Extend selection/remove indent
SHIFT+TAB
Open Help on a class
F1
Delete the previous word
CTRL+BACKSPACE
Open the Find/Replace dialog
CTRL+F
Find the next occurrence
F3
Compile
F7
Compile and close a method
F8
Set and delete a breakpoint
F9
Replace
CTRL+R
Jump to a method
CTRL+SHIFT+SPACEBAR
Mark a column
ALT+O
Columbus IT Partner Russia, ApS
10
Navision Axapta To undo and redo
Press
Undo
CTRL+Z (latest ten actions)
Redo
CTRL+Y (latest ten actions)
To go to...
Press
The next method
CRTL+TAB
The previous method
CTRL+SHIFT+TAB
To look up...
Press
A label
CTRL+ALT+SPACEBAR
A Definition
CTRL+SHIFT+SPACEBAR
Properties and methods
CTRL+SPACEBAR
To list...
Press
Tables
F2
Classes
F12
Types
F4
Enums
F11
Reserved words
SHIFT+F2
Built-in functions
SHIFT+F4
You can also use the toolbar buttons in the editor to enable the facilities listed above and to save you code.
Use shortcut keys in the debugger To make it easier and faster to use the system’s debugger, use these shortcut keys: When you want to...
Press
Run the debugger
F5
Set or delete a breakpoint
F9
Show breakpoint table
SHIFT+F9
Step into
F8
Step over
SHIFT+F8
Step return
CTRL+F8
Open or close the variables window
ALT+2
Open or close call stack window
ALT+3
Open or close system variable window
ALT+4
Switch line numbers on/off
F4
11
Columbus IT Partner Russia, ApS
Navision Axapta
You can also use the toolbar buttons in the debugger to enable the facilities listed above. The keys F5, F9 and SHIFT+F9 can also be used in the editor.
Modify the Help document This Help document was created using RoboHELP® for Microsoft HTML Help version 9 from eHelp Corporation. If you want to add or delete text from the Help document you need to acquire RoboHELP. You also need the HTML source files for the compressed Help file, Help project files (.mpj, .hhc, and .hhk), and style sheet file (.css). If you want to modify only the Contents tab (for example to remove one or more topics), you need the .hhc file.
Always keep a backup before making any modifications to files supplied with the Axapta system
To modify a Help topic 1. Create a directory, and a number of subdirectories, on your hard disk where you can place the project files and the document source files, for example HelpDir. The topics for each book in the Help file are located in a separate directory. The directory name is a three or four letter abbreviation of the title of the book, for exampe CRRP for "Creating Reports", CRDB for "Creating a Database". Within each directory, the file names are prefaced the directory "CRRP_Reports_basics.htm" and "CRDB_Databases_and_MorphX.htm".
name,
for
example
Underscores are used because the Microsoft HTML Help compiler currently cannot handle spaces. 2. Copy the .htm files to subdirectories and the project files and the style sheet to HelpDir.
The project files and the .htm files are not normally shipped with the system.
3. Activate RoboHELP and select the project file called axdvgus.mpj. 4. From the Project tab, open the file you want to modify. 5. Modify the text as needed and re-compile the Help project. To use the revised Help document, copy the .chm file to the directory where you have installed your Axapta system.
To modify the Contents tab The table of contents for an HTML Help file is saved in a file with extension .hhc. The .hhc file is a text file that you can modify in any text editor. This approach will probably be the easiest if you merely want to delete a single entry in the Contents tab or modify a title.
Removing an entry from the Contents tab does not restrict the user's access to the information in the topic through the Index Tab in the Help project.
In RoboHELP there is a graphical tool dedicated to manipulate the .hhc file. You should use this tool if you want to make extensive modifications. Also, whenever you remove an entry from the contents, you should also delete the corresponding topic to prevent the user from getting access to information, you find unnecessary. When you have deleted or edited a topic as described in steps 1 through 5 in How to modify a Help topic you must 1. Activate the TOC Composer in RohoHELP Columbus IT Partner Russia, ApS
12
Navision Axapta 2. Delete or modify a Book or Page as needed 3. Save the revised .hhc file and exit the Contents Tab Composer 4. Recompile the Help project. To use the revised Help document and contents file, copy the .chm file to the directory where you have installed your Axapta system.
13
Columbus IT Partner Russia, ApS
Navision Axapta
2. Developing Axapta Applications 2.1. The Seven Steps of Application Development MorphX has been designed to make it easy to develop Accounting and Business Management Systems and Enterprise Resource Planning applications. When you create an application in the IDE, the Application objects will be generated automatically. Normally about 80 % of the Application objects you create will not require any modifications before they can be used. The remaining 20% of the Application objects will require some modifications to be made by the application programmer. MorphX contains code, form, and report editors, and so on to help you do this. One of the basic concepts when developing Axapta applications is reuse. Depending on whether your job is to make a new application from scratch or if your are going to modify or extend an existing application, it is very often possible to reuse functionality. If your job is to add new functionality to an existing application, then make sure that you know the individual parts of the existing application. If you do not know and understand the existing application, you may end up having created functionality that was not really necessary, because it already existed in the application. When designing an Axapta application you have to complete the following seven steps: 1. Conceptualization: understand the problem. 2. Create Extended Data Types based on the primitive data types. 3. Create tables to hold your data. 4. Create classes for handling business procedures. 5. Create forms for interacting with the user. 6. Create reports to extract information and present surveys. 7. Create menus and menu items for accessing the functionality in your application. This of course is an iterative process. When you have been working with for example step four for some time you will discover that you will have to redesign some of the things you made at step three and so on. You will always have to perform a parallel activity besides the ones mentioned above: testing your application. The scope of this text is not to teach you a specific technique for developing or testing software. Refer to one of the numerous textbooks available describing OOA, OOD, prototyping, and testing techniques.
Conceptualization: understanding the problem The first major step in the development process is realizing what the problem you want to solve is really about. These first thoughts give you valuable information about the purpose of the application. Another valuable source of information is the end users that are going to use the application. It is always a good idea to involve the end users at an early stage of the development process to make sure that your application solves the correct problem. By identifying how the application is going to be used and which routines the users will perform with the system you get a good idea of the data your application is going to handle. This makes it possible for you to come up with a set of Extended Data Types that can be used in your tables. Designing the tables will often be the most difficult part of the entire application development process. Getting your table design right is crucial as the rest of the application is built on top of the tables. In the conceptualization process it is also important that you identify the forms and reports that are needed. This is the only way you can design the underlying system to provide the information necessary in them. The most important results of this step is a clear picture of... • the problem the system is going to solve • the functionality of the system, that is, how will the application solve the problem Columbus IT Partner Russia, ApS
14
Navision Axapta • who is going to use the system Other results of this step are first ideas of... • which Extended Data Types are needed • which tables are necessary (and relations between them) • which forms and reports the users need • the structure of the menus that gives access to the entire application When you have completed this step, test your results with the users/customers. Create a requirements specification together with your customer. The requirements specification can be made as a description of criteria which must be fulfilled.
Create Extended Data Types based on the primitive data types Extended Data Types are data types defined by the application programmer. An Extended Data Type is based on one of the primitive data types (or another Extended Data Type), but one or more properties have been modified to reflect a real world domain more accurately. Typically your analysis will identify a number of common types of data which occurs throughout the application. Assume for the moment that you have some items that you want to register in your application and that each item has a unique ID number. Instead of defining this unique ID number as a String with length 14 each time you need an unique ID number, MorphX allows you to define an Extended Data Type such as UniqueIDNo. Once this Extended Data Type has been defined, it is globally available in you application. Do not use Extended Data Types unless you are absolutely sure that the types of the data in the fields are identical. Using Extended Data Types in the wrong places will create unnecessary dependencies between otherwise unrelated modules in your application.
Create tables to hold your data Your tables and the relations between them make up the foundation of your application. A bad table design affects the whole application. This is why it is important to analyze your data and break it into tables before you create any other application objects Defining relations between your tables are closely related to defining Extended Data Types (the previous step). As in other systems based on relational databases it is possible to define relations between tables in MorphX. But in MorphX this concept is taken a step further. When you define your Extended Data Types you are allowed to define relations between the tables. You should make sure that your tables adhere to the first three normal forms. This brings many benefits, such as an increase in consistency and maintainability, a reduction in data redundancy and better search performance from smaller tables (with narrower rows). If you are not familiar with the relational model and the normal forms, you should refer to The Relational Model for Database Management Systems (1990) by E. F. Codd. When designing the logic of your application you should be aware of that MorphX allows you to modify the standard behavior of your tables by adding code to methods. This can be used to enforce integrity rules and define logic for your tables. The results of this step should be tested with... • your conceptual model • the customer (use the requirements specification) • Normalization rules 1, 2, and 3.
Design classes for handling business procedures Classes in MorphX allow you to reuse common functionality. Once you have defined a set of classes, they can be used from all other application objects in your application. Classes are not very useful on their own, but are intended to be used to solve tasks for other application objects, such as forms and reports. 15
Columbus IT Partner Russia, ApS
Navision Axapta You might be tempted to start with coding as the first step to see how it works. This approach is not ideal in an Axapta application because code only runs in the context of an application object and an associated event. The results of this step should be tested with... • your conceptual model
Create forms for interacting with the user Axapta forms are not just screens for entering and editing data. To the users of your application the forms are the application, as it makes up most of the application’s user interface. Forms are the most important way for your users to interact with your application. By interacting with forms the users control the flow of your application. Start by creating a form that is used to enter data in your application. Add a few sample records of sample data to your tables. This makes it easier to see whether your forms (and reports) display the data you want. For each form, determine what data you want on it, and then create a data source that contains the data. This is also a test of your tables because you will be able to see if you can get the data you want from the tables. Normally the forms you create in MorphX are created directly in the Application object Tree. Having defined the form here, its visual layout is automatically generated by MorphX based on the information in your Extended Data Types and your tables. In most common situations the system-generated layout is ready to use, but depending on your special requirements you might want to modify the layout. The results from this step should be tested with... • your conceptual model • your customer
Create reports to extract information and present surveys Reports are used to get printed overview of information extracted from your application’s data. Typically you produce phone lists, sales summaries, or mailing labels using reports. Just like any other application object, reports are also created using the application object tree. The Axapta Report Editor automatically generates the report based on the design you define in the Application Object Tree.
Create menus and menu items for accessing the functionality in your application Creating menus and menu items is the final step before your application development process is finished. The end users access the functionality in your application through menus. Menus in MorphX are very flexible compared to other systems. An Axapta application normally has several menus that are customized specifically to certain uses of the systems. Furthermore MorphX allows the end users to make their own modifications and create their own special menus. Your Application objects are not accessed directly from the menus. Instead they are accessed by menu items. The Menu items serve as a layer between the end users and the application objects. The menu items are also used to limit access to the application, based on the privileges defined for the user. The results from this step should be tested with... • your customer • the conceptual model This completed the seven steps involved in developing an Axapta application. If you have followed the previous steps it is now time to check that the application you have made lives up to the criteria you and your customer have put up in the requirements specification. Columbus IT Partner Russia, ApS
16
Navision Axapta
3. Using MorphX 3.1. Working with the Application Object Tree To open the Axapta Application Object Tree point to Open, and then click Application Object Tree on the File menu.
Pic. 3-1 The Application Object Tree holds all objects in your application along with tools to develop your own application, or to modify the standard modules in the Axapta application. The structure of the tree resembles what you see in Microsoft Explorer, or the Windows Registry Editor. The tree is a hierarchy with a number of main nodes that you can click to branch to individual levels of nesting. From the main nodes, expand the tree to a number of levels. The small icon with a plus indicates that another expansion level is available. The small empty box icon indicates that the node is currently empty of contents but that you can create some contents. The nodes share two features: • A shortcut menu opened by right-clicking the node. The menu will look different depending on the kind of node; however, you will always find the Properties command (see next item). • A set of properties you can view in the node property sheet. To see the properties of the current node, right-click the node to open the shortcut menu, and click the Properties command, or click the properties icon in the toolbar.
The New command To create a new class, a new table in the database, a new form or a new report, right-click the relevant node to open the shortcut menu, and then click the New command. The New command will always create a new object of the type that can be inserted in the current node. 17
Columbus IT Partner Russia, ApS
Navision Axapta For example a form consists of three types of objects – methods, data source, and graphical layout. So if you choose New on the Forms, a new form object with three subnodes is created. When it is possible to insert more than one object, the New command opens a submenu.
An overview of the commands in the AOT shortcut menu The available commands in shortcut menu depend on the type of node you open it on: Command
Use it to...
Add-Ins
open a submenu holding various MorphX tools, for example the crossreference system and a compare feature. Tip You can add you own commands to the submenu.
Compile
compile a method or a subtree. When you exit the editor without compiling (or saving) the system will automatically do so for you.
Copy
create a copy of the current object.
Cut
delete the current object while keeping a copy in the buffer.
Delete
delete the current object.
Duplicate
create a copy of the current object.
Edit
edit the X++ code or the graphical design of the current object.
Export
extract information from the system to a text file.
Find...
locate an object in the Application Object Tree. The dialog is virtually identical to the Find Files or Folders... dialog in Windows Explorer. Tip Use shortcut key CTRL+F.
Generate Design
have the system generate a report design based on the query structure.
Generate Specs From Query
have the system generate a design structure similar to the data source structure in the query.
Layers
view object in all layers. Note You always save, modify and delete in the current layer.
Lock
temporarily lock the current node for modifications from other users. This command is useful only in installations with multiple clients with access to the same data.
New
create an object that can be inserted in the current node.
New Programmable Section
have the system generate a section in your report that you must activate from your X++ code.
Open
activate the current object.
Open New Window
create a new window with the current object and its sub-nodes. The current object becomes the root of the new tree structure.
Override Method
choose a method to override. When you create a new an application object of type class, table, or form, a number of methods are created by the system. These methods call super() and thus execute the system's implementation of the method. You can add you own code to the methods thereby overriding the system's standard
Columbus IT Partner Russia, ApS
18
Navision Axapta behavior. Use Override Method to add your own X++ code to one of these methods. For classes, the superclass' methods that can be overridden are also shown. Page Formatting
set up your report page size, paper source, orientation, and so on.
Paste
insert the object you have previously cut or copied.
Print...
print the current object.
Printer Setup
set up your report printer.
Properties
open the properties window with properties for the current object.
Refresh
update the list of application objects. To update the contents of the application objects, use the Restore command.
Remove
remove the current object from its present context. This command is useful, for example, when you want to remove an application object from a project but not from the Application Object Tree.
Rename
give the current object a new name. Tip You can also rename an object through its property sheet, or by clicking it twice.
Restore
re-read the current object from disk and discard the changes made since the last save. Note If you have set the Auto-Save option, the object restored from disk may be the one save by the system.
Save
commit the current object to your database.
Synchronize
synchronize the database with the SQL database. Whenever global changes to the data dictionary occur, you have to synchronize the SQL database as well. Global changes are changes that are not specific for a given table, such as the Extended Data Types, or Feature Keys. Since such a synchronization may take a while on large amounts of data, it is not done automatically, when a single change is made and saved (contrary to altering the properties on a given table, or index, which does cause an automatic SQL synchronization when the changes are saved). Note Whenever the system requires synchronization, the color of the Data Dictionary icon changes from yellow to red. Tip It is recommended to perform the synchronization when no other users are using Axapta.
Unlock
unlock the node you have previously locked for modifications from other users.
Application Object Tree nodes: an overview Node
Description
Data Dictionary
Use the Data Dictionary node to set up the data types and tables that make up your database. To define a database: •
19
Define the data types you plan to use in your set of tables Columbus IT Partner Russia, ApS
Navision Axapta •
Set up each table in your database with fields, indexes and object methods.
Macros
A macro is a code or text substitution that cannot run independently, but can be used anywhere you can write code in the system, for example in jobs, classes and forms. The Macros node holds the macros used by the standard application. Besides viewing the existing code you can add your own macros.
Classes
Each class in the Classes node holds a class declaration with the class variables and a number of class methods with the code that operates on these variables. The classes are global and can be used anywhere. Most of these classes are part of the standard application. A different icon represents the classes that are an integral part of the development environment.
Forms
Using the Forms node, design the dialogs that are the user’s interface to the database. To create a form: •
Attach objects from the database using the Data Sources node
•
Define X++ functions to manipulate the form
•
Define the graphical layout of the form.
Web Forms
Using the Web Forms node, design the dialogs that are the user’s Web interface to the database.
Reports
A report is an effective way to present your data in a printed format. In the Reports node you design the ways you would like to display information. To create a report:
Queries
•
Use the Data Source node to attach a query
•
Define X++ functions to manipulate the report
•
Define the layout of the report.
Queries are used as the source of records for forms and reports. Use the Queries node to: •
Define which database tables you want to see data from
•
Define X++ functions to manipulate the data.
Jobs
The Jobs node typically holds small X++ programs that are often executed as batch jobs.
Menus
In the Menus node you design the menus you want the end user to see.
Menu Items
The Menu Items node holds the complete list of the functions that can be presented in a menu. When designing a user menu in the Menus node, you choose from this collection.
System Documentation
The System Documentation node contains reference documentation for the development environment.
Application Developer Documentation
The Application Developer Documentation node contains reference documentation for application tables and classes.
Application Documentation
The Application Documentation node contains reference documentation for the Axapta application. Documentation is also available on the individual forms in the application.
Columbus IT Partner Russia, ApS
20
Navision Axapta
Working with projects A project is a subset of the Object Tree that allows you to group the components you are currently working on. A project is either private or shared. A private project is only available to the user who created it. In contrast, a shared project is available to all users, and can be used as a tool for workgroups to manage their work. Because a project is a subset of the complete tree, everything you create or modify in your project also automatically exists in the tree. Besides providing an overview of the process you are currently working on, using projects offer additional advantages. • When a node is edited in the project, the modifications are also automatically reflected in the Object Tree. • You can group application objects any way you like. • Projects can be generated automatically using the project filter, or the project group's properties. • The project remembers the state you last left it in: which windows were open, which branches expanded and so on. • You can compile and save all project objects at one time. A number of shared projects are supplied with your Axapta installation.
Saving your work The MorphX save and compile strategy ensures that • You are always aware when you should save your work • Your work is automatically compiled when required. When you have created an application object in the tree that has not yet been saved, the system indicates this by adding a red line to the object.
Pic. 3-2 When you subsequently save the object, the system automatically compiles it when necessary. If you compile the object rather than save it, the system automatically saves as well. The red indicator line disappears as soon as the object has been saved. If you neither save nor compile your application object but immediately try to execute it (for example by clicking Open in the shortcut menu), the system automatically compiles and saves your object.
The MorphX property sheet Properties are displayed in a secondary window that remains open on your screen until you deliberately close it. The window always shows the properties on the node currently in scope; this means that when you traverse the tree, the contents of the property sheet automatically change.
21
To display the Object Tree and the property page next to each other, click Tile in the Windows menu
Columbus IT Partner Russia, ApS
Navision Axapta
Properties and categories Typically the number of properties grows as you expand the tree to increasing levels of detail. On the deepest levels the number of properties is frequently about 40. To improve your overview the properties are grouped in categories. An example of a category could be the properties defining the position of a control on a form, that is left, right, width, height, and whether the control should be visible on the form. Categories are displayed alphabetically sorted.
Modifying a property You can modify a property simply by clicking it and selecting a new value from a list, or entering the new value. You can also modify any property directly through your X++ code.
Colors in the properties window The property editor uses two colors: pale red and pale yellow. Pale red indicates that the property is an identifier, in other words, the name of an application element. An example would be the name of a form. Pale yellow identifies all texts that should have been entered as a label but were not.
Common properties If you select several objects in the tree, you can see their common properties and the properties that have identical value. Common properties for which the current values differ are blank. Using this technique you can also modify the properties of several objects at a time.
MorphX concepts you need to know Some central object-oriented mechanisms and terms appear repeatedly as you develop with MorphX. Below is a brief explanation of the most important ones. MorphX Concept
What is it and how does it work?
System class
A system class is an interface to functionality defined in MorphX, for example to create, or run a form.
Class
A class defines an object’s interfaces. It instructs or explains how to construct an object of a particular type. An essential characteristic of a class is that you can "new" it, or in other words, create a new instance (an object) of the class. Forms are an example of a class: MorphX has a class definition that prescribes exactly what happens when a form object is created.
Controls
A control is a graphical object, such as a text box, a check box, a command button, or a rectangle, that you place on a form or report when designing it to display data, perform an action, or make the form or report easier to read. There are approximately 20 different controls and each is defined by about 50 properties.
Data Source
A data source holds those data variables that a form or a query uses. These data variables may be one or more tables, or individual fields from tables.
Designs
A Designs node provides access to define the layout of a form or a report.
Encapsulation
Encapsulation means that data in the system are hidden behind methods and can be changed only by the methods.
Final
Final is a class or method modifier that defines that the class or method cannot be extended (overridden).
Columbus IT Partner Russia, ApS
22
Navision Axapta Inheritance
Inheritance is a central concept in MorphX. It means that what you define at lower levels in the system is automatically ”inherited” by higher levels. An illustration of the hierarchy of inheritance is that your own methods may be built on and extend one of the methods defined in MorphX. In the code this is indicated by the ”super” reference. You can always recognize an inherited method on the down arrow in the method’s icon .
Method or object method
Methods are tasks you can tell an object to do. Methods can be programmed at several levels: • As part of a table • As part of a form Methods for a form may be related to: • The general management of the form such as running the form closing it • The data displayed in the form such as deleting or writing data • Form controls such as moving the cursor • As part of queries • As part of a general class library Initially the methods are only frames that activate MorphX’s methods (indicated by the “super()” call). The small icon in the tree structure indicates that there is, as yet, no user code in the methods. When you have added some code of your own, a small color indicator is displayed in the icon. The color bar is green when your code has no syntax errors, and red in cases where your method has errors. In a method you can • Add code to be executed prior to the method’s main action. • Write you own method or let MorphX handle it (the “super()” call). • Add code to be executed after the method’s main action.
Object
Object is the central MorphX concept. Any form and any control is an object. The database is an object. Objects are created from classes; thus an object is said to be an instance of a class. Objects provide a convenient, logical way to organize procedures and data. Objects are encapsulated which means that they contain both their code and their data. To use an object, you must keep a reference to it in an object variable.
Property
Properties are data that describe an object. Each type of object has different types of properties. A method typically has only a few properties, one of which defines where it is to run. Conversely, a control frequently has about 50 properties which define position, size, color, and so on.
Query
A query is a filter mechanism to retrieve the data you want to see from your database tables. Queries are typically used as the source of records for forms and reports.
23
Columbus IT Partner Russia, ApS
Navision Axapta
3.2. Application Object Layers Application object layers hold everything in the Application Object Tree. The layers are a hierarchy of levels in the Axapta application source code to ensure that you can make modifications and additions without interfering with the application objects on the level below your own. The idea is that when you make an object modification on one level, the modification overshadows the object on a lower level. You could for example choose to add E-mail information to a standard form. The addition would be saved on your level only; the revised form would replace the standard form but you would always be able to go back to the original one on the level below your own simply by removing the new form. The layers are designed with the Axapta customer groups in mind. Basically three customer groups have an interest in adding and modifying application objects: • Application developers who create the standard application • Business partners • Axapta end users Each of these three groups has two layers in which they can add and modify. SYS
The standard application is implemented at the lowest level, the SYS layer. The application objects in the standard application can never be deleted.
GLS
When Damgaard Development certifies and distributes a solution that has not been developed in-house, this solution is distributed in the GLS layer. GLS is short for GLobal Solutions.
DIS
When the application is modified to match country specific legal demands, these modifications are saved in a separate layer, the DIS layer (for DIStributor). If an application object, for example a form, is modified in the DIS layer the modifications are saved in the DIS layer only and Axapta ensures that the modified version of the forms is used.
LOS
A layer where the distributor can implement local partner solutions. LOS is short for LOcal Solution.
BUS
When a business partner creates his own generic solution, his modifications are saved in the BUS layer and – again – Axapta ensures that the top level application objects are used.
VAR
Customers with a VAR (Value Added Reseller) status may make their own, customer specific modifications to the business partner solution. Such modifications are saved in the VAR layer.
CUS
The supervisor or administrator of an end user installation may wish to make modifications generic to the company. Such modifications are saved in the CUS (CUStomer) layer.
USR
Lastly the end user may wish to make his very own modifications, for example his own reports. His modifications are saved in the USR layer.
Each layer is saved in a separate file called Ax.aod, for example Axsys.aod for the SYS layer, Axdis.aod for the DIS layer and so on. The .aod extension is an acronym for Application Object Data file. In addition to the six layers, each layer has a patch layer. For each layer, there is a corresponding label file.
Columbus IT Partner Russia, ApS
24
Navision Axapta
Using the top level version of an object at all times A single index file called Axapd.aoi automatically ensures that the top-level version of an application object is always used. The USR layer is the top layer and the SYS layer the bottom one. This means that when a user opens for example a form object, Axapta first checks whether there is a USR version of the form, next whether there is a CUS version, next for a VAR version and so on until finally the SYS version is used.
USR
CUS
VAR
BUS
LOS
DIS
GLS
SYS
The majority of application objects (table, field, index, and enum type, Extended Data Type, feature key) have unique id numbers in addition to names. Axapta uses eight number series corresponding to the eight layers. SYS layer object numbers:
1-7999
GLS layer object numbers:
8001-15999
DIS layer object numbers:
16001-17999
LOS layer object numbers:
18001-19999
BUS layer object numbers:
20001-29999
VAR layer object numbers:
30001-39999
CUS layer object numbers:
40001-49999
USR layer object numbers:
50001-59999
When an object is initially created, Axapta automatically manages ids and assigns a new id according to the above table. Note, though, that when you modify an existing object, the object keeps its original id and is not assigned a new id in your layer. 25
Columbus IT Partner Russia, ApS
Navision Axapta
Layer benefits The fact that each layer is saved in a dedicated file means that it is easy to locate the file to backup. It also means that you can easily remove undesired modifications: you can simply delete the layer file.
In that case you should also delete the index file to make the system re-generate it.
The layers ensure that: • Any user of the Axapta application, whether a distributor, a business partner or an end user, can customize the Axapta application to suit his/her needs. • The standard application is never overwritten. • When you delete an object, you delete it in the current layer only.
Additional patch layers In addition to the eight layers, each layer has a patch layer. The patch layers are called SYP, GLP, DIP, LOP, BUP, VAP, CUP, and USP. The patch layers are designed to make it easy to incorporate updates in your current application. The basic idea is that when a minor update or correction is made, it is distributed in a patch file, for example Axsyp.aod. When a patch file is present, the modified objects in the patch file take precedence of the regular objects and are automatically used. USP USR CUP CUS VAP VAR BUP BUS LOP LOS DIP DIS GLP GLS SYP SYS
The patch files used the same number series as the regular files. Columbus IT Partner Russia, ApS
26
Navision Axapta The major benefit of the patch layer concept is that you can easily create and distribute an update - for example using the Internet – without interfering with the existing application. When you subsequently incorporate the update in the regular layer file, you can simply delete the patch file (Ax??p.aod ) and the index file (Axapd.aoi).
Viewing layers in the application during development In the Application Object Tree, you can choose whether you would like to see what layer the individual objects belong to. The layer is given in parenthesis after the object name.
Pic. 3-3 To choose a view, click Options... on the Tools menu. Click the Development tab. The field labeled “Application object layer” defines your current view. View
What is displayed?
Show no layers
No objects are labeled with layer indication.
Show all layers
All objects are labeled with layer indications for all layers in which they exist. This means that if an object from the standard application (the SYS layer) was modified in for example the DIS and VAR layers, the object would be labeled (sys, dis, var)
Show highest layer
All objects are labeled with layer indication for the highest layer. All objects are labeled. If an object from the standard application (the SYS layer) was modified in for example the DIS and VAR layers, the object would be labeled (var)
Show corrected layers
Only objects that have been modified in the current layer or a higher one are labeled and only with indication for the highest layer. This means that if an object from the standard application (the SYS layer) was modified in for example the DIS and VAR layers, the object would be labeled (var)
27
Columbus IT Partner Russia, ApS
Navision Axapta Show all from corrected layers
Only objects that have been modified in the current layer or a higher one are labeled but with indication for all layers. This means that if an object from the standard application (the SYS layer) was modified in for example the DIS and VAR layers, the object would be labeled (sys, dis, var)
You can see the layer you are currently modifying in the system’s status bar.
Using the Layers command When an application object exists in several layers, the Layers command is enabled in the shortcut menu on an application object (table, macro, class, form, report, query, and menu). Click Layers to view each application object as a separate instance. For example, if you have modified the Address form in the standard application in the USR layer, clicking Layers on the Address object displays two instances on the form.
Pic. 3-4 All modifications are made in the top layer only. Tables and classes are special in the sense that when you modify a single method, only that method exists in several layers. So clicking the Layers command on a modified method displays only that method in two instances.
Pic. 3-5 Note that when you have modified, you can only compile in the current layer- there can be no modifications in other layers that makes re-compiling necessary. Tables and classes are also special in another sense: when you have modified an object, for example the Address table, and next click the Layers command, then all other layers but the current one “disappears”. Only information saved with the table or class (and not in the application object layer file) is shown.
Pic. 3-6 As you can see from the above example, DeleteActions are saved with the table and consequently visible for the SYS layer also.
Columbus IT Partner Russia, ApS
28
Navision Axapta
Setting the current layer The current layer is set when Axapta is installed. Using the Axapta Configuration Utility (ACU) you can view and modify the current level. Note that you cannot modify the original configuration – you must create a copy and modify that – and that you must supply a password before you are allowed to modify the “Appl. object layer”.
Pic. 3-7
Exporting objects from a selected layer 1. Open the Application Object Tree and make the root node the current one. 2. Choose Export on the Command menu. 3. In the Export dialog, select the layer checkbox and choose the relevant application object layer from the list.
You can always see the current layer in the status bar.
Use the Browse button to find a location and a name for the export file. The extension for an export file is .xpo. 4. Click Export to perform the export with the selected options. Now the export process begins, exporting all objects from the selected layer.
Tables and classes are special cases Tables and classes are special cases in the sense that they may have sub nodes that are saved in different layers. For example, the table Tab1 in the SYS layer may have a field, Field1, that exists both in the SYS and in the USR layer. 29
Columbus IT Partner Russia, ApS
Navision Axapta When you export the USR layer, the Tab1 tables is exported as well but the export file will hold only the description of Field1 and not the remainder of the table. When Tab1 is subsequently imported, only Field1 is affected.
Tips
.
If you want to move X++ code to another layer Follow the procedure below if you want to move X++ code to another layer while keeping your data: 1. Start Axapta in the layer the X++ code is to be moved from. 2. Use the Export command in the Application Object Tree shortcut menu to export the X++ code to an .xpo file. 3. Use the Data export/import command on the Administrator menu (Database submenu) to export data in the relevant tables. Relevant tables are the tables to be moved to another layer and possibly other tables with references to the tables you move. 4. Delete the X++ code in the current layer. 5. Click Synchronize in the Application Object Tree shortcut menu. Axapta now updates following your deletes in step 4. 6. Exit Axapta. 7. Start Axapta in the layer that to which you want to move X++ code. 8. Use Import on the Command menu to import the .xpo file you created in step 2. 9. Click Synchronize in the Application Object Tree shortcut menu to synchronize the tables you have just created. Now you have the tables you have in the initial layer, only with a new Id. 10. Use the Data export/import command on the Administrator menu (Database submenu) to import data. The data import does not use Ids but is based on table and field names to identify the data import target.
If you want to move tables to another layer Tables in Axapta are identified by their IDs. Different ranges of IDs are used for different application object layers. For example, IDs in the range 1-7999 are used for SYS-layer objects while objects in the VAR-layer use IDs in the range 30001-39999. It is important to realize this if you want to move table definitions and the data the tables hold from one application object layer to another, for example from the CUS to the DIS layer. Follow the procedure below if you want to move tables to another layer while keeping your data: 1. Start Axapta in the layer the tables exist in. 2. Export data from the tables you want to move. Use the Data export/import command on the Administrator menu (Database submenu) to export data.
Choose Binary format in the Export options dialog. Binary exports are faster and container fields are preserved intact.
3. Export the tables you want to move. Select the tables to export in the Application Object Tree and use the Export command on the shortcut menu to export the tables to an .xpo file. 4. Delete the tables from the Application Object Tree. Use the Delete command on the Application Object Tree shortcut menu to delete the tables. Columbus IT Partner Russia, ApS
30
Navision Axapta 5. Exit Axapta. 6. Re-start Axapta in the layer you want the tables to be present in in the future. Use the Axapta Configuration Utility to select layer. You can see the current layer in Axapta's status bar. 7. Import the tables using the Import command on the Command menu. Following the import, the tables are present in the Application Object Tree. 8. Synchronise the database. Select the Data Dictionary node and click Synchronize on the Application Object Tree to synchronize the database. 9. Import data using the Data export/import command on the Administrator menu (Database submenu). The data import places data in the correct tables with their new IDs.
3.3. Working with projects A project is a subset of the Object Tree that allows you to group the components you are currently working on. A project is either private or shared. A private project is only available to the user who created it. In contrast, a shared project is available to all users, and can be used as a tool for workgroups to manage their work. Because a project is a subset of the complete tree, everything you create or modify in your project also automatically exists in the tree. Besides providing an overview of the process you are currently working on, using projects offer additional advantages. • When a node is edited in the project, the modifications are also automatically reflected in the Object Tree. • You can group application objects any way you like. • Projects can be generated automatically using the project filter, or the project group's properties. • The project remembers the state you last left it in: which windows were open, which branches expanded and so on. • You can compile and save all project objects at one time. A number of shared projects are supplied with your Axapta installation.
Open a project 1. Click Open project on the File menu, or click the project icon on the toolbar. This will open the project window with all projects.
31
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 3-8 2. Expand the Private or the Shared folder. 3. To open a project, double-click the one you want to work with. You can also right-click the project, and then click Open on the shortcut menu.
Create a new project 1. Click Open Project on the File menu This open the Projects window with the Private and Shared projects.
Pic. 3-9 2. Right-click either the Private or the Shared node, and select New Project. This creates a new, empty project that you can give a suitable name. 3. Open the project using the Open command on the shortcut menu, or the open icon on the project toolbar.
Pic. 3-10 Now you can begin working with the project. Use a drag-and-drop operation to include objects from the Application Object Tree in the project.
Alternatively, use the project filter to create the project's contents.
Create new objects using the New command on the shortcut menu. Note in particular the Group command, which is a grouping mechanism to enhance your overview of your workspace, and to allow you to structure your project.
Columbus IT Partner Russia, ApS
32
Navision Axapta
Pic. 3-11 The project is automatically saved when the project window is closed.
Use the ProjectGroupType property on a project group to change the icon in the project tree to the ones used in the AOT. However, using a specific icon does not enforce the corresponding object to be of a specific type, and any type of objects can be included.
Create a new ptoject using the project filter funtion Using the project filer function you can set up criteria for searching the Application Object Tree. The objects located in the search are automatically included in the project. 1. Click Open Project on the File menu. This open the Projects window with the Private and Shared projects. 2. Right-click either the Private or the Shared node, and select New Project. This creates a new, empty project that you can give a suitable name. 3. Open the project using the Open command on the shortcut menu, or the open icon on the project toolbar. Now you can begin working with the project. 4. Click the filter icon on the project toolbar to open the Project Filter dialog. 5. Use Append or Overwrite to define how the system should handle the project. Select Overwrite to have the project's former contents deleted before new objects are added. 6. Click one of the buttons below the Grouping heading to define how the system should group the objects in the project. If you select AOT, the system automatically creates nodes labeled like the nodes in the Application Object Tree, for example Classes, Forms, Menu Items. If you select By user, the system automatically creates nodes labeled with user identification. 7. Click Select to define the query to be used. The query can locate objects in • the application object database (UtilElements table), • the application help texts (UtilApplHelp table), • the application delveloper help texts (UtilApplCodeDoc table), and in • the system help texts (UtilCodeDoc table). 8. Click OK to close the query dialog and save query. 9. Finally click OK in the Project filter dialog to generate a project according to the query defined.
Autogenerate a project group Use New Group on the project shortcut menu to add a heading node to your project. Next you can add application objects that belong under the heading and thus gain an overview of the subset of the AOT that you are curretnly working on. The heading might be the name of the current project, the name of a project member, or the name of a feature. You can choose to drag-and-drop objects from the AOT to your project group, or you can autogenerate the contents of a group. 33
Columbus IT Partner Russia, ApS
Navision Axapta
To autogenerate the contents of a project group 1. Create a new project, or open an existing one. 2. Click New Group on the project shortcut menu to create a group in the project. 3. In the group's property sheet, use ProjectGroupType to select the application object type to include in the project, and use GroupMask to enter a regular expression to select objects. An example: Set ProjectGroupType to "Forms", and enter "BOM" in the GroupMask property. The project group will now have all forms with the string "BOM" in the name.
The Help information for the Match system function in the Axapta internal help system has an overview of the syntax of regular expressions.
Autogenerated projects are refreshed each time Axapta is started. Objects that have been added manually to an autogenerated group are removed from the project when the project is refreshed.
Project tips Drag-and-drop If you drag a project from the Private node to the Shared node, the project is moved. If you drag a project from the Shared node to the Private node, a copy is created. This is because others might want to use the shared project.
Delete or remove When you delete an object in a project, the object is also deleted in the Application Object Tree. Before an object is deleted, however, a warning is displayed:
Pic. 3-12 Use Remove to delete an object from the project only.
Naming Private and shared projects may have identical names.
3.4. Using the editor You can attach your own X++ code to various objects in the system such as forms, classes, reports, queries, and to individual tables in the database. To open the X++ editor, double-click on a method name or click Edit in the shortcut menu. The name of the selected method is displayed on a tab. The editor makes it easy to work on several methods at the same time. Double-click another method within the same class, and a new tab is created.
Columbus IT Partner Russia, ApS
34
Navision Axapta
Pic. 3-13 In the example above, there are several tabs in the X++ editor. To change from one method to another, click the tab or use the arrow buttons. The editor lets you perform standard Windows editing functions like copy, cut ,and paste. Undo and redo is available ten actions back. The editor has shortcut menus (activated by right-clicking) where the available commands depend on whether you have selected text in the editor. Use F1 to have context-sensitive help on a system class. Use the ESC-key to exit the editor. If you have made changes, the system asks whether you would like to save.
Editor color codes These colors are used for X++ code in the editor: Color
Used for
Color
Used for
Blue
Reserved words
Green
Comments
Red
Strings
Black
Everything else
Use editor shortcut keys To make it easier and faster to use the editor, use these shortcut keys: When you want to...
Press
Indent selection
TAB
Extend selection/remove indent
SHIFT+TAB
Open Help on a class
F1
Delete the previous word
CTRL+BACKSPACE
Open the Find/Replace dialog
CTRL+F
Find the next occurrence
F3
Compile
F7
Compile and close a method
F8
Set and delete a breakpoint
F9
Replace
CTRL+R
35
Columbus IT Partner Russia, ApS
Navision Axapta Jump to a method
CTRL+SHIFT+SPACEBAR
Mark a column
ALT+O
To undo and redo
Press
Undo
CTRL+Z (latest ten actions)
Redo
CTRL+Y (latest ten actions)
To go to...
Press
The next method
CRTL+TAB
The previous method
CTRL+SHIFT+TAB
To look up...
Press
A label
CTRL+ALT+SPACEBAR
A Definition
CTRL+SHIFT+SPACEBAR
Properties and methods
CTRL+SPACEBAR
To list...
Press
Tables
F2
Classes
F12
Types
F4
Enums
F11
Reserved words
SHIFT+F2
Built-in functions
SHIFT+F4
You can also use the toolbar buttons in the editor to enable the facilities listed above and to save you code.
Editor lookup facilities The position of the cursor defines the type of information the system displays when you click the Lookup command. If you have positioned the cursor on an object...
Columbus IT Partner Russia, ApS
The system displays a list of the object’s data and methods. If, for example, you click Lookup on a table object, you will see the table’s fields and methods.
36
Navision Axapta
If you select an object method from such a lookup list, the system inserts the method name followed by a begin parenthesis. Also, the method’s parameter profile is shown in a ToolTip. Tip If you type :: after the name of a class, table, enum, or map, the editor looks up static methods or Enum values as appropriate. If you have positioned the cursor on an object that has no data or methods...
The system displays a ToolTip informing about the object type. If for example you click on an object of type ToDate, you will see the information “Extended Data Type: ToDate (Date)” in the ToolTip. The ToolTip disappears when you click elsewhere or move the cursor.
If you have positioned the cursor on a space or on a word about which the system has no information...
The system displays “No Lookup Information” in the status bar.
The automatic IntelliSense is an option you can disable. Click Options on the Tools menu, and then click the Development tab.If you have disabled the automatic IntelliSense, you can use CTRL+SPACE to look up information.
Printing your code Print source code directly from the Application Object Tree by clicking the Print command on the File menu. This prints the contents of the current method.
Editor scripts: What they are and how they work Editor script is a way to customize the X++ code editor to make it easier and quicker to perform frequent tasks. Such tasks could for example be to insert a header with the time, date, and user identification, to mark a block of code as comments, or to add information about the place where the method is executed. Editor scripts are available from the X++ editor shortcut menu from the Scripts submenu. The scripts are created by writing X++ code so anything that you can code in X++, you can do in an editor script.
3.5. Using the Debugger To activate the debugger automatically when code is compiled 1. Click Options on the Tools menu. 2. Click the Development tab. 37
Columbus IT Partner Russia, ApS
Navision Axapta 3. Define the system’s behavior when executing code by setting the Debug mode.
Pic. 3-14 If you set the property to...
It means that...
No
The debugger is never activated.
Always
The debugger is activated when the first code is executed. As code is executed when the system starts, the debugger is activated upon startup.
On Breakpoint
The debugger is activated only when a breakpoint is encountered.
The line in your code where the debugger breaks, changes color (to a dark blue).
To set breakpoints You can set a breakpoint in the debugger, and in the X++ code editor. 1. Position the cursor where you would like to insert the breakpoint. 2. Click the breakpoint icon in the title bar or press F9. The line changes color (to a dark red) to indicate that a breakpoint has in fact been inserted. If you have inserted an invalid breakpoint, this is indicated with a gray color. Note that invalid breakpoints are not marked in the editor. To see a list of breakpoints, click Breakpoints on the Edit menu. Alternatively, you can press SHIFT+F9. In the breakpoints list, delete breakpoints by using the DELETE key.
Use debugger shortcut keys To make it easier and faster to use the system’s debugger, use these shortcut keys: When you want to...
Press
Run the debugger
F5
Set or delete a breakpoint
F9
Show breakpoint table
SHIFT+F9
Columbus IT Partner Russia, ApS
38
Navision Axapta Step into
F8
Step over
SHIFT+F8
Step return
CTRL+F8
Open or close the variables window
ALT+2
Open or close call stack window
ALT+3
Open or close system variable window
ALT+4
Switch line numbers on/off
F4
You can also use the toolbar buttons in the debugger to enable the facilities listed above.
The keys F5, F9 and SHIFT+F9 can also be used in the editor.
Using debugger information When you have chosen to execute your code with debug information, the code lines are displayed in a debug window.
Pic. 3-15 With the X++ debugger you can • Execute code • Step through the individual code lines • Insert breakpoints • Open a variable window displaying a line for each variable with name, type, scope and value. • View the call stack • View system status • Display line numbers in your code. You switch on these functions by clicking the toolbar buttons or by using shortcut keys.
39
Columbus IT Partner Russia, ApS
Navision Axapta
3.6. Working with more languages Ladels: What they are and how they work When you create a database table you may, for example, have a field named CompName, and another one called ZipCode that indicate the kind of data they hold. However, in the form presented to the end user where he views and enters information in the table, you may want to display other texts, for example “Company name”, and “Postal code”. To do so you define a label for each of your database fields, or for the Extended Data Type used. Label is a property on an Extended Data Type and on a database field.
Pic. 3-16 You can also define a label as part of the properties for each control on a form or from X++ code, but the advantage of having set the Label property on the database level is that it is inherited on all forms where the table is used as a data source. Whenever possible, you should define your labels on your Extended Data Types. The background color of the label property's value field is pale yellow until a label has been defined. A label is identified by a unique label ID that consists of • an at sign, • a three-letter label file ID, and • a number, for example @SYS58401. The three-letter label file ID is part of the label file name and is SYS or SYP for any label supplied with the standard system. The standard label file is called AxSYS.ald where country is an abbreviation of the language used, for example En-us for American English, En-gb for British English, or Da for Danish. If you create a new label file, the three-letter label file ID may be chosen freely. The number is assigned and managed by the system. A label has the same ID in all the languages you work with. If you have created a label with the label ID @ABC58401 in your current language, the label is automatically created in all laguages you work with. This means that if you work with an American and a German label file, AxABCEn-us.ald and AxABCDe.ald, the label @ABC58401 exists in both of them.
Axapta standard for a label Every user interface text must be defined using labels. Columbus IT Partner Russia, ApS
40
Navision Axapta Context information must be given in American English in the comment field. This is particularly important for shorter labels where the context is not completely clear. A new label must be created for each new semantic use. A label must have an uppercase first letter and all other letters in lowercase. When possible, a label should be created on an Extended Data Type rather than a field. If an existing Extended Data Type can be reused but the existing label is considered unsuitable, create a new Extended Data Type based on the former one and change only the label.
Creating a label 1. Open the property sheet for the object you want to define a label for, for example an Extended Data Type, a database field, or a control. The background color of the label property's value field is pale yellow until a label has been defined. You can also create a label from X++ code. To do so, click the insert label icon in the X++ editor. 2. Click the Label property and enter the text to be displayed on the user interface. If a label has already been entered you will see the label id (for example @SYS1109) when you click the property field. 3. Click the label icon to open the label dialog. The system now searches all available label files to check whether the text you entered already exists as a label. This is to ensure that identical labels are not accidentally created. If the label does not exist, use CTRL+N to create it. Optionally, you can enter a description. 4. Click Paste label to insert the new label.
To delete the current label, use ALT+F9 or click the delete record button on the toolbar.
The label dialog The label dialog for searching, creating, and inserting labels is opened when you click on a Label property in a property sheet, or the insert label icon on the X++ editor's toolbar.
Pic. 3-17 41
Columbus IT Partner Russia, ApS
Navision Axapta Label tab Find what
The text to search for in the label system interface. The search locates all instances of the string. To create a new label with this text, use CTRL+N.
Language
Select the language you want enter the label text in. The label ID is automatically reserved in all language files.
Advanced tab Auto search
Select Auto search if you want the system to automatically begin searching when the label dialog is opened.
Auto create
Select Auto create if you want the system to automatically create a new label when no match is found during the search.
Label file ID
Select the label file you want to create new labels in. Use the Label File Wizard to create a new label file. Once a label file is created, the label file ID is automatically available in the list.
Select languages to be shown in the label dialog
Select one or more languages to be able to see translations of the current label.
Paste label
Paste the current label to the property sheet or the X++ code.
Used by
Open the cross-reference system to find out where the current label is used.
The search buttons Click this
To do this
Click this
To do this
Find now
Begin your search.
Stop
End your search.
New search
Begin a new search. If you click this button, you lose the results of your previous search.
Line breaks in labels A label may hold one or more line breaks. To format such labels properly use the strFmtLB method on the Global application class. The method takes a label as parameter and returns a string with the proper line breaks. An example box::yesNo(strFmtLB("@SYS59537"),DialogButton::No);
Creating a label file The system is shipped with a label file called AxSys.ald that exists for all available languages, for example AxSysEn-us.ald, AxSysDa.ald, and AxSysDe.ald. This file is updated whenever a new version is released. New texts for service packs may be released in a label file called AxSyp.ald. When you need to create new user interface texts, you should create a label file of your own. To help you do that, Axapta includes a label file wizard. 1. On the Tools menu, point to Development, then Wizards, and click Label File Wizard.
Columbus IT Partner Russia, ApS
42
Navision Axapta
To ensure that only valid file names are used for label files, always use the Label File Wizard to create new files and languages. The label editor cannot open a label file that has an invalid name and the user will be presented with a message to that effect if a label file has been renamed.
2. The wizard asks you select a label file ID and one or more languages. If you do not want to create a new label file ID but just add a new language, you do not have to enter a file ID in the wizard dialog. The language you add is added to all your label files. If, for example, you have these label files AxABCEn-us.ald and AxDEFEn-us.ald and want to add Danish as a new language, you do not enter any label file ID but select Danish in the list of languages. When the wizard finishes, you have these additional files: AxABCDa.ald and AxDEFDa.ald
You can add but not remove languages from the initial list of selected languages. The list is created on the basis of other language files present on your installation. For example, if the language files AxSysEn-us.ald, AxSysDe.ald, and AxSysDa.ald are present when you are creating a new language file, the wizard will present English(United States), German, and Danish in the list of available languages. You can add more languages but you cannot remove the three original ones.
Click Create new language if you need to create labels in a language not present in the list of available languages. 3. Click Finish to create a label file for each of the selected languages.
3.7. Working in MorphX System classes: What they are and how they work A system class is functionality implemented in MorphX, and used by MorphX, that has been exposed through an interface so you can use it. The fact that it is implemented in MorphX means that you cannot see the actual implementation (the code lines); you just have the calling syntax (number and type of parameters), and a description of what the function actually does. The fact that it is used by MorphX means that the system classes hold the functions that are activated whenever you use the tree to create your application. There are about 150 system classes in the system. FormDesign, shown below, is just one example of a system class. The system uses FormDesign when you define the layout of your form in the Designs node in the Application Object Tree. For example, when you click New CheckBox in the Application Object Tree, the system activates the ControlName method with a CheckBox type control as parameter.
43
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 3-18 As the icons indicate, a system class typically has • Properties (or rather member functions to set properties) for example LeftMargin • Methods. All system class methods are final, meaning that no extended class can override the behavior of the method. The system classes allow you to do everything in X++ code possible by clicking nodes and commands in the Application Object Tree. Now, presumably you would not want to design your forms from scratch using X++ code invoking the system classes, and that is not really the intention with the system classes. The system classes are a means of making the system more flexible and dynamic exactly where you need it to be. One typical, and advanced, use of the system classes is to change the application dynamically during runtime. For example, a sequence of forms with choices where the available options in form number three depend on the user's choices in the preceeding forms. Another example of dynamic changes performed during runtime, adding information (an extra column, a subtotal, another header and so on) to an existing report.
Locking the datebase in a multiuser environment When several users have simultaneous access to updating the database a conflicting situation can arise if two users are trying to modify the same application object. The scenario might be as follows: 1. DeveloperA modifies a table by adding a field. 2. DeveloperB also wants to add a new field, so while DeveloperA is making his modification, DeveloperB makes the same one. 3. DeveloperA finishes his table addition, and saves it. What now happens when DeveloperB attempts to save his modified table that does not include DeveloperA’s recent addition? MorphX resolves these types of conflicts by giving each application object a version stamp. When you try to save an application object, the system compares your object’s version stamp to the version stamp of the object in the database. If your object’s version stamp is older than the one in the database, you are not allowed to save. In the scenario described above DeveloperB will probably be quite annoyed when he is informed that he cannot save the work he has just done, even though the system ensures data integrity.
Columbus IT Partner Russia, ApS
44
Navision Axapta To avoid such situations, use the Lock command when you are modifying an object and you are not sure whether another user is also about to make updates. When you have saved your updates, use Unlock. To make sure that updates are always seen immediately by all users, ensure that Auto-Update has been selected (click Options on the Tools menu and click the Development tab). Use the Refresh command to have the system update the application objects you currently see. Modifications made by other users then become visible.
When a node is locked... When you lock an application object for modifications from other users, a small padlock symbol is automatically added. The padlock symbol is yellow when you have locked the object, and red if it has been locked by another user. When you try to save modifications made to an object locked by another user, a message is displayed informing you that the node has been locked and the name of the user that has locked it. When you have finished working with an object that you have locked, unlock it to make it available to other users. If you are logged on as supervisor (the default user name is “admin”), you can unlock other users’ locks.
Using the fundamental classes The fundamental application classes in Axapta are listed at the bottom of the Classes list in the Application Object Tree. To indicate that the classes are special, their icons differ from that of the other classes.
Pic. 3-19 The classes extend a system class of almost the same name, only prefaced with an 'x'. Most classes have a global variable used to access the class. The global variables need no variable declaration and are pre-instantiated. The classes each serves a different purpose and the extent to which you will need to use them vary. Using the classes, you should • Always use the application classes rather than use the system classes directly. • Use the variables to access the classes. • Never instantiate the classes. The Session class must be new'ed, though. • Specify the class name to access static methods. Application class
System class
Global variable
Runs on...
Session
xSession
(none)
client and server
Application
xApplication
appl
server
45
Columbus IT Partner Russia, ApS
Navision Axapta Company
xCompany
app.company()
server
Info
xInfo
infolog
client
ClassFactory
xClassFactory
classFactory
client and server
Global
xGlobal
(none)
client and server
An example: Below is an example of a job that uses the global classes. You can safely create a new job in the Application Object Tree and copy-paste the below code lines into the job. static void GlobalClasses1(args a) { treeNode treeNode; args args; formRun formRun; // appl variable print appl.buildNo(); // "company" variable appl.company().reloadRights(); // infolog variable treeNode = infolog.findNode('\\forms\\custTable'); // classFactory variable args = new args(formstr(vendTable)); formRun = classFactory.formRunClass(args); formRun.init(); formRun.run(); formRun.detach(); // global class info("This is a message on the infolog"); pause; }
Using global variabies The need for global variables often arises because of flawed implementation design. However, if used for caching purposes global variables can provide performance boosts. This topic describes how you can implement a global variable with zero maintenance during upgrade.
Columbus IT Partner Russia, ApS
46
Navision Axapta
Why use this approach? Using the approach described below, no standard application classes are modified and consequently no conflicts with the subsequent version are introduced. This means stable code with zero upgrade maintenance and fast three-tier performance.
How to set the variable First get the globalCache variable located on the ClassFactory class: SysGlobalCache globalCache = classFactory.globalCache(); Then call set with three parameters: globalCache.set(str owner, anytype key, anytype value); Parameters
Description
Owner
Must be a unique name identifying you as the user. It is recommended to use classIdGet(this) or classStr(myClass).
Key
Is how you identify your variable. This is useful if you need more than one global variable from the same location.
Value
Is the actually value of your variable.
How to get the variable First get the globalCache variable, also located on the ClassFactory class: SysGlobalCache globalCache = classFactory.globalCache(); Then call get with three parameters: value = globalCache.get(str owner, anytype key, anytype returnValue = ‘’); Parameters
Description
Owner
Must be a unique name identifying you as the user.
Key
Is how you identify your variable.
ReturnValue
Is the value you want if the global variable has not been set. This is useful for caching purposes. See the example.
Example (from Classes/ImageListAppl) void new() { SysGlobalCache globalCache; if (this.keepInMemory()) { globalCache
= classFactory.globalCache();
imageListAppl = globalCache.get(classStr(ImageListAppl), classIdGet(this), null); } if (!imageListAppl) { imagelist = new Imagelist(Imagelist::smallIconWidth(), 47
Columbus IT Partner Russia, ApS
Navision Axapta Imagelist::smallIconHeight()); this.build(); imageListAppl = this; if (this.keepInMemory()) { globalCache.set(classStr(ImageListAppl), classIdGet(this), this); } } }
Three-tier considerations Due to the dual nature of ClassFactory, the global variable exists either on the client or the server. The implication is that what you insert on the client side will not be retrievable from the server side. This means potentially less network traffic as it is possible to have the global variable on both sides. You just have to set it twice. If you want to share your global variable across the network and will accept the performance penalty of a client/server call, use the infolog or appl classes instead of ClassFactory. They reside respectively on the client and on the server.
WinAPI (Windows Application Programming Interface) As the name indicates, this class is an application programming interface to Windows functions, for example files management. Primarily, the WinAPI methods access functions in these DLLs: • USER32.DLL Operating system functions to manage the user interface, for example functions to create windows, draw windows, menus, dialog boxes, images, icons and so on. • COMDLG32.DLL Operating system functions to the COMmon DiaLoGinterface, for example Open File, Save File, Print, Choose Color, Page Setup, and so on. • KERNEL32.DLL Operating system functions to the kernel interface, for example functions to start processes, threads, timers, file management, memory, string manipulation, and so on. • ADVAPI32.DLL Operating system functions to advanced kernel interface, for example functions to encryption, services, user profiles, security, registry, and so on.
Where to use the WinAPI class When Windows-related functions are needed, methods to access them might be in this class. If a function is missing, but you know it is in the WinAPI class is a good place to look to see how DLL functions are called.
Columbus IT Partner Russia, ApS
48
Navision Axapta
3.8. Securing date MorphX provides a variety of different methods you can apply to secure your data. • Restrictions on individual tables and fields. • Limiting the availability of application features. • User-level security, which can be used to limit what parts of the database the user can access or change. • Non-modifiable information.
General access restrictions on tables and fields When creating a table in your database you can restrict the availability of the data it holds. You do this by modifying a table property named MaxAccessMode that on one end of the scale can bar all access, and on the other end provide full access to create, modify and delete data. The restrictions defined here apply to all users. Setting the MaxAccessMode property restricts what the user can see in forms and reports. You can also limit access to modifications on individual fields in a table. A field has two modification properties, AllowEditOnCreate and AllowEdit. The first one determines if the user is allowed to enter data in the field when a new record is created and the second one if the user is allowed to modify data in an existing record.
Customizing by limiting application features Use feature keys to enable and disable application functionality to customize the application to the users’ needs. One feature key could for example enable all features to do with general ledger functions. The ledger feature key could have child feature keys enabling for example feature to do with balance sheets, coverage, or budgets. A whole range of feature keys have been defined in the Axapta application. The feature keys are automatically enabled when the system is first started yielding the system 100 percent functionality. In addition to the advantage of having an application that is customized to the users’ requirements, using feature keys also yields a faster system. This is due to the fact that when you de-select features, the database tables and fields supporting those features are not generated. The result is less database management and lesser storage requirements.
User-level security The most flexible and extensive method of securing data is called user-level security. This form of security is similar to methods used in most network systems. Users are required to identify themselves and type a password when they start the Axapta system. Within the workgroup information file, they are identified as members of a group. Axapta provides a default user named “Admin” who is a member of the group by the same name, but additional groups and users can be defined. Permissions are granted to groups to regulate how they are allowed to work with each object in a database. For example, members of a group named “Users” might be allowed to view, enter, or modify data in a customers table, but not be allowed to change the design of that table. The “Users” group might be allowed to only view data in a table containing order data, and be totally denied access to a payroll table. Members of the “Admin” group have full permissions on all of a database's objects. You can set up more fine-grained control by creating your own group accounts, assigning appropriate permissions to those groups, and then adding users to those groups. Feature keys constitute the primary way to give groups various permission levels in the Axapta application. Having configured feature keys to define what features the application should include, the keys are used for security purposes to grant permissions to the individual groups. The main reasons to apply user-level security are to: 49
Columbus IT Partner Russia, ApS
Navision Axapta • Allow users to do their designated tasks only. • Protect sensitive data in the database. • Prevent users from inadvertently breaking an application by changing code or objects on which the application depends. Axapta also offers another way to configure user-level security in that you can define user group permissions for individual tables and fields.
The Axapta security system lets the user see only what he has access to, and handles the appropriate access level for each user. Security is applied on the user interface, that is, when the user access Axapta through menus, menu items, reports, and forms. Access through X++ code is not subject to the security system.
View but not modify... To protect sensitive data, you can make information visible without making it modifiable. When designing forms to display and enter data from the database, you can limit the access to modify selected fields. You do this by disabling the control that is bound to the field you want to protect. In this manner the database information is visible but not modifiable. Use the Enable property to disable/enable the control.
Feature keys: What they are and how they work Feature keys are application objects located beneath the Data Dictionary node in the Application Object Tree. You use feature keys to disable features in the application and to control user group access to specific features. Initially the Axapta application has the complete range of business management features. The primary purpose of using feature keys is to present Axapta users with precisely the features they use and avoid loading and managing functions they do not want. Once the subset of Axapta features is defined, user groups are given access to those features as part of the security setup. To define a feature key the first task is to identify the application objects that belong together and that should be enabled or disabled as a group. One such group for example could be all tables and menu items that have to do with ledger balance sheets, another group could be tables and menu items that have to do with ledger closing. Having identified the two groups, you define two feature keys, LedgerBalanceSheets and LedgerClosing, and set each key on the appropriate tables and menu items. Now you can enable or disable the group of features related to ledger balance sheets just by toggling the LedgerBalanceSheets feature key. In addition to tables and menu items, you can also attach a feature key to Extended Data Types, Base Enums, indexes, individual fields, menus, and form controls. Both ledger balance sheets and ledger coverage, along with a number of other functions, belong to the same major group of functions that deal with ledger as such. To reflect this structure, you can create a Ledger feature key that is the parent key to all functionality dealing with ledger. In the illustration below, you can see that Ledger is the parent of a whole range of feature keys. You can now enable or disable all ledger functionality by toggling the Ledger feature key.
Columbus IT Partner Russia, ApS
50
Navision Axapta
Pic. 3-20 With the above feature keys structure you can • Enable the complete set of ledger functions • Enable ledger functions, but disable the functions that have to do with ledger account references, ledger allocation, ledger alternative accounts and so on. When you have created the appropriate feature keys, you apply them on the relevant application objects by setting the FeatureKey property. In the standard application for example, the Ledger feature key has been applied to the LedgerTable table, to the LedgerBalances table etc., the LedgerAllocation feature key has been applied to the LedgerAllocateTrans table, and to the LedgerAllocation table etc. There are several advantages to using feature keys to manage application functionality: • The user’s working environment does not become clouded with features and facilities he does not use. • As tables and fields that have been disabled through the feature key system are not created in the database, database load decreases yielding a positive influence on performance. When you have defined feature keys and applied your keys to application objects, use the Feature key setup form to view your feature key hierarchy and to turn keys on and off. • A default setup is automatically loaded when the system in installed. As part of the installation process, you are presented with this setup and given the opportunity to disable individual keys. When you define a feature key, you also define where the key should have effect. A feature key may enable or disable features • in the user interface only, • in the database or • in the user interface as well as in the database.
User interface When a feature key that has effect on the user interface is activated, this means that application objects grouped under that key are visible in the user interface. When the feature key is not activated, the objects, for example menu items, automatically disappear from the interface.
51
Columbus IT Partner Russia, ApS
Navision Axapta
Database Activating a feature key that has effect on the database means that the application objects – typically tables - grouped under the key, exist in the database. De-activating the feature key on the other hand means that the objects are removed from the database. You will probably very rarely use this option.
User interface + Database Most feature keys will probably have effect on both the database and the user interface. When such a feature key is active, the objects controlled by the key are present in the database and in the user interface. When the feature key is not active, the objects do not exist in the database and are consequently not displayed in the user interface.
Define and enable a feature key 1. Define a feature key Right-click the Feature Keys node and choose the New Feature Key command.
Pic. 3-21 Use the property sheet to define the feature key. Normally you will define a feature key in relation to one or more other feature keys. 2. Set the FeatureKey property on the application objects you wish to group under the feature key. You can set the FeatureKey property on an Extended Data Type, a Base Enum, the individual values of a Base Enum, a table, an individual field, an index, a form control, a menu or a menu item. 3. Open the Feature key setup form to ascertain that your feature key has been included. You can open Feature key setup from the Feature keys menu, a submenu on the Administrator menu.
Disabling a datebase feature key A feature key can be of three types: • User Interface • Database or • User Interface+Database The type is defined by the Type property on the feature key. When a feature key of the latter two types is disabled, this has impact on data whereas meta data in your application object database (Ax???.aod) are not affected. For example, if you disable the customer table feature key, all records in the customer table are removed from the database but the customer table application object remains in the application object database. This means that constructions like select custTable where .... will not fail even when no data exist in the database.
Columbus IT Partner Russia, ApS
52
Navision Axapta
Creating a feature keys hierarchy 1. Right-click an existing feature key and choose the Add Parent Feature Key command. This creates a new, empty node.
2. Use the property sheet to set the FeatureKey property to one of the existing feature keys. The new
node is the parent node. You can use the parent node in the feature key hierarchy to enable or disable all child features.
Feature key organization The full Axapta package consists of a number of series corresponding almost to the submenus on the Main menu. Example of series are Ledger, Bank, Sales, Cust, Purch, Vend, Invent, and so on. To make it easy to set up feature keys, both with respect to global availability of features and with respect to the security system, feature keys are organized in the same manner for all series. The overall idea is to have four basic feature keys for each series: • One that should be used for the basic features within a series, called Default. • One that should be used for features that form extensions to the basic functionality, called Extended. • One that should be used for various minor options within a series, called Options. • One that should be used for features that have a concealed dependency to some other feature, called Dependencies. Each feature key has the name of the series as a preface. Feature key
Type of features the key should be used for
<series>Default
Features that comprise the standard functionality within the series. As these features comprise the standard, basic functionality, they cannot be disabled globally for the system and consequently the Feature property has been set to No. User group access can be defined for the features, though, and the Security property has been set to Yes. Example: Chart of accounts in the Financial series. The Chart of accounts is basic in the series and disabling it would make no sense. On the other hand, users may well have different permissions with repect to the chart of accounts information.
<series>Extended
Features that go beyond the standard functionality but are a natural extension to the basic functionality within the series. As these features are extensions to the basic functionality, they can be disabled globally for the systen and consequently the Feature property has been set to Yes. User group access can also be defined for the extended features, and the Security property has been set to Yes. Example: Periodic journals in the Financial series. Using periodic journals goes beyond basic ledger functionality and constitutes an extension to the necessary ledger features. It is a feature that can be de-selected globally, and for each user group access can be defined.
<series>Options
Specific and detailed options within the series. As these features are optional, they can be disabled globally for the system,
53
Columbus IT Partner Russia, ApS
Navision Axapta and the Feature property has been set to Yes. The Security property has been set to No because it does not make sense to restrict access to the feature. Example: Contact person for project in the Project series. Having a contact person for projects is a option some companies may choose to use while others will not want it. For the companies that do use it, though, is does not make sense to set up varying degrees of user group access. <series>Dependencies
Features that depend on the availability of some other feature to make sense. The user should not have to make any decisions about these feature keys in either of the feature key setup dialogs. The properties Feature and Security have both been set to No for the Dependencies feature key. Example: Production BOM in the Production series. When the user has chosen production bills of material as part of the production setup, he has implicitly chosen bills of material within Bills of material as well. Therefore bills of material within production is also a child of BOM dependencies.
Tip As both Feature and Security properties have been set to No, dependency feature keys cannot be seen in either of the two dialogs. To be able to see them in the dialogs, right-click to open a shortcut menu and choose Extended tree. Typically the feature keys have the Type property set to User interface + Database which means that when disabled globally from the Feature key setup dialog, the application objects concerned are removed from the interface and from the database. The figure below illustrates the feature key organization and the settings of the Feature and Security properties.
The ledger series is an example of the feature key organization.
Columbus IT Partner Russia, ApS
54
Navision Axapta
The feature keys are hierarchical: Default and Extended are children of the <series> feature key and Options and Dependencies are children of Default.
As the feature keys structure is hierarchical, a feature key may be a child of (a child of a child of ...) a child of one of the four standard keys mentioned above. And a key may have more than one parent. The ANDParents property is relevant for feature keys that have more than one parent.
3.9. Backup of Application Objects Using the application object export import facilities Use Axapta’s application object export-import facilities for backup purposes, or if you want to re-use objects from one Axapta installation at another one.
A typical export-import workflow for selected application objects could be 1. Open the Application Object Tree. 2. Select the objects you want to export.
To ease the process of exporting objects of different types, create a project with the objects you want to exportThen select individual objects in the project or export the entire project. If you choose to export the entire project, the individual objects as well as the project with all objects are exported.
3. Choose Export on the Command menu, or on the Application Object Tree shortcut menu. 4. Make the export file available at the Axapta installation where you want to use the application objects, for example on a network drive or on a disk. 5. Open the Application Object Tree at the Axapta installation where you want to import application objects. 6. Choose Import on the Command menu, or click the import icon in the toolbar. 7. Locate the import file and open it. The objects in the export file are presented in a tree structure where you can select all or only some objects. 55
Columbus IT Partner Russia, ApS
Navision Axapta
Export application objects 1. Open the Application Object Tree and select the objects you want to export. 2. Choose Export on the Command menu. 3. In the Export dialog, select the application object layer checkbox if you want to export from another layer than the current one. Selecting the layer checkbox enables the list with all layers.
You can always see the current layer in the status barIf you want to export an entire application layer, make sure that the current node is the AOT root node and then select the relevant layer.
Use the Browse button to find a location and a name for the export file. The file name list holds the five most recently used .xpo file names. The extension for an export file is .xpo. 4. Click Export to perform the export with the selected options.
Import application objects 1. Open the Application Object Tree. 2. Choose Import on the Command menu. 3. In the Import dialog, use the Browse button to locate the file to import and open it. The file name list holds the five most recently used export file names. The objects in the export file are presented in a tree structure.
Pic. 3-22 Initially all objects in the tree are selected for import. To de-select individual objects, expand the branches in the tree and clear the checkbox next to the object you want to exclude from the import. The names of objects that already exist in the Application Object Tree appear in bold in the import tree. The AOT shortcut menu is available in the import dialog. Particularly the Compare command is helpful in deciding whether you want import a particular application object.
All commands in the shortcut menu are performed on objects in the Application Object Tree. For example, if you use Find and replace or Replace source, you are doing the replace in the AOT.
4. Click OK to perform the import with the selected options. Columbus IT Partner Russia, ApS
56
Navision Axapta When you click OK, a warning appears if one or more objects already exist in the Application Object Tree. You can choose to evaluate each individual object, or click Yes to all/No to all.
Delete table and class members This check box only has effect for application objects of types table and class. For other application object types, the check box is always implicitly selected and they are always overwritten. When the check box is not selected, the import overwrites existing members. If the application object in the AOT has more members, for example additional methods, these methods are untouched. When the check box is selected, the import overwrites existing members AND deletes members in the AOT that are not present in the import file. The overwrite check box had effect for these member types: For tables
Fields Field Groups Indexes Relations Methods
For classes
Methods You always import objects into the current application object layer.
A note about exporting tables and classes During export and import, tables and classes are handled differently than other application object. When you export a table or a class, only the members (fields, field groups, indexes, relations, and methods) that have been created or modified in the layer you are exporting from are included in the export. When you later import such objects, you should make sure that the Delete table and class members check box is not selected. As opposed to tables and classes, application objects like forms, reports, and queries are always fully exported. This means that for example all methods, controls and so on are exported, whether or not they have been created or modified in the current layer.
3.10. Tips Setting development options The Options... command on the Tools menu opens a dialog where you can set various system options. One of the tab pages in particular, the Development tab page, is useful during the development process. To view the development options 1.
Click Options... on the Tools menu.
2.
Click the Development tab.
General Startup project
Load this project on startup.
Application object layer
Use the Application object layers list to define layer view on objects in the
57
Columbus IT Partner Russia, ApS
Navision Axapta tree. Show no layers No objects are labeled with layer indications. Show all layers All objects are labeled with layer indications for all layers in which they exist. Show highest layer All objects are labeled with layer indication for the highest layer. Show corrected layers Only objects that have been modified in the current layer or a higher one are labeled and only with indication for the highest layer. Show all from corrected layers Only objects that have been modified in the current layer or a higher one are labeled but with indication for all layers. Message limit
Number of lines in the message window. When this limit is reached, the lines are discarded. To view the discarded lines, you can examine the object’s log file in the system’s main directory. Log files are called comp.log, for example Bankcomp.log for the log file resulting from a compile of the object called BankAccountReconcile. These log files are temporary and the file names are not unique. The log file in the above example is overwritten when you next compile an object called, for example, BankDepositSlip.
Cross reference
Select this if you want the system to update X-reference data automatically when you compile. Selecting the Cross-reference box invariably slows down compilation. On the other hand, you will always have updated information when you want to use the cross-reference system or the Application Hierarcy Tree utility.
Development warnings
Select this if you want developer warnings during X++ code translation. A warning is given if, for example, SQL statements exist that will most probably result in inferior performance. The SQL statements below result in a warning if a key on the table myTable with the fields myField1 and myField2 does not exist: select * from myTable where myTable.myField1==x && myTable.myField2==y;
AOT Log
Have information during import, export, and compile written to a log file.
Debug Show debug information
Check this if you want the debugger to show the debug information window.
The debug information window is the small window in the lower right corner and the debug stack window is the one in the lower left corner that shows the Columbus IT Partner Russia, ApS
58
Navision Axapta call stack. Show debug stack
Check this if you want the debugger to show the debug stack.
Debug mode
Use the Debug mode list to define when the debugger is activated. No The debugger is never activated. Always The debugger is activated X++ code when is executed. On Breakpoint The debugger is activated when a breakpoint in the X++ code is encountered.
Editor Overwrite selected text
Check this if you want typing to replace selection in the X++ editor.
IntelliSense
Check this if you want to use automatic IntelliSense features in the X++ editor.
Insert at cursor
Enable insert mode (as opposed to overwrite mode) in the editor.
Auto Auto-update
Enter the number of seconds the system should wait before initiating a new update cycle. Entering 0 disables the system’s update cycle. An update cycle comprises three types of updates: •
Auto-refresh
•
Auto-save
• Garbage collection When you have given an interval here, you can enable or disable the three options individually. Auto-refresh
Check this if you want the system to update application objects automatically so that objects made by other users become available to all users. In addition, the system updates lock indications in the Application Object Tree. You can also refresh manually using the Refresh command in the shortcut menu on for example the Forms or the Queries nodes. Note Refresh is one of the three components in an update cycle, and is performed only when an update cycle interval is given (the Auto-Update option).
Auto-save
Check this if you want the system to save application objects automatically. When the Auto-Save option is enabled, the system automatically saves unsaved objects when you exit. Note Automatic save is one of the three components in an update cycle, and is performed only when an update cycle interval is given (the Auto-Update option).
Garbage collection limit
Number of application objects no longer in use. MorphX automatically performs garbage collection when the number given here is reached. The system uses memory each time an application object is opened in the Application Object Tree. Unless a value is given here, application objects are never discarded from memory. Note Garbage collection is one of the three components in an update cycle, and is performed only when an update cycle interval is given (the Auto-Update option).
59
Columbus IT Partner Russia, ApS
Navision Axapta Best Practices Click Check Best Practices on the AOT shortcut menu to perform checks according to the below selections. General check
Various checks (for example for the use of the AutoDeclaration property) not covered by the specialized checks listed below.
Check AOS
For optimal AOS performance, hints are given on setting methods and classes to run on client or on server. Note The hints given here are based on a static analysis and consequently they may not tell the whole truth about AOS performance. AOS hints should only be implemented after careful evaluation using the best of your knowledge of the dynamics of application execution. To learn more about AOS hints, refer to Developer's Guide books "Axapta Object Server: How it Works" and "Axapta Object Server: Best Practices for Application Development"
Check label use
User interface texts are implemented using labels, for example @SYS23660 rather than "Auto update". Text constants in single quotes in X++ code should be system related text that does not appear on the user interface. Consequently it is not required that they are implemented using labels.
Check AOT path
Each path in the Application Object Tree is unique. This means that all subnode for a given node must be named differently.
Trace Database trace
Select this if you want the system to trace to the message window whenever the database is accessed.
Method trace
Select this if you want the system to trace to the message window whenever a method is activated.
Client-Server trace
Select this if you want to include information about where classes are executed.
ActiveX trace
Select this to enable tracing of ActiveX control events. This means that all events fired by the ActiveX controls are logged in the message window. Different ActiveX controls fire different events, but most ActiveX controls share a common set of events, such as MouseMove, MouseDown, MouseUp, KeyDown, KeyUp, etc.
Property sheet Sort alphabetically
Select this option to have properties sorted alphabetically when displayed in the property editor.
Easing your login procedure When you start Axapta, the first dialog that appears is the Logon dialog:
Pic. 3-23
Columbus IT Partner Russia, ApS
60
Navision Axapta Because Axapta supports unified login, you can bypass this dialog and have Axapta depend on your operating system login name and authorization check.
To make Axapta use your operating system’s integrated security 1. Click Options on the Tools menu. 2. On the General tab page you can see the name you have used to logon and possibly your full name. 3. Enter your operating system name in the field labeled OsAccountName.
Pic. 3-24 The next time Danny Jansen starts Axapta, it will check whether he exists as a user and since he does, he never sees the logon dialog.
Modifying other users The User setup dialog above gives you access to modifying your own setup only. If your have administrator permissions in Axapta, though, you also have access to other users’ accounts and to create and modify user information. To simplify other users’ login procedure by making Axapta depend on their operating system account names, use the Administrator menu. 1. Double-click Users on the Administrator menu.
61
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 3-25 2. Make sure that you have given the operating system user name in the User dialog.
Pic. 3-26 In the example above the user, Peter Smith, has given his operating system account name as peter. When Peter Smith next starts Axapta, it will check whether he exists as a user and since he does, he never sees the logon dialog.
Using Windows Regional Settings Windows Regional Settings are read when the Axapta system is started. Axapta uses the settings listed below.
Number settings Country code Decimal symbol (decimal separator) No. of digits after decimal Digit grouping symbol (1000 separator) Negative number format Display leading zeros
Time settings Time separator (':','/',' ' or '.') AM/PM or 24 hours Columbus IT Partner Russia, ApS
62
Navision Axapta
Date settings Short date style Date separator ('/','-' or '.')
Reports run on the server uses the client's regional settings.
How do I locate… When you have opened a form from the Main menu, use the Setup command on the form's shortcut menu to locate various kinds of information about the form. 1. Right-click a form to open the shortcut menu.
Pic. 3-27 2. Click Setup to open the User setup form.
Pic. 3-28 Use the Information tab and the Add-Ins button to locate various types of information about the form.
For each control the Permissions section displays the name of the feature key used as well as the access. Click More info... to display the Feature key permissions tab on the Users dialog. This
Locate the name of an application object 1. Click the Information tab in the User setup dialog to view the form name.
63
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 3-29 2. Using the name, you can now locate the form in the Application Object Tree yourself.
Locate the form in the AOT and open it in a seperate widow 1. Click the Fields tab in the User setup dialog. 2. Click the Add-Ins button, point to Open new window and then click Open application object window. The form is now opened in a window of its own.
Locate the label ID for a container control 1. Click the Fields tab in the User setup dialog. 2. Select the container control in the tree structure. 3. Click the Add-Ins button and then click Properties. The property sheet for the control is now opened. Properties can be viewed for other types of controls as well but typically their label is inherited from and Extended Data Type and consequently not immediately visible from the control's properties.
Locate the name of a field behind a control 1. Click the Fields tab in the User setup dialog. 2. Select the container control in the tree structure. 3. Click the Add-Ins button and then click Properties. The property sheet for the control is now opened. The DataField and DataSource properties display information about the underlying data source.
Add company logo to the Main menu When the Main menu opens, it displays the name of the license holder and the installation's serial number. The information is obtained from the License information dialog and shown also in the About box. To add your company logo in bitmap On the server, place a bitmap file called "companylogo.bmp" in the application folder's \share\include directory.
Executing commands on startup When Axapta starts, the startup methods on the fundamental application classes Application (appl. startup()) and Info (info.startup()) are called. Use this if you need to have a command executed on startup. Columbus IT Partner Russia, ApS
64
Navision Axapta
The startup methods are used for vital system and version specific calls, and you should never modify them directly. Serious consequences may follow if the SYS layer versions of the methods are not called.
Instead, use the SysStartupCmd class framework available for this specific purpose. Calls on startup are executed in this sequence: appl.startup() //here the SysStartupCmd class is instantated sysStartupCmd.applInit() super() sysStartupCmd.applRun() info.startup() sysStartupCmd.infoInit() super() sysStartupCmd.infoRun()
Execute a command on startup 1. Create a class that extends the SysStartupCmd class to perform your specific task. Example: In the standard application the class SysStartupCmdBuildNoSet is used to set the build number. Use a similar approach for your task. 2. Modify the construct method on the SysStartupCmd class so that your class is called. Example: /* code lines left out here */ switch (s) { case 'SetBuildNo': return new SysStartupCmdBuildNoSet(s,parm); case 'UpdateBuildNo': return new SysStartupCmdBuildNoUpdate(s,parm); } /* code lines left out here */ 3. If you need to add parameters to commands executed on startup, add them to the Startup command field on the General tab in the Axapta configuration utility. Example: In this example, the application build number wil be set to 493 when Axapta starts. Instead of giving the command from the Axapta Configuration Utility, you may choose to use the command line parameter -startupcmd=.
65
Columbus IT Partner Russia, ApS
Navision Axapta
4. Working with MorphX Development Tools The Application Object Tree constitutes your normal view of the application object database when working in Axapta’s integrated development environment. In additions to the AOT, however, MorphX includes a number of tools that offer alternative views on the object database.
Pic. 4-1 Using the various tools you can customize your view of application obejcts to suit your current work situation and thus facilitate the development process. The MorphX development tools are: Name
Use the tool to...
Application Hierarchy Tree
Use the Application Hierarchy Tree tool to improve your overview of how your classes, tables, and Extended Data Types are inherited. The objects are presented in a hierarchical tree structure that enables you to see how objects extend each other.
Application management
Use the Application management tool to record the developers responsible for the individual application objects. Click the Update command on the Tools submenu to generate your own updated application management list.
Application object
Use the Application object tool to generate an alternative view of the objects in the Application Object Tree.
Count of application objects
Use Count of application objects to count application objects and code lines on the different methods in the Application Object Tree.
Cross-reference
Use the Cross-reference system to see the connection between variable names, type names and application paths. The cross-reference system gives you direct access to modify X++ code.
Last choice
Use Last choice to get an overview of the most recent database updates. Last choice lists manipulations that were made through a query or through a job execution.
Locked application objects
Use Locked application objects to have an overview of all application objects that are currently locked. You can also use the dialog to remove a lock.
Number of records
Use Number of records to make the system count the number of records in each table in the current company.
Report Wizard
Use the Report Wizard to help you create a report. The wizard takes you through the necessary steps and offers to save the report in the Application Object Tree.
Columbus IT Partner Russia, ApS
66
Navision Axapta Table Definitions
Use Table Definitions to generate a report presenting an overview of selected tables. The overview includes fields, types, labels, feature keys, and help texts.
Visual MorphXplorer
Use the Visual MorphXplorer to visualize the relationship between tables and classes by drawing Entity Relation Diagrams.
To access the tools click the General tab on the application’s main menu and then expand the Development menu. Alternatively, you can click the Development submenu on the system’s Tools menu. Many of the tools are also available on the Add-Ins submenu on the AOT shortcut menu. When activated from the Add-Ins submenu the tools take the current node as point of departure. Typically a tool like for example Application Hierarchy Tree would be activated with a specific node as its point of departure.
4.1. Using the Cross-Reference system The Axapta cross-reference system was designed to improve your overview of application objects. The cross-reference system can answer questions like • Where is a field accessed (read/written)? • Where is a method activated from? • What are the type names used in the system? • What are the variable names used in the system? Cross-references are based on what happens in the X++ code, on labels, and on information in the property sheets. The latter comprises information about the use of tables, fields, indexes, Extended Data Types and Base Enums. To be able to use cross-references you must make the system generate the necessary information first.
Create a cross-reference system Creating a cross-reference system for your application is very easy! You just click Update Periodic on the Cross-reference submenu. The Cross-reference submenu is located on the Development submenu on the Tools menu. In the update dialog you can check
This means that...
Delete all
All previously generated cross-reference information is deleted.
Update all
The complete cross-reference update starts. This is how you should first generate your cross-reference system. Note This is a time-consuming process as the entire application is re-compiled and approximately 500,000 records are updated.
Selective
Selected information only is updated. Use the Select button to enter range and sorting criteria for the information that must be updated. When you click Select, a dialog is opened where you can choose which application objects you wish to generate cross-references for. Tip You will normally update selectively when you have made modifications to your application.
67
Columbus IT Partner Russia, ApS
Navision Axapta Update data model
Cross-reference information used by the MorphXplorer is updated. Tip If you want to update only what is strictly necessary to use the MorphXplorer, click the Select button and make a select on a non-existent object, for example Record Type ”Displaytool” and Name ”z” (click the Advanced button in the query form to see Name).
Update type hierachy
Cross-reference information used by the MorphXplorer and the Application Hierarcy Tree is updated.
You can use the Batch button in combination with any of these selections. When you click Batch a dialog is opened where you give batch parameters, for example start date and start time. You will normally use Batch to ensure that periodic updates are undertaken when the system is not heavily loaded.
Having the system update cross-references automatically If you do not want to manage periodic updates yourself, you can choose to have the cross-references updated automatically 1. Click Options on the Tools menu. 2. Click the Development tab and check the XReferences box.
This means that whenever you make modifications, save and compile then your crossreferences are updated automatically. This will increase the save and compile time somewhat.
Using the cross-reference system When you have generated your cross-reference information, the system provides three ways to access it Names When you click Names the system provides a list of application objects with name, type, and number of references in the cross-reference system.
Pic. 4-2 Application object
Name
Type name
The object’s type, for example ”Extended Type”, ”Table”, or ”Class”.
The name of the application object.
The name of the application object type. If the ”Type name” field is empty, the entry is a reference to an application object defined in the
Columbus IT Partner Russia, ApS
68
Navision Axapta tree. In the illustration above, there is an application object named ”ZipCode” of the ”Table” type in the tree. If the ”Type name” field is not empty, the entry is a reference to something defined on a type or declared of a type. The type is listed in the Type name field. Examples: A variable will have its variable name in the name field and its type in the Type name field. A field will have its name in the name field and its table name (it's type) in the Type name field A static method in a class will have its name in the name field and its class name in the Type name field Clicking the References button opens a list of references with paths in the Application Object Tree.
Pic. 4-3 The list shows actions on the selected object: The variable is declared, read, written in the Construct method of the InventABC class, and it is declared in the InventABCUpdate class. Path When you click Path the system provides an overview of paths in the Application Object Tree. In the window you can see: • The path in the Application Object Tree. • The date and time of the most recent cross-reference update. • The id of the user who performed the cross-reference update. • The number entries in the cross-reference system (”References”). • Whether the object is still valid. Deleted objects are not automatically removed in the crossreference system. Click the Delete all Non Valid button to remove them. You can use the information to see where objects are used in the X++ code. The References button lists each entry in the cross-reference system. The illustration below lists the 8 references to \Classes\AVI\Length and provides an overview of what happens in the X++ code. The Edit button opens the X++ editor to allow you to modify your selection. The illustration below shows the editor when the line \Classes\AVI\Length was double-clicked. The deleteAllNonValid button automatically removes all objects with the Valid box unchecked. 69
Columbus IT Partner Russia, ApS
Navision Axapta
4.2. Generating an Application Hierachy Tree To generate an application hierarchy tree: 1. Point to the Tools menu, then the Development submenu and click Application Hierarchy Tree.
Pic. 4-4 The left pane displays the object types available in hierarchy view. The right pane is empty until an object in the left pane is selected. When you expand one of the nodes, information about the the current node is displayed in the right pane. The nature of the information displayed depends on the type of the node.
For classes and tables particularly, the most beneficial way to access hierarchy information is to activate Application Hierarchy Tree from the Add-Ins submenu on the AOT shortcut menu. The selected class or table is then the point of departure for the tree.
The illustration below is an example of three levels of inheritance hierarchy on a string type.
Pic. 4-5 Right-click a node in the hierarchy tree to open a shortcut menu. Use the Search command to have a complete one-level list of the selected object type rather than a hierarchical view.
Application Hierarchy Tree information What object types are you looking for information about? Application Heerachy Tree information for tables For tables information about methods, fields and indexes is displayed.
Columbus IT Partner Russia, ApS
70
Navision Axapta
Pic. 4-6 A static method is indicated with preceeding double colons, for example ::CreditMax. A mandatory field (the Mandatory property on the field has been set to Yes) is marked with an asterisk (*). A unique index (the AllowDuplicates property on the index has been set to No) is marked with two asterisks (**).
As the Application Hierarchy Tree is available for system tables as well, use it to view system table indexes. System tables are marked with a red padlock symbol in the Application Hierarchy Tree.
Application Hierarchy Tree information for classes The first column lists the methods on the selected class. The following columns list the superclass methods that have been overridden within the subclass.
Pic. 4-7
The same information, though without method information, can be created and displayed graphically using the Visual MorphXplorer.
A static method is indicated with preceeding double colons, for example ::ValidateAccount. The Application Hierarchy Tree is available for both system and application classes. System classes are marked with a red padlock symbol in the Application Hierarchy Tree. Right-click a class in the Application Hierarchy Tree to open a shortcut menu. The commands Compile forward and Compile backward are particularly useful. Compile forward
compiles the current class and all its children.
Compile backward
traverses the tree to the parent of the current class and compiles the root parent and its children down to and including the current class.
71
Columbus IT Partner Russia, ApS
Navision Axapta Use Show X-ref on the shortcut menu to switch to viewing cross-reference information. The toggle-facility is useful for locating variables, for example with the purpose of ensuring that they have been named consistently. Application Hierarchy Tree information for data types For all types, the Label and the HelpText properties are inherited so this is the information provided by the Application Hierarchy Tree.
Pic. 4-8
The Search on the shortcut menu is particularly useful for types. Use it to have a complete one-level list of types rather than a hierarchical view.
The Add-Ins submenu is also available on the shortcut menu. Use for example the cross-reference system's Used by command to explore where a particular data type is being used.
If information for a hierarchical view is not available... When you activate Application Hierarchy Tree you may be presented with a message like this one.
Pic. 4-9 The message indicates that the system does not have sufficient information to present the tree. To generate this information you must update the cross-reference system. 1. Point to the Tools menu, the Development submenu, then Cross-reference, and click Update on the Periodic submenu. 2. Make sure that Update type hierarchy is checked and click OK.
4.3. Using the MorphXplorer You use the MorphXplorer to visualize the Axapta data model by drawing Entity Relation Diagrams. You can depict the relations between tables with this information: • The current table’s 1:n relations. • The current table’s n:1 relations. • The classes that use the current table. • The maps that the current table is a part of.
Columbus IT Partner Russia, ApS
72
Navision Axapta
Pic. 4-10 You can also depict relations between classes.
Pic. 4-11 In a class visualization diagram you can depict: • What classes the current class uses. • What classes the current class is being used by. • The current class’ super class. • The current class’ sub classes. All commands for visualization are available on the current object’s shortcut menu. Using the General and Colors tabs, you can give any diagram a title and define your own color setup.
Creating a tables relation diagram 1. Click the General tab in the Main menu, then expand the Development node and double-click MorphXplorer. Alternatively you can open the Explorer from the Development submenu in the Tools menu. 2. Right-click anywhere in the dialog to open a shortcut menu and click Table in the New submenu. 3. Double-click the name of the table you want to see relations for. A rectangle representing the table appears. Click at the position where you want to place the visualization of the table. A rectangle with rounded corners represents the table.
Pic. 4-12
73
Columbus IT Partner Russia, ApS
Navision Axapta The rectangle is labeled with the name of the table, the table label, the table id, and the company (or the virtual company) that the table belongs to in your current setup.
If the textual information is difficult to read, use the Zoom command on the shortcut menu.
4. Right-click the table rectangle to open a shortcut menu and click n:1 or 1:n on the Relations submenu. Clicking n:1 opens a list of tables that the current table has a many-to-one relationship to. The list gives the name of the table and the name of the relation. If the relationship is expressed by a relation explicitly defined on the table, the relation name is preceded by a plus sign, for example '+BankAccountTable'. Typically, the relation consists of more than one field. If the relationship is expressed by a relation explicitly defined on the table, and it is a Field fixed conditional relation, the relation name are surrounded by parenthesizes, for example '+(Bank)'. Typically, it is an optional relation. If the relationship is expressed through an Extended Data Type, the name of the field is given. Examples: The Address table has a many-to-one relationship to the CompanyInfo table. This is defined by the CompanyData relationship on the Address table. The Address table also has a many-to-one relationship to the Country table. This is defined by the Extended Data Type on the Country field in the Address table. Clicking 1:n opens a list of tables that the current table has a one-to-many relationship to. The list gives the name of the related table and the name of the relation. For the example above, the Address table, the 1:n submenu has no entries. However, when the current table is CustTable, one of the entries in the list is CustTrans, AccountNum. This means that the CustTable table has a one-to-many relationship with the CustTrans table expressed by the Extended Data Type on the AccountNum field.
If the list of relations is empty this may be because you have not generated cross-reference information that the Visual MorphXplorer depends on.
5. Select a table in one of the lists and click anywhere in the MorphXplorer window. The symbol for the table is positioned where you click and the relation is automatically drawn as a line between the two tables. Repeat steps 4 and 5 for each new table you want to add to the MorphXplorer diagram.
You can join two identical objects by positioning them on top of each other.
Include class and map information in a table relations diagram When you have created a table relations diagram, you can include information about the classes that use the current table and information about the maps that the current table is a part of.
To include classes information 1. Right-click a table in a tables relation diagram 2. In the shortcut menu, click Used by in the Composition submenu. 3. Select a class and position it.
To include maps information Columbus IT Partner Russia, ApS
74
Navision Axapta 1. Right-click a table in a tables relation diagram 2. In the shortcut menu, click Maps in the Generalization submenu. 3. Select a map and position it.
Pic. 4-13
Creating a classes diagram 1. Click the General tab in the Main menu, then expand the Development node and double-click MorphXplorer. Alternatively you can open the Explorer from the Development submenu in the Tools menu. 2. Right-click anywhere in the dialog to open a shortcut menu and click Class in the New submenu. 3. Double-click the name of the class you want to investigate. A rectangle representing the class appears. Click at the position where you want to place the visualization of the class.
Pic. 4-14 The rectangle is labeled with the name of the class, an indication of where the class is, and the class id. 4. Right-click the class rectangle to open a shortcut menu and click Using or Used by in the Composition submenu. Clicking Using opens a list of classes that the current class uses. Clicking Used by opens a list of classes and tables that use the current class.
If the list of classes is empty this may be because you have not generated cross-reference information that the MorphXplorer depends on.
5. Select a class in one of the lists and click anywhere in the MorphXplorer window. The symbol for the class is positioned where you click and the relation is automatically drawn as a line between the two classes. Repeat steps 4 and 5 for each new class you want to add to the class diagram.
You can melt two identical objects by positioning them on top of each other.
Including super and sub classes information in a class diagram When you have created a class diagram, you can include information about the sub classes of the current class and about which is the current class’ super class. 75
Columbus IT Partner Russia, ApS
Navision Axapta 1. Right-click a class in a class diagram 2. In the shortcut menu, click Super Class or Sub Classes in the Generalization submenu. Note that there is only one super class while there may be a number of sub classes. 3. Select a class and position it.
Opening, saving, and printing diagrams from the MorphXplorer To open a diagram in the MorphXplorer 1. Right-click anywhere in the MorphXplorer window. 2. Click Load in the shortcut menu. 3. Select the Varchart project file (*.vcn) you want to open and click Open.
To save a diagram in the MorphXplorer 1. Right-click anywhere in the MorphXplorer window. 2. Click Save in the shortcut menu. 3. Enter a name for your diagram and click Save. You may also choose an existing file and overwrite it.
To print a diagram from the MorphXplorer 1. Click the print button in the toolbar. 2. Click Print to start printing the diagram. The MorphXplorer printing environment also allows you to • Scroll with the Next and Previous buttons. • Show as single or multiple pages with the Single button. • Define your page layout with the Page layout button. • Set up your printer with the Printer setup button.
Arranging, zooming, and copying in the MorphXplorer To arrange a diagram from the MorphXplorer 1. Right-click anywhere in the MorphXplorer window. 2. Click Arrange in the shortcut menu. All tables, classes, and relations are now re-arranged according to a best-fit algorithm.
The Arrange cannot be undone.
To zoom from the MorphXplorer 1. Right-click anywhere in the MorphXplorer window. 2. Click Zoom in the shortcut menu and select the zoom factor you want.
To copy from the MorphXplorer 1. Right-click anywhere in the MorphXplorer window. 2. Click Copy to clipboard in the shortcut menu. The diagram is now copied to the clipboard and you can paste it into the application you are currently working in, for example Microsoft Word. Columbus IT Partner Russia, ApS
76
Navision Axapta
Legend in the MorphXplorer The Visual MorphXplorer uses Unified Modeling Language (UML) notation.
Tables
Classes
4.4. Other Tools Using the application objects list To generate a view of application objects on a list format 1. On the Tools menu, point to the Development submenu, then the Application objects submenu, and click Application objects.
Pic. 4-15 77
Columbus IT Partner Russia, ApS
Navision Axapta Typically you will use the list view for search purposes. The list view displays one line for each application object. Use the Filter command on the shortcut menu to filter on for example a specific user or a type of application object. For each application object, this Information is available: UtilLevel
The application object layer that the object was created and saved in (sys, syp, dis, dip, and so on)
RecordType
The application object type.
Name
The name of the application object as you can see it in the Application Object Tree and in X++ code.
Type name
If the record type is a method, this column gives the name of the class or table that the method is a member of.
Modified by
The user who last modified the object.
Modified date
The date the object was last modified.
Modified time
The time the object was last modified.
Use the tabs to view general details, created and modified information and version control information.
Using the buttons in the dialog Edit
When the current line in the application list identifies a method, you can use the Edit button to open the X++ editor and modify the code directly.
Application management
Use Application management to handle application object review. With the Approve button in the Application management dialog you can stamp date and time information as well as your user id on the object.
Cross-reference
Use the Names or Path commands to see where the object is referenced. If you do not get the expected result, this may be because you have not generated the necessary cross-reference information.
Document handling
Use Document handling to open Axapta’s document handling system. The dialog lists the document references and corresponding notes attached to the selected record in the active form. You can choose between viewing all references or only those references typed by the current user. The dialog box allows you to:
Add-ins
•
Show notes
•
Create notes
•
Show documents
•
Create new documents
•
Edit existing documents
•
Print existing documents
•
Link existing document references to other references
Use the Add-ins button to access the commands in the Add-ins menu with specific reference to the object on the current line in the application object list, for example Compare or Find and replace.
Columbus IT Partner Russia, ApS
78
Navision Axapta
4.5. Creating Wizards A wizard is a special form of user assistance that automates a task through a dialog with the user. Wizards help the user accomplish tasks that can be complex and require experience. Wizards can automate almost any task, such as creating a new report, facilitating data import, or defining access rights. They are especially useful for complex or infrequent tasks that the user may have difficulty learning or doing, or for tiresome, often performed tasks. A wizard is a series of presentations or pages that helps the user through a task. The pages include controls that you define to gather input from the user; that input is then used to complete the task for the user. Examples of standard Axapta wizards are: • The Report Wizard that leads you through the steps of creating a report. The Report Wizard simplifies the report generation process in that the user is led through the steps necessary for creating a report. The wizard, though, does only what the user can do himself if he chooses to use the commands in the Report node’s shortcut menu. The Report Wizard is available from the Tools menu (choose Development, then Wizards and then click Report Wizard). • The Setup Wizard that guides you through setting up Axapta. The Setup Wizard ensures that you go through the large number of steps required to set up Axapta – in exactly the right sequence. The Setup Wizard starts automatically the first time you start Axapta. To help you create your own wizards with the same look and feel as the standards ones, Axapta includes a Wizard Wizard. Like the Report Wizard, the Wizard Wizard is available from the Tools menu. When you activate the Wizard Wizard, you open a wizard with some steps where you define the contents of the steps the user will go through in the resulting wizard. Step 1
A welcome dialog where you just click Next to continue. In the finished wizard you should use this page to describe the results of using the Wizard.
Step 2
In the naming dialog you must give the name of the wizard. You can choose the first part of the name freely must end in 'Wizard', for example SysTableAccessWizard. The objects (a private project, a class, a form, and a menu item) that are created as a result of the wizard-generation are automatically given identical names.
Step 3
In the type selection dialog you must choose which type of wizard you want to create. The choice will decide the context in which the wizard will appear. You can choose between •
a default wizard
•
a default data wizard, and
•
a feature key wizard.
Step 4
In the setup dialog you must choose the number of steps in the resulting wizard. However, you can add or remove pages later.
Step 5
In the last dialog you must click Finish to have the system generate the wizard.
The result of running the Wizard Wizard is the creation of a private project with three objects, a form, a class, and a menu item. To make the wizard perform the desired task, you must now modify the form and class objects. If the wizard is of standard type, you may also want to insert the menu item in a suitable menu.
79
Columbus IT Partner Russia, ApS
Navision Axapta
Use the Application Hierarchy Tree facility to get a list of all wizards in Axapta. 1. Open the Application Object Tree and select the SysWizard class. 2. Right-click to open the shortcut menu, point to Add-Ins, and select Application Hierarchy Tree.
Create a wizard 1. From the Tools menu, choose Development, then Wizards and click Wizard Wizard. 2. Click Next in the wizard wizard’s step one, the Welcome dialog. 3. Enter a name for the wizard in the wizard wizard’s step two, the naming dialog. Wizard naming: You must enter the wizard name in the top most field. The name must end in ”Wizard”, for example ”MyReportWizard”, ”MyFormWizard”. The fields below the Axapta object names heading are for information purposes only and cannot be modified. They are the names of the objects that are created automatically by the Wizard Wizard. To enable the Next button, click one of these fields. 4. Choose wizard type in the Wizard Wizard’s step three and click Next. The available wizard types are: • Standard wizard, • Default data wizard, and • Feature key wizard. A standard wizard is used to help the user perform general tasks. The Report Wizard is an example of a standard wizard. A default data wizard is used to help the user create necessary default data like address information and number sequences. All default data wizards are automatically included in the system’s Default Data Wizard and its status, whether it has been executed or not, is indicated. The Default Data Wizard can be started from the Axapta Setup Wizard that is automatically activated when you first start Axapta, and from the Company accounts menu. A feature key wizard is used to help the user set up feature keys. All feature key wizards are automatically included in the system’s Feature Key Wizard and its status, whether it has been executed or not, is indicated. The Feature Key Wizard can be started from the Axapta Setup Wizard that is automatically activated. 5. Choose number of steps required in the Wizard Wizard’s step four and click Next. This is the number steps that the Wizard Wizard creates automatically. You can always change the number of steps later simply by adding or removing a new tab page to the wizard form. The number of steps include the Welcome and the Finish dialogs. 6. Click Finish to complete the wizard generation. The result of running the Wizard Wizard is the creation of a private project with three objects: a menu item, a form, and a class. The objects have the name you entered in the Wizard Wizard’s naming dialog.
To complete the wizard • Give the wizard a title. Do this by modifying the Caption property on the Design node, or by using the description() method.
Columbus IT Partner Russia, ApS
80
Navision Axapta • Give each step, except the first and the last ones, a title and an explanatory text. Do this by modifying the Caption and HelpText properties on each tab page control. • Add a description of the results of using the wizard to the first tab page. Do this by adding a StaticText control to the tab page. • Add a description of the results of clicking the Finish button to the last tab page. • Add functionality (methods) to the wizard class. • Add visual layout to the wizard by modifying the wizard form. All multi line texts should be created as StringEdit controls. Recommended property settings AutoDeclaration
Yes
AllowEdit
No
Width
Column width
Height
Column height
Skip
Yes
Border
None
MultiLine
Yes
BackgroundColor
Button face (3D)
ShowLabel
No
• Make your wizard available from a menu using the wizard's menu itemNote
If you choose to run your wizard from the Application Object Tree, you should run the class and not the form.
Guidelines for wizard development The guidelines below are general Microsoft development guidelines available on http://msdn.microsoft.com that have been slightly modified to suit Axapta. • Model your Wizard after the ones that ship with Windows 2000 and Office 2000. • Always include a statement of purpose for the wizard on the first page and include a graphic on the left side of the page. The purpose of this graphic is to establish a reference point, or theme, such as a conceptual rendering, a snapshot of the area of the display that will be affected, or a preview of the result. You can continue to include a graphic on the interior pages for consistency or, if space is critical, use the entire width of the window to display instructional text and controls that require user input. • Minimize the number of pages that require the display of a secondary window. Novice users are often confused by the additional complexity of secondary windows. • Avoid a wizard design that requires a user to leave the wizard to complete a task. Lessexperienced users rely heavily on wizards. Asking the user to leave a wizard to perform a task can lead to confusion. Instead, design your wizard so that the user can do everything from within it. • Make it visually clear that the user interface elements in a graphic illustration on a wizard page are not interactive. You can do this by varying elements from their normal sizes or rendering them more abstractly. • Include default values or settings for all controls where possible. • Avoid advancing pages automatically. The user may not be able to read the information before a page advances. In addition, wizards are intended to allow the user to be in control of the process that the wizard automates. 81
Columbus IT Partner Russia, ApS
Navision Axapta • Display a wizard window so that the user can recognize it as the primary point of input. For example, if you display a wizard from a control that the user chooses in a secondary window, you may need to position the wizard window so that it partially obscures that secondary window. • Make sure that the design alternatives offered by your wizard provide the user with positive results. You can use the context, such as the selection, to determine which options are reasonable to provide. • Make sure that it is obvious how the user can proceed when the wizard has been completed. This can be accomplished in the text on the last page of the wizard.
The wizard class Depending on the type of wizard you chose, your wizard class extends either the SysWizard class, the SysBaseDataWizard class, or the SysFeaturekeyWizard class.
Useful methods on the SysWizard class boolean validate()
This method is called before the wizard is closed. Return false if the user input is invalid. This will prevent the run() method from being called when the user clicks the Finish button. The method is used to validate user input.
FormRun formRun()
Returns a formRun which is an instance of the form of the same name as the class. This method is always overridden but should not be changed.
static void main(args args)
Creates a new instance of the wizard and calls wizard.run on the SysWizard class. This method is always overridden but should not be changed.
void run()
This method is called when the user clicks the Finish button – if validate() returned true.
void setupNavigation()
Use this method to set up whether the Next and Back buttons should be enabled from the start. Default is that all is enabled, except back in the first step and next in the last. The buttons can then be enabled runtime when a certain condition is fulfilled.
Useful methods on the SysBaseDataWizard class boolean Enabled()
Determines whether the wizard should be displayed in the list of basic setup wizards.
boolean MustRun()
Determines whether the base data already there or whether the wizard should create it.
str Description()
Returns a short description of what the wizard does. The description is used in the wizard’s caption if the Caption property has not been set.
Useful methods on the SysFeaturekeyWizard class FeatureKey featureKey()
Determines which feature key, along with the feature key’s children, the wizard sets up. This method MUST return a valid feature key. If the feature key has been disabled, the wizard will not appear in the Feature Key Wizard (SysFeaturekeyWizard). Note Feature keys that have the Security property set to Yes cannot be disabled.
Columbus IT Partner Russia, ApS
82
Navision Axapta Such keys can be disabled as part of the user group administration only. The system class variable featurekeySet should reflect the user’s choice. The FeatureKeySet system class has the method boolean enabled(featureKey p1 [, boolean enable] ) to enable/disable the feature key.
The wizard form The wizard form has one tab and the number of tab pages you specified as steps in the Wizard Wizard. The following methods are available on the form: FormTabControl tab()
Returns the tab
classDeclaration()
Holds a variable named like your wizard of type sysWizard. In the run() method on the form the variable will be assigned to the wizard’s class.
On your own wizard controls Do not set the Left property to Left edge, and Do not set the Top property to Top edge. These settings do not conform with the Axapta wizard standard. Most frequently you should let the controls have Auto settings. The first and the last tab pages The first and the last tab pages have identical layout. These pages must only have controls where you can set the background color to white. The controls automatically have their color set to white and the AllowEdit property set to Yes. The middle tab pages The middle tab pages have identical layout. On these pages, the Caption and the HelpText properties are used. The Caption property is used as heading and the HelpText property is used as an explanatory text.
Pic. 4-16 All tab pages If the Visible property has been set to false, the tab page is skipped. If the Feature property has been set and the user does not have delete rights, the tab page is also skipped. This can be used to control the flow of the wizard.
Wizard tips Enable a button depending on user input When the user goes through wizard steps, you will occasionally need to make sure that he has entered the proper input before he is allowed to go on. In practical terms this means that the Next button should not be enabled until the user has entered the necessary information. Example: Input dependent button enable 83
Columbus IT Partner Russia, ApS
Navision Axapta This is used in the Database Log Wizard. On the Domains tab page, the user must select which domain he wants to register database changes for. He is not allowed to continue until he has actually made a selection.
Pic. 4-17 When you create a wizard using the Wizard Wizard, one of the methods that exists on your wizard class is called setupNavigation. This method used to set up the initial states of the Back and Next buttons on your wizard. Example: Enable Back and Next buttons On the SysDatabaseLogWizard, the setupNavigation method looks like this: void setupNavigation() { nextEnabled[2] = false; } The single statement disables the Next button on the second tab page. The test to discover whether the user has entered the required information and the Next button enabling is performed on the relevant form control method. Example: Testing user input For the SysDatabaseLogWizard the relevant form control is the ListView control that displays the list of companies: int mouseDown(int x, int y, int button, boolean ctrl, boolean shift) { //statements missing .... { // statement missing .... Columbus IT Partner Russia, ApS
84
Navision Axapta sysWizard.nextEnabled(true); } return ret; } Another example: On the SysWizardWizard form is another example of enabling the Next button. On the Naming tab page, the user must enter a wizard name that ends in "wizard" before the Next button is enabled. The code to test whether this condition has been fulfilled is located on the StringEdit control's textChange method: #define.nameTab(2) void textChange() { super(); // statements missing... { if (!sysWizard.isNextEnabled()) { sysWizard.nextEnabled(true, sysWizard.curTab(), false); } } else { if (sysWizard.isNextEnabled()) sysWizard.nextEnabled(false, sysWizard.curTab(), false); } } Two things are interesting here: • The use of isNextEnabled() to test whether the Next button has been enabled, and • The two additional parameters to nextEnabled. The second parameter (sysWizard.nextEnabled(false, sysWizard.curTab(), false);) is the tab page where the Next button should be enabled. This parameter is optional and the default is the current tab page. The third parameter (sysWizard.nextEnabled(false, sysWizard.curTab(), false);) indicates whether focus should be moved to the Next button. This parameter is optional and the default is true.
Control wizard flow - skipping a tab page To control the wizard flow by skipping a tab page when certain conditions are fulfilled, use the skipTab method available when your wizard is based on the SysWizard class. Example: Skip a tab page On the Account use tab page in the LedgerTableWizard, the user specifies what the account is to be used for. Based on the selection, one of the following tab pages concerning sales tax is skipped. boolean modified() { 85
Columbus IT Partner Russia, ApS
Navision Axapta boolean ret; #DEFINE.TaxPage(8); ret = super(); ledgerAccountUse = this.selection(); if (ledgerTable.AccountPlType >= LedgerAccountType::AccountOperations && ledgerTable.AccountPlType <= LedgerAccountType::AccountCost && ledgerAccountUse == LedgerAccountUse::Tax) sysWizard.skipTab(#TaxPage,true); Return ret; }
4.6. Tips
.
Searching on properties Use the Find dialog to search on properties. For example, you could use the Find dialog to locate all tables that have been set up as parameter tables, i.e. have the TableGroup property set to Parameter.
Search on properties 1. In the Containing text field, enter a regular expression that matches the contents of the complete property sheet. All properties and their values as you view them in the property sheet are seen as one text, one property per line. Properties and property values are separated by one or more blanks and a number sign (#). A regular expression that matches the TableGroup property and the value parameter: TableGroup: *#Parameter The asterisk (*) matches Zero or more characters, inluding like blanks, tabulations and control characters such as Enter (new line). To learn more about regular expressions press F1 in the Find dialog, and follow the Regular Expressions link to the documentation of the match system function. Match is one of the functions used internally by the Find dialog. 2. Select Show source text to display the property and its value in the result panel. As the expression is a constant in this example, this is not necessary. 3. Click the Advanced tab and select All nodes. You must change the default behavior (Methods only) to make the Find dialog search the properties.
This kind of search cannot run in concurrency mode.
4. Enter other criteria as needed. 5. Start the search from the Tables node, or for a selected set of tables. The above description is generic: The technique described can be used to find any property or property value on any node. For example, to find form group controls that are bound to a table group by some name, and not - as is the standard - by a label (like @SYS9362): Columbus IT Partner Russia, ApS
86
Navision Axapta 1. Enter this regular expression in the Containing text field: DataGroup: *#:n 2. Select Show source text to see the different texts used. 3. Click the Advanced tab and select All nodes
87
Columbus IT Partner Russia, ApS
Navision Axapta
5. Creating a Database 5.1. Database Basics Databases and MorphX The environment you work in when creating a Axapta application is often referred to as the integrated development environment, or IDE, because it integrates many different functions such as design, editing, compiling, and debugging within a common environment. In most traditional development tools, each of these functions would operate as a separate program, each with its own interface. MorphX is an IDE for developing Accounting and Business Management Systems. MorphX is not tied to a specific database platform, but was designed to be used on top of a relational database, such as Microsoft SQL Server.
Pic. 5-1 The data itself is stored in tables. When you start creating tables for storing data, you will create one table for each type of information you want to store (Customers, Suppliers, Products, Orders and so on). To bring the data from multiple tables together in a query, form, or report, you define relationships between the tables. Relationships can be defined several places in MorphX. You can choose to define the relationships directly on the tables, or you can define the relations when you create Extended Data Types. MorphX allows you to work with more than one company. When working with more than one company in an application, you reuse the application logic, but work with different sets of data in the tables. When working with tables in MorphX, the programmer can use SQL-like X++ commands to manage the data. MorphX also lets the programmer define integrity rules to ensure that the data obeys the business rules for the application area. Furthermore, you can modify the default system behavior by writing X++ code in a table’s methods.
The MorphX Interface Layer The foundation of any Axapta application is the database. With MorphX, you are not tied to a specific database platform, as MorphX supports multiple platforms via the MorphX Interface Layer.
Pic. 5-2
Columbus IT Partner Russia, ApS
88
Navision Axapta The illustration shows where the MorphX Interface Layer is located. When your application interacts with the database, the MorphX Interface Layer performs on-the-fly conversion of the communication. The communication between MorphX and the database system is based on the Microsoft ODBC protocol. Most major database system vendors support this protocol, or at least a closely related variation. Due to the MorphX Interface Layer, the end usr does not see which database MorphX is working on top of. MorphX can be used with a number of SQL based database systems. The list of SQL based database systems supported by the MorphX Interface Layer is continuously growing.
5.2. Databases and Companies Dividing a database into companies Databases in MorphX can hold information for several companies. Each company in an application uses the same application logic, but has its own set of data for one or more tables. Data stored in one company cannot be directly accessed from other companies. This means that if you define that a table’s data belongs to company A, its data will only be available to application objects within this company. Assume that an accountant has to work with five different companies, named A, B, C, D, and E. Companies A and B will share chart sof accounts, as will C and D. All five companies will share information about customers. MorphX does this by creating five companies, and three virtual companies. This is illustrated below:
Pic. 5-3 The above combination of companies and virtual companies allows the accountant to reuse the same application logic (the same application objects and relations) while working with different sets of data where needed. End users do not deal directly with the virtual companies, but only with companies. Companies can be based on a number of virtual companies. Virtual companies are the means by which MorphX groups parts of an application that is going to be reused in several companies.
To select a company 1. Choose File, Open, Company. 2. A dialog that shows a list of all existing companies appears. Double-click the name of the company. 3. The name of the selected company now displays on the status bar.
89
You can also open the dialog to select a company by double-clicking the company name on the status bar. Columbus IT Partner Russia, ApS
Navision Axapta
Working with companies Databases in MorphX can hold information for several companies, or in other words, MorphX allows you to have several sets of data while using the same application logic. Some of the tables in an application may contain information that can be reused by several companies. MorphX uses the following concepts. • Table Collections. This is a specification of a list of table names. Each table in your system only occurs once in any one table collection, but you can add a table to more than one table collection. There is no table data stored in a table collection. Data is stored in a virtual company or in a company. • Virtual Companies. A virtual company uses a list of one or more table collection to define which tables it contains. The tables included in the table collections are stored in the virtual company. The end user can not work directly on a virtual company, but only on a company. • Companies. A company is based on one or more virtual companies. When adding data to a table that is not in a virtual company, the data is stored directly in the company.
When to use companies Tables containing static information like ZIP codes are normally assigned to a virtual company that contains similar static information. This allows this type of information to be used by an accountant who works with several unrelated companies. This means that although an accountant works with several companies, the information in the ZIPCode table can be accessed from all the companies in the database.
Where is data stored
Pic. 5-4 Notice that companies and virtual companies only deal with table data. When you create a new table in your application, it is available in all companies in your system. While the data in your tables are stored on a per company basis, the definitions of the tables are stored separately, and have global scope within the application.
Creating table collections, virtual companies and companies Assume that you have an application that is based on tables named A, B, ..., H as illustrated below
Pic. 5-5 By dividing the tables in your application into companies, you can split your application data into parts which hold static information such as lists of ZIP codes, lists of currencies and so on, and into other parts which Columbus IT Partner Russia, ApS
90
Navision Axapta contain information of a more dynamic nature. To divide the tables in your application into companies, start by creating table collections.
Pic. 5-6 When you have made the needed table collections, the virtual companies can be defined based on the table collections.
Pic. 5-7 As the user cannot access the virtual companies directly, a number of companies must be defined before the end users can use the virtual companies. Assume that you create two companies: X and Y, which are based on the virtual companies. The illustrations below show which tables will be available in each company, and where the data will be stored.
Pic. 5-8 The illustration above shows that the data for the tables A, B, C, D, E, F, and H are stored in the ComAndTools virtual company, while the data in the G table is stored in the X company.
91
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 5-9 The illustration above shows that the data for the tables A, B, C, D, F are stored in the OnlyCommon virtual company, while the data for the E and H tables are stored in the Tools virtual company. The data for the G table is stored directly in the Y company.
Who creates what Who creates the components related to defining a company? Find the answers in the table below. Component
Short description
Created by the ...
Used by the...
Comments
Table Collection
A list of table names. Only a definition of related tables.
application developer
system administrator
Normally only a few table collections are defined.
Virtual Company
One or more table collections. The data for the tables in the table collections are stored in this virtual company. Can not be accessed directly by the end user.
system administrator
end user
A typically use is to define a virtual company that contains static information which can be reused in all companies, such as ZIP codes and currency codes.
Company
Based on zero or more virtual companies. Data for tables which are not in any of the virtual companies are stored here.
end user
end user
One company for each of the companies the accountant works with.
When you create a company, you will also come across domains which is a security concept.
5.3. Extended Data Types Extended Data Types are your own customized data types. Based on the primitive MorphX data types, you can create your own customized data types. These customizations modify the system-defined behavior of the primitive data types. By creating extended data types, MorphX you are able to be more specific in your system design than most other IDEs. Assume that you need to store product IDs in a table. By making a special ProductID data type based on the primitive data type string you can make modifications such as determining that these strings have a maximum length of 65 characters. If later in the application development process, you realize that it Columbus IT Partner Russia, ApS
92
Navision Axapta is sufficient with a length of 45 characters, modify the definition of the extended data type ProductID. Then this modification is automatically used by all other application objects that use the ProductID data type. If you know that the data you are going to store in a field in a table normally consists of more than one part, then define your Extended Data Type as an array. When you create an Extended Data Type, define that it consists of a number of elements. This is useful if you know that the information you are going to store in fields of this type normally consist of more than one piece. A typical example is an Extended Data Type for handling a customer address. Instead of defining, for example, three fields on a form to enter the customer address, you can just define that the Extended Data Type CustomerAddress consists of three elements. An important feature of Extended Data Types is that you can base one Extended Data Type on another. “Extended” means that you inherit the characteristics of an existing Extended Data Type when you create a new one. Each level of inheritance specializes the previous definition. This allows you to create hierarchies of Extended Data Types where each level refines the previous. Another very important feature is that you can define relationships directly on an Extended Data Type. When you use an Extended Data Type in a column in a table, MorphX automatically uses the relationships defined on the Extended Data Type.
Primitive data types The table below describes the primitive data types in MorphX.
Field data type
Used to store...
Comments
String
alphanumeric characters. Example: “Hello World”
The maximum size of a string is: 1000, or infinite if marked as a memo field. Use the backslash ‘\’ within a string to tell MorphX to treat the next character as a special character. Use: \t to inset a tab \n to insert a new-line character \” to insert a “ quotation mark
Integer
integers. Example: 34654 Example: 54
The range for integers is: [-(2)31-1, 231-1]
Real
real numbers. Example: 343,345.43545 Example: 3.1415926535
The range for reals is: [-(10)64, 1064]
Date
dates. Example: 04-27-98 Example: 01-14-99
The range for dates is: January 1, 1901 to December 31, 2155
Enum
an enumeration of values. Example: Yes, No Example: Red, Green, Blue
The maximum number of values in an enumeration is 255.
Container
All types of fields, even containers, can an untyped array of fields. Example: [123, “Hello”, [“Hi”, 456], 04-27- be stored in a container. 98]
Basing an Extended Data Type on a primitive type When you want to create new Extended Data Types of the integer, real, string, date, or container type, always base it on the primitive type. 93
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 5-10 When working with enums, first define the primitive enums. This is done below the Base Enums node in the Application Object Tree. When you have created the primitive enums, create an extended enum type just as you would any other Extended Data Type. To learn how to create an Extended Data Type, click
.
Description of properties for Base Enums Property
Use this property when you want to...
Rules and hints
Name
give the base enum a name.
Axapta standard An enum name must either indicate the possible (few) enum values or indicate the type of the enum value. Examples of enums named according to the possible values are: InclExcl, NextPrevious. Examples of enums named logically, according to the type of the enum value are: ArrivalPostingType, ListStatus.
DisplayLength
set the number of characters displayed.
FeatureKey
be able to control use of the base enum by means of a feature key.
Help
create a help string for the field. The help string displays when the field is used in a form.
ID
see the internal ID of the object.
Label
specify a label which will be shown in forms and reports.
Style
change the default display of the enum.
UseEnumValue
use the values for each enum element given in the element's EnumValue property.
Axapta standard This property must have a value. The Help property must not be identical to the Label property. Axapta standard This property must have a value.
Basing one Extended Data Type on another When you create a new Extended Data Type, you do not have to base it on one of the primitive data types. One Extended Data Type can be based on another Extended Data Type. This means that you can create, for example, an Amount type which is based on the String type, and later create another Extended Data Type called FrenchAmount. This Extended Data Type would modify the Alignment property to make amounts in French currency align differently from what is standard for amounts in your application. Columbus IT Partner Russia, ApS
94
Navision Axapta
Defining Extended Data Types as arrays When you create an Extended Data Type, you can define that it consists of a number of elements. This can be useful if you know that the information you are going to store in fields of this type normally consists of more than one piece. A typical example is an Extended Data Type for handling an address. Instead of defining, for example, three fields on your form to enter the address, you can just define the Extended Data Type MyAddress to consist of three elements.
Pic. 5-11 When you create a form based on a table that contains a field of the MyAddress type, MorphX automatically generates a field on your form for each element in the MyAddress definition. The above definition of the MyAddress type causes the following fields to be generated on a form.
Pic. 5-12 You can make arrays of all six categories of Extended Data Types.
Creating Extended Data Types To create a new Extended Data Type: 1. Expand the Database node and locate the Extended Data Types node. MorphX displays:
Pic. 5-13 2. Right-click the Extended Data Types node to display the shortcut menu. Choose New from the menu. MorphX displays a submenu that contains all possible categories of Extended Data Types. Notice that these categories correspond to the primitive MorphX data types. 3. Choose a category for your Extended Data Type. 4. In the property sheet, modify the Extends property to define the type on which you want to base the Extended Data Type. MorphX only lists valid choices, that is, Extended Data Types which belong to the same category as the one you chose in step three. 95
Columbus IT Partner Russia, ApS
Navision Axapta 5. Rename your new Extended Data Type. 6. Use the property sheet to customize the new Extended Data Type to your special needs. 7. Save your new Extended Data Type.
Creating arrays of elements for an Extended Data Type 1. Expand the relevant Extended Data Type, and locate the Array Elements node. 2. Right-click the Array Elements node, and choose New Element in the shortcut menu. 3. Display the property sheet for the element.
Pic. 5-14 4. Rename the element by changing the Label property. Notice that by default the value of the Label property array element is inherited from the Label property of the first element in the array. 5. If you want a help string to display when using the Extended Data Type in a form, use the HelpText property. 6. Save your modifications.
Customizing Extended Data Types When you create a new Extended Data Type, it has exactly the same properties as the type on which it is based (except for the name). To customize an Extended Data Type, you have to modify its properties. What you can do and how to do it is illustrated in the example below. Example: Customizing a PhoneNumber Imagine that you have created a new Extended Data Type called PhoneNumber, which is based on the primitive data type String. The default property values for this new Extended Data Type are shown below
Pic. 5-15 Columbus IT Partner Russia, ApS
96
Navision Axapta In order for this new Extended Data Type to be useful, it needs some modifications. Let’s say that you want this data type to hold telephone numbers for your customers all over the world. This means that the default size of the string (10 characters) is not sufficient. Change this to, for example, 16 characters by setting the StringSize property in the property sheet. You can also decide how many characters you want to display when a field of this type displays in a form or report. Set the DisplayLength property to 16 characters, as this was the value you defined for StringSize. If you want MorphX to automatically insert a label when a table field of this type displays on a form, enter a text in the Label property. If you want a message to display on the status bar, enter a text in the HelpText property. If you already have created another Extended Data Type that is related (same category) and has a similar behavior, use the Extends property. By typing the name of the other Extended Data Type, the new Extended Data Type inherits all of its properties instead of the properties of the primitive type.
Description of properties for Extended Data Types Property
Exists for this type
Modify this property to...
Alignment
String Real Integer Date Time
change the alignment of the text (Left, Right, Center).
AllowNegative
Real Integer
determine if the field can accept negative values or not.
ArrayLength
String Real Integer Date Time Container
specify how many elements are included in this Extended Data Type.
AutoInsSeparator
Real
let the system insert a decimal separator automatically (for example: if you enter 222222, the system automatically shows 222.222,00).
ButtonImage
String Real Integer Date Time
specify the image to be displayed when the Extended Data Type is used for a lookup button on a form. The possible values are: Arrow (default) Mail (possible use: the email type) URL (possible use: the URL type) ThreeDots (...) OpenFile (possible uses: the FilenameOpen and FilenameSave types) Calendar (possible use: date types)
ChangeCase
String
define how text entered in a string control should be formatted. For example you can get the text formatted as upper case or with title caps.
DateDay
Date
determine how the day should display.
DateLayout
Date
determine the layout of a date.
DateMonth
Date
determine how the month should display.
97
Columbus IT Partner Russia, ApS
Navision Axapta DateSeparator
Date
determine the separators between year, month and day.
DateYear
Date
determine how the year should display.
DecimalSeparator
Real
choose the decimal separator.
DisplayHeight
String
modify the number of lines displayed at the same time when this Extended Data Type is displayed in a form.
DisplayLength
String Real Integer Date Time
specify a maximum number of characters to be displayed in a form or report.
Extends
Enum String Real Integer Date Time Container
base this Extended Data Type on another Extended Data Type.
FeatureKey
Enum String Real Integer Date Time Container
define the feature key for the Extended Data Type.
FormHelp
Enum String Real Integer Date Time
specify a form to be used when performing lookup from a field in a form.
HelpText
Enum String Real Integer Date Time
create a help string for the Extended Data Type. The help string is displayed when the type is used in a form. Axapta standard Do not set the HelpText property to the same as the Label property.
Label
Enum String Real Integer Date Time
define a label for the type. The label is shown when the type is used in a form or report. Axapta standard Do not set the Label property to the same as the HelpText property.
Name
Enum String Real Integer
change the name of the type. The name is used when referring to the type from the X++ language. Axapta standard Extended Data Types must be named like the things in the
Columbus IT Partner Russia, ApS
98
Navision Axapta Date Time Container
real world they model. If the Extended Data Type belongs to a application module (like customers or vendors), the name must be prefixed with the name of the module. If an Extended Data Type extends another Extended Data Type, its name can be the name of the parent followed by its own specialization. If it is a data type for identification purposes, such as for a key field in a table, the name must be postfixed with "Id". If there is another commonly used postfix term than "Id" for the Extended Data Type, this can be used ("Code", "Num", or "Type" are accepted). Examples: JournalId, InventJournalId CustGroupId RouteOprTimeQueueBefore VendId AmountMST CurrencyCode
NegativeAdjustme nt
Real Integer
indent the number to the left if it is negative.
NoOfDecimals
Real
determine the number of decimals when a value displays on a form or a report.
RotateSign
Real Integer
negate the number, that is, change ‘-‘ to ‘+’ and vice versa.
ShowZero
Real Integer
determine if the value zero is shown as an empty field.
SignDisplay
Real Integer
display the sign ‘-‘ of a number if the value is negative. Also determines if the sign displays before or after the number.
StringSize
String
modify the maximum size of the string.
TimeFormat
Time
determine how times should be formatted.
TimeHours
Time
determine if hours should be included.
TimeMinute
Time
determine if minutes should be included.
TimeSeconds
Time
determine if seconds should be included.
TimeSeparator
Time
determine the separator used when displaying times.
ThousandSeparat or
Real
choose the thousand separator.
Adding dimensions The standard application uses three dimensions: Department, Cost center, and Purpose. Dimensions are based on Extended Data Types that are defined as arrays and consequently easy to extend. As all database fields in Axapta are based on Extended Data Types, as are X++ variables, adding a new dimension and making the new dimension available throughout the application is an easy matter. This only requires modifying the Extended Data Types.
99
Columbus IT Partner Russia, ApS
Navision Axapta Complete these steps to add a dimension:
1. Add a new array element to each of the above mentioned five Extended Data Types. Add a new array element
Add a new array element to all the Extended Data Types that control dimensions in Axapta. The Extended Data Types are: Dimension, DimensionCriteria, DimCheck, DimensionLedgerJournal, and MandatoryDimension. Give the new array element a suitable label and help text. Te Extended Data Type Dimension, for example, originally looked like this:
Pic. 5-16 When a new array element has been added, the Extended Data Type now looks like this:
Pic. 5-17 Repeat this for each dimension you want to add.
2. Modify the relations on the Extended Data Types Dimension and DimensionCriteria.
Modify the relations on the Extended Data Types Dimension and DimensionCriteria Modify the relations on two of the Extended Data Types: Dimension and DimensionCriteria. You must do this to be able to look up the dimensions table from dimension fields. The Extended Data Type Dimension, for example, originally looked like this:
Pic. 5-18
Columbus IT Partner Russia, ApS
100
Navision Axapta When relations have been added, the Extended Data Type now looks like this:
Pic. 5-19 3. Add the new dimension to base enum SysDimension.
Add the new dimension to base enum SysDimension Add the new dimension to the base enum called SysDimension. You must do this to be able to create the new dimensions in the dimension table. The SysDimension originally looked like this:
Pic. 5-20 Now it looks like this:
Pic. 5-21 4. Add a relation to the LedgerJournalTrans table.
Add a relation to the LedgerJournalTrans table Add a relation to the LedgerJournalTrans table. You must do this to be able to lookup in the Dimension table from the intercompany account dimension field in the ledger journals. The LedgerJournalTrans originally looked like this:
101
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 5-22 Now it looks like this:
Pic. 5-23 5. Exit Axapta, restart and recompile all forms that handle dimensions.
The easiest will be to recompile all forms.
You can now open the Dimensions form and create records for new dimension.
Columbus IT Partner Russia, ApS
102
Navision Axapta
5.4. Table Basics Tables are the primary application objects; they store the data used by your application. Table descriptions are stored in the Application Object Database, just like any other type of application object. Each table holds descriptions of a particular subject, such as Customers or Products. A table is made up of records, which hold information about a single entry in the table, that is, a specific customer or product. A record consists of a number of fields. Since each record contains the same fields, records and fields are also named rows and columns. Each field is a single bit of information of a specific data type. When you view a table in the Application Object Tree it looks like this
Pic. 5-24
Naming your tables A name consists of a combination of letters and numbers, but must begin with a letter. Spaces and special characters are not allowed.
Fields in tables Each field you define, corresponds to a column in the table. You can create as many columns as you like in a table, although it is not common to have a large number of columns for any one table. Each field in a table has a number of properties that describe the behavior of the field.
Dividing fields into groups In MorphX the fields in your tables are divided into groups. Fields are defined outside the groups and do not need to be in a group. Each field can belong to one or more groups. Adding a field to a group makes it easier to create a logical and pleasing form layout. A typical example is an Address table with three fields: FirstName, LastName, and Address. If you put these three related fields into the same group, for example CustomerAddress, the system puts a frame around these three fields when a form is generated. Below the Field Groups node, two groups are automatically created when you create your table. The groups are called AutoReport and AutoLookup. The AutoReport group is empty until you place some fields in it. The group is special in the sense that the fields you place in it are the ones that form the basis for the system’s automatic reports. Using the automatic report feature you can generate a report on data displayed in any form by clicking the File menu’s Print... command when the desired form is open. The AutoLookup group is also empty. The fields in the group are used for automatic lookup information on forms. In addition to fields, you can also add methods of a particular nature to field groups, namely display and edit methods. This is particularly useful for the AutoLookup field group. Example. The LanguageTable table has a display method, description, that returns a language decription, for example 'English(United States)' for 'en-us'.
103
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 5-25 This is used for lookup on several forms, among them the CustTable form on the General tab page.
Pic. 5-26 The field on the CustTable form is called LanguageId and has the Extended Data Type CustLanguageId. As the below snapshot from the Application Hierachy Tree browser shows, CustLanguageId extends LanguageId that in turn extends LanguageIdAll.
Pic. 5-27 LanguageIdAll has a relation to a field in the LanguageTable,
Pic. 5-28 where the display method was included in the AutoLookup field group
Axapta standard for field groups You must use a label for the field group Name property. Standardized group names are: Identification, Description, Administration, Dimension, Address, <module name> (for example “Ledger”). The Dimension field must always be in a group named Dimension. You should define a group when several fields logically belong together and are shown together on forms. Columbus IT Partner Russia, ApS
104
Navision Axapta Any field that appears in the user interface must belong to a group. This means that you can always use FieldGroups to design your forms. You must place at least two fields in the AutoReport field group for any table. The fields placed there should be the ones that the user expects to print when he first clicks Print... on the File menu.
Data types for fields By specifying a data type for a field (column) in your table, specify what kind of data is to be stored in it. MorphX checks to make sure that only valid data is entered into each field in the table. MorphX does not accept invalid numbers to be entered into a number field, and for Date columns it ensures that only valid dates are entered in the field. Besides the primitive data types offered by MorphX, you can create your own Extended Data Types.
Primitive data types The table below describes the primitive data types in MorphX. Field data type
Used to store...
Comments
String
alphanumeric characters. Example: “Hello World”
The maximum size of a string is: 1000, or infinite if marked as a memo field. Use the backslash ‘\’ within a string to tell MorphX to treat the next character as a special character. Use: \t to inset a tab \n to insert a new-line character \” to insert a “ quotation mark
Integer
integers. Example: 34654 Example: 54
The range for integers is: [-(2)31-1, 231-1]
Real
real numbers. Example: 343,345.43545 Example: 3.1415926535
The range for reals is: [-(10)64, 1064]
Date
dates. Example: 04-27-98 Example: 01-14-99
The range for dates is: January 1, 1901 to December 31, 2155
Enum
an enumeration of values. Example: Yes, No Example: Red, Green, Blue
The maximum number of values in an enumeration is 255.
Container
All types of fields, even containers, can an untyped array of fields. Example: [123, “Hello”, [“Hi”, 456], 04-27- be stored in a container. 98]
Indexes, and keys Indexes are used together with your tables to improve performance of data retrieval and to ensure unique records. An index is a mechanism that can reduce the number of I/O operations needed to locate and retrieve data in a table. It is up to the database-specific Query Optimizer to use available indexes to facilitate efficient data retrieval. Indexes in the DBMS are generated based on a definition made by the programmer in the Application Object tree.
105
Columbus IT Partner Russia, ApS
Navision Axapta
Tables and user defined methods MorphX recognizes certain things that happen to your tables, such as when records are created, inserted, deleted, or modified. When these events happen, MorphX calls a number of standard methods. Each table in Axapta has such methods that define the standard system behavior. Some of those methods are visible on the table’s Methods node in the Application Object Tree, and some are visible in the list of system classes only. The two groups of methods are equally valid and necessary to the system. The difference between them is the that those available in the Methods node can be overridden. This means that you can add you own X++ code to these methods, and thus change the standard system behavior. You can also create your own methods. The table methods, both the standard system defined methods and the ones you yourself create, are typically called from forms.
Table properties The table has a number of properties that define its behavior.
Creating tables When you create a table you have to decide which types of information you want to store in it. Creating a table in MorphX is basically a three-step process: First create the table, give it an appropriate name, then define the fields for the table, and finally create one or more groups for the fields in the table.
Creating a table using the Application Object Tree To create a table: 1. Expand the Database node in the Application Object Tree. 2. Right-click the Tables node, and select New Table from the shortcut menu. 3. Rename your new table. On its own a table is not very useful. Before you can actually use it you have to add fields. The layout of your tables should be based on results from your analysis and the design of the current problem. Adding fields to a table is done in almost the same way, no matter if you are using primitive type fields or Extended Data Type fields. If you are using Extended Data Types in your table, the first step is to select the category of the field you want to insert. The categories correspond to the six primitive data types. To add fields to a table: 1. Right-click the Fields node, and a submenu appears. The submenu contains a list of all the primitive field data types. 2. Choose the appropriate data type for each field. If you are not using Extended Data Types you are finished now. (You can now customize the fields by modifying their properties). 3. When you want to use an Extended Data Type for one or more fields, there is an additional step involved. In step 2, select the category corresponding to the Extended Data Type you want to use. For example, if you know that the Extended Data Type is based on a String, choose String at this step. 4. After having specified the categories, modify the ExtendedDataType property in the property sheet for each Extended Data Type field.
Columbus IT Partner Russia, ApS
106
Navision Axapta
Pic. 5-29 5. Save your modifications. The fields in your table do not need to be in a group. The benefit of defining groups is that you can set up the system to automatically show related fields in groups on your forms. If you want to use groups, you have the option of putting each field into more than one group. Note that if you do this, the field occurs several times on the forms (once for each group you have added it to). To create a group: 1. Expand the Tables node. 2. Right-click the Field Groups node, and choose New Group. 3. Repeat the previous steps for each group you want to define. Rename the new groups. 4. Use the mouse to drag and drop fields from the Fields node to the groups you have defined. 5. Save your modifications.
Using keys in tables A primary key is a column or combination of columns that identifies a row in a table. A primary key has two properties: • It is unique. No two rows in the table have the same values. • It is not allowed to contain a null value. In Axapta a primary key is expressed using a relation. The relation can either be defined on a table, or on an Extended Data Type. The latter is the typical case. The relation on an Extended Data Type must be self-relating. The relation on a table must be validating (the Validate property must be set to Yes). The Extended Data Type CustAccount is a typical example from the application.
Pic. 5-30 107
Columbus IT Partner Russia, ApS
Navision Axapta In the CustTable table, the AccountNum field has the Extended Data Type CustAccount. Consequently the relation above is self-relating, and it then becomes the primary key for the table. Normally a relationship defined on an Extended Data Type is validating. This means that the system automatically checks whether the conditions defined by the relationship are fulfilled, for example before exiting a form. Self-relating relationships are not validating. Also, there is no lookup information provided.
5.5. Relationships MorphX works with the relational database model. This means that you can use data from more than one table at a time. If your database contains tables with related data, you can create a relationship between them. Relationships in MorphX: • Are used to keep the database consistent (referential integrity). • Are used to create Auto Join in forms. • Make it possible to look up values in other tables (through lookup list/selection list boxes and the Go to Main Table command). • Are used to validate data. • Automatically propagates changes from one table to other tables. • Are used to generate ToolTips. • Are used to auto-define relations in queries. The most common use of relationships is to make it possible for end users to look up information in another table from a field in a form. If you have created a relationship, users can use the lookup button to display the lookup list from a field in a form. Tables are related by specifying one or more fields that contain the same value in related tables. These matching fields often have the same name in each table. For example, in a SalesOrder table you might have a field which identifies the salesperson who took the order. To make this relation, you would tell MorphX to relate the SalesPersonID field in the SalesOrder table with the SalesPersonID field in the SalesPerson table.
If you do not define relations yourself, the system uses what is considered the best possible relation. You can see that relation in the Queries node in the Application Object Tree.
Relationships between tables are created, viewed, and edited in the Application Object Tree. You can create relations on an Extended Data Type, or on a table.
Pic. 5-31
Columbus IT Partner Russia, ApS
108
Navision Axapta
Pic. 5-32 MorphX allows you to add conditions to a relationship. When you create a relationship you can define certain conditions which must be fulfilled for your relation. The relationships between your tables are known from your analysis of the problem you are solving. Axapta standards for relations • A relation must be named like the table it relates to. • Relations in the data model must be expressed in relations. Such relations must be validating. This means that the Validate property must be set to Yes. • To enhance performance for example when opening forms, express navigational relations. A navigational relation has the Validate property set to No. Such a relation exists between two tables that share data, but are not otherwise related. Defining a navigational relation benefits the system’s auto join system when opening one form from within another. The CustTrans relation on the LedgerTrans table is an example of a purely navigational relation. If a table has a key, the key must be defined using relations.
Pic. 5-33
Creating a relationship There are two relationships in MorphX: • Single field • Multiple field You can add conditions to both types at runtime based on user input. Relationships are defined at different places in MorphX. You can define a relationship on...
This allows you to create
an Extended Data Type
•
Single field relationships
•
Conditions on a relationship
•
Single field relationships
•
Multiple field relationships
•
Conditions on a relationship
a table
109
Columbus IT Partner Russia, ApS
Navision Axapta
Creating a relationship on an Extended Data Type You can define a relationship at the same time you create an Extended Data Type. An Extended Data Type allows you to define a relationship between a column in one table, and a column in another table. The relationships you define on an Extended Data Type are automatically inherited by the later tables. When MorphX recognizes that you are using an Extended Data Type in a column in your table, it automatically uses the relation you defined on the Extended Data Type. Extended Data Types allow you to create relationships of the single field type. If you need to define a multiple field relationship, you have to define it directly on the table.
To create a relationship on an Extended Data Type 1. Locate the Relations node for the relevant Extended Data Type.
Pic. 5-34 2. Right-click the Relations node, and select New from the shortcut menu. MorphX displays a submenu. 3. Choose Normal from the submenu to add the relation. This adds a line below the Relations node 4. Click on the new line below the Relations node, and display the property sheet.
Pic. 5-35 5. Finish the definition of the reference by setting the Table property to the table you want to refer to, and set RelatedField to the field (column) you want to refer to in this table. 6. If you do not need to make the relation conditional then you are finished now. 7. Save your modifications.
Creating a condition on a relationship on an Extended Data Type When creating a condition on a relationship on an Extended Data type, MorphX allows you to use the Related field fixed condition. If you need to create a Field fixed condition, you have to define it on the table.
To create a condition for a relationship on an Extended Data Type 1. It is assumed that you have already created a relationship. 2. Locate the Relations node for the relevant Extended Data Type. 3. Right-click the Relations node and select New from the shortcut menu. MorphX displays a submenu. 4. Choose Normal, and the name of the table you want to create a relationship to in the Table property. Columbus IT Partner Russia, ApS
110
Navision Axapta 5. Right-click the Relations node and select New from the shortcut menu. Choose Related field fixed This adds a line below the Relations node. 6. Click on the new line below the Relations node, and display the property sheet.
Pic. 5-36 7. Enter the name of a field in this table in the RelatedField property. 8. Enter the enum value that you want to use as the conditional value in the Value property. 9. Save your modifications.
Creating a relationship on a table MorphX allows you to create both single and multiple field relationships on a table.
Single field relationship If you want to create a relation that is not already defined using an Extended Data Type in your table, create it using the Relations node in the Application Object Tree.
Multiple fields relationship For each table you can create one or more relationship nodes, and below each relationship node define one or more relationships plus any number of conditions. You can define relations to several different columns in another table. If you do that, all columns will be shown in the lookup list.
Creating the relationship 1. Locate the Relations node for the relevant Table.
Pic. 5-37 2. Right-click the Relations node and choose New Relation. MorphX creates a new relation node labeled Relation1 with this property sheet.
Pic. 5-38 111
Columbus IT Partner Russia, ApS
Navision Axapta 3. Modify the Name property to set the name of the new relationship. 4. Use the Table property to define the table to which you want to refer. 5. Use the Validate property to decide if the relation should be used to validate data when entering information in forms. 6. Right-click the node for your new relation, and choose New in the shortcut menu. MorphX displays a submenu. 7. Choose Normal in the submenu to define the relation.
Pic. 5-39 8. Open the property sheet for the relation.
Pic. 5-40 9. Finish the reference definition by setting the Field property to a field in the current table, and set RelatedField to the field (column) you want to refer to in the other table. 10. If you do not need to make the relationship conditional you are finished. 11. Save your modifications.
Creating a condition on a relationship on a table When creating a condition for a relationship on a table, MorphX allows you to use both Related field fixed and Field fixed conditions.
To create a condition for a relationship on an Extended Data Type
You must have already have created a relationship on your table.
1. Locate the Relations node for your table and expand it.
Columbus IT Partner Russia, ApS
112
Navision Axapta
Pic. 5-41 2. Right-click the relationship to which you want to add a relationship, and select New from the shortcut menu. MorphX displays a submenu. Choose Normal, Field fixed, or Related field fixed conditions from this submenu. If you want to create a Field fixed condition continue with the next step, or if you want to create a Related field fixed condition, jump to step 7. 3. If you want to add a Field fixed condition, choose it in the submenu. This adds a line below the Relations node
Pic. 5-42 4. To finish the definition of the Field fixed condition, access the property sheet for it.
Pic. 5-43 5. Enter the name of the field (in your table) you want to put a condition on in the Field property. 6. Enter an integer value in the Value property. This value is compared with the value of the field you entered at the previous step. Now you have completed the definition of a Field fixed condition. If you want to create a Related field fixed condition continue with the next step, otherwise jump to step 11. 7. If you want to add a Related field fixed condition, choose it in the submenu. This adds a line below the Relations node.
113
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 5-44 8. To finish the definition of the Related field fixed condition, display the property sheet for it.
Pic. 5-45 9. Enter the name of a field in the other table (the one to which you have made a relation) in the RelatedField property. 10. Enter an integer value in the Value property. This value is compared with the value of the field in the other table. Now you have completed the definition of a Related field fixed condition. 11. Save your modifications.
Adding conditions to your relationships MorphX allows you to add conditions to the relationships you define between your tables. Conditions on a relationship between tables in MorphX come in two types referred to as Field fixed and Related field fixed. The table below explains these conditions. The following table refers to “your table”, the one you are currently working with, and “the other table”, the one you are referring to. Condition type
Format
Use it to...
Field fixed
Field fixed (Table.Field==<EnumValue>)
put a constraint on your table as to which fields will have a lookup list with values from another table. The condition is ANDed with your relation.
Related field fixed
Related field fixed (<EnumValue>==Table.Field)
filter the records selected in the other table, that is, when MorphX is selecting records in the other table, it only selects the records which meets this condition The condition is ANDed with your relation.
Using Field fixed conditions Use a senario wherein you have a company that sells clothing by telephone. Your company is very successful, and you have collections for men, women, and children. When a customer calls to place an Columbus IT Partner Russia, ApS
114
Navision Axapta order, the sales assistant asks a number of question to determine if the customer wants to buy clothes from the men’s, women’s, or children’s collection. In your Orders table you would have a column with information about the collection. The possible values could be defined by an Enum with the values Man, Woman, and Child. When you design your tables, you would have to make relations between your Orders table and all three collection tables (MensCollection, WomensCollection and ChildrensCollection). You would also have to add a Field fixed condition to each relation. This relation would enables one relation, and disables the other two based on the Sales Assistants determination. This allows you to lookup information in three different tables from the same field in Orders table. The table MorphX uses depends on an Enum value in one of the other columns in your Orders table.
Using Related field fixed conditions Continuing with the above scenario. Assume that your men’s collection both covers stylish, business, and formal leisure clothing. You could have a ClothingCategory column in your MensCollection table to describe this. When the Sales Assistant enters the category in the MensCollectionCategory column in Orders table, and then displays a lookup list of the individual items, MorphX limits the number of items in the lookup list, based on the value in the MensCollectionCategory column. This makes it easier for the Sales Assistant to find the appropriate item, as the items in two out of the three men’s collection categories do not appear in the lookup list.
Validation and integrity It is the application programmer’s responsibility to make sure that user input is validated, and integrity is maintained in the database. MorphX has a number of mechanisms to support this.
Performing validation and maintaining referential consistency Both the Validate and DeleteAction properties on a relation and on a DeleteAction node respectively are used to maintain referential consistency in the database. This is done by making sure that records on the child-side of a relation are deleted before the record on the father-side of the relation is deleted. This is typically done by setting the DeleteAction property to Cascade. The DeleteAction property can also be used to prevent a user from deleting a record and its related transactions. If the DeleteAction property is set to Restricted, a message will be displayed when the user tries to delete a record if it has a number of transactions related to it. Similarly, the programmer uses the Validate property to maintain consistency when records are updated or inserted. If the Validate property on a relation is set to Yes, the system uses the relation to perform the validation automatically.
How MorphX retrieves information for validation and lookup MorphX has a strategy for performing validation and retrieving information for lookup lists. This strategy ensures that the content of a field is validated thoroughly, in a user-friendly manner. For this strategy to work, the following assumptions are made: • Multiple field relations are organized in a logical sequence, which corresponds to the hierarchical data structure they reflect. • Relations on a table have priority over relations on Extended Data Types. Notice that this may not be true if the relation is mandatory. • Mandatory relations have higher priority than conditional relations. When performing a field validation, MorphX does the following: 1. MorphX checks if the field is part of a relation on the table. If it is, this relation is used for the validation. If there is more than one relation using the field on the table, MorphX chooses the relation that contains the highest number of fields. 2. MorphX checks if a relation has been defined on the Extended Data Type used in the field, or if there exists a relationship on the Extended Data Type from which it is inherited. 115
Columbus IT Partner Russia, ApS
Navision Axapta
Using delete actions Maintaining consistency in your Axapta database is very important. MorphX includes some special features to help manage the consistency of data spread in several different tables, namely a combination of relations and delete actions. The picture below illustrates the CustTable table that has a number of delete actions defined below the DeleteAction node.
Pic. 5-46 Defining delete actions for a table ensures that consistency is maintained when a record is deleted in a table. MorphX uses the delete actions together with the relations defined on Extended Data Types or directly on the tables. For example, you can use cascading delete to define that the system should delete the address related to a customer when you delete a customer from the CustTable table. Another example is to use restricted delete to prevent deleting a customer if one or more transactions exist for the customer. When you define delete actions, you have to decide what type of delete action you need. You have the following options: This type of delete action
causes the system to...
None
disable the delete action.
Cascade
delete related records.
Setting DeleteActions to Cascade extends the functionality of the table’s Delete method. This means that super() in Delete initiates a cascaded deletion so that the deletion propagates from table to table. Note that a cascaded delete is implicitly protected by tts so that database changes are not committed until the entire transaction is complete. An example from the application: On the CustTable table, a cascading delete action has been defined for the CustBankAccount table. This means that when a customer is deleted in the customers table, the Delete method manages that the corresponding bank account information is automatically deleted as well.
Restricted
restrict deletion in the current table if data is present in related tables.
Setting DeleteActions to Restricted extends the functionality of the table’s ValidateDelete method. This means that super() in ValidateDelete checks whether records exists on related
Columbus IT Partner Russia, ApS
Comment
116
Navision Axapta tables. If this is the case, ValidateDelete returns false. The forms system then automatically manages that and the deletion is not performed. In your own X++ code, you should take care to respect the return value of ValidateDelete. An example from the application: On the CustTable table, a restricted delete action has been defined for the CustTrans table. This means that when a customer is deleted in the customers table, ValidateDelete checks whether transactions exist for the customer. If this is the case, ValidateDelete returns false. Cascade+Restricted
cascade delete even though records exist on related tables.
Setting DeleteActions to Cascade+Restricted extends the functionality of the table’s ValidateDelete and Delete methods. This means that super() in ValidateDelete checks whether records exists on related tables. The cascaded delete is performed regardless of the result. There is no example of this combination in the standard application. However, you could have a situation when you would prefer a total clean up so that when you deleted a customer, you also wanted to delete all the transactions associated with the customer.
System tables Cascading delete also works with system defined tables. For example, if you delete a user, the system automatically deletes the related information in the UserGroupList table.
5.6. Using Code in Tables MorphX recognizes certain things that occur when you use a table, for example when data is inserted, updated, or deleted. In response MorphX executes X++ code defined in a method associated with the table. Any table in Axapta has a number of system defined methods (ValidateWrite, ValidateField, ..., Caption).
117
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 5-47 System defined methods are predefined methods that are called when you use the table. Which methods are called and when they are called depends on how the table is used. The bodies of system defined methods initially only contain a call to super() in MorphX. When you add X++ code to the system defined methods, you override the default system behavior. Table objects in MorphX have the following system-defined methods: System defined method
Executed when...
Caption
a heading for a form is displayed. super() in the Caption method generates the text to be displayed from properties on the table.
Clear
the fields in the current record are cleared (hold NULL values).
Rules and hints
Axapta does not support the concept of NULL values as known from the DBMS world. A field in Axapta always has a type and a value. However, for each data type one value is considered NULL, for example when the ValidateField method is executed. Type
Columbus IT Partner Russia, ApS
What is treated as NULL...
118
Navision Axapta String Integer Real Date
an empty string 0 0.0 dates prior to January 1, 1901 (01-01-1901) Time 00:00:00 Enum first entry
One of the consequences of this is that when the ValidateField method checks whether a user has entered a value in a mandatory field, 0 is not accepted in an Integer type field, the first entry is not accepted in en Enum type field etc. Also, the values listed in the above table will yield false in a boolean comparison. Note that variables of type container, classes and variables of table type can be NULL in the traditional DBMS sense. A table type is NULL if all its fields have their NULL value. Delete
a record is deleted
Axapta standard Secure any related transactions with tts. If you have DeleteActions on Table A set to Cascade delete on Table B or performance reasons, you should try to avoid writing code on the Delete method on
Table B. If you have added no code here, cascading deletes can be done quickly by the database management system using SQL deletes directly. n the other hand, if you have added code here (- which may be necessary in 119
Columbus IT Partner Russia, ApS
Navision Axapta some cases), the system creates a while select statement and executes Delete on all child tables. As Delete is performed over the net and one record is deleted at a time, performance is less good than when an SQL delete is performed on the server. s an example from the standard application, Table A could be the CustTable table and Table B could be the CustTrans table. HelpField
a help text for a field is displayed in the status bar, for example when you jump to the next field on a form.
When manipulating an array, use the standard method on the Global application class: FieldExt2Id, FieldId2Ext and FieldExt2Id.
InitValue
a new record is added. InitValue is automatically called from forms.
Note that the super() call does not do anything! Use the method to assign initial/default values to a new record.
Insert
a new record is inserted into the table. If the record cannot be inserted, the super() call throws an error.
Axapta standard Secure any related transactions with tts.
Merge
two records are merged.
PostLoad
a record has been loaded.
RenamePrimaryKey
the table’s primary key is renamed.
ReRead
a record is re-read.
ToolTipField
the mouse pointer is placed on a field in a form.
ToolTipRecord
a ToolTip for the current field is to be displayed. super() in ToolTipRecord calls Caption.
Update
before an existing record is modified.
Axapta standard When manipulating an array, you should use the standard method on the Global application class: FieldExt2Id, FieldId2Ext and FieldExt2Id.
Generally Axapta updates only the specific fields that the user has modified – not an entire row in the database. As a result, the system can handle the situation when one user modifies address
Columbus IT Partner Russia, ApS
120
Navision Axapta information for example at the same time another user is modifying terms of payment for the same customer. The super() call in the table’s Update method manages the actual database update. For integer and real fields, use the FieldUpdate property to define a specific update strategy for a field. Absolute and relative updates Absolute updating ensures that changes to a value in a record are saved exactly as they are entered regardless of any other user updates.
Absolute update scenario
User_B reads the value 10000 User_A reads the value 10000 User_A writes the value 10010 User_B writes the value 10020 Final database value: 10020
Relative updating can be used in multi-user environments. This allows multiple users to work on the same record at the same time. When using relative updates, MorphX combines each of the user’s modifications before the record is saved in the database.
Relative update scenario
User_B reads the value 10000 User_A reads the value 10000 User_A writes the value 10010 User_B writes the value 10020 Final database value: 10030
121
Columbus IT Partner Russia, ApS
Navision Axapta ValidateDelete
a record is deleted. ValidateDelete is automatically called from forms and is used to check whether the current record can be deleted. The super() call checks whether there are related records in tables with DeleteActions of type Restricted. If that is the case, super() in ValidateDelete returns false.
Axapta standard You should respect the task perfomed by the super() call. The method should return a Boolean – do not throw here!
ValidateField
you leave a field in a record, for example when you jump to the next field in a record. The super() call checks validating relations, that is, relations on a field where the Validate property is Yes. ValidateField is automatically called from forms with the fieldId of the field that must be validated.
Axapta standard You should respect the task perfomed by the super() call. The method should return a Boolean – do not throw here! When manipulating an array, you should use the standard method on the Global application class: FieldExt2Id, FieldId2Ext and FieldExt2Id.
ValidateWrite
before a record is written to the database. The super() call examines all fields for the setting of the Mandatory property.
Axapta standard You should respect the task perfomed by the super() call. The method should return a Boolean – do not throw here!
Axapta standards for table methods • You should not write X++ code to solve problems that can be solved by setting properties. • The code you write on table methods must be directly related to the table. • You should create these methods on any table with a unique key: find
The parameters to find are The table’s key, and an optional boolean used to indicate select for update Returns a record indicated by the key.
exist
The parameter to exist is the table’s key. Returns a boolean that is true if a record with the supplied key exists. In the exist method you should call the find method rather than re-write the same statements.
checkExist
The parameter to exist is the table’s key. Returns a boolean that is true if a record with the supplied key exists. The check-method also places text in the InfoLog.
txtNotExist
Takes no parameters. Returns a static text with an error message.
You can see examples of these methods on the CustTable table. Columbus IT Partner Russia, ApS
122
Navision Axapta
Sequence of execution of methods The nature of the user interface in MorphX is event driven. This means that when an event recognized by MorphX occurs, the X++ programmer can modify the system’s default behavior if necessary. A table does not have a visual representation on it’s own. The only way to work with the data in your tables through the user interface, is through a form. Both forms and tables have methods that are executed in response to the actions performed by the end user. Below are descriptions of typical sequences of events that occur in a normal MorphX application. When the end user...
This sequence of table methods is called...
runs a form which is using a table as a data source.
HelpField
inserts a new record via a form using CTRL+N
InitValue
jumps from field to field when entering data in a record by using the Tab key
ValidateField, HelpField
enters a new record via a form and leaves the current record, for example, by using the arrow keys to move to the next line in a grid
ValidateWrite, Write, Insert
modifies an existing record via a form and leaves the current record, for example, by using the arrow keys to move to the next line in a grid
ValidateWrite, Write, Update
places the mouse pointer over the current field in the current record in a form
TooltipField
Defining and modifying methods in your tables When you create a new table in the Application Object Tree, MorphX automatically creates a number of methods for it. By adding X++ code to these system defined methods you can modify the default behavior of the system. You can also define your own methods. The system and the user defined methods share the same scope within the table. This makes it easy to add new methods and use them from the system defined methods. Notice that you cannot modify the return type, parameter list or parameter types for the system defined methods, but you can add additional parameters if you declare a default value for them.This differs from any additional methods you define. These can be modified in any way you please: you can modify the return type, the parameter list and parameter types.
To modify a system defined method for a table 1. Expand the Database node in the Application Object Tree and locate the table you want to modify. 2. Locate the Methods node for your table and expand it. Double-click the method you want to modify. MorphX displays the editor.
Pic. 5-48 3. Modify or add the code as necessary. 123
Columbus IT Partner Russia, ApS
Navision Axapta 4. Compile and save the modifications. You can also create your own new methods. From any method defined for your table you can access all the other available methods. This is because any method defined for a table shares the same scope.
To create an new method 1. Expand the Tables node in the Application Object Tree and locate the table you want to modify. 2. Expand the node for the table and locate the Methods node. 3. Right-click the Methods node, and select New Method from the shortcut menu. 4. Rename the new method. 5. Double-click the new method to open the editor. 6. Add code to the method in the editor. 7. Save your modifications.
5.7. Indexes
.
Imagine that you have a textbook that you use frequently. If the textbook does not contain an index, one strategy might be to start reading the book from the beginning each time you need to find some information in it. Eventually you might make your own index. The advantage of an index is, of course, that it helps you to quickly find the various topics in the book. The reason the index provides faster access is that the index normally is smaller than the entire book. Because an index is ordered alphabetically it is useful even if it contains all the words in the book, has the same size, that is. When you have found the word you are looking for in the index, you know where to find the topic in the book. A database can also use indexes. Indexes in databases have exactly the same purpose as in a printed book although they are made in another way. An index for a book guides you to the pages in the book, while an index for a table in your database provides a reference to a record. An index in a database is essentially a quick lookup table which makes it faster to find records (rows) in your tables. Once created, indexes for your tables are managed automatically by the DBMS every time a record is inserted, updated, or deleted, that is, no manual interaction is necessary. Indexes can, once they have been defined, be enabled or disabled. Notice that a disabled index is not physically present in the database. When you disable an index, it is deleted from the database, and rebuilt if you re-enable it later. One or more fields may define the index. The system tries to order the index according to the first field, if there is more than one record with the same value in this field, the sorting conflict is resolved by looking at the next field, and so on. In theory, you can define as many indexes for a table as you want. However, it is not common to have more than a few (less than five) indexes enabled because inserts, updates, and deletes are slowed down since each change causes every enabled index to be updated.
Unique and non-unique indexes There are two types of indexes: unique and non-unique. If a unique index is created based on a column (or a set of columns), the Axapta DBMS ensures that no duplicate key values occur in that column (or set of columns). That is, MorphX prevents you from inserting records with duplicate key values. This is done by simply rejecting the insertion. Non-unique indexes are created for performance reasons. They provide a quick way of retrieving data, rather than doing a full-table search of all the records in your table.
Keys and Foreign Keys It is useful for the application programmer to employ concepts such as key (also known as primary keys) and foreign key. Columbus IT Partner Russia, ApS
124
Navision Axapta • A key is one or more columns that uniquely identify one record in a table from all the others. Keys are unique. A typical example is a customers table where the customer number is used as a key. A key should have a unique index. • A foreign key is a column in one table that is the (primary) key in another table. A typical example of a foreign key is a customer transactions table that has a column called customer name which is a foreign key to the customers table. A foreign key can be indexed and should be if it is essential that information can be retrieved very fast. Notice that you cannot use container or memo (string with dynamic length) fields as field in a key.
Indexes – hints and advice Create exactly the indexes needed in the application. Indexes have different characteristic on the different databases but the following rules are general in nature: + Unique indexes guarantee uniquely identifiable records in the database. + Normally the use of indexes in queries results in (much) better performance. - Indexes take up space (the more and the longer fields, the more space). - Indexes decrease performance on inserts, updates, and deletes. Note that some databases will monocase values in fields that are indexed.
Deciding what to index Although using indexes speeds up record retrieval, there are both advantages and drawbacks to using a large number of indexes. When a table is modified (update, insert or, delete operations), the indexes also have to be modified accordingly, and this slows down the modification process. When deciding which fields to index, consider the following with regard to columns: • on which you search by range • involved in joins • you order or group by
How to apply an index You do not have to worry about how and when to use an index. If you have made an index for a table and it can be used in a given context, then MorphX automatically uses it when the table is accessed.
Forcing a specific index in a SELECT statement Indexes are used automatically when you access the data in your tables from X++ code. The application programmer can use the INDEX keyword to give MorphX a hint of which index to apply when records are selected. select Orders index OrderDate order by desc where Orders.AccountNo == Customers.AccountNo;
If the INDEX keyword is used alone without ORDER BY or GROUP BY, the selected records will occur in the order specified by the index definition.
125
Columbus IT Partner Russia, ApS
Navision Axapta
Creating an index When you create an index for a table in your database, you decide how detailed it should be, that is, how many columns it requires.
Create an index 1. Expand the node for the table for which you want to create an index, and locate the Indexes node. 2. Right-click the Indexes node to display the shortcut menu, and choose New Index. 3. MorphX creates an index with a system generated name. Rename your new index. 4. Right-click the new index to display the shortcut menu, and choose Add to add a new field to be included in the index 5. Drag one or more fields from the selection list. Notice that the ordering of the fields is significant, and defines how the index is built. After you have dragged the fields into the index, change the ordering of the field by moving them with the mouse. Note that any field of type String that is part of an index is transformed into lower case. 6. Display the property sheet for the new index
Pic. 5-49 7. The default value for the AllowDuplicates property is Yes. That is, MorphX does not prevent you from entering records if they are not unique. Set this to No if you want to prevent duplicate entries in the index. A special situation occurs if you try to create a unique index for a table and MorphX discovers that it is impossible due to existing duplicate entries in the table. This causes MorphX to display a message to the user. In most situations you can solve this problem by adding one or more fields to the definition of the index until it is unique. If you include a RecId component in an index, the index will be unique by default. If you still set the AllowDuplicates property to Yes, the index is nevertheless treated as unique and a warning is issued to the user if he attempts to insert non-unique values.
When SQL warnings in the Options dialog (available from the Tools menu) have been enabled, you get this warning: 'Warning: Since unique field [RecId] is part of your non-unique index [] on table [], you should consider making the index unique. Axapta will create it as being unique.'
8. The default value for the Enabled property is Yes. That is, the index is active right away. If you want to disable the index, set the Enabled property to No. 9. Save the modifications.
Description of properties for indexes Property
Use this property to
Id
see the internal ID of the object
Name
give the index a name.
Columbus IT Partner Russia, ApS
Rules and hints
Axapta standard 126
Navision Axapta Use the field name for single field index. You can use “Idx” as suffix in index names. AllowDuplicates
have the system prevent duplicate entries in the index. Setting AllowDuplicates to Yes means that you allow the index to be non-unique. Setting AllowDuplicates to No means that you want the index to be unique. If you do not create at least one unique index, Axapta creates one by combining the first index and the RecId.
Axapta standard There should be one unique index per table for tables that belong to the groups Main and WorksheetHeader. The index on the key should be the (first) unique index on the table.
Enabled
disable the index.
Tip This property is normally always set to Yes.
FeatureKey
be able to control use of the index by means of a feature key. An index field that is disabled through a feature key is automatically removed from the index.
Tip You should use a feature key so that the index is disabled for features that are disabled.
Forms sort on the first index.
5.8. Ways to customize A table in MorphX has a set of properties which describes certain characteristics of the table. When a table is created MorphX assigns a set of default values to the table’s properties. A table can be looked upon as a persistent class because its fields, and therefor its state information, are saved and restored to and from storage. Below is the property sheet for a table.
127
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 5-50 Property
Use this property to...
Id
see the internal ID of the object.
Name
change the name of the table. The name identifies the table and is used when referring to it from the X++ language.
Axapta standard Prefix: "Tmp" for temporary tables + Module short name, for example TmpCustLedger. Infix: Logical description of contents, for example CustCollectionLetterTrans. The postfix typically denotes the type of contents, for example *Trans, *Jour, *Line. The primary tables for the major business areas are postfixed with the word “table”. Examples are CustTable InventTableLedgerTable ProjTable VendTable VendTrans
Label
specify a user friendly name for the table
Axapta standard Mandatory property. The text value of the label must be unique for all tables (excluding temporary tables and maps).
FormRef
specify the default form for the table. The default form is the one you want the system to display when the end user activates Jump to Main Table by using the shortcut menu for a field on a form.
Axapta standard When the TableGroup parameter is one of the following * Parameter
Columbus IT Partner Russia, ApS
Rules and hints
128
Navision Axapta The form is referenced through a menu item of type Display. If you leave this field blank, MorphX tries to activate a form that has the same name as the table you are referring to.
TitleField1, TitleField2
Add information to the window caption in a form. A form caption is constructed from these three components: 1. The label from the field given as TitleField1 follwed by colon (:), and a space 2. The value of the field given as TitleField1 followed by comma (,) 3. The value of the field given as Titlefield2. The key field is typically given as Titlefield1, while TitleField2 is a descriptive field. Technically the form uses the Caption method (on the table) and the Caption method uses TitleField1 and TitleField2.
Temporary
mark a table as temporary. Temporary tables are not persistent. They are written to local disk storage but not stored in the database. Use a temporary table when you need to gather temporary information in a table format.
FeatureKey
define the feature key for the table. Feature keys allow a system administrator to enable and disable certain parts of an application. This is used to customize the application to individual requirements and adapt the application to suit specific user profiles. Important note If you define a feature key for a table of type Journal header or Journal line (the type is defined by the TableGroup property), the feature key must be a security feature key. A security feature key has its SecurityKey property set to Yes. This is to prevent the situation when
129
* Group * Main * WorksheetHeader then, you must have a form to maintain the table records. When you have a form that you use to maintain data in a table, the main rule is that the form should have the same name as the table. CustTable in the Axapta application is an example of this rule. If you choose not to follow this convention, you must give the name of the form here. For tables where the TableGroup property has been set to Group, Main, or WorksheetHeader a form must exist.
Axapta standard Mandatory property. The feature key used must be of type Database. This ensures that the table is removed when the feature key is disabled. The feature key can be of type User Interface only in instances when the application cannot "survive" without the fields and tables covered by the feature key.
Columbus IT Partner Russia, ApS
Navision Axapta disabling one single table might disable the system. Axapta standard Mandatory property. If the table is a transactions table, set the property to View.
MaxAccessMode
define the access rights when the table is used as a data source in a form or a report. If the table is used as a data source in a form, then the access rights in the form cannot exceed the access rights defined for the table. You can set this property to View on a transaction table to prevent the end users from modifying the transactions.
CacheLookup
determine how to cache the records retrieved during a lookup operation.
CreateRecIdIndex
have the system create an index on the Record Id field.
Set the property to Yes only if you actually need an index on the Record Id field. Tip All tables have a Record Id index. However, it is set to passive when CreateRecIdIndex is set to No.
SaveDataPerCom pany
have the system save data in the current company. If you set the property to No, data are saved without company identifier (DataAreaId). Generally this is not recommended. To see a list of tables with non companyspecific data. Tip The company acronym can be seen in the status line. Double-clicking the acronym opens a dialog to change company.
Axapta standard The property must be set to Yes.
TableGroup
determine which group the table should belong to. Table groups are used to define whether the system should prompt the user when he updates or deletes from the table in forms using the table as data source.
Axapta standard Mandatory property. Set to Group for a table that has several other tables relating to it where Those tables’ foreign keys are not indexed (Tables B and C) The table (Table A) holds data of lesser importance
Group should then be defined with Confirm delete. Typical examples from the standard application are the CustGroup and VendGroup tables. Columbus IT Partner Russia, ApS
130
Navision Axapta Axapta standard Mandatory property.
PrimaryIndex
select which index is used as primary index for the table. Only a unique index can be selected. The property is used for SQL optimization purposes, and to indicate which unique index to use as caching key. If none is specified, the unique index with the lowest ID is used as caching key.
ClusterIndex
select which index is used as clustered index for the table. The property is used for SQL optimization purposes only.
ModifiedDate
have the system maintain the ModifiedDate field for the records in a table. The ModifiedDate field records the date of the last modification of a record.
Axapta standard Set this property to Yes only if you need the information it provides.
ModifiedTime
have the system maintain the ModifiedTime field for the records in a table. The ModifiedTime field records the time when a record was last modified.
Axapta standard Set this property to Yes only if you need the information it provides.
ModifiedBy
have the system maintain the ModifiedBy field for the records in a table. The ModifiedBy field records who performed the last modification to a record.
Axapta standard Set this property to Yes only if you need the information it provides.
ModifiedTransacti onId
have the system maintain the ModifiedTransactionId field for the records in a table. The ModifiedTransactionId field contains the Id of the transaction that performed the last modification to a record.
Axapta standard Set this property to Yes only if you need the information it provides.
CreatedTime
have the system maintain the CreatedTime field for the records in a table. The CreatedTime field contains the time when a record was created.
Axapta standard Set this property to Yes only if you need the information it provides.
CreatedBy
have the system maintain the CreatedBy field for the records in a table. The CreatedBy field contains information about who created a given record.
Axapta standard Set this property to Yes only if you need the information it provides.
CreatedDate
have the system maintain the CreatedDate field for the records in a table. The CreatedDate field contains the date when a record was created.
Axapta standard Set this property to Yes only if you need the information it provides.
CreatedTransacti onId
have the system maintain the CreatedTransactionId field for the records in a table. The CreatedTransactionId field contains information about which transaction created the record.
Axapta standard Set this property to Yes only if you need the information it provides.
Customizing fields in a table Each field (column) in a MorphX table has a set of properties which describe certain characteristics of the field. When a field is created, MorphX assigns a set of default values to the field’s properties. The table below describes properties for fields in tables The primitive data types are: String, Integer, Real, Date, Time, Enum, and Container. 131
Columbus IT Partner Russia, ApS
Navision Axapta Property
Data Type
Use this property to...
Id
all
see the internal Id of the field
Type
all
Determine the type of a field.
Name
all
change the name of the field. The name is used when referring to the field from the X++ language.
Axapta standard A field must be named like the Extended Data Type used. If the field is named differently, the name must be logical.
HelpText
all
create a help string for the field. The help string is displayed when the field is used in a form.
Axapta standard Mandatory property. Typically the value is not actually set here but inherited from the field’s Extended Data Type. If you choose to overwrite the value, the value supplied here must be different from the one given on the Extended Data Type. Do not set the HelpText property to the same as the Label property. Compared to the Label property, the HelpText property is more frequently overwritten and made more precise for the specific field.
Label
all
specify a label which appear in forms and reports
Axapta standard This property must have a value. Typically the value is not set here, but inherited from the field’s Extended Data Type. If you choose to overwrite the value, the value supplied here must be different from the one given on the Extended Data Type. Do not set the Label property to the same as the HelpText property.
GroupPro mpt
all
define a label for the field when it appears in a group. Tip Use this to eliminate superfluous information. For example, if a field group on a form was labeled “Customer”, you could remove the customer-prefix from all fields in the goup so that instead of “Customer telephone”, “Customer fax” and so on, you would write “Telephone”, “Fax” etc.
SaveCont ents
all
determine if the contents of a field should be saved in the database, or if it is a virtual field. The contents of a virtual field can be calculated at run time when the field is displayed, and has no physical representation in the database.
Columbus IT Partner Russia, ApS
Rules and hints
Axapta standard Since virtual fields are rarely used, this property should practically always be set to Yes. Instead of virtual fields, you should use display and edit method modifiers.
132
Navision Axapta Mandator y
all
determine if it is required to fill in data in this field. The system checks whether this property is set in the table’s ValidateWrite method. When you manipulate a field that has the Mandatory property set to Yes from your own X++ code, you must call ValidateWrite to have the check performed. Forms always call ValidateWrite before Write is called.
Axapta standard If the field is the primary key (or part of the key), the property must be set to Yes. Tip Do not set the Mandatory property to Yes on an enum field.
AllowEdit OnCreate
all
determine if the end user is allowed to enter data in the field when a new record is created from a form.
Axapta standard This property is normally set to Yes.
AllowEdit
all
determine if the end user is allowed to modify data in an existing record in a form.
Axapta standard If the field is the primary key (or part of the key), the property must be set to No.
Visible
all
determine whether the field should be visible in the user interface. Tip Setting Visible to No can be used for non-user related fields.
FeatureK ey
all
define the feature key for the field. The feature key system makes use of the Visible and SaveContents properties: when a feature key is disabled, the user interface effect is that Visible is set to No and the database effect is that SaveContent is set to No.
AliasFor
all
determine the table field for which the field is alias.
Extended DataType
all
determine the Extended Data Type to be used for this field.
Adjustme nt
String
determine if this field should be left or right aligned when stored in
133
Axapta standard This property must have a value inorder to disable the field. Typically the value is not actually set here, but inherited from the field’s Extended Data Type. If you choose to overwrite the value, the value you give here must be different from the one given on the Extended Data Type. Disabling a table’s feature key will also disable the fields in the table.
Axapta standard This property must be set. Fields that hold the same information must share the Extended Data Type. Amount fields on transaction tables that can be “corrected” should be Stornoenabled. This means that the properties DisplaceNegative should be set to for example 10 and SignDisplay set to None. The data types AmountMSTDebCred and AmountCurDebCred can be used.
Columbus IT Partner Russia, ApS
Navision Axapta the database. Note This affects the search result when searching for a value in a table using the relational operators >, <, >=, or <=. Length
String
set the length in character of the field. The maximum field length is database dependent. •
The special value (Memo) indicates that the field is unlimited in length.
•
Note that if you use (Memo)
•
You cannot perform free text search and
•
Performance during fetch deteriorates
•
Memo field must NOT be used in WHERE clauses
FieldUpda te
Integer Real
determine if MorphX should use relative or absolute updating when saving information in the database.
EnumTyp e
Enum
determine the enum type to base this field on.
Modifying tables that contain data When you design a table in your database, you determine its characteristics, such as which fields it contains, the data type of the fields, indexes and so on. At a later step in your development process it may be necessary to change some of these characteristics. Typically you need to add one or more new columns, or maybe delete one. It may also be necessary to rename some of the fields or modify an index. The table below describes rules and restrictions for modifying tables containing data. Combine the rows with the columns to get answers to questions like: “Which rules apply when modifying a table”, or “Which rules apply when deleting an index”, and so on. Which rules apply when...
a table?
a field?
an index?
modifying
Modify a table’s properties by using the Application Object Tree, or at run time from X++ code.
Modify a field’s properties by using the Application Object Tree or at run time from X++ code. You cannot modify the data type for a field.
Modify an index using the Application Object Tree. MorphX allows you to add new fields, delete fields, and change the order of the fields in the index.
renaming
Tables can be renamed at design time using the Application Object Tree, or at run time from X++ code.
Fields can be renamed at design time using the Application Object Tree, or at run time from X++ code.
Indexes can be renamed at design time using the Application Object Tree.
deleting
Tables can be deleted using the Application Object Tree, or from X++ code.
Fields can only be deleted if there is no data in the field in any of the records in the table.
You can delete an Index at design time using the Application Object Tree. At run time you can disable
Columbus IT Partner Russia, ApS
134
Navision Axapta an Index using the Enabled property. This deletes the index from the database, but the index definition still exists in the Application Object Tree.
Temporary tables Regard temporary tables as a temporary variable used to hold a table. A temporary table is intended to be used as a buffer for table data in X++ programs. Temporary tables are declared just like any other variable, and have the following characteristics: • They do not contain any data when they are first created • They obey normal scoping rules, that is, their scope is determined by where they are declared • They are automatically deleted by MorphX when they go out of scope • Temporary tables are not persistent. They are written to local disk storage but not stored in the database. Temporary tables are used when you want a variable in X++ that has the same structure and characteristics as a table.
Temporary tables versus containers MorphX supports a special data type called a container. In some cases this data type can be used in the same way as you would use a temporary table. One major difference between temporary tables and containers is that data in containers are stored sequentially, and thus retrieved sequentially, while a temporary table allows you to define indexes to speed up data retrieval. This means that containers provide slower data access if you are working with large numbers of records. However, if you are working with only a few records, you should use a container. Another important difference between temporary tables and containers, is when using a temporary table in a method call, the information is passed by reference, while containers are passed by value. This means that if you are using a container as a parameter in a method call, it will be pushed on the system stack. If you are keeping many records in a container, and then pass it as a parameter, it will be pushed on the internal system stack. If your computer has a limited amount of memory, this causes the computer to start swapping part of the memory space to the disk, which slows down the execution of your application. In this case you should use a temporary table instead of a container.
Creating a temporary table Temporary tables are created just like any other table. The only thing you have to do, is to set the Temporary property to Yes.
Using maps Often you will find that you have a number of tables in your application that are very similar to each other. These tables may have several columns that contain the same type of information, although the names of the columns may be different. Often you have a number of other application objects that use the data in the tables. For example, a class which implements functionality to process data in the tables. If these tables use exactly the same names for the columns, you could reuse your data processing classes. But you might want to use column names that are as descriptive as possible to make the application easier to maintain. MorphX has a powerful feature called a map that fulfills both these requirements. By creating a map, you can access fields in different tables, if the fields are of similar types but have different names.
135
Columbus IT Partner Russia, ApS
Navision Axapta
Address (Map)
CompanyInformation
CustomerAddress
(Table)
(Table)
Notice that each table in your application can be accessed through more than one map. Typically, if more than one map accesses the same table, each map accesses different subsets of fields in the table. The Address map above can be used to access two tables called CompanyInformation and CustomerAddress. Imagine that the tables contain fields similar to the following: Field in CompanyInformation table
Field in CustomerAddress table
Field in Address map
Name
CustomerName
Name
Address1
Address
Street
Address2
Address1
City
ZIPCode
ZIPCode
PostalCode
Accessing the CompanyInformation and CustomerAddress through the Address map, lets you use the uniform field names defined by the map.
Creating a map To create a map: 1. Expand the Database node in the Application Object Tree, and locate the Tabels node. 2. Right-click the Tables node, and choose New, Map from the shortcut menu. 3. Rename your new map and expand it.
Pic. 5-51 4. Below the Fields node you can add fields, just as when creating a table. Right click the Fields node, and choose New Field from the shortcut menu. MorphX displays a submenu. Choose data type for the field. Repeat this until you have created the fields you need. 5. If you do not want to organize the fields in groups, then skip this step. To add fields to a group, right click the Field Groups node and choose New from the shortcut menu Repeat this until you have created the groups you need. Drag the fields from the Fields node, and drop them in the appropriate groups. Columbus IT Partner Russia, ApS
136
Navision Axapta 6. Now define how the map is supposed to redirect accesses to fields in the map. Right click the Mappings node, and choose New Mapping from the shortcut menu. MorphX adds a line below the Mappings node. 7. Click the new line, and display the property sheet.
Pic. 5-52 8. Set the MappingTable property to define the table you want to provide a mapping to. MorphX adds lines below the Mappings node for each field you have defined in your map.
Pic. 5-53 9. Click the first line and display the property sheet.
Pic. 5-54 10. Set the MapFieldTo property to define which field in the table you want to map this map field to. 11. Repeat this for each line below the Mappings node. 12. Compile and save the map.
5.9. Tips
.
Using Index and Order By in select statements If data ordering is important, use ORDER BY in your SELECT statements. If you can predict that the database will not be capable of deciding which index it should choose, use the INDEX keyword to give the database a hint of which index to choose. Combine this with an ORDER BY expression to get MorphX to select records in a specific order. Using the INDEX keyword but without ORDER BY the selected records are sorted according to the definition of the INDEX. If an index has been deactivated (Enabled=No), the SELECT statement is still valid. However, the database cannot use the hint (as the index does not exist), and has to choose some other index. 137 Columbus IT Partner Russia, ApS
Navision Axapta In general, use indexes to optimize selection of records. As a well-defined side effect, data are sorted according to the index definition. Use the REVERSE keyword if you want the sorted output in reverse order. The table below provides an overview of how to use the INDEX and ORDER BY keywords in your SELECT statements. To...
Use this...
Select records. Order not significant.
SELECT .. WHERE ...
Select records. Order is significant.
SELECT .. ORDER BY ... WHERE ...
Select records. Force a specific index to be used. Note: Assume that two or more indexes are equally good from the DBMS’s point of view. This is how to force the DBMS to use a specific index.
SELECT .. INDEX ... WHERE ...
Select records. Order is significant. Force a specific index to be used. Note: Assume that two or more indexes are equally good from the DBMS’s point of view. This is how to force the DBMS to use a specific index.
SELECT .. INDEX ... ORDER BY ... WHERE ...
Use ORDER BY together with INDEX if you want to be sure that the order of the records is as you intended it to be. Do not use ORDER BY together with INDEX if you just need to retrieve the records in the ordering defined by the index. Example: Get the transactions from last week from the set of all ledger transactions select LedgerTrans index DateIdx order by AccountNumber, Date where LedgerTrans.AccountNumber >= '1000' && LedgerTrans.AccountNumber <= '4000' && LedgerTrans.Date >= 28\04\97 && LedgerTrans.Date <= 05\05\97; Example: Get the transactions for the entire fiscal year select LedgerTrans index ACDate order by AccountNumber, Date where LedgerTrans.Kontonummer >= '7000' && LedgerTrans.Kontonummer <= '7008' && LedgerTrans.Dato >= 01\07\96 && LedgerTrans.Date <= 05\05\97;
Caching lookups The database record caching in Axapta is a performance-enhancing feature aimed at avoiding database access when it is not strictly necessary. Retrieving database records from memory instead of retrieving from Columbus IT Partner Russia, ApS
138
Navision Axapta the database will speed up data retrieval significantly. Caching can limit the performance-penalty for accessing the same database records repetitively. Caching is transparent to the application; it is all handled within the Axapta kernel. However, caching should only be used after having considered the following topics: • When updating a table that is cached, only the Axapta (two-tier clients or all thin clients on same Object Server) doing the update or delete has a cache that is synchronized with the table in the database. The cache data has no time-out. An Axapta Object Server refreshes its cache automatically each night at midnight. • If the application is not specifically designed to handle updates to cached tables, data corruption can occur. Currently, the only way to refresh all types of caches, in both 2- and 3-tier solutions, is to restart Axapta. This applies to a lesser degree to the result-set caching.
Record Caching Record caching is enabled for a table when all of these statements are true: • The CacheLookup property on the table is enabled (notITTS, Found, or FoundAndEmpty). • The table has a unique index, either the primary index or the first unique index. The RecId index does not qualify as a caching index. The field(s) in the unique index comprises the caching key. A record is placed in cache when these three criteria are met: • The table is cached, see above. • The select statement that selects the records uses an equal operator (==) on the caching key. • All fields in the record are retrieved. • A record is looked-for in the cache when these three criteria are met: • The table is cached, see above. • The select statement that selects the records uses an equal operator (==) on caching key. • The select is either outside TTS, or inside TTS, the table is Found, FoundAndEmpty or EntireTable cached and the select is not forupdate. CacheLookup property setting
Result
None
No data will be cached or retrieved from cache for this table. No caching should be used for tables that are heavily updated or where it is unacceptable to read outdated data.
NotITTS
All successful caching key selects are cached. When in TTS (after ttsbegin), the record is read once from database and subsequently from cache. The record is select-locked when read in TTS which ensures that the record cached is not updated while the TTS is active. A typical example of its use is the CustTable in the Axapta standard application. It is acceptable to read outdated data from cache outside TTS, but when data is used for validation or creating references it is ensured that it is real-time data.
Found
All successful caching key selects are cached. All caching key selects are returned from cache if the record exists there. A select forupdate in TTS will force reading from the database and replaces the record in the cache. This is typically used for static tables like ZipCodes where the normal
139
Columbus IT Partner Russia, ApS
Navision Axapta case is that the record exists. FoundAndEmpty
All selects on caching keys are cached, even selects not returning data. All caching key selects are returned from caching if the record exists there or the record is marked as non-existing in the cache. A select forupdate in TTS will force reading from the database and replaces the record in the cache. An example of this type of caching is found in the Discount table in the Axapta standard application. For this table the normal case is that no record exists, in this case it is therefore of great value to register the non-existing keys.
EntireTable
See below.
When caching a table that is updated, consider that only the Axapta doing the update or delete has a cache that is synchronized with the table in the database and that the cache data has no time-out. If the application is not specifically designed to handle updates to cached tables, data corruption can occur. Currently, the only way to refresh all types of caches, in both 2- and 3-tier solutions, is to restart Axapta.
Entire table caching This form of caching is available through setting the CacheLookup property on the table to EntireTable. This setting will create a copy of the table as an Axapta temporary table, and thus exploits the caching and search mechanisms implemented for Axapta temporary tables. All selects against the table will be performed on the copy. Joins that include the table will only be performed against the copy when all tables participating in the join are EntireTable cached. Otherwise a database join is performed. Operations that change data (insert, update and delete) are performed against the database as well as against the copy. The reread method will retrieve the data from database and update the copy data. The Axapta Object Server thin client will regard an EntireTable cached table as FoundAndEmpty cached as well, and will therefore build a recordCache locally when accessing the table.
Result-set caching The result-set caching is made available through the RecordViewCache class. The RecordViewCache is instantiated using a X++ select with a where clause that defines the resultset. The RecordViewCache is not shared between Axapta clients, and is deactivated as soon as the RecordViewCache object goes out of scope or is destroyed. The following rules apply to the instantiating X++ select: • It may not be a join. • It must be noFetch. • The table may not be temporary • When running an Axapta Object Server thin client, instantiation must be on the server. Due to concurrency issues, the forupdate keyword on the instantiating X++ select should only be used when all of the records in the resultset will be updated. Otherwise it is a better strategy to select forupdate the records that are updated. The RecordViewCache is used when a select is from the same table, not a join and matches at least the where clause that the RecordViewCache was instantiated with. When modifying rows that match the instantiating where clause, consider the following: • The database is changed at the same time as the RecordViewCache. • Updating the key of a row that did not qualify the resultset at instantiate time, will not result in the row being included in the cache. Columbus IT Partner Russia, ApS
140
Navision Axapta • Inserts are always included in the RecordViewCache(s) for that table. Care should therefore be taken when inserting massive number of rows in a table and at the same time having a RecordViewCache on the same table. • A delete will remove the row from RecordViewCache(s) on that table. • A Delete_from will invalidate RecordViewCache(s) on that table. The reread method will retrieve the data from database and update the copy data. Do not use field-lists unless certain that the omitted fields will never be used, there is no warning or error when selecting fields from the RecordViewCache that were not included in the select that instantiated the resultset.
The RecordViewCache can be instantiated using a select without where clause, this will effectively create a copy of the table in memory and thus function like a personal table copy in memory. The RecordViewCache is useful for caching tables that are not of static nature, or that contain so many records that the other caching methods would be impractical. When using this form of caching consider the memory consumption, as there is no internal limitation to the memory allocated for a single table. Different application behavior with regards to applying this caching form when running on server versus client could be an option.
Browsing data Once you have created a forms interface and entered entered data in a table, you can use the table browser facility to view your data. To open the table browser: 1. Open the Application Object Tree shortcut menu on the table object from which you want to see data. 2. Activate Table browser in the Add-ins submenu.
Pic. 5-55 The table browser displays data from all fields in the table. Use the Auto report button to limit the fields to the ones defined in the AutoReport field group. You can edit and delete the records you browse. Use the edit field to enter an SQL statement. Click the execute button to have the statement applied to the data source. This feature is useful to test the SQL statements used in your code. Testing SQL statments like this is much easier than writing a job to do the same. An example: When browsing the CustTable, the statement select custTable where custTable.custGroup=="40" 141
Columbus IT Partner Russia, ApS
Navision Axapta will display only the customers who are in customer group 40.
The table browser does not support display of fields of type container. This means that even when you choose to see all fields, container fields are excluded.
You can use the table browser anywhere a table is used as a data source: in a form, in a report, and in a query. Property settings on a table or a field may prevent you from editing or deleting. If you cannot edit or delete data, check the table property setting for MaxAccessMode and the field property setting for AllowEdit.
You can also use the table browser to view the contents of system tables. System tables are located in the Tables node beneath the System Documentation node in the Application Object Tree.
Columbus IT Partner Russia, ApS
142
Navision Axapta
6. Creating forms 6.1. Form basics What is a form and what is it used for? Forms can be used for a variety of purposes: • To enter data in the database, • To open other forms or reports, • To activate commands like Create Record or Delete Record, • To accept and act on user input. Most of the information displayed in a form comes from data stored in the database tables. Other information in the form is stored in the form’s design; information of this type is typically descriptive text and graphic elements like lines, images etc. Create the link between a form and its database source by using graphical objects called controls. The most common type of control used to display and enter data is a text box. Other types of controls are tab, list box and check box. The form below is a complex one with several tabs. It is used to display and enter information in a table. The command buttons to the right open other forms or reports.
Pic. 6-1
The basic steps in defining a form The simplest way to create a form is to use the Application Object Tree. One of the major advantages of the tree is that you continually see the available options because when the New command is activated in a node's shortcut menu, an object of the wanted type and structure is created in the tree. When you become an expert X++ designer, you may find it more dynamic and convenient to program your forms. Use the forms system classes to do this. For an overview of the forms system classes. There is an important difference between a form created in the Application Object Tree, and one created through X++ code in that the latter is not saved in the tree. Forms may be created for a variety of purposes. Typically, a form is used to display information from a table in the underlying database, and to enter new data, or modify existing data.
143
Columbus IT Partner Russia, ApS
Navision Axapta
Create a form linked to a table 1. Right-click the Forms node in the Application Object Tree, and click New Form on the shortcut menu. A new node is created called Form1. You will probably want to give the form another name; use the Rename command in the shortcut menu to do this. Axapta standard for a form name: The main naming rule for a form is that it should be named like its main data source, including a possible “table” postfix. Examples are: CustTable, VendOpenTrans. 2. Define from which table the form should display data. Do this in the Data Sources node on the newly created form node: move the desired table from the Tables node using a drag-and-drop operation. Now all fields from the table are available, and you may reference them in the form. 3. Define the graphical layout of the form. Do this in the Design node on the newly created form node: move the desired fields from the Data Sources node to the Design node using a drag-and-drop operation. According to your needs, you can choose to move individual fields or groups of fields. Normally you will always choose to move groups of fields. Field groups ar dynamic and any change you make on the underlying table is automatically reflected on the form. Based on the default settings, the system automatically chooses which type of control the individual field should be represented by. This means that you can now run your form, and see it as the end user will see it by clicking Open in the shortcut menu on the form node. 4. Write X++ code to be attached to the form. Do this in the Methods node on the newly created form node. When you create a new form, the system automatically creates the essential general methods for manipulating a form as well as a 'place holder' - a class declaration - for variables. These methods are virtual methods implemented in MorphX and inherited from there but you may add code or choose to override the MorphX implementation of the standard functions. To do so, point to Override Method and select the desired method from the list. You can also add you own methods using the New Method command on the shortcut menu. Usually, you will not make any changes. In addition to adding code to the Methods node, you can also override or add methods in the Data Sources node, and on each control in the Design node. Where you should write your code is defined by what you want to accomplish. Finally, compile your form and check that it looks the way you want: click Compile, Save and then Open in the shortcut menu on the form node. The form is now complete and may be used in your application. One way to integrate it is to move it to Menu Items, which is the 'pool' of application objects that can be opened from a menu. Menu items: What they are and how they work Menu items are a collection of items that can be activated from menus and forms. Each item runs an application object: a form, a report, a class, or a query. You must always create a menu item when you want to activate an application object from a menu or from a form. Menu items represent an additional level of indirection. This means that you never reference an object directly. The example illustrates the situation when you have four forms, forms A to D, that each have a button to open the same form, form X. These forms do not reference form X directly; rather they reference the menu item that references form X. The advantage of this becomes obvious when you need to change the application so that forms A to D open another application object – this could be a form but it could also be a Columbus IT Partner Russia, ApS
144
Navision Axapta class, a report, or a query. In such a situation you need modify only the menu item that references form X and all objects that use the menu item are updated automatically. A menu item is created using the Menu Items node in the Application Object Tree. The Display, Output and Action nodes are categories you can use to have an improved overview of your items that rapidly grow in number (the standard application comprises more than 1000 application objects!). The Display node typically holds items that are displayed on the screen, typically forms The Output node typically holds items that generate output, primarily reports The Action node typically holds items that activate in batch, primarily queries and classes. However, the nodes are identical in structure and you can use them as you wish. They are merely a help facility when structuring your references. Note, though, that the name of a menu item must be unique within a group. The menu structure in MorphX Menus in MorphX are extremely flexible and can be custom made to suit the exact needs of any company and user. Menus allow you to organize commands so that the end user can find and use them quickly. An Axapta application normally has several menus customized to the individual users' area of responsibility. Typically the person responsible for sales and marketing will have a menu that is radically different from the bookkeeper's menu. Such menus are created and opened from the File menu. The standard application has a default main menu. However, the main menu can be customized to suit the need of the individual company. All menus in Axapta are based on menu items. When you create a menu, you create references to your Menu Items collection. So creating menu items are a prerequisite for creating any menus
What are controls and how do their properties relate to properties in their underlying fields? All the information on a form is contained in controls. Controls are objects on a form that display data, perform actions, or decorate the form. For example, you can use a text box on a form to display data, a command button on a form to open another form, or a picture on a form that shows a company logo. When you create a bound control by dragging a group or an individual field from the Data Sources, the system copies all formatting and display length properties from the field in the underlying table. In this way the control inherits the underlying field’s properties. You can change the settings of any inherited properties in the control's property sheet. If you change a control's property setting, the change does not affect the setting of that property for the field in the underlying table or query. It is always an advantage to set properties in the underlying field rather than in a control. This way, you can be sure that you have consistent settings whenever you add fields to a form. Also, no less important: it gives you less work if you set the properties once and for all.
You can duplicate, copy and paste, drag-and-drop form controls. Both within a form and between different forms.
The following table lists the available controls with a brief description of each, gives a description of the central properties. Also listed in the table are properties inherited for each type of bound control when you drag a field from the Data Sources to the Design node or set the DataSource and DataField properties. Control Name
What it is
ActiveX
Any ActiveX control available on the computer.
145
Comments
Inherited properties
Columbus IT Partner Russia, ApS
Navision Axapta Animate
A control used to display an *.avi file. The .avi file must be without a sound track.
Setting the AutoPlay property to Yes and the Loops property to 0, you can have the system play the designated .avi file indefinitely.
Button
A rectangular button.
No function attached - this must be programmed in the button methods.
ButtonGroup
Facility used to group buttons that belong together under a heading.
CheckBox
A square box that is selected or cleared to turn an option on or off. More than one check box can be selected.
Auto selected for type Enumerated with two possible values.
ComboBox
A text box with an attached list box.
Auto selected for data type Enumerated.
CommandButt on
A button to activate a command, for example to close the form, to save all, or to activate one of the system’s menus.
DateEdit
A rectangular box in which the user enters a date. If the box already contains a date, the user can delete it, and type a new one.
Auto selected for data type Date
Grid
Table with rows and columns.
In a grid control you can select multiple records and perform delete (ALT+F9) and copy (CTRL+INS) operations. The delete operation begins by deleting the current and continues until a record is encounted that cannot be deleted.
Alignment DateFormat DateSeparator DateYear DateMonth DateDay
The copy operation uses a tabseparated, text format that can easily be pasted into for example Microsoft Excel. Access to forms cache To access the forms record cache in a grid control from X++ code use these form data source methods:
int mark( [int mark]Set or get the mark flag on the current ) record. This flag can be used in the other methods, and a value other than 0 will result in the record showing up as marked in grids. int Set or get the mark on the markRecord(recor flag
Columbus IT Partner Russia, ApS
146
Navision Axapta d r, [int Mark])
specified record. This method can be used if the record has been found using a select or method call outside the form, and the cache will be searched for the record (on RecId match), and the mark value will be set/returned.
record getFirst([intReturn the first Mark = 0],record with the [boolean specified mark fetchahead =value. TRUE]) The fetchAhead parameter can be used to specify if only the cached records should be looked at (fetchAhead=FALS E), or if the cache should be expanded, and all records looked at. record getNext()
Uses a previous getFirst, and returns the next record matching the specified mark value.
Group
Facility used to group several fields under a heading. Automatically used when a whole group of fields from a table is displayed on a form.
HTML
A control used to display and edit HTML based text.
IntEdit
A rectangular box in which the user can enter an integer. If the box already contains an integer, the user can delete it, and type a new one. If the user enters an expression in an IntEdit or a RealEdit control, for example 125+3*(10/3)-(8/(11+3)), the expression is evaluated when the user leaves the control.
The DataSource and DataField properties identify the database field when bound. Auto selected for data type Integer.
Listbox
A list box presents the user with a list of possible choices.
Can also be used for data type Enumerated but this must be set in the property sheet.
ListView
A special extended selection list box that displays a collection of items, each item consisting of an icon and a label.
This control is typically used where the representation of objects as icons is appropriate. ListView controls can display content in four different views: Large Icon
147
Alignment SignDisplayRotate Sign ShowZero DisplaceNegative
Columbus IT Partner Russia, ApS
Navision Axapta Small Icon List Details These views are identical to those in Windows Explorer. The ListView control must be programmed. The ListView control is used in the standard application in SysMenuForm. MenuButton
Facility used to create a submenu.
Once a submenu is created, you can place a CommandButton, a MenuItemButton, a Separator, or a Button on it.
MenuItemButt on
A button to activate a menu item.
Two properties are essential to this control: MenuItemType, and MenuItemName. These properties identify the function to be activated.
Progress
A control used to show the percentage of completion of a lengthy operation. It consists of a bar that “fills” from left to right.
Can also be used for data type Enumerated but this must be set in the property sheet.
RadioButton
Round button used to select one of a group of mutually exclusive options.
RealEdit
A rectangular box in which the user enters a real. If the box already contains a real, the user can delete it and type a new one. If the user enters an expression in an IntEdit or a RealEdit control, for example 125+3*(10/3)-(8/(11+3)), the expression is evaluated when the user leaves the control.
The DataSource and DataField properties identify the database field when bound. Auto selected for data type Real.
Separator
A line used to divide groups of command menus.
Can be used on a MenuButton.
StaticText
Any fixed text
The text you would like to display in the form is given in the Text property.
StringEdit
A rectangular box in which the user can type text. If the box already contains text, the user can delete it, and type new text.
The DataSource and DataField properties identify the database field when bound. Auto selected for data type Text. Note that a StringEdit control may span multiple lines. This is defined by the MultiLine property.
Columbus IT Partner Russia, ApS
Alignment SignDisplay RotateSign ShowZero DisplaceNegative ThousandSeparato r DecimalSeparator NoOfDecimals AutoInsSeparator
Alignment Uppercase
148
Navision Axapta Tab
A placeholder for TabPages.
The Tab property controls which tab pages should be displayed when the user opens the form, e.g. if Tab = 2 the second tab pages will be in focus when the form is opened.
Table
A spreadsheet-like table with rows and columns.
This control is not tied to the database; it looks much like a Grid but unlike a grid the table may display values of different types in a single column. The Table control must be programmed. The Table control is used in the standard application in SysQueryForm.
TabPage
An additional page on the form. Typically used when there is too much information to display in a single dialog. A TabPage can only be inserted on a Tab.
The Caption property gives the text that displays on the tab.
TimeEdit
A rectangular box in which the user enters the time. If the box already contains the time, the user can delete it, and type an alternative one.
Tree
A special list box control that displays a set of objects as an indented outline based on their logical hierarchical relationship.
The Tree control must be programmed. The Tree control is used in the standard application in SysQueryForm.
Window
A simple window that can display a bitmap.
The central property is ImageName, which is where you give the filename of the graphics file to be displayed.
Access keys on forms Axapta automatically generates access keys (underlined letter) using the label assigned to the control. Therefore access keys will very rarely be the same in two different languages. An example A form has four controls, A, B, C, and D. Control
Label
Access key
A
AB
A
B
AB
B
C
AB
Control C is assigned no access key because both A and B have been used.
D
BC
C
149
Columbus IT Partner Russia, ApS
Navision Axapta
Using the graphical forms editor Click Edit in the shortcut menu on a form’s Design node to open the graphical form editor where you can position and size controls. The editor automatically opens a palette with the available controls.
Pic. 6-2
To insert a new control 1. Select a control type on the controls palette. 2. Click the form where you want to position the control. If you click the form or a container control (Grid, Group, Tab, TabPage, Table, ButtonGroup), the new control is inserted as the last one on the form/container. If you click another control, the new control is inserted right after the control within the same container. You can use these keys during graphical editing: TAB
Selects the next container or control.
SHIFT+TAB
Selects the previous container or control.
ENTER
Shows the property sheet for the current control.
ALT+UP
Changes the sequence of the controls, moves the current control up in the tree.
ALT+DOWN ARROW
Changes the sequence of the controls, moves the current control down in the tree.
DEL
Deletes the current control.
ESC
Closes the graphical editing window.
Automatic reports on data in forms It is simple to set up Axapta to generate a report from the contents of any form that the user currently has open. Such automatic reports are based on the fields placed in the AutoReport field group.
To have automatic reports on forms • On tables used as data source on a form, move fields from the Fields list to the AutoReport field group. When the user has a form open and clicks Print... on the File menu, a report based on data displayed in the form is generated. Columbus IT Partner Russia, ApS
150
Navision Axapta If the form has more than one data source, the fields on the first one are displayed in the report.
Pic. 6-3 The user can click Print in the Auto Report dialog and have the report gernerated and printed. Or he can use the buttons in the dialog to modify the default settings.
Guidelines for form design Following the guidelines below will help you make functional, logical and better-looking forms. The primary concern is that any form should appear simple and intuitive to the user.
Size • A form must fit into a screen with 800*600 resolution. • Normally a form should have one column only, with a maximum of two columns.
Relation to underlying data source • The field groups from the underlying table should be used in a form. • The name of a form must be related to the name of the underlying table.
Layout • When planning the position of fields, groups and tab pages the typical situation when the form is used should be considered. Does the user need to see much information, or will he use the form to enter a lot of information? • Whenever a form has a grid, its height should be Auto. • Tab pages should be used when there is not enough space on a form for the required number of fields. Tab pages should always be named sensibly so that the user can guess what is on the page. The first tab page should normally be named 'General' and hold the information the user most frequently needs to see, or edit before moving on to the other pages. Fields on the first tab page will frequently come from other groups of fields (perhaps on another tab pages); they should be hidden on the tab pages from which they originate. The last tab page could be named 'Miscellaneous'. • Groups can have frames around them. The FrameType should be Auto, Outside, and all margins should be Auto. Groups with frames can have a caption. The caption text should be a label and normally identical to the one used as a group name in the table.
151
Columbus IT Partner Russia, ApS
Navision Axapta
Choice of controls As a general rule, the system's auto selections of controls should be used. Although, a RadioButton can be selected for an enumerated type if the user changes the value each time he uses the form, and if the number of options dictate it.
6.2. Ways to Customize Your Form Add a picture to a form Once you have created a form, you can add a picture such as a company logo. 1. Right-click the Design node, and select Window on the New Control submenu. 2. Modify the two image relevant properties, ImageName and ImageMode. ImageName identifies the file name and location. ImageMode identifies how the image should be displayed (for example 'centered'). You can also use X++ code to add a picture to a form.
Add a control to a form Everything you add to a form is a control. Text boxes, list boxes, option buttons, command buttons, and images are examples of different controls. The way you create a control depends on whether you want to create a bound control, an unbound control, or a calculated control.
Create a bound control 1. Locate the form where you would like to add a control in the Forms node. 2. Display the field list in the form's Data Sources. 3. Select one or more fields in the field list. To select
Do this...
One field
Click the field.
A block of fields
Click the first field in the block, hold down the SHIFT key, and then click the last field in the block.
Nonadjacent fields
Hold down the CTRL key and click the name of each field you want to include.
4. Drag the selected field(s) from the field list to the form's Design node. The system creates the appropriate control for the field, and sets certain properties based on the field's data type.
To take advantage of the groups defined on your tables, it is preferable to move a whole group from your data source.
If the field you would like to display is not in the form's Data Source... Any field you would like to display on your form must be in the form’s Data Source node. When you add a field to a group in the underlying table, the field is automatically added in the object bank, and if you display the group on your form, the field appears there as well. Columbus IT Partner Russia, ApS
152
Navision Axapta
Create an unbound control 1. Locate the form where you would like to add a control in the Forms node. 2. Right-click the form's Design node, click New Control, and select the control you want to create. Subsequently you might want to modify some of the default property settings (as a minimum Name and Label).
Create a calculated control As a simple example of a calculated control, you might have two fields in a table that you would want to display on one of your forms along with their total. The following example assumes that you have two integer fields in your table (MyTable) called Subtotal_A and Subtotal_B, and that you have already created two (bound) controls displaying their values. 1. Add your own method that calculates the total to your table called MyTable. Display int SubtotalSum(MyTable t) { return t.SubTotal_A + t.Subtotal_B; } You add the method to the table rather than to the form because in this way you may make use of the same code in other forms if you should want to. Display is a modifier (like static, private, public etc.) that enables you to show the result of your computation. 2. In the properties on the newly created control, you set DataSource to MyTable (the table where the method was defined), and DataMethod to SubTotalSum (the name of the method that calculates the sum).
Note that whenever you add a new control the size of the form auto-adjusts; you will never experience that some information or control is only partially visible.
Create a form with tabs To create a form with tabs, begin by creating a tab that is a placeholder for the tab pages want. Then you create each of the tab pages. 1. Right-click the Design node, and select Tab on the New Control submenu. 2. Right-click the new Tab, and select TabPage on the New Control submenu. 3. Modify the Caption property to give the tab page a name. 4. Repeat 2. for each new tab page you want to add. You can now place controls on the tab pages, either by moving groups or fields from the Data Sources node, or by using the New Control submenu.
Bind an unbound control to a field When you right-click the Design node, and select a control in the New Control submenu, you get an unbound control, a control that is not tied to any underlying data source. To subsequently bind the control to a field 1. Locate the control in the form's Design node, and open its property sheet. 2. Modify the DataSource and DataField properties to specify the field you want to bind the control to. 153
Columbus IT Partner Russia, ApS
Navision Axapta If you create a bound control by dragging fields from the field list, the bound control inherits certain Auto properties from the underlying field. For more information about which properties are inherited, and how this inheritance works.
Change the tab order on a form When you create a form with several tab pages, the system automatically inserts tab pages in the order you create them. The Tabs property shows how many tab pages you have on your tab container, and the Tab property defines the active one. To re-order the pages, simply move the pages in the tree.
Delete a control on a form To delete a control on your form, right-click the control to open the shortcut menu and click Delete. The group structure you have defined on the underlying table is automatically reflected in the form. This means that if you delete a field from your database table, it is automatically removed from your form. Also, if you move a field to another group in your table, it is automatically moved on the form as well - provided, that is, that you have moved a whole group rather than individual fields from the Data Sources node to the Design node.
When you move a whole group of fields from the Data Sources node to your form layout, you cannot delete an individual field; it will re-appear.
Format groups on your form Controls that logically belong together are normally grouped on a form. The system has a default setup for the layout of the group separators that can be modified by changing two properties on the group: • FrameType, • FramePosition.
Group controls on your form Controls that logically belong together may be grouped below a division line and a common heading on a form. 1. Right-click the Design node, and select Group on the New Control submenu. Modify the Caption property to give the group a heading. 2. Move the desired fields from the form's Data Sources node to the newly created group, or create new controls using the New Control submenu. When a control is created using the New submenu, it can be bound to a field in the form's Data Sources by modifying the properties DataSource and DataField. If you move an entire group of fields from a form's Data Sources to the Designs node, the grouping is automatically reflected in the form layout with the creation of a Group. Modify the Caption property to give the group a heading.
Use image lists for Tree controls and ListView controls If you use a Tree or a ListView control in a form, you must generate an image list that you load when the form is opened, and release when the form is closed.
Columbus IT Partner Russia, ApS
154
Navision Axapta
How an image is referenced You refer to an image through a DEFINE statement in the macro library resAppl. Use the tutorial_resources form to gain an overview of the available ressources.
How is an image list generated An image list is generated through a class inheritance hierarchy. The class to inherit from is called ImageListAppl. The ImageListAppl class loads only the single image, “Axapta”, and the general idea is to inherit from this class and add more images to the list. An example of this is the ImageListAppl_Prod class that adds a number of general production images. For example, new, more specialized images might be added in the ImageListAppl_Prod_Special_1 class. When you need an image list, locate a suitable node and level in the hierarchy, and load the list. The basic idea is that image lists are maintained in one place only. For example, this means that when an addition to the order system is performed at a suitable place in the hierarchy, the new image is readily available to all forms using the image list or inherited versions of the list.
How to accomplish this 1. Create a class that extends the ImageListAppl class. 2. Name the class ImageListAppl_XXX (see for example ImageListAppl_Aot, ImageListAppl_Prod) and 3. Override the Build method. Example void Build() { super(); // Do NOT forget to call super()!!!!!! this.Add(#ImageProduction); this.Add(#ImageItem); this.Add(#ImageBOM); this.Add(#ImageService); this.Add(#ImageSetUp); this.Add(#ImageProcess); this.Add(#ImageQty); }
How to use the image list in forms Everywhere you use a Tree control or a ListView control in a form, make modifications corresponding to the ones in the example below. The example uses the ImageListAppl_Prod image list. void ClassDeclaration() {
155
Columbus IT Partner Russia, ApS
Navision Axapta #resAppl ImageListAppl_Prod imageListAppl_Prod; FormTreeControl tree; FormListControl list; } void init() { tree = element.control(control::myTree); list = element.control(control::myList); imageListAppl_Prod = new ImageListAppl_Prod(); tree.SetImageList(imageListAppl_Prod.ImageList()); list.SetImageList(imageListAppl_Prod.ImageList()); } void InsertTreeItem(int parent, str name) { FormTreeItem item = new FormTreeItem(name,imageListAppl_Prod.Image(#ImageProduction) , 1); tree.AddItem(parent, FormTreeAdd::LAST, item) } void InsertListItem(int parent, str name) { FormListItem item = new FormListItem(name, imageListAppl_Prod.Image(#ImageProduction)); list.AddItem(item) }
Refer to the forms tutorial_formListControl and tutorial_formTreeControl to see examples of image list construction techniques.
You can also use an image list in a Window control if the control is bound to an integer database field. The control uses the value of the field as an index to the image to be used.
Modify the shortcut menu on controls The shortcut menu on controls is the menu that appears when a user clicks the right mouse button in a form control. The content of the menu is controlled by the system and defined according to the current context. Columbus IT Partner Russia, ApS
156
Navision Axapta An example of a shortcut menu:
Pic. 6-4 When the user right-clicks a control, the context() method is called and its super() call calls the showContextMenu method. The parameter to showContextMenu is a handle to the system’s shortcut menu. Use showContextMenu to add your own item to the system’s menu items. Example int showContextMenu(int MenuHandle) { int ret; PopupMenu m = PopupMenu::Create(MenuHandle,this.hWnd()); int myMenuItem = m.insertItem("MyItem"); // Save the handle of the appended menuitem ret = m.draw(); // Show the menu if (ret == myMenuItem) // Check if the user selected "our" item { print "MyItem was selected"; pause; return 0; } else Return ret; }
Note that you do not call super() in the method but rather the draw method. showContextMenu should return the user’s selection if the system should take normal menu action on the selection, or zero (0) if no action should be taken.
Description of properties for controls To see hints and advice about setting properties for controls. Property
157
Modify this property to...
Applies to
Columbus IT Partner Russia, ApS
Navision Axapta A ActiveBackColor
set the background color of the current record.
Grid
ActiveForeColor
set the text color of the current record.
Grid
AlignChild
define that an individual control should not be part of the general arrange system. If you had set AlignChildren to Yes on the Design node, you might not want Group2 to be arranged with the other three groups. In that case you would set AlignChild to No on Group2.
Tab Group ButtonGroup TabPage
AlignChildren
align the child controls.
Tab Group ButtonGroup TabPage
In the above example the children of the Design node are Group1 to Group4. The node cannot 'see' the two StringEdit controls that are the children of Group1. AlignControl
define whether controls should be aligned. The top left corner of the controls is aligned immediately following the longest label. This is particularly useful to align a number of edit fields.
all
Alignment
change the alignment of the text (Left, Right, Center)
StaticText RealEdit IntEdit DateEdit TimeEdit
AllowEdit
allow modifications to the data. When set on a container control, modifications are disabled or enabled for all controls within the container.
all
AllowNegative
define whether integers displayed in this control can be negative.
IntEdit
AnimateFile
give the name of the .avi file to be used in the control. Note The .avi file must not have a sound track.
Animate
AppendNew
append new text to the list on editing. This property can be used on unbound controls only.
ComboBox
ArrangeGuide
This is a system property. Do not modify.
ButtonGroup Group Tab TabPage
ArrangeMethod
change how the controls on the container should be arranged (vertically, horizontally...)
Tab Group ButtonGroup TabPage
Columbus IT Partner Russia, ApS
158
Navision Axapta ArrangeWhen
change when the controls on the container should be arranged (on startup, on demand, never...)
Tab Group ButtonGroup TabPage
ArrayIndex
define the array element to be displayed in the control. If ArrayIndex=0, all elements are displayed. This is for example used in methods modified by display. To learn how.
StringEdit IntEdit RealEdit DateEdit TimeEdit
AutoArrange
have the system arrange the items in your list automatically.
ListView
AutoDataGroup
Group
AutoDeclaration
have the system delare a variable of the same name as the control. Note This means that two controls cannot have identical names.
all
AutoInsSeparator
let the system insert a decimal separator automatically
RealEdit
AutoPlay
set the .avi file to play automatically when the form is opened.
Animate
Property
Modify this property to...
Applies to
BackgroundColor
change the color used for the background
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox Listbox CheckBox RadioButton Grid Tab Group ButtonGroup CommandButton MenuItemButton MenuButton Button Window Table TabPage ListView Tree
BackStyle
change the background to transparent
StaticText StringEdit
B
159
Columbus IT Partner Russia, ApS
Navision Axapta CheckBox Group Button RealEdit IntEdit ComboBox Window DateEdit RadioButton ButtonGroup CommandButton MenuButton MenuItemButton Listbox TimeEdit Bold
display text in another style (medium, semibold, bold, heavy...). See Also: Font
StaticText StringEdit RealEdit IntEdit DateEdit ButtonGroup Listbox TimeEdit
Border
change the border type of the control (no border, 3D border, single line...)
StringEdit RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Tree ListView Animate HTML
BottomMargin
change the default bottom margin of the controls on the container. An exact margin may be given in pixels.
Tab Group Grid ButtonGroup TabPage MenuButton Table
ButtonDisplay
define whether the button is to display an image, as text only, or both text and image. The text to be used is defined with the Text property. The image to be used is defined with the properties: NormalImage, NormalResourceDisabledImage, and DisabledResource.
Button CommandButton MenuButton MenuItemButton
Columbus IT Partner Russia, ApS
160
Navision Axapta
Property
Modify this property to...
Applies to
CanScroll
define whether it should be possible to scroll. This could be relevant if you would like to control the user’s view from your code.
ListView
Caption
give a heading for some grouped controls.
Group RadioButton ButtonGroup TabPage
Center
define whether the .avi file should be centered in the control.
Animate
ChangeCase
have the system change the case of any text entered in the control.
StringEdit
C
CharacterSet
Button ButtonGroup ComboBox CommandButton DateEdit Group IntEdit ListBox ListView MenuButton MenuItemButton RadioButton RealEdit StaticText StringEdit TimeEdit Tree
CheckBox
choose whether a checkbox should be added to the control.
ListView Tree
ClassName
give the class ID of an ActiveX control. The class ID is also used during runtime.
ActiveX
ColorScheme
choose another color palette. You can change the color palette for an entire form by setting the ColorScheme property for the largest container and keeping the default values for the individual controls.
StaticText StringEdit Tab CheckBox Group Button RealEdit IntEdit ComboBox Window DateEdit RadioButton
161
Columbus IT Partner Russia, ApS
Navision Axapta Grid ButtonGroup TabPage CommandButton MenuButton MenuItemButton Listbox TimeEdit Table Tree ListView Column
set the initially active column.
Table
ColumnHeader
define whether the column should have a heading. Only valid when the ViewType property is set to Details.
ListView
ColumnHeaderBu tton
define whether the header should be a button to be clicked to defined sort order (like, for example, the column headers in Windows Explorer). The ColumnHeaderButton property is valid only when the ColumnHeader property has also been set. Only valid when the ViewType property is set to Details.
ListView
ColumnImages
like each item in a column to include an image. Give the name of the file holding the icons in the SmallIcons property.
ListView
Columns
change the number of columns used to display the information. Note that the grouping of fields defined on an underlying database table is preserved so that a group is never split in several columns.
Tab Group RadioButton ButtonGroup TabPage Table
Columnspace
set space between columns.
Tab
ComboType
define the type of combination box to be used.
ComboBox
Command
define the command to be activated when the user presses the button.
CommandButton
Custom
open the property sheet for the ActiveX control. This is possible when the form is in Design view only. Note that not all ActiveX controls have a property sheet, or allow editing it.
ActiveX
Property
Modify this property to...
Applies to
define from which field on the underlying table (given by the DataSource property) data is displayed.
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox
D DataField
Columbus IT Partner Russia, ApS
162
Navision Axapta Listbox CheckBox RadioButton DataGroup
change the group of fields from the underlying table that are displayed in the current group on the form. The DataGroup may be an AutoDataGroup.
Group
DataMethod
activate a method on the control (rather than have data displayed from an underlying field). The method may be selected from The table that is used as a data source for the form. The Data Sources node on the form. The Object Methods node on the form.
StaticText StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit RadioButton TimeEdit
DataSource
which table from the database data are displayed from or scrolled in (for container controls like Tab). Also, the DataSource is the join source when another form is activated.
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox Listbox CheckBox RadioButton Grid ButtonGroup Tab TabPage Group
DateDay
determine how the day should be displayed.
DateEdit
DateFormat
determine the layout of a date
DateEdit
DateMonth
determine how the month should be displayed.
DateEdit
DateSeparator
determine the separator between year, month and day.
DateEdit
DateValue
enter a static text for a date rather than use a data source. Note that this property is not used if the DataSource/DataField properties are set.
DateEdit
DateYear
determine how the year should be displayed
DateEdit
DecimalSeparator
choose the decimal separator ‘,’ or ‘.’
RealEdit
DefaultButton
define that this should be the default button.
CommandButton MenuItemButton MenuButton Button
DisabledImage
define the button image to be used when the button is disabled. The image is any graphics file. If no DisabledImage is defined, the system generates one on the
Button CommandButton MenuButton
163
Columbus IT Partner Russia, ApS
Navision Axapta basis of the NormalImage property. Image display is defined by the ButtonDisplay property. Related properties: ButtonDisplay, Text, NormalImage, NormalResource, and DisabledResource.
MenuItemButton
DisabledResource
define the button image to be used when the button is disabled. The image is located in a system table. For an overview of system resource images, see the tutorial_resources form. If no DisabledResource is defined, the system generates one on the basis of the NormalResource property. Image display is defined by the ButtonDisplay property. Related properties: ButtonDisplay, Text, NormalImage, NormalResource, and DisabledImage.
Button CommandButton MenuButton MenuItemButton
DisplaceNegative
indent the number to the right if it is negative.
RealEdit IntEdit
DisplayHeight
limit the height of the control. Used in conjunction with the MultiLine property to define a entry field that may span several lines.
StringEdit
DisplayLength
limit the number of characters displayed in the control. Indirectly this gives the width of the control – but in number of pixels. By contrast, the Width property is in pixels.
StringEdit RealEdit IntEdit ComboBox DateEdit TimeEdit
DragDrop
allow that the field can be drag-and-dropped. Note Drag-and-drop fields require code to support it. For examples, see the tutorial_FormListControl and tutorial_FormTreeControl forms in the application.
ActiveX Animate Button ButtonGroup CheckBox ComboBox CommandButton DateEdit Grid Group HTML IntEdit ListBox ListView MenuButton MenuItemButton Progress
Columbus IT Partner Russia, ApS
164
Navision Axapta RadioButton RealEdit Separator StaticText StringEdit Tab TabPage Table TimeEdit Tree Window
Property
Modify this property to...
Applies to
EditLabels
make it possible to edit the label of a node.
Tree ListView
Enabled
make the system disable (shade) the control so that it cannot be modified.
all
EnumType
give a control access to the values in an enumerated type. A typical example is an unbound control listing for example possible currencies.
ComboBox RadioButton Listbox
ExtendedDataType
use the formatting defined for an extended type for the control.
StringEdit RealEdit IntEdit DateEdit TimeEdit
E
Property
Modify this property to...
Applies to
FeatureKey
select the feature key used to control display of this control.
all
Font
choose another font, font size and effects through Windows' standard font selection dialog. The Bold, Underline, Italic and FontSize properties may be set individually or through the Windows' standard dialog.
StaticText StringEdit RealEdit IntEdit DateEdit ButtonGroup Listbox TimeEdit ListView Tree
F
165
Columbus IT Partner Russia, ApS
Navision Axapta FontSize
change the size of the text. Font
StaticText StringEdit RealEdit IntEdit DateEdit ButtonGroup Listbox TimeEdit
ForegroundColor
change the color used for the foreground.
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox Listbox CheckBox RadioButton CommandButton MenuItemButton MenuButton Button Window ListView Tree
FormatMST
change whether a value is formatted according to national currency. Possible values Auto: National currency formatting depends on the data type. No: Do not format value as national currency. Yes: Format value as national currency.
RealEdit
FramePosition
change the position of the frame.
Group Window ButtonGroup
FrameType
change the default frame type.
Group Window ButtonGroup
Property
Modify this property to...
Applies to
GridLines
define whether grid lines should be displayed. Only valid when the ViewType property is set to Details.
ListView
Property
Modify this property to...
Applies to
G
Columbus IT Partner Russia, ApS
166
Navision Axapta H HasButtons
have expand/collapse buttons ( / ) displayed.
Tree
HasLines
have the tree displayed with connector lines.
Tree
Headerdragdrop
make it possible to re-arrange the columns. Only valid when the ViewType property is set to Details.
ListView
Height
change the height of the control - measured in pixels. Tip See the tutorial_arrange form for an illustration of the arrange principles using the Height and Width properties.
all
HelpText
create a help string for the control. The help string is displayed when the control is used in a form or report. For bound controls, the value of the field is shown in case no text has been entered.
all
HideFirstEntry
emulate the behavior of a enum database field with the Mandatory property set to Yes.
ComboBox ListBox RadioButton
HideIfEmpty
do not want the IntelliMorph system to hide an empty container control (if set to Yes, the container control is hidden). This will have no effect if the container control has its size properties (Width and Height) set to Auto as its size is then zero, but if you use, for example, Column width for a group, you can see the group caption. This means that you can use the group as a divider between groups.
Tab Group ButtonGroup TabPage Table
HighlightActive
want the current record to be displayed in another color.
Grid
Property
Modify this property to...
Applies to
ImageList
give the name of the .bmp file that holds the bitmaps to be used in the tree.
Tree
ImageMode
define how the bitmap defined by ImageName will display (Center, Tile...).
ImageName
select which image to display through Windows' standard Open dialog. You can select files of type .bmp.
Window
ImageResource
use an image from the integrated resource file. Give the id of the image you want here. The images can be seen through the form tutorial_resources.
Window
Italic
have text displayed in italic. Font
StaticText StringEdit RealEdit IntEdit DateEdit ButtonGroup Listbox TimeEdit
I
167
Columbus IT Partner Russia, ApS
Navision Axapta Item
define which item should be the current one when the form is opened.
ComboBox RadioButton Listbox
ItemAlign
align the items in the list.
ListView
Items
define the number of selections to choose from in the control.
ComboBox RadioButton Listbox
Property
Modify this property to...
Applies to
Label
modify the text given as label for the control.
StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Window
LabelAlignment
change the alignment of the label (center, left, right?) – the longest text defines the point of alignment.
StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Window
LabelBold
display label (defined by the Label property) in another style (medium, semibold, bold, heavy...). See Also: LabelFont
StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Window
L
LabelCharacterSet
Columbus IT Partner Russia, ApS
CheckBox ComboBox DateEdit Group IntEdit ListBox RealEdit StringEdit 168
Navision Axapta TimeEdit Window LabelFont
choose another font, font size and effects through Windows' standard font selection dialog for the text given in the Label property. The LabelBold, LabelUnderline, LabelItalic and LabelFontSize properties can be set individually or through the Windows' standard dialog.
StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Window
LabelFontSize
change the size of the label (defined by the Label property). See Also: LabelFont
StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Window
LabelForegroundC olor
change the color used for the label foreground.
StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox Listbox CheckBox
LabelHeight
define the height of the label.
StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Window
LabelItalic
italicize the label (defined by the Label property).
StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Window
LabelPosition
change the position of the label (left or above?)
StringEdit
169
Columbus IT Partner Russia, ApS
Navision Axapta CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Window LabelUnderline
underline the label (defined by the Label property).
StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Window
LabelWidth
define the width of the label.
StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit Window
LargeIcons
enter the name of the .bmp file holding a list of large icons. The system supplies a default list of icons. You can see the list by opening the SysShowIcons form. The icons in the list are numbered. The icons with numbers from 0 to 199 come from the operating system. Those from 200 and higher are supplied with the Axapta system.
ListView
Left
change the position of the top, left corner of the control. There are a number of auto selections (for example Auto (left) and Auto (right)) to choose from, as well as the possibility to give your own, exact position in pixels.
all
LeftMargin
change the default left margin of the controls on the container. An exact margin may be given in pixels.
Tab Group Grid ButtonGroup TabPage MenuButton Table
LimitText
limit the number of characters that can be entered in a control. A typical use of the combination of DisplayLength and LimitText could be an E-mail address where: LimitText could be set to 80 characters because such an address might be very long while, DisplayLength could be set to 20 characters because an 80-
StringEdit RealEdit IntEdit DateEdit TimeEdit
Columbus IT Partner Russia, ApS
170
Navision Axapta character long edit field is not very pleasing to the eye. LinesAtRoot
have the outer lines drawn from the root as well.
Tree
LookupButton
display a button to look up a valid value in the database for the control. This is set up through relations on the database tables.
StringEdit RealEdit IntEdit DateEdit TimeEdit
Loops
define the number of times the .avi file should be played. “0” means indefinitely.
Animate
Property
Modify this property to...
Applies to
MenuItemName
define which function should be activated when the button is pressed. The combination of the properties MenuItemName and MenuItemType identify exactly the function to be activated. Note that they must both be set.
MenuItemButton
MenuItemType
define which function should be activated when the button is pressed. The combination of the properties MenuItemName and MenuItemType identify exactly the function to be activated. Note that they must both be set.
MenuItemButton
MultiLine
choose whether the text should be allowed to span several lines. If the property is set to Yes, vertical scroll bars are automatically added.
StringEdit
MultiSelect
define that the button is active when the user multi-selects. For a grid, the property defines whether it is possible til multi-select.
Button CommandButton Grid MenuButton MenuItemButton
Property
Modify this property to...
Applies to
Name
change the name of the control
all
NoOfDecimals
determine the number of decimals when a value is displayed on a form or a report.
RealEdit
M
N
NormalImage
Button CommandButton MenuButton MenuItemButton
NormalResource
Button CommandButton MenuButton MenuItemButton
171
Columbus IT Partner Russia, ApS
Navision Axapta
Property
Modify this property to...
Applies to
OneclickActivate
have the system activate an item on a single click. Only valid when the ViewType property is set to Details.
ListView
Property
Modify this property to...
Applies to
PasswordStyle
have asterisks ('*') displayed instead of normal characters.
StringEdit
Pos
define the current (integer) position of the progress bar.
Progress
ProgressType
define how the progression is visualized (Normal or Smooth)
Progress
Property
Modify this property to...
Applies to
RangeHi
set the high range of the progress bar.
Progress
RangeLo
set the low range of the progress bar.
Progress
RealValue
set the initial value of a real, typically used for an unbound control.
RealEdit
ReplaceOnLookup
have the system replace existing text with the result of a look up. If set to No, the look up text is pasted instead of the selected text. If no text was selected, the look up text is inserted at the cursor. If set to Yes, the look up text replaces the original text.
StringEdit RealEdit IntEdit DateEdit TimeEdit
RightMargin
change the default right margin of the controls on the container. An exact margin may be given in pixels.
Tab Group Grid ButtonGroup TabPage MenuButton Table
RotateSign
negate the number, that is, changes ‘-‘ to ‘+’ and vice versa.
RealEdit IntEdit
Row
set the initially active row.
Table
Rows
change the number of rows used to display information.
Tab Group RadioButton ButtonGroup TabPage Table
RowSelect
select an entire row (rather than a single element) to be selected on click. Only valid when the ViewType property is set to Details.
ListView
O
P
R
Columbus IT Partner Russia, ApS
172
Navision Axapta
Property
Modify this property to...
Applies to
SaveRecord
save changes in the current record before the button’s command is activated.
MenuItemButton CommandButton
SearchAfterInput
have the underlying query select records that match the expression entered. The property applies only to bound controls (controls bound to a database field). If the property is set to Yes, no data is stored when the user enters data in the control. Instead, the input string is fed to the query to select records that match the expression entered.
all
SelectControl
have the first control selected on tab change.
Tab
Selection
set the initial value. The property displays the actual value during runtime.
ComboBox RadioButton Listbox
ShowColLabels
show the label defined by the Label property as row heading.
Grid Table
ShowLabel
choose whether to display the label (defined by the Label property), or not.
StringEdit CheckBox RealEdit IntEdit ComboBox DateEdit Listbox TimeEdit
ShowRowLabels
display a column where the current record is indicated by an arrow and new records by an asterisk.
Grid Table
ShowSelAlways
have the system keep the visual selection when focus moves.
Tree ListView
ShowShortCut
define whether access keys (underlined letter) should be displayed. Access keys are generated automatically. This property is typically set to No when a form has so many buttons that there are no free letters left.
Button CommandButton MenuButton MenuItemButton
ShowTabs
define whether tab pages should be displayed on the tab. If No only information on the first tab pages is shown. Note that you can still address the tab pages from your X++ code.
Tab
ShowZero
determine if the value zero is shown as an empty field.
RealEdit IntEdit
SignDisplay
display the sign ‘-‘ of a number if the value is negative. Also determines if the sign is displayed before, or after the number.
RealEdit IntEdit
SingleSelection
define whether the user should be able to select severeal objects at a time, or whether the selections should be mutually exclusive.
ListView Tree
SizeHeight
have the system give all buttons in the group identical height.
ButtonGroup
S
173
Columbus IT Partner Russia, ApS
Navision Axapta SizeWidth
have the system give all buttons in the group identical width.
ButtonGroup
Skip
make the system skip the control when the TAB key is used to navigate in the form.
all
SmallIcons
enter the name of the .bmp file holding a list of small icons. The system supplies a default list of icons. View the list by opening the SysShowIcons form. The icons in the list are numbered. The icons with numbers from 0 to 199 come from the operating syste. Those from 200 and higher are supplied with the Axapta system.
ListView
Sort
define whether the system should sort (no sort, ascending, or descending).
ListView
Step
define the integer value that the bar increases in one step.
Progress
Property
Modify this property to...
Applies to
Tab
change which tab page should be the active one when the form is opened.
Tab
TabAutoChange
the TAB key should result in a jump to the following tab page rather than the next visible field.
Tab TabPage
TabLayout
define how the tabs should be arranged.
Tab
TabPlacement
define the position of the tabs.
Tab
Tabs
see the number of active tab pages on the tab control. The number is automatically updated by the system.
Tab
Text
set a static text. For StaticText, StringEdit and Button, the text given in the Text property is static. For ComboBox, RadioButton and Listbox the Text property gives the text to be displayed in the list or next to the option. The Text property may be modified when the Item and Items properties have been set to values different from 0. Note If the control is bound, the list or button text comes from the underlying data source. For CommandButton and MenuItemButton the Text property can be used as an alternative to the system selected text for the button. The Text property is typically set for controls that are not tied to an underlying data source.
StaticText StringEdit Button ComboBox RadioButton MenuButton Listbox CommandButton MenuItemButton Listbox
ThousandSeparator
choose the thousand separator ‘,’ or ‘.’
RealEdit
TimeFormat
change the default time format (10:29:49 PM or 22:29:49).
TimeEdit
TimeHours
determine whether hours should be shown
TimeEdit
TimeMinute
determine whether minutes should be shown
TimeEdit
TimeSeconds
determine whether seconds should be shown
TimeEdit
TimeSeparator
determine the separator between hours, minutes and seconds (colon, comma, space...).
TimeEdit
Top
change the position of the top of the control. In addition to Auto, there are a number of pre-defined positions (for example Bottom
all
T
Columbus IT Partner Russia, ApS
174
Navision Axapta edge) to choose from, as well as the possibility to give your own, exact position in pixels. TopMargin
change the default top margin of the controls on the container. An exact margin can be given in pixels.
Tab Group Grid ButtonGroup TabPage MenuButton Table
TrackSelect
define that it should be graphically visible, which element would be activated if the user clicked. An element is highlighted whenever the cursor moves across it.
ListView
Transparent
define whether the background should be transparent.
Animate
TransparentColor
define the color that will be replaced with the background color when using bitmaps. Typically a color is selected that is used nowhere in the bitmaps:
Tree ListView
TwoClickActivate
have the system activate an item on a double click. Only valid when the ViewType property is set to Details.
ListView
Property
Modify this property to...
Applies to
Underline
have underlined text. See Also: Font
StaticText StringEdit RealEdit IntEdit DateEdit ButtonGroup Listbox TimeEdit
Property
Modify this property to...
Applies to
Value
change the initial value of the control.
CheckBox IntEdit
VerticalSpacing
modify the amount of space above and below the control (measured in pixels).
all
ViewType
define the view (Large Icons, Small Icons, List, Details – similar to the views available in Windows Explorer).
ListView
Visible
make the system hide the control.
all
VisibleCols
limit the number of columns the system should display. A scroll bar is automatically added to enable scrolling to the remaining columns. When set to Auto, all columns are displayed.
Grid
VisibleRows
limit the number of rows the system should display. A scroll bar
Grid
U
V
175
Columbus IT Partner Russia, ApS
Navision Axapta is automatically added to enable scrolling to the remaining rows. When set to Auto, all rows are displayed.
Property
Modify this property to...
Applies to
change the width of the control – measured in pixels. Tip See the tutorial_arrange form for an illustration of the arrange principles using the Height and Width properties.
all
W Width
Hints and advice about form control property settings Use the system's Auto property values whenever you can To ensure a uniform application interface and to save you, the application programmer, from repetitious work, we have taken great care and consideration setting the Auto values for properties. Our goal is that you should be able to create a form by dragging, dropping and setting only a few properties. We also strongly recommend that you take advantage of the automatic properties setting. Dimension properties like Top, Left, Width, and Height are good examples of the usefulness of the Auto settings. Auto settings make allowances for preferences with respect to font, font style, font size etc., in that the dimensions simply change dynamically when, for example, a larger font size is selected. Mutually exclusive properties The following properties are mutually exclusive: • DataSource / DataField • DataMethod and • ExtendedDateType Although you are allowed to set all of them on a control, the system disregards the less important one when the more important one is set. The combination of DataSource and DataField properties ALWAYS has the highest priority. The system first checks to see whether these two properties have been set, and if they have not been defined, then checks the DataMethod property. If DataMethod has not been set, the system examines the value of the ExtendedDataType property. Typical properties for unbound controls: Text, Value, RealValue, and DateValue The properties Text, Value, RealValue, and DateValue are typically used to give an initial value to unbound controls, and to set/get the value during runtime through X++ code. AllowEdit You will find the AllowEdit property on • Each field in a table. • A table used as the data basis for a form; in other words on a form data source. • Each control on a form, on container controls like tabs, and on individual controls. The evaluation order is control -> form data source -> table. If AllowEdit has been set to No in one of these, the user is not allowed to make any modifications. Fixed vs. dynamic forms When the form size is static, the Size and Maximize commands in the form’s system menu are disabled. The form size is static when one of the size properties (Left, Top, Width, and Height) is not set to Auto. AutoDataGroup and DataGroup Columbus IT Partner Russia, ApS
176
Navision Axapta When a data group on a form has AutoDataGroup set to Yes • Fields within the group cannot be moved, • Fields within the group cannot be deleted, nor can new fields be added, • Fields within the group cannot have their properties changed, and as a consequence the property sheet is grayed, • Methods on the fields cannot be overridden.
Setting AutoDataGroup to Yes is strongly recommended for performance reasons, particularly when running in a three-tier environment.
When AutoDataGroup has been set to Yes, the individual fields on the form are not saved but are read from the underlying table. This means that the form is loaded and displayed much faster. Because that fields are read from the table, fields are displayed in the sequence they appear in the table. ButtonDisplay and related properties The ButtonDisplay property is related to these other properties: • Text • NormalImage • NormalResource • DisabledImage • DisabledResource
Description of properties for a form data source Property
Use this property to ...
Rules and hints
Name
change the name of the data source.
Axapta standard The name is merely used for display purposes. However, if you would like to change the name, you should do so on the database table.
AllowCheck
allow that the permissions on table level are checked.
Axapta standard Should normally be set to Yes, but this is no fixed rule. You should deliberate what is appropriate for your application.
AllowCreate
allow new records to be created in the data source.
Axapta standard Must normally be set to Yes, but this is no fixed rule. You should deliberate what is appropriate for your application.
AllowDelete
allow deletions in the data source
Axapta standard Must normally be set to Yes, but this is no fixed rule. You should deliberate what is appropriate for your application.
AllowEdit
allow modifications to the data source
Axapta standard Must normally be set to Yes, but this is no fixed rule. You should deliberate what is appropriate for your application. Tip You can set the AllowEdit property for the whole form here but to let you to prohibit
177
Columbus IT Partner Russia, ApS
Navision Axapta modifications for individual fields, the same property exists on each field in the data source. AutoNotify
allow notification upon change of record.
Axapta standard Must be set to Yes. Part of Axapta’s AutoJoin system
AutoQuery
have the system automatically generate a query for the data source that joins it with the data source given by the JoinSource property.
Axapta standard Must be set to Yes. Part of Axapta’s AutoJoin system.
AutoSearch
have the system automatically perform a search on the data source.
Axapta standard Must be set to Yes. Part of Axapta’s AutoJoin system.
Company
change the level to which the table data belongs
CounterField
use one of the database fields as counter in the form. The field must be of type Real.
Tip A CounterField is typically used to ensure that a record inserted in a form is given a line number that corresponds to the actual, sequential position in the form. For example, if a new line is inserted between lines 3 and 4, the new line is given line number 3,5. This is used for example in the CustWorksh in the standard application. To achieve this effect the field given as CounterField should be given as index on the database table.
DelayActive
delay the execution of the data source’s Active method.
Axapta standard Must be set to Yes. Part of Axapta’s AutoJoin system. Tip This property is particular useful when two data sources are linked (when the LinkType property is Delayed). Setting the property to Yes means that the data sources Active method is not activated until after a certain delay (20 milliseconds). This is to handle the situation when the user presses the down arrow to scroll in a list on his data source.
Index
use one of the indexes defined on the table specifying that you want data from the table sorted according to that index.
InsertAtEnd
create a new record when the user moves the cursor past the last record in the table (for example by pressing F8).
InsertIfEmpty
have the system insert an empty record ready for entering data if it finds no records in the table. If InsertIfEmpty is set to No, the user must create a new record himself (for example by pressing CTRL+N)
Columbus IT Partner Russia, ApS
178
Navision Axapta JoinSource
have the system join two data sources.
This property is set only when two or more tables are used as data source and you would like to join them.
LinkType
have the system maintain an active link between two data sources and research the second table when focus in the first one changes.
Axapta standard Must be set to Delayed. Part of Axapta’s AutoJoin system. Tip This means that when you have a one-to-many relationship between two tables, scrolling in one automatically updates the other. An example of this is a customer table and a table of transactions for each customer. With LinkType set to Active, scrolling from one customer to the next also automatically updates the transaction list to display transactions for the current customer. Setting the property to Delayed means that updating a linked data source is not performed until after a certain delay (100 milliseconds). This means that if the user presses the down arrow to scroll in a list on his data source, the linked data source is updated for the last record only (the record the user finally focuses on). When you set the LinkType property to Delayed, the linked data source may not be refreshed immediately after the super() call in the Active method on the master form.
OnlyFetchActive
select fields on controls in the form.
This property is designed to be used in lookup forms. There is no code in these forms, and they will open faster because the result set is smaller. When OnlyFetchActive has been set to Yes, records cannot be deleted from within the form. This is to preserve data integrity by ensuring that delete is never attempted on incomplete records. Should the user attempt to delete a record, an error message is issued.
StartPosition
define whether the first or the last record should be the current one upon startup.
Axapta standard Unless your form is used for postings, the StartPosition property should be set to First.
Table
use data from this table.
Axapta standard For clarity, the Name and Table properties should be identical.
Description of properties for form design Practically all properties on the form Design node also exist on the individual controls, for example the Width and Height properties. However, when you set a property on the Design node - as opposed to setting it on a control - the setting affects the entire form. A few properties exist only on the Design node. They are described below. Property 179
Modify this property to...
Rules and hints Columbus IT Partner Russia, ApS
Navision Axapta Frame
modify the frame used for the form.
Axapta standard Normally the Frame type is Standard. The other types do not have a caption and are typically used when a new form is opened from within a form (for example, when a form is opened when the user clicks a lookup button).
HideToolbar
hide form specific buttons on the toolbar.
The property is intended for forms that are not tied to the database.
Mode
set the data entry mode for the form.
setCompany
have the system change company when the form gets focus.
TitleDataSource
choose the data source to be used in the form caption.
WindowResize
allow form re-size.
WindowType
specify the window type.
The form title consists of the TitleDataSource property followed by the string generated by the table’s caption method, for example Customers (Customer Account: 6743245) When the user is creates a new record, the caption will be Customers ()
Joining data sources on forms To display related fields from different tables, you can join or link two data sources.
Joining data sources To display fields from different tables intermixed within the same grid control, you can join two or more data sources in a form. Compared to using edit and display modifiers to have field values displayed in a grid control, joining data sources gives far superior performance. Also, joining data sources allow selects, inserts and updates simultaneously in more than one table since it only uses one query. Navigation is performed within the query and the active() method is fired on both the master and child data source when the selection changes. The property used to define the type of join is called LinkType. To join a child data source to a master data source, set the JoinSource property to the master dataset and the LinkType to InnerJoin, OuterJoin, ExistJoin, or NotExistJoin.
Linking data sources If you pass a data source from one form to another, for example using the DataSource property on a menu item buttons, you create a link between the master data source and the child data source on the other form. The same behavior can be obtained in one form by setting the JoinSource property on the child data source, and setting the LinkType on the child data source to Active, Passive or Delayed. Updates of linked child data source in relation to the parent data source is controlled by setting LinkType to Passive, Delayed, or Active on the parent data source. Since a linked child data source may itself be a master data source in another relation, Passive, Delayed, and Active property settings determines how data sources linked to the child data source are updated. Example of parent and child data sources are orders and order lines. When the user selects a new order, the list of order lines must be updated accordingly. Columbus IT Partner Russia, ApS
180
Navision Axapta JoinSource and LinkType properties When data sources are linked on a form or between forms, the behavior is controlled by the JoinSource and Link Type properties. The figure below illustrates how their settings interact:
Pic. 6-5 When the user changes record in the parent data source, the active() method is called. When the method is called is controlled by the DelayActive property. DelayActive can be Passive, Delayed, or Active. The super() call in the active() method on the parent data source calls the linkActive() method on all linked child data sources. How and when this is performed is controlled by the LinkType property on the parent data source. LinkType can be Passive, Delayed or Active. If the property LinkType is InnerJoin, OuterJoin, ExistJoin or NotExistJoin the child data source is joined with the parent data source. In this case the linkActive() method on the child data source is not called as the joined data sources are considered to be one data source.
Name
How the join is performed
Passive
Linked child data sources are not updated automatically. Updates of the child data source must be programmed on the active() method of the master data source.
Delayed
A pause is inserted before linked child data sources are updated. This allows for faster navigation in the parent data source since the records from child data sources are not updated immediately. For example, the user could be scrolling past several orders without immediately seeing the order lines for each one.
Active
The child data source is updated immediately when a new record in the parent data source is selected. Notice that continuous updates are resource-consuming.
InnerJoin
Selects records from the main table that have matching records in the joined table – and vice versa. In other words, you get one record for each match and records without related records are eliminated from the result.
OuterJoin
Selects records from the main table whether or not they have matching records in the joined table.
ExistJoin
Selects a record from the main table for each matching record in the joined table. The difference between InnerJoin and ExistJoin: When the join type is ExistJoin, no more potentially matching records are searched for once the first match has been found. When the join type is InnerJoin, all matching records are searched for.
NotExistJoin
Select records from the main table that do not have a match in the joined table.
181
Columbus IT Partner Russia, ApS
Navision Axapta
Use the form tutorial tutorial_Join to see the different results produced when you change the LinkType property.
Join data sources 1. Set up the relationship between the tables to be joined. This can be done either on the tables or on the Extended Data Type of the field(-s) to be joined. 2. On the form, set the JoinSource property of the child data source to the data source you want to join with. 3. Set the LinkType property on the child data source. If you are linking the data sources you should also set the LinkType property on the parent data source. This is not mandatory but recommended since it makes it easier to see what you want to accomplish. 4. Create the form design and display the relevant fields from the form data sources. Typically you would choose a grid control for your joined data sources. Designing the layout of a form When designing the layout of a form where a table is used as the underlying data source, use a drag-anddrop operation to move a group, or individual fields from the pool of groups and fields in the form's Data Sources node to the form's Design node. On the basis of the field's data type the system automatically selects the control best suited to represent the field. A StringEdit control is selected for a text type, an IntEdit control for an integer type, a RealEdit control for a real type, a DateEdit control for a date type and a ComboBox for an enumerated type. You will also see that a lot of properties have the value Auto. These properties are typically inherited from the underlying field. To see a description of the available controls, click
.
At any stage in the development process, you can see what the form looks like by clicking Compile and then Open in the shortcut menu on the form. Note that when you move a group, the group remains a group in the layout, and can be given its own heading. Normally, the system's auto-selections are adequate; however, if you would like to modify any of the default properties that define name, position, color, margin etc., click the property sheet icon . You can also modify the form layout by clicking Edit in the shortcut menu on the Design node. This opens the form in design mode soyou can size the individual controls manually. Note, however, that you are not allowed to size bound controls with Auto properties. For example, if a field has the Width and Height properties set to Auto, then you cannot modify the size of the control. The form editor is advantageous because you can follow the system's sizing and positioning of each control, and correct any undesired positioning or size immediately. Groups are dynamic... Note that when you move whole groups as they were defined in the underlying table data source from the Data Sources node to the Design node, the groups are dynamic. This means that whatever you do on the underlying table (add or remove a field from the group) is automatically reflected on the form. On the other hand, you cannot simply delete a control from a group. If you do so, the control automatically re-appears. More methods... Columbus IT Partner Russia, ApS
182
Navision Axapta When you move a group or a single field to the Design node, the system automatically creates the necessary methods to detect, for example, mouse movements, check focus, and validate. Also more advanced facilities... Moving a group of fields or a single field to the Design node to create a form is the most basic way to design a very simple form. The system also provides facilities to create forms with the following: • • • •
Multiple tabs, Group headings, Buttons to activate functions, menu commands and other forms and reports, Lines and pictures.
One data source Joined data sources are treated like one data source. This means that • selects, • updates, and • creates from forms are performed on both/all tables. Methods that operate on the data source, like next, executeQuery and so on, are redirected to the data source that owns the join, the main data source. Init is run for both/all data sources. Notification methods like active are run for both/all data sources.
6.3. Designing Forms Determining the opening view of a form The DataSource property defines the table from which you see data from when you open a form. Browsing the properties of a form's Design node you will see the DataSource property in several places both on containers like Design, Tab, TabPage and Group and on individual controls (like StringEdit, IntEdit etc.) Data source is given on containers to define in which table to scroll when the user changes to next or previous record (using F7 or F8). The system first checks the container for a data source: if the container has a data source, the system changes record in the table indicated here. If the container does not have a data source, the data source on the control is used. The DataSource property is only set automatically by the system when individual fields are moved from the Data Source. Several controls with different data sources may be located in the same group or on the same tab page and in such cases the data source on the container indicates the table to scroll in. The sequence in which the individual records in the underlying table are shown is set up by the indexes defined on the table. Generally the query system selects the index best suited to the task in hand. However, if you find that the query system uses another one than you would like, or if there are two, equally suited indexes, you can set the Index property on the form data source. If using an index does not suffice... When records are retrieved for display in a form, the mechanism that handles the retrieval process is a query that the system automatically generates. The indexes defined are used in this auto query. If you
183
Columbus IT Partner Russia, ApS
Navision Axapta would like another sorting sequence than the one defined by the index (for example descending rather than ascending), one way to obtain this is to modify the auto query from your X++ code.
Specify whether a form opens for modification and data entry When you create a form you can specify what actions the user is allowed to perform on the data in the underlying table. You restrict access through the following properties on the form data source: Property
The property's function
AllowEdit
Allow modifications to the data source
AllowCreate
Allow new records to be created in the data source
AllowDelete
Allow deletions in the data source
Implicit forms variable declarations Normally you need to declare variables before you can use them. Working with forms, though, some variables are implicitly declared by the system. A variable named like the form data source to reference the table, for example MyTable. This enables you to 1. Call a method defined on the table used as underlying data source for the form, for example MyTable.SetDefault(ReadWrite::Write);
2. Reference the individual fields on the table, for example A_No = MyTable.AccountNo;
A variable named like the form data source postfixed with _ds to reference properties and methods on the form's data source, for example MyTable_ds. This gives you direct access to invoking the methods in the FormDataSource system class, for example MyTable_ds.ReSearch();
If you wish to call for example ValidateWrite, which exists on both the form data source and on the table, you must use the _ds variable (for example MyTable_ds.ValidateWrite) to activate the method on the data source.
A variable called element to reference the whole form object Element is typically used in assignments like the one shown here. NotifyDate = Element.Design().Control(Control:: NotifyDate);
Validate or restrict data in forms There are many different ways to restrict or validate data in forms. The most obvious way is to create controls that by their nature limit the values that can be entered. For example, you can create a check box that accepts only Yes/No values or a list box that requires you to pick from a list of previously entered values. You can also limit or restrict data entry by setting control properties and form properties. In most cases, you will want to use the AllowEdit, AllowCreate and AllowDelete on the form data source. This way, you only have to set the properties once. Columbus IT Partner Russia, ApS
184
Navision Axapta Any bound control that you create inherits properties set for the field in the table. If the controls on your form are unbound, however, you may want to set properties in the form controls. In the large majority of cases, you can validate or restrict data using properties that you set on the table or on the form. In certain cases, however, you may need to create your own methods for additional power and flexibility. For example, you may want to display different error messages for different types of errors in a field, or you may want to verify that any two of three fields are filled in before saving a record.
Order of evaluation for controls and fields The calling sequence when data is modified through a control on a form is top down: first the methods on the control are evaluated, then the methods on the data source, and finally the methods on the table. This means that when a control is exited the following methods are activated: Method
On the...
Comments
Leave
form control
Here you can only use the property system to get the value. The method is always activated when you leave a control.
Validate
form control
Here you can only use the property system to get the value. The method is activated only if the user has edited the contents of a control.
Modified
form control
Following the call to super() the value in table field has been set. Modified is activated in the following situations: When an edit field (one of the following controls: StringEdit, IntEdit, RealEdit, DateEdit or TimeEdit) is exited. When a selection in either CheckBox, RadioButton, ComboBox or Listbox is changed. The method is activated only if the user has edited the contents of a control.
Validate
form data source
The value in table field has been given its new value. The method is activated only if the user has edited the contents of a control.
ValidateField
table
The method is activated only if the user has edited the contents of a control.
Modified
form data source
The method is activated only if the user has edited the contents of a control.
If any of the validate functions returns false then the field is not given a new value.
Auto-arrange principles in forms To ensure a uniform application interface, all properties have sensible Auto values. The aim is that a form can be created using a drag-and-drop operation, setting only very few properties manually. It is highly recommended to take advantage of the automatic setting of properties. Occasionally, though, the system’s Auto property values may not suit the current situation and therefor it may be helpful to understand the auto-arrange principles in forms. When the system generates a form based on property settings, this is done in three phases 1. Size: the form size is determined. 2. Position: the position of the individual controls is determined. 3. Alignment: the controls are aligned.
185
Columbus IT Partner Russia, ApS
Navision Axapta
Phase 1: Size The size of a control is defined as the size of the control itself plus the control label. The sample form below shows 5 groups (in different colors) that each has one or more controls. The fact that the size of a control is the control plus the label becomes important when the system begins the alignment phase.
Pic. 6-6 The Width and Height properties define the dimensions of the control and the corresponding ones for the label (LabelHeight and LabelWidth) define the label. The Auto settings here make allowances for preferences with respect to font, font style, font size etc. in that the dimensions simply change dynamically when for example a larger font size is selected.
Phase 2: Position Container controls (Tab, TabPage, and Group) are arranged in one or more columns as specified by the Columns property on the parent control. In the above example, the five groups are arranged in two columns. Whether the groups should be arranged in columns or in rows is defined by the ArrangeMethod property. In the example the method is horizontal. Regardless of the preferred method, the first column (row) always has the higher priority. In the example three groups have been placed in the first column, and two in the second. The VerticalSpacing property defined the space (in pixels) after the control. In the example below the VerticalSpacing spacing property for Group1 (the gray group) has been changed from Auto to 40.
Pic. 6-7 The overall purpose of the Top and Left properties is to allow you to reserve space (for example for a button or a group of buttons) relative to another form. Use the Top property to glue the control to the top edge or the bottom edge, and the Left property to align to the left or the right edge. In the example below the Top property for the green group has been set to Top edge, and the Left property to Right edge. Also, the AlignChild property on the group has been set to No. Columbus IT Partner Russia, ApS
186
Navision Axapta
Pic. 6-8 The general rule is that the more edges a control is tied to (for example both the top and the right edge), the more space is reserved. Rather that select one of the predefined values in the system, you can choose to give coordinates in the Top and Left properties. A control where you have entered coordinates has higher priority during the form’s arrange phase than one with Auto properties.
Phase 3: Alignment The three central alignment properties are: AlignChildren
for container controls
When set to Yes, the control aligns the controls it can see, its immediate children. In the example above, the children of the form are the five groups and the children of the gray group control are the controls named “Label Label Label” and “Label”.
AlignChild
for container controls
When set to Yes, the control accepts to be part of the alignment defined by the parent control. Setting the property to No indicates that the control is not to be included in the alignment that is performed by the parent control (the container control).
AlignControl
for individual controls
When set to Yes, the control accepts to be part of the alignment defined by the parent control. Setting the property to No indicates that the control is not to be included in the alignment that is performed by the parent control (the container control)
In the example below, in the second control (called “Label”) the AlignControl property has been set to No, and in the second group (the yellow one) the AlignChild property has been set to No.
Pic. 6-9
187
Columbus IT Partner Russia, ApS
Navision Axapta
Sizeable forms Sizeable forms can be dynamically sized by the user to display more information than was originally displayed. Typically information heavy forms like forms with grids or several tab pages are sizeable. The majority of Axapta forms are sizeable. The fact that a form is sizeable is indicated by the lines in the form's lower right corner. Forms that will not display more information if made larger should not be made sizeable. The Currency form on the General ledger menu is an example of this type of form. Whether a form is sizable or not is determined by the settings of the Height and Width properties on the individual controls. When set to Column height and Column width respectively, the form can be sized. Note, though, that for controls to be sizeable, the container control (group, tab, tap page etc.) that holds them must also be sizeable. During form resizing, the controls on the form are resized to fit the new form size. Controls positioned in several columns share the additional height when a form is made larger. However, they do not share additional width: the last column gets any extra width.
Properties cannot be changed for a control in a group that has the AutoDataGroup property set to Yes.
See the tutorial_arrange form for an illustration of the possible combinations of Height and Width settings on various controls.
Toggling between different views on data As an example of a situation where X++ code is used on a form control, consider the situation where we have two forms based on data sources with a one-to-many relationship between them. An example of this could be the customer records and the customer postings. For each customer, there may be any number of postings of which some or all may be settled. To be able to toggle between viewing all postings and viewing open (unsettled) postings only, you modify one of the control methods. The CustTable and CustTrans forms from the standard application are examples of forms with the one-tomany relationship described above. In the CustTrans form there is a CheckBox control to toggle between viewing all or viewing open postings only.
Pic. 6-10 When the user checks the box labeled “Show open only”, the system should do a research in the data source. Consequently the Clicked method has been modified.
Columbus IT Partner Russia, ApS
188
Navision Axapta
Pic. 6-11 CustTrans
is the implicitly declared variable used to reference the table data source
ds
is short for '(form) data source' and references the FormDataSource system class
ExecuteQuery
is the method in the FormDataSource system class that executes the query automatically generated by the system
Display a message box When you want to display a brief, modal message, use the application class Box. The Box methods correspond to the different values of the system enum dialogBoxType: Dialog type
Enum value/method names
When to use the Box methods
Information dialog
infoBox
The user should be informed of something, and must click OK.
Warning dialog
warnBox
The user should be warned of something, and must click OK.
Yes/No dialog
yesNoBox
The user is given a choice where he must click Yes or No.
Stop dialog
stopBox
The application has stopped, possibly beacause some error happened, or something serious is going to happen, and the user must click OK.
Yes/No/Cancel dialog
yesNoCancelBox
The user is given a choice where he must click Yes, No, or Cancel.
When you implement Box::<method> you should • Choose the box method appropriate to the situation. • Use the return value (of type DialogButton) for situations that require the user to make a choice (the Yes/No dialog, the Yes/No/Cancel dialog, and the Ok/Cancel dialog) • Define a default button (of type DialogButton) when you use more than one button (for the dialog types mentioned above) • Write a text that the user can understand. • Define a suitable caption. • Write a suitable help text. Examples Box::warning("@SYS53167', "@SYS18245')
189
Columbus IT Partner Russia, ApS
Navision Axapta (box::yesno(strfmt("@SYS24509", ledgerJournalTrans.paymentReference), "@SYS24283", "@SYS29058") == DialogButton::Yes)
DialogButton::Yes,
The application class Box makes use of the system class DialogBox. However, you should not call DialogBox directly, but always use Box as an indirection.
Using display and edit method modifiers Display is a method modifier used to indicate that the method’s return value is to be displayed on a form or a report. The return value is typically a calculated value, for example a sum. Only methods with a return value can be modified by display. You can use the display modifier on methods in five different places: • On table methods • On form methods • On form data source methods • On report methods • On report design methods Write your display methods on a table because in this way you can use the same code in several forms or reports if you want.
Define a display method To define a display method, give the display keyword right before the method’s return type, for example: display Amount Amount() which is a method on the CustTrans table. The exception to this is when you define display on a form data source method. If you choose to write a display method on a form data source, you must include the data source as parameter, for example display InventQty Accumulated(InventBudgetInvent Budget) which is a method on the data source for the InventBudgetInvent form.
You must use display on a form data source method when the return value is to be shown on a grid control.
A display method is called each time the form is re-drawn and consequently a display method should never hold calculations more complex and time consuming than what corresponds to one direct lookup in the database. A display (or an edit) method is not activated if it is on a hidden tab page.
Use a display method on a form or a report Once you have created the method, use it on a control shown on a form or a report. The way in which you do that is identical no matter where you have chosen to write your display method. Note Identical control and method return types are required.
Columbus IT Partner Russia, ApS
190
Navision Axapta This means that if, for example, you have a RealEdit control on your form, the display method you are using must return a value of type real. The Amount method mentioned above is used on the CustTrans form on the Amount control.
Pic. 6-12 The DataSource property indicates where the method is located, and the DataMethod property gives the name of the method. If the DataSource property is not set, the system assumes that the method has been defined on the form. Looking at a report example, the BalanceCur method is used on the CustTransList report on the BalanceCur control.
Pic. 6-13 The DataMethod property gives the name of the method that has been modified by display. As the Table property has not been set, the system assumes that the method has been defined on the report (on the design or on the report) or possibly in the ReportRun system class where for example page is a display method. When you set the Table property the system looks for the BalaceCur display method (given in the DataMethod property) on the database table. The ExtendedDataType property If the ExtendedDataType property is set, formatting, help text, and so on is taken from the type given here. The ArrayIndex property If the display method returns an array, set ArrayIndex to 0 to indicate that all array elements are to be shown on the report. If, for example, you set it to 2, this indicates that only array element number two is shown. 191
Columbus IT Partner Russia, ApS
Navision Axapta
Use an edit method on forms The edit modifier is an extension of display so that controls using an edit method can do the following: • Display a value and accept user input The edit modifier can be used on the following: • Table methods • Form methods • Form data source methods The parameter profile, though, is a bit different from that of display methods. This is an example of an edit method on a table: edit FreeTxt TxtDefault(boolean Set, FreeTxt Txt) Both parameters are used when the method is subsequently tied to a control on a form. The boolean parameter Set is true if the user has entered anything in the control The text parameter Txt is used to hold the values that the user has entered in the control The parameter profile for edit used on a form method is identical to the one above for edit used on a table method. When edit is used on a form data source method, the data source must also be included as a parameter, for example edit Amount Settle(boolean set, CustTrans _CustTrans, Amount U) which is a method on the data source for the CustOpenTrans form. The method is used on the Settle control on the form. Like in the above example with the display method, the DataSource and the DataMethod properties must be set on the control.
Like other fields, both edit and display methods may be added to field groups on the underlying table.
Summary of parameter profiles for display and edit Parameters for display
Parameters for edit
table method
none
boolean Set value
form method
none
boolean Set value
form data source method
data source
boolean Set data source value
report method
None
(Not applicable)
report design method
None
(Not applicable)
The standard lookup form: what it consists of The contents of the system’s standard lookup forms are based on relations set up on the database table, and on the Extended Data Type. It consists of these components • TitleField1 from the related table • TitleField2 from the related table • The fields making up the relation Columbus IT Partner Russia, ApS
192
Navision Axapta If any of these are identical, the system automatically leaves out duplicates.
An example from the application: the Customer group field on the CustTable form Clicking the lookup button on the Customer group field on the CustTable form’s General tab page give you a list like the following:
Pic. 6-14 The lookup information is based on the relation on the CustGroupId Extended Data Type used for the CustGroup field.
Pic. 6-15 TitleField1 and TitleField2 from the CustGroup table, the related table, are CustGroup and Name.
Pic. 6-16 So the values in the first column are CustGroup field values, and the column heading is the CustGroup field label “Customer group” that is inherited from the Extended Data Type. The values in the second columns are Name field values, and the column heading is the Name field label “Description”, also inherited from the Extended Data Type. The third component, the related field, is omitted as it it identical to TitleField1.
The lookup facility: creating you own lookup forms When you choose to have a lookup button on your control, the Lookup method on your form control is activated when the user clicks the button. The Lookup method displays a standard form but if you want to display another form instead, you can either • Override the Lookup method, or • Create your own custom lookup form, or • Use the AutoLookup field group on the underlying data source.
Overriding the Lookup method on a form control The super() call in Lookup checks whether the control is bound to a field, or to an Extended Data Type and calls either performDBLookup(FieldId,FileId,Company); or performTypeLookup(ExtendedDataType,arrayIndex,Company); 193
Columbus IT Partner Russia, ApS
Navision Axapta which are both member functions (methods) on the Formcontrolname class (FormStringControl, FormRealControl, FormIntControl, FormDateControl or FormTimeControl). You can override the super() call, and call one or the other method yourself, and give the necessary parameters. One possibility is to call performDBLookup with only FieldId, in which case you can perform a lookup on another field within the same data source. void Lookup() { FormStringControl FEL; FEL = element.design().control(control::Country); //12 is the Id for the field to be shown on the Country control FEL.performDBLookup(12); }
Both methods may also be called with an alternative Company to achieve a lookup in another data file. Default company is the one that the current data source belongs to.
Use the ButtonImage property on the Extended Data Type to choose a suitable image to display next to your field. To learn about the property, click.
Custom lookup Creating the lookup form yourself offers you even greater flexibility. To do this use the method performFormLookup(FormRun); which is also a member function (method) on the FormcontrolnameControl class (FormStringControl, FormRealControl, FormIntControl, FormDateControl or FormTimeControl). When you use this method, you must do more programming yourself but the lookup form may be anything you like. In the form to be used as a lookup form, you must do the following: 1. Set the Frame property to Border. This means that the form will have no caption or size frame. 2. Close the form using the CloseSelect(str) method. CloseSelect is a member function on the FormRun class. As the name indicates, the method closes the form while selecting the string given as parameter. An example The form ColorLookup looks like this Green
Red
Blue
Yellow
It has four buttons in different colors with the names of each color. The idea of using this form as a lookup form is that when the user clicks one of the buttons, the name of the button (the color name) is pasted in the control. Consequently, the Clicked method is overridden for all four controls. Below is the Clicked method for the green button. Columbus IT Partner Russia, ApS
194
Navision Axapta void Clicked() { Element.CloseSelect("Green"); } In the Lookup method on the control that you want to have a custom lookup, you do the following: void Lookup() { FormRun FR = New FormRun(New Args("ColorLookup")); FR.Init(); this.PerformFormLookup(FR); } where “ColorLookup” is the name of the form displayed upon lookup. Continuing the example from above… When the color lookup form is used, it looks like this:
Pic. 6-17 The Lookup method on the StringEdit control labeled “Color:” has been modified as indicated above.
Details about PerformFormLookup PerformFormLookup calls the SelectMode and SelectTarget methods (also in the FormControlName class) on the form given as argument. These two methods set the form in SelectMode and identify where the value is to be inserted (using the SelectTarget method). Alternatively, you can call SelectMode yourself, passing a control in the lookup form as parameter. The value of the control will be pasted in the target control. In this case you do not have to pass a string as parameter to CloseSelect.
AutoLookup field group Use the AutoLookup field group to customize the lookup form without any programming at all. First, set up the relation for the lookup. Then on the relatede table, add the fields to the AutoLookup field group that are to be added to the lookup. An example: 1. Create a relation on the table used as data source. The relation may also be defined on an Extended
Data
195
Columbus IT Partner Russia, ApS
Navision Axapta
Type.
Pic. 6-18Creating
a run-time lookup form
A standard lookup form is created through relations on the database table, and on the Extended Data Type. If, however, you need to create a runtime lookup form that looks up other database fields than the ones offered by the standard lookup form, use the application class SysTableLookup and override the lookup method on the relevant form control. How to use the SysTableLookup class 1. Create a new instance of SysTableLookup by giving the tableId to the table you want to have lookup on. sysTableLookup = new SysTableLookup(tableId);
2. Add fields to the gridControl. sysTableLookup.addLookupfield(_fieldId, _returnItem);
_fieldId
The field ID
_returnItem
Whether the field's value is to be returned. Default the first added field.
3. Limit the data selection. sysTableLookup.parmQuery(query);
4. Override the formControl.lookup() and delete super(). FormRun formRun();
Columbus IT Partner Russia, ApS
196
Navision Axapta void lookup() { ... // super(); this.performFormLookup(sysTableLookup.formRun()); }
A complete example of overriding the lookup method on a form control void lookup() { Query query = new Query(); QueryBuildDataSource queryBuildDataSource; QueryBuildRange queryBuildRange; SysTableLookup sysTableLookup; TableId tableId; FieldId fieldId; ; tableId = tablename2id('myTable'); sysTableLookup.parmTableId(tableId); fieldId = fieldname2id(tableId, 'MyField_1'); sysTableLookup.addLookupfield(fieldId); fieldId = fieldname2id(tableId, 'MyField_2'); sysTableLookup.addLookupfield(fieldId);
queryBuildDataSource = query.addDataSource(tableId); queryBuildDataSource.orderMode(OrderMode::GROUPBY); queryBuildDataSource.addSortField(fieldId));
sysTableLookup.parmQuery(query);
197
Columbus IT Partner Russia, ApS
Navision Axapta this.performFormLookup(sysTableLookup.formRun()); }
This manner of creating a lookup form is used in the DocuType form in the application. The full path to the modified lookup method is: \Forms\DocuType\Designs\Design\[Tab:Tab]\[TabPage:Overview]\[Grid:Grid]\StringEdit:ActionClassName\ Methods.
The SysTableLookup is limited to making lookups on fields in a table.
Tips
.
Create a new record when the user opens a form To create a new record each time the user opens a form • Call the create method on the form data source, and • Use suitable settings for the data source properties InsertAtEnd (= No) and StartPosition (= First). An example from \Forms\PurchCreateOrder\Methods\run void run() { purchTable_ds.create(); element.modifyForm();
super();
// more code lines }
Drag-and-drop You can duplicate, copy and paste, and drag-and-drop form controls - both within a form and between different forms. If the data source specified on the control you copy is not present on the target form, the DataSource property is left blank. Between forms, drap-and-drop will always perform a copy operation. Within the same form, drag-and-drop performs a move operation. To copy, press the CTRL key on the keyboard while moving the object.
Columbus IT Partner Russia, ApS
198
Navision Axapta
6.4. Using ActiveX controls When creating an Axapta form, you can benefit from using ActiveX controls. An ActiveX control is a COM object that can be used as a graphical control inside an application. ActiveX controls can be purchased from a large number of vendors. The diversity of functionality is enormous. The software available as ActiveX components spans from simple components such as check and combo boxes, to larger more complex components such as spreadsheets, calendars, Internet browsers, and communication programs. When you install software such as Microsoft Office, or Microsoft Internet Explorer, a large number of COM objects and ActiveX controls are added to your computer. Before a COM object can be used it must be registered in the registry. The installation program normally handles this as part of the installation process.
Adding an ActiveX control to a form Inserting an ActiveX control in a form in Axapta is done using the Application Object Tree, as you would do for any other type of control. 1. Right-click the Design node for the form, and choose New Control from the menu. 2. Choose ActiveX from the sub-menu. The ActiveX Browser appears. The browser displays a list of all the ActiveX controls registered on your machine (according to the registry). 3. Choose the control you want to insert from the list. A good example is the Microsoft Calendar control (part of Microsoft Office).
Pic. 6-19 Now the control is inserted. The next step is to communicate with the control. 4. Right-click the ActiveX control in the Application Object Tree, and start the ActiveX Explorer.
199
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 6-20 This displays all the events that can be started by the control, and a list of all the methods that can be executed on the control. The list of methods is read from the object’s Type Library, and gives you information on how to call the methods. The list of events is also retrieved from the object’s Type Library. However before Axapta can handle any of the events that the ActiveX control can start, you need to add event handlers (methods) for them. 5. Do this by selecting the events you want your form to handle, and click the Add Event Handler button. This creates a number of methods. By adding X++ code to these event handler methods, you can control how Axapta reacts to specific events. Most ActiveX controls offer specific ActiveX properties. These can be set from your X++ code. On the Methods tab page of the ActiveX Explorer, you can see the property methods that the ActiveX control offers to modify the properties as well as other ActiveX specific methods. For example, the Microsoft Calendar control offers a Day property method that is used to set and get the day selected in the ActiveX control.
See and set ActiveX properties 1. Open the visual form designer. On the form's Design node, right-click to open a shortcut menu and select Edit, or Double-click the form's Design node.
2. Right-click the ActiveX control and select Properties on the shortcut menu. 3. Click the Custom property's lookup button to access the ActiveX control's properties.
Pic. 6-21 Columbus IT Partner Russia, ApS
200
Navision Axapta
6.5. Forms System Classes The forms system classes are listed in the Classes sub node in the System Documentation node. They are easily recognizable, as they all contain the prefix Form (FormRun, FormStringControl etc.). The forms system classes enable you to manipulate - create, modify or run – forms from your X++ code. You may even modify forms during runtime so that, for example, one or more controls are hidden on a form depending on the user's selections in the preceding form. Generally, forms system classes are closely connected to the node for the individual form, and the three form sub nodes.
From an overall point of view, the forms fall in two categories: form build classes and form run classes. As the names indicate, the build classes are the ones used during the visual creation of a form, while the run classes are used during execution. System class name
Final
Extends
Form
FormObject
yes
FormRun
yes
FormDataObject
Holds
Use it to...
the form name property and methods to add to the three form sub nodes in the Application Object Tree.
create a form from your X++ code rather than by using the Application Object Tree
methods to execute a form.
activate a form from your X++ code
FormObject
FormDesign
yes
the properties on the Design node in the Application Object Tree and methods to create a control.
FormDesignView
yes
the form name property and the methods activated when a control is modified in edit mode (when you have clicked Edit in the Design shortcut menu).
add a control to a form from your X++ code
FormBuildDesign
yes
the properties on the Design node in the Application Object Tree, and methods to add a control.
create the graphical layout of a form from your X++ code
FormObjectSet
yes
the data source name property and methods on a form data source in the Application Object Tree.
FormBuildObjectSet
yes
FormDataSource
yes
FormBuildDataSourc
yes
201
FormObjectSet
the properties and methods on a form data source in the Application Object Tree.
manipulate the data source on a form from your X++ code
FormBuildObje
the properties on a form data
manipulate the
Columbus IT Partner Russia, ApS
Navision Axapta e
ctSet
FormControl
yes
Form
yes
FormBuild
yes
source in the Application Object Tree.
properties on a form data source from your X++ code
the properties common to all control types and methods to update and exit. FormControl
the properties and methods for the control as seen in the Application Object Tree.
access individual form controls from your X++ code
the properties for the control as seen in the Application Object Tree.
Form control system classes For each control there is a system class called FormcontrolnameControl, for example FormIntControl, FormTabPageControl, and FormCheckBoxControl. A form control system class allows you to manipulate controls from your X++ code, assuming you declared a class variable to set properties, and activate class methods. FormIntControl FInt; // X++ statements missing here FInt.Value(MyTable.sum()); FInt.Update(); //more X++ statements
Constructing a form from your X++ code When you construct a form from your X++ code, you must use the system classes. Your code lines should look similar to the following form = ClassFactory.FormRunClass(new args(“CustTable”)); form.init(); form.run(); ClassFactory is an object of the class xClassFactory that holds the method FormRunClass that returns a new FormRun object. The idea of using this indirection is to make it possible to inherit the FormRun class and override selected methods to change the behavior of the form executor. Subsequently, you can have all forms in the system executed with the new class instead of the ordinary FormRun by supplying the inherited class in the FormRunClass() method. The system constructs all forms activated from the Application Object Tree using the xClassFactory.
An Alternative way to program the form construction form = new formRun(a); form.init(); form.run(); Method
Function
Columbus IT Partner Russia, ApS
202
Navision Axapta new
The form constructor that loads the form from disk and creates the form object.
init
Creates the form to be displayed on the screen and manages the construction of the data source.
run
Makes the form window appear on the screen and performs a database search for the data to be displayed in the form.
This sequence of execution is handled automatically by the system whenever a form is activated from the Application Object Tree.
Add a picture to a form using a system class Assume that you have created a form with an unbound Window control named CompanyLogo. In this control you want to display the bitmap named Picture.bmp. 1. Declare a variable to hold the result of your computation in the class declaration method on your form. class FormRun extends ObjectRun {
FormWindowControl CompLogo; }
FormWindowControl is a system class that implements all the properties of a Window control along with a number of methods to manipulate the control. 2. In the form’s Init method you write the code that accesses the control named CompanyLogo. void Init() {
super(); CompLogo = element.design().control(control::CompanyLogo); }
The following is an explanation of the code Sets the variable CompLogo to point to the relevant control: element.design()
addresses the design node of the current form
element.design().control
addresses the controls in the design node
element.design().control(control::CompanyLogo)
addresses the control called “CompanyLogo”
3. In the form’s Run method, write the code that sets the value of the property that holds the bitmap name. Use the following example: void Run() {
super(); 203
Columbus IT Partner Russia, ApS
Navision Axapta CompLogo.ImageName('Picture.bmp'); }
The following is an explanation of the code Sets the ImageName property to Picture.bmp
The bitmap is located in the current directory. The complete path must be given if the file is located elsewhere.
The code is written in the Run method to initialize the bitmap display. 4. To ensure that the image is updated, if you choose to link to another form, the code is also inserted in the LinkActive on the form’s Data Sources node. void LinkActive() {
super(); CompLogo.imageName('Picture.bmp'); }
Accessing the active query on a form When you have set the AutoQuery property on a form data source to Yes, the system automatically generates the query necessary to retrieve data to display in the form. As the result of user input in the form, though, you may want to modify the system generated query to display a different set of data.
To access and modify a system generated query (code examples from the CustTrans form) 1. Declare a variable of the type QueryBuildRange in the class declaration method on your form. class FormRun extends ObjectRun {
QueryBuildRange CriteriaOpen; //additional declarations {
QueryBuildRange is a system class used to specify the search scope of a query. 2. Initialize the variable in the form data source’s Init method. The initialization must be after the super() call which generates the query. void init() {
super(); CriteriaOpen= This.Query().DataSourceNo(1).addRange(fieldnum(CustTrans,Open)); }
Columbus IT Partner Russia, ApS
204
Navision Axapta Calling after the super() call in init is equivalent to calling before the super() call in the Run method.
The following is an explanation of the code: Sets the variable CriteriaOpen to point to the Open field in the CustTrans table This
is a reference to the current form data source
Query()
is a member method on the form data source used to get a reference to the form’s query. An instance of the Query system class is always available (see comment above about the AutoQuery property on the form data source) on a form data source as the class is automatically instantiated when the form is opened.
DataSourceNo(1)
is a method on the Query class used to identify the data source that takes an integer as parameter to identify the data source. The first data source is number 1. Returns a QueryBuildDataSource MorphX object.
AddRange
is a method on the QueryBuildDataSource class used to add a search range to the active criteria. It takes a field id as parameter and returns a QueryBuildRange.
FieldNum(CustTrans, Open)
is a built-in function that returns the field id, in this case of the Open field in the CustTrans table.
This is the way to get a reference to the active query in order to add a range. The only values that vary are the parameters to DataSourceNo and to fieldnum.
3. Modify the form data source ExecuteQuery method that is activated when the form is opened for data display. The method must be modified prior to the super() call. In the example below, the switch statement performs a test on the variable IncludeAll. Depending on the value of the member variable Value, the QueryBuildRange variable is set to 1 or 0..1. The query can now be executed. void executeQuery() { switch (IncludeAll.Value()) { case (1) : { CriteriaOpen.Value('1'); //see the class declaration: //CriteriaOpen is a variable of type QueryBuildRange break;
205
Columbus IT Partner Russia, ApS
Navision Axapta } case (0) : { CriteriaOpen.Value('0..1'); break; } } super(); }
6.6. Events on forms An event is a specific action that occurs on or with a certain object. Axapta can respond to a variety of events: mouse clicks, changes in data, forms opening or closing, and many others. Events are usually the result of user action. By adding your own code to one of the system’s methods or by creating methods of your own, you can add your own custom response to an event that occurs on a form. However, in order to know where to add your code, or where to call a method of your own, it is necessary to understand the nature of the methods’ super() calls, and the order of events that occur during common form operations such as
Opening a form: sequence of events When you open a form the following sequence of events occurs:
Pic. 6-22 1. The new constructor on the form is activated. 2. The init method on the form is activated. 3. The init method on the form data source is activated. 4. The run method on the form is activated. 5. The executeQuery method on the form data source is activated. 6. The firstField method on the form is activated.
Closing a form: sequence of events When you close a form by clicking a Cancel button, the following sequence of events occurs:
Pic. 6-23 1. The closeCancel method on the form is activated. Columbus IT Partner Russia, ApS
206
Navision Axapta 2. The canClose method on the form is activated. 3. The close method on the form is activated. When a form is closed with CloseCancel, user modifications are not saved. When you close a form by clicking the close button or an OK button, the following sequence of events occurs:
Pic. 6-24 1. If the form is closed with an OK button, the closeOK method on the form is executed. closeOK is not activated if a close button is used to close the form.
Leaving a control: sequence of events When a control is exited, the sequence of events occurs:
Pic. 6-25 1. The leave method on the control is executed. 2. The validate method on the control is executed. 3. The validate method on the data source is executed. 4. The validateField method on the table is executed. 5. The modified method on the control is executed. 6. The modified method on the data source is executed
Leaving a record: sequence of events When a record is exited, the following sequence of events occurs:
Pic. 6-26 1. The validateWrite method on the data source is executed. 2. The write method on the data source is executed. 3. The insert (if it is a new record), or the update (if it is an existing record) method on the table is executed.
Deleting a record: sequence of events When you delete a record from a form, the following sequence of events occurs: 207
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 6-27 1. delete on the data source is executed. 2. validateDelete on the data source is executed. If validateDelete returns true ... 3. validateDelete on the table is executed. If validateDelete returns true... 4. The record is then re-read from the database by the kernel. Unless the record is deleted or updated by another user, then... 5. delete on the table is executed.
Creating a record: sequence of events When you create a record from a form, the following sequence of events occurs:
Pic. 6-28 1. create on the data source is executed. 2. initValue on the data source is executed. 3. initValue on the table is executed.
Methods on a form When you click New on the Forms shortcut menu to make a new form, a Methods node is automatically created. The purpose of the Methods node is to allow you to add logic to individual forms.
Whenever possible, you should write your code on the underlying table. Methods written on a table are available on any form that uses that table as the data basis. In terms of re-use and inheritance, the Methods node is only the 'second best' place to add code.
The node holds what is called virtual methods which are methods implemented in MorphX, but which you can override to change the form's default behavior. In these methods the function call 'super()' results in the activation of MorphX's implementation of the method. As the name indicates, classDeclaration is the declaration of a class, namely the class FormRun. In the classDeclaration you define the variables you are going to use in X++ code written on the form, i.e. the scope of any variable defined here is the form's Data Sources, and the form's Designs nodes. Method name
Is executed when...
Comments
canClose
the form is closed
The super() call checks whether it is a valid action to close the form. canClose is activated by closeCancel and by closeOK. Use this method to add your own checks to the system’s close verifications.
Close
the form is closed
The super() call closes the form window, manages database updates, and sets the boolean flag closed. Depending on the close state of the form, close is activated either by closeCancel, or by closeOK.
closeCancel
the user presses a Cancel button, or the ESC key
The super() call sets the boolean flag closedCancel, and calls the close method. When a form is closed with closeCancel, user
Columbus IT Partner Russia, ApS
208
Navision Axapta modifications are not saved. Closed
the form is closed
Use the flag to check whether the form has been closed.
closedCancel
set by closeCancel
This flag is set if the form was closed by a cancel action (Cancel button or ESC key). Use the flag to check whether the form was closed with Cancel.
closedOK
set by closeOK
This flag is set if an OK button closed the form. Use the flag to check whether the form was closed with OK.
closeOK
the user presses an OK button
The super() call sets the boolean flag closedOK, and calls the close method.
closeSelect
a lookup form is closed following the user's selection in the form.
closeSelect is called before close is called, and closeSelect calls closeOK.
Copy
the user performs a copy operation (CTRL+C) on the form.
If the user has selected multiple records, the super() call in copy handles this. Otherwise copy calls the corresponding method on the form control.
Cut
the user performs a cut operation on the form (CTRL+X)
cut calls the corresponding method on the form control.
doApply
the user closes a modal window
docCursor
is not called by the system. The method can be used to query the current record's data source.
docCursor was designed specifically for use by the document management system. The method returns a cursor to the current record's data source. Useful when a form has more than one data source.
Finalize
the form is closed to destruct the form object
The form destructor that releases the space allocated for the form object.
firstField
focus moves to the first field on the form
The super() call locates the first field on the form.
Init
the form is opened to create the runtime image of the form
Init is activated immediately after new. Note super() in Init must be called Before the super() call in the method, you can modify the form using the FormBuild system class. The super() call creates the form to be displayed on the screen. Also in the super() call, the data source is constructed. This is done by activating the Init method on the data source. The form data source Init creates the query to fetch data from the database and sets up links in case the form is linked to another form. In the Init method you will typically initialize variables for specific controls.
lastField
focus moves to the last field on the form
The super() call locates the last field on the form.
messageProc
Do not use. For internal use only.
new
the form is opened.
209
new is the first method called when a form instance is created. For an overview execution sequence, click . Columbus IT Partner Russia, ApS
Navision Axapta This means that when new is executed, data source and form controls do not yet exist. When you need to add code to be executed when the form is opened, do so in the init method instead. nextField
focus moves to the next field, for example when the user presses the Tab key to advance focus
The super() call locates the next field on the form. When a form is opened, Nextfield is activated to focus on the first visible, editable field. Generally for the NextField/NextGroup and PrevField/PrevGroup operations: When a Next or Prev method is executed, the system checks the DataSource property on the control’s container to see from which table data should be displayed. The Next and Prev methods are invoked when the toolbar, the menu, or the keyboard is used.
nextGroup
focus moves to the next group of fields, for example when the user presses SHIFT+TAB key to advance focus
The super() call locates the next group on the form.
paste
the user performs a paste operation (CTRL+V) on the form.
paste calls the corresponding method on the form control.
prevField
focus moves to the previous field
The super() call locates the previous field on the form.
prevGroup
focus moves to the previous group of fields
The super() call locates the previous group on the form.
print
when the user has a form open activates the Print... command on the File menu.
A report based on the data source fields in the AutoReport field group is automatically generated. Add your own code if you want to change the layout of the standard report.
printPreview
when the user has a form open activates the Print Preview command on the File menu.
See comments to print command.
reload
Reserved for future use.
run
the form is opened, immediately after Init, to show the form
Before the super() call, you would typically do the following activate/de-activate fields etc. modify the query The super() call makes the form window appear on the screen, and performs a database search for the data to be displayed in the form. Activating the ExecuteQuery method on the form data source performs the search.
setApply
Not activated by the system.
Takes as a parameter the object, typically a form, to be activated. An apply() method must be present on the form or class and is called if a command button exists on the calling form. Tip Run the tutorial class Tutorial_Apply, and examine the code in the class and in the form of the same name.
task
the user performs some task in a form: uses the
The super() call examines the task and activates the relevant method, for example nextField if the task consists
Columbus IT Partner Russia, ApS
210
Navision Axapta toolbar, the menu or the keyboard
in the user activating the TAB key
equal
Not activated by the system.
Used for debugging purposes. Use equal to find out whether the object given as a parameter is equal to the current object.
toString
Not activated by the system.
Used for debugging purposes. Returns the name of the form as a string.
wait
the system waits for a form to finish execution.
Methods on a form data source The table below lists the form data source methods and explains when they are executed. Method name
Is executed when...
Comments
active
the user scrolls to make a new record the current one.
The super() call makes a new record the current one.
create
the user creates a new record in the data source, for example by using the default shortcut key for insertion (CTRL+N).
The super() call creates a new record before the current one on the screen. To have the new record created after the current record, set the method’s After parameter to true.
defaultMark
the user clicks mark area (top left corner) in a grid control.
When records are loaded and presented in a grid, they are marked with a default mark value of one (1). The fact that they are marked is used for delete and for copy.
delete
the user deletes a record in the data source.
The super()activates validateDelete and (if it returns true) manages the database delete action.
deleteMarked
the user deletes (ALT+F9) one or more marked (selected) records in the data source.
If no records have been marked (selected), delete is executed.
displayOption
before a record is displayed.
displayOption is executed once for each record, before the record is displayed and after it has been loaded. The method is used to set text color and background color for individual records. Note The code lines you add to the displayOption method are not necessarily executed sequentially. Consequently you should not base you code on the first lines being executed before the last lines.
executeQuery
the form is opened for data display.
The super() call executes the query generated by the init method and displays records.
filter
the user activates the Filter command on the form shortcut menu.
Write code lines on the filter method if you want to add information to the standard filer functionality.
findRecord
(activated by findValue)
The super() call finds a specific record and makes it the current one.
findValue
the user clicks the Find Value command in the shortcut menu on a form control.
The super() call finds the specified value, and makes the record with that value the current one using findRecord.
211
Columbus IT Partner Russia, ApS
Navision Axapta first
focus moves to the first record in the data source.
The super() call moves to the first record in the data source.
init
the form is opened.
On the basis of the properties on the data source, the super() call creates the query to load data to be displayed in the form.
initValue
a new record is created. The purpose is to fill in initial values in the record.
The super() call activates the table’s initValue method and the values initial values are filled in. In this method you would typically assign values to a new record. The system does not consider the record to be modified until the user has entered values in one or more fields.
last
focus moves to the last record in the data source.
The super() call moves to the last record in the data source.
leave
focus moves to a new record, or to a new data source.
leave is executed regardless of changes to the record. The super() call does not do anything and the method is merely used as a notification.
leaveRecord
focus moves to a new record.
Note Do not override the leaveRecord method. super() calls validateWrite and, potentially, write and should always be called.
linkActive
the user scrolls to a new record in a form with its data source linked to another data source.
The super() call activates executeQuery on the data source that the form is linked to. This method is only used when a link between two data sources has been established (by setting the LinkType property to Yes on the data source).
next
focus moves to the next record in the data source.
The super() call moves to the next record in the data source.
prev
focus moves to the previous record in the data source.
The super() call moves to the previous record in the data source.
print
the user activates the Print command in the File menu.
The super() call prints the current record using the system’s auto report facilities (the SysTableReport report, located in the Reports node).
prompt
the user activates the Filter Records command (from the Command menu or by activating the CTRL+F3).
The super() call activates the standard form used to limit the query range (the sysQueryForm form).
Refresh
The super() call updates the screen (all fields in the data source). refresh calls refreshEx. The contents of the active record are re-drawn without load from disk. You can for example use refresh if you need to update in the course of a major operation.
RefreshEx
a form is activated where records have been selected.
refreshEx is an extended version of the refresh method. It has one parameter and refreshes a single line.
RemoveFilter
the user clicks the Cancel Filter command in the shortcut menu on a form control.
The super() call resets the query, i.e. removes all modifications to the original query generated by the form data source init method.
Reread
Not activated by the system.
The super() call re-reads the current record from the database.
Columbus IT Partner Russia, ApS
212
Navision Axapta Research
Not activated by the system.
The super() call refreshes the database search defined by the query automatically generated in the init method. Corresponds to re-activating executeQuery with the exception that research preserves the query’s filter, sorting and so on. research vs. executeQuery If you want to refresh the form with records that were inserted in a method or job that was called, then you should use research. If you want to change the query to show other records, perhaps based on a modified filter, then you should use executeQuery.
ValidateDelete
a record is to be deleted.
The super() call invokes the validateDelete method on the table. Use this method to add your own data validation checks whenever necessary.
ValidateWrite
a new or updated record is to be written.
The super() call invokes the validateWrite method on the table. Use this method to add your own data validation checks whenever necessary.
Write
the user inserts a new record or updates an existing one.
The super() activates validateWrite and (if it returns true) manages the database write action.
Methods on form controls The table below lists the form control methods and explains when they are executed. Method name
Is executed when...
Comments
activateItem
the user activates an item.
The super() call manages the activation of the item (for example a program) represented by the icon.
ListView
activeCellChanged
the user has changed cell.
Table
allItemsDeleted
the user has deleted all items in a list.
ListView
Tree
the user begins editing (re-naming) the label of a node.
You can use the return value to prevent label editing.
clicked
the user clicks a control.
Here you would place code to be activated on user-click, see the progress control example.
beginLabelEdit
CheckBox CommandButton MenuItemButton Button
Table
The super() call returns the text given as column heading.
command
The super() call.
context
the user right-clicks the control.
colLabel
The super() call displays the shortcut menu.
StaticText
213
Columbus IT Partner Russia, ApS
Navision Axapta StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Grid Tab Group ButtonGroup CommandButton MenuItemButton Button Window Table Tree ListView Progress Animate HTML
The super() call returns the contents of a cell. Note Do not override the data method.
Data Table
doubleClick
the user has double-clicked an item.
ListView
editControl Table
The super() call returns the control type to be edited.
Tree
the user has ended editing (re-naming) the label of a node.
enter
the user moves focus to a control.
endLabelEdit
StringEdit
Columbus IT Partner Russia, ApS
214
Navision Axapta IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Tree ListView Progress Animate HTML
expanded
the tree has been expanded.
Tree
expanding
the tree is expanding.
Tree
Filter
You can use the return value to prevent tree expansion.
the user clicks the Filter command in the shortcut menu on a form control.
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Grid Tab Group ButtonGroup CommandButton MenuItemButton
215
Columbus IT Partner Russia, ApS
Navision Axapta Button Window Table Tree ListView Progress Animate HTML
gotFocus
the user brings the control into focus.
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Grid Tab Group ButtonGroup CommandButton MenuItemButton Button Window Table Tree ListView Progress
Columbus IT Partner Russia, ApS
216
Navision Axapta Animate HTML
HDC
Not activated by the system.
Handle to Device Context.
the user clicks the control.
The super() call displays the text in the HelpText property on the control, on the table or on the extended data type. The precedence is in the order indicated: control, table, and data type. Display another help text by overriding the method.
the user enters input in a bound control.
If you override the method, return false to suppress search for input, and use the field as a normal input field or perform a custom search. The super() call in InputSearch calls Filter(Value) on the control which in turn calls Filter on the data source
Image
helpField StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Grid Tab Group ButtonGroup CommandButton MenuItemButton Button Window Table Tree ListView Progress Animate HTML
inputSearch All controls
217
Columbus IT Partner Russia, ApS
Navision Axapta field. Any search results are appended to the existing query. To search in the entire data set, clear the filter before searching. itemDeleted
the user has deleted an item in the tree or list.
Tree ListView
itemInserted ListView
jumpRef StaticText StringEdit
the user has inserted an item in the tree or list. the user activates the shortcut keys (default CTRL+ALT+F4) or clicks the Go to main table command in the shortcut menu to jump to the field’s main table.
The super() call changes data source, shows the table.
IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Grid Tab Group ButtonGroup CommandButton MenuItemButton Button Window Table Tree ListView Progress Animate
Columbus IT Partner Russia, ApS
218
Navision Axapta HTML
Leave
the user moves focus out of a control.
StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Tree ListView Progress Animate HTML
lockDC
Not activated by the system.
Lock Device Context.
Image
Lookup StringEdit
the user uses the lookup facility. For more information about relations and lookup, click .
IntEdit RealEdit DateEdit
lostFocus
the user brings the control out of focus.
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox
219
Columbus IT Partner Russia, ApS
Navision Axapta RadioButton Grid Tab Group ButtonGroup CommandButton MenuItemButton Button Window Table Tree ListView Progress Animate HTML
Modified StringEdit IntEdit
an edit field (StringEdit, IntEdit, RealEdit, DateEdit, TimeEdit) is exited after editing a value in a CheckBox, a RadioButton, a ComboBox, or a ListBox has been changed.
The super() call manages the table update (by a sequence of calls to Validate on the data source, ValidateField on the table, and Modified on the data source).
RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Tree ListView Progress Animate HTML
mouseDown
the user releases the mouse button.
Columbus IT Partner Russia, ApS
220
Navision Axapta
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Grid Tab Group ButtonGroup CommandButton MenuItemButton Button Window Table Tree ListView Progress Animate HTML
mouseMove
the user moves the mouse pointer.
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit
221
Columbus IT Partner Russia, ApS
Navision Axapta ComboBox CheckBox RadioButton Grid Tab Group ButtonGroup CommandButton MenuItemButton Button Window Table Tree ListView Progress Animate HTML
mouseUp
the user presses the mouse button.
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Grid Tab Group
Columbus IT Partner Russia, ApS
222
Navision Axapta ButtonGroup CommandButton MenuItemButton Button Window Table Tree ListView Progress Animate HTML
Paint Window
The super() call draws the background and displays the .bmp file. Do not use.
processBase HTML
Do not use.
processForm HTML
Do not use.
processLink HTML
Do not use.
processPicture HTML
Do not use.
processTitle HTML
rowLabel Table
selectionChanged
The super() call returns the text given as row heading. the user has moved the selection to another item.
Tree ListView
selectionChange
the user alters his selection.
ComboBox RadioButton
selectionChanging
the user is moving the selection to another item.
You can use the return value to prevent selection change.
Tree ListView
tabChanged
a change of tab pages has taken place.
Tab
tabChange 223
immediately before change of tab page. Columbus IT Partner Russia, ApS
Navision Axapta Tab
If the method returns false, the system does not change tab page.
textChange
the user enters characters in a field.
StringEdit IntEdit RealEdit DateEdit TimeEdit
toolTip
the user moves the mouse pointer over a control.
StaticText StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Grid Tab Group ButtonGroup CommandButton MenuItemButton Button Window Table Tree ListView Progress Animate
Columbus IT Partner Russia, ApS
224
Navision Axapta HTML
unlockDC
Not activated by the system.
Unlock Device Context.
exits a control after entering values.
Here you can use a member function to get the value. For example this.text(); if the control is a StringEdit and this.selection(); if the control is a ComboBox. The super() call activates validateField on the database table.
Image
Validate StringEdit IntEdit RealEdit DateEdit TimeEdit ComboBox CheckBox RadioButton Tree ListView Progress Animate
HTML
6.7. Forms: Examples An example: a typical form from the standard application
Pic. 6-29 CustTable is one of the central forms used to create and maintain customer information in the standard application. Also, CustTable is an excellent example of how forms are generally created in the application: 225
Columbus IT Partner Russia, ApS
Navision Axapta • Based on one table only • Auto-generated layout • Designed with tab pages to display and enter information in the central table, and buttons to open forms with information from other tables • Practically no code written on the form itself but on the underlying table The following section reviews central issues and concerns when creating a form like CustTable, particularly which properties to set and where to add X++ code.
Selecting a data source Once you create the form by clicking New in the Forms node's shortcut menu, the next step is to select a data source using a drag-and-drop operation to move one or more tables from the Tables node. CustTable is typical of the large majority of forms in the standard application in that it uses one table only as its underlying data source: CustTable. When CustTable has been moved to the Data Sources node, you can view the table's properties.
Pic. 6-30 To manipulate the underlying data from the form (as opposed to merely viewing data), the AllowEdit, AllowCreate and AllowDelete properties must be set to Yes. In order to make use of the system's capability to create queries on the basis of the relations set up in the database, set the property AutoQuery to Yes. To make the system automatically scroll in a child form when the user scrolls in the parent form, set the LinkType property as well. This concludes the work to be done in the Data Sources node. The next topic is the Designs node.
Designing the layout At first glance the CustTable form may look quite complex with eight tab pages and the row of buttons. However, there are actually only few, central tasks involved which are repeated several times.
The tab with tab pages To create a tab with pages, first create the container tab by clicking New Tab, and the individual tab pages by clicking New TabPage on the container. Columbus IT Partner Russia, ApS
226
Navision Axapta If you have more than one data source, set the DataSource property on the individual pages. On the individual pages, Caption should be set. To ease later modifications the caption should not just be a text but rather a label. When the page displays a large number of fields, like for example the General tab page, the information may be displayed in several columns by setting the Columns property.
Groups and headings Generally each tab page holds a number of groups with the groups of fields from the CustTable table; the General tab page, for example, consists of four groups of fields: General, Exchange, Credit, and Administration. Simply moving them from the corresponding ones in the Data Sources node to the tab pages in the Designs node created the latter three groups. Having moved a group, only two properties should be set: Name and Caption. Again, any text that you enter should be a label. The General group is an example of a group where the groups from the database table have not been moved directly. General consists of three fields from three different groups; each of these fields has been moved individually. The DataSource and DataField properties should be set for all fields; this is automatically done by the system. The DataGroup property should also be set. You can modify the auto-selected frame by setting the FrameType and FramePosition properties.
Re-arranging the sequence of fields within a group Within the individual group on the form, controls for fields are added in the sequence the fields occur in the table. To re-arrange the fields do one of the following: • • •
Click the Edit command in the shortcut menu to see the finished form in design mode. Here you can move controls within the group. Re-arrange the fields in the Design node. Re-arrange the fields in the group in the table.
Alignment To align the controls, use the properties AlignChildren and AlignChild. Setting AlignChildren to Yes means, “yes, I will align my child controls”. Setting AlignChild to Yes means, “yes, I accept to be part of my parent control’s alignment scheme”
Lookup and data validation On practically all of the tab pages in the CustTable form, you see the small lookup icon . The icon indicates that by clicking it you get a list of the possible field values. This serves the dual purposes of helping the user, and ensuring that an invalid value is not accidentally entered. As you have seen if you have made your own copy of the CustTable form, the lookup icons were added automatically when the fields were dragged to the Designs node; there was no extra work involved. This is because the necessary relations were defined in the underlying database. 227
Columbus IT Partner Russia, ApS
Navision Axapta In the CustTable form there are examples of the two basic types of relations • •
Single field relations and Multiple field relations
The lookup on Country is an example of a single field relation.
Pic. 6-31 Single field relations are defined on the extended data type. The field Country in the CustTable table is based on the extended data type CountryId.
As shown above, the extended data type CountryId has a relation to the field CountryId in the table Country. This means that when the user clicks the control labeled Country in the “Address” tab page, the system looks up information in the Country table's CountryId field. However, as you can see from the illustration above, there is also a column called Description giving the full-length text. This is additional information added automatically when the TitleField2 property has been set on the Country table.
Columbus IT Partner Russia, ApS
228
Navision Axapta
Pic. 6-32 The lookup on State is an example of a multi-field relation.
Pic. 6-33 Multi field relations are created on tables. A relation is created on the CustTable table that stipulates that • •
229
The Country field has a relation to CountryId in the State table and The State field has a relation to StatId in the State table
Columbus IT Partner Russia, ApS
Navision Axapta
When the user clicks the control labeled State in the Address tab page, the system looks up information in the Country table's CountryId, and StatId fields. As in the single fields relation described above, the additional information in the Description column is added automatically when the TitleField2 property has been set on the Country table. Whether a lookup button is actually displayed is defined by the LookupButton property on the individual control; the property is automatically set to Auto. When the relations have been defined, the lookup functionality is there - whether the button is actually displayed or not.
6.8. An additional benefit of creating relations... Having created a relation, whether it is a single or a multiple field relation, gives the end user an additional benefit using the form in the application. When he right-clicks, for example, the State field, a shortcut menu with the Go to main table command is opened.
Pic. 6-34 Go to main table means: open the form displaying data from the table in which the information was originally stored. In the Customer example this means that when the user clicks Go to main table on the State field, the State form is opened displaying information from the State table.
Creating a relationship There are two relationships in MorphX: • •
Single field Multiple field
You can add conditions to both types at runtime based on user input. Relationships are defined at different places in MorphX.
Columbus IT Partner Russia, ApS
230
Navision Axapta
You can define a relationship on...
This allows you to create
an Extended Data Type
Single field relationships Conditions on a relationship
a table
Single field relationships Multiple field relationships Conditions on a relationship
Multi line fields One of the controls you see on the Address tab page is the control for address information labeled Address. The address field is based on the Addressing extended data type that is a String field that has its StringSize property set to Auto. The only modification necessary following the system's auto-generation of the StringEdit control is to set the control's MultiLine property to Yes.
The ButtonGroup The group of buttons to the right in the CustTable form consists of a MenuItemButton and five MenuButtons with additional MenuItemButtons. The buttons are all used to activate other forms in the application. To have a button control open another form you merely set the Module, Group and Function properties on the control.
Caption on child form When you open another form, for example CustTrans, you will notice that in addition to the form's own caption some information has been added in parenthesis: account number and company name. This information comes from the properties TitleField1 and TitleField2 on the CustTable table.
Automatic scrolling in child form (synchronizing) You will notice when you open another form, again for example CustTrans, and scroll in the parent form is that the information in the child form scrolls as well. In other words, the information in the forms is automatically synchronized. This was set up when you set the LinkType property on the data source to Yes.
An example of a Progress control This example illustrates the programming of a Progress control.
Pic. 6-35 The form has a progress bar, and integer field to show the current integer value illustrated by the bar and a button to start the progression. All controls are unbound. In the Application Object Tree, the form looks like this: 231
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 6-36 Code is written on one method only, the method that is activated when the user presses the button labeled “Start”. Line void Clicked() { 1
FormProgressControl p;
2
FormIntControl i;
3
int j;
4
i = element.design().control(control::intEdit);
5
p = element.design().control(control::progress);
6
for (j=0; j<100; j++) {
7
i.value(j);
8
p.pos(j); } }
The following is an explanation of the code: Line 1-3
Variable declarations. FormProgressControl and FormIntControl are form control classes.
Line 4-5
Sets the variables i and p to point to the relevant controls. element.design()
Addresses the design node of the current form.
element.design().control
Addresses the controls in the design node.
Columbus IT Partner Russia, ApS
232
Navision Axapta element.design().control(control::intEdit) element.design().control(control::progress)
Addresses the controls called “intEdit” and “progress”.
Line 6
A for-loop that increments j from 0 to 100
Line 7
Sets the Value property of the control equal j
Here the IntEdit control is updated.
Line 8
Sets the Pos property of the control equal j
Here the Progress control is updated.
An example of a Window control A Window control could for example be used to display company logo in a form. In the standard application the form CompanyLogo does exactly that. In addition to the Windows control, the form has two buttons to change and to remove the logo. The data source for the form is the CompanyInfo table.
The code to display the bitmap is written on the form 1. A variable of type FormWindow is declared class FormRun extends ObjectRun { FormWindow companyLogoBMP;
2. The method to display the company logo is written. If a bitmap file name is given as part of the company information table, this bitmap is displayed. Otherwise one of the system’s standard bitmaps is used. void showLogo() { Image logoImage; ; // X++ code lines missing here .... }
3. When the form is opened, the ShowLogo method is activated. void run() { super(); element.ShowLogo(); } In the standard application, the CompanyInfo form for example uses the CompanyLogo form.
233
Columbus IT Partner Russia, ApS
Navision Axapta
6.9. Optimizing and Troubleshooting Forms Troubleshoot forms What do you need help with?
My form is blank. Why can I not see my data? A form may appear blank for any of the following reasons: • One or more of the fields on the underlying table may have had the Visible property set to No. • The form may not be bound to an underlying table. Check the Data Sources node to make sure that an actual table is given here. • The form may be bound to an underlying data source that does not have any data. Check the underlying data source to make sure that it has data.
My ComboBox control does not display all options. Why can I not see all options? This is relevant only if you have an Enum type field in your database that is tied to a ComboBox control. If you have a database field of type Enum where the field’s Mandatory property has been set to Yes, and you use this field as the underlying data source for a ComboBox control, then you will not be able to see the Enum’s first Enum value (value 0). This is because the first Enum value is invalid. To be able to select the first Enum value, set the field’s Mandatory property to No.
The property sheet for my form control is grayed. Why can I not change the settings? The property sheet for a form control within a data group is grayed if the AutoDataGroup property for the group has been set to Yes. This is the recommended setting as it yields considerable performance improvements.
Optimize form performance There are several things you can do to make your forms run faster.
Performance Tips • Use bitmaps and other graphic objects sparingly. • Use black-and-white rather than color bitmaps. • Close forms that are not being used. • If the underlying record source includes many records and you want to use the form primarily to enter new records, set the StartPosition property of the form to Last so that the form opens to a blank record. If you open a form with all records showing, Axapta has to read in each record before it can display the blank record at the end of the recordset. • Do not use the Visible property method (exists on all controls) on controls each time a new record becomes active. This operation will make MorphX re-arrange the entire form. Instead you should use the Active property method.
Columbus IT Partner Russia, ApS
234
Navision Axapta
7. Creating Queries 7.1. Quiries basics What makes the database in MorphX important is data, but what is really important is the system’s ability to retrieve exactly the information you want and display it in the order you want to see it. Using MorphX queries you can ask questions about the data in the tables in your database. You can also create queries that combine information from more than one table. The information you select by using a query can be used as the basis for a form, report or even another query.
What they are and how they work Using a query you can retrieve data from the tables in your database. When you design the query in the Application Object Tree you decide which information the query will find. Notice however that queries are not static. Using functionality in MorphX classes allows you to modify and change a query at run time. Queries in MorphX do not have a visual representation of their own. This means that you can not see the information selected by a query without using a form or a report. However, a query may have a visual component called a QueryForm. A QueryForm is a form like any other form in MorphX, but it has been designed specially to let the user interact with the query. MorphX is very flexible as it allows the application programmer to create as many customized forms for interacting with the user as needed. However, a standard QueryForm called the SysQueryForm exists in the standard application. This is the default QueryForm used by MorphX when you create a new query.
The standard QueryForm At run time the standard QueryForm lets the end user change ranges, sort order, and also to save and retrieve customized queries. The Ranges tab
Pic. 7-1 The Ranges tab presents a list of fields you can define a range for. For example, you could narrow down the range for AccountNumbers to 1000..2000. When you run a query from the Application Object Tree, the list of fields appearing on the Range tab corresponds to a default setting defined by the programmer who created the query. However, the standard QueryForm allows the end user to add other fields to this list at run time. The Sorting tab 235
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 7-2 The Sorting tab also presents a list of fields. This lets you define if the records should be sorted in ascending or descending order according to the fields appearing in the list. When you run a query from the Application Object Tree, the list of fields appearing on the Sorting tab corresponds to a default setting defined by the programmer who created the query. However, the standard QueryForm allows the end user to add other fields to this list at run time. Load and save
Pic. 7-3 The Load and save tab presents a list of at least two queries: the original query and the one most recently used. You can choose to save and load settings when you have customized the standard query. A query has a UserUpdate property. This property determines if the QueryForm should remember its state when it is reopened. If the UserUpdate property is set to Yes the QueryForm restores the previous settings when activated. If the end user does not want to reuse these settings, the Reset button can be used to revert to the original query. Advanced If you select the Advanced check box, the standard QueryForm will look like this:
Columbus IT Partner Russia, ApS
236
Navision Axapta
Pic. 7-4 A tree-structure is opened in the left part of the dialog. The tree shows the tables that have been used as data sources in the query. An embedded data source will appear as indented. The Range and Sorting tab shows a list of the fields for the table you have selected in the field above. By changing focus between the tables used as data sources, the corresponding list of fields is automatically updated. Use this list of fields together with the arrow buttons to add field you want to appear on these tab pages. When you have customized the Range and Sorting tabs, use the Save button on the Load and save tab to save the settings. Running the query To run the query use the OK button, otherwise use the Cancel button.
Organization of queries Like any other database object, a query consists of a number of other elements. The organization of a query is as follows
Pic. 7-5
Data Sources In a query node you will find a hierarchy of data sources. Each data source is related to a specific table in the database. The structure of the hierarchy determines how records are retrieved from the tables. As the screen shot above shows, another data source node is embedded in the first one. If a data source is embedded in another, all records in the embedded data source (within the specified range) is selected, every time a record from the outer data source is selected. When you embed one data source in another, you can define relations between the individual fields in the data sources. By doing this you tell the query system that the values in these fields must match. If you have more than one data source at the same level, the query system runs through the data sources sequentially, and fetches the records from each of them. 237
Columbus IT Partner Russia, ApS
Navision Axapta
Sorting For each data source you can specify a sorting for the records. This is specified in the Sorting node for each data source. The sequence of the fields you specify below the Sorting node is significant. The sorting is performed in the order the fields appear. By modifying the Ordering property you can determine if you want MorphX to retrieve the records in ascending or descending order.
Ranges For each data source you can define a number of ranges. Each range is defined through the Value property. The Value property is a string that describes conditions to be met by the records in the data source. Example: if you want to define some restrictions on which AccountNumbers the query should retrieve, you would write ".. 5000, 5012 .. 5014, 5500, !6500, 6000.." to tell the system that you want • records with AccountNumbers less than or equal to 5000, • records in the range from 5012 to 5014, the record with the AccountNumber equal to 5500, • records with AccountNumbers above 6000, except for the record with the AccountNumber equal to 6500
Queries and methods MorphX recognizes certain thing that happen to your tables, such as when a record is fetched. When these events happen, MorphX calls a number of system defined methods. By adding your own X++ code to these methods you can change the default behavior of the system. You can also create your own methods that you can call from the system-defined methods.
7.2. Creating a query Queries are defined in the Application Object Tree. Besides creating a query, you will normally also create a sorting and a range for your query. To create a simple query based on a single table 1. Right-click on the Queries node in the Application Object Tree, and choose New from the shortcut menu. MorphX creates a new empty query with a system generated name. 2. Rename the new query. 3. Right-click on the Data Sources node and choose Add. MorphX adds a new data source below the Data Sources node. 4. Select a table by setting the Dataset property for the new data source. 5. The Dynamic property on the Fields node is used to determine if the query should work on all fields or on a subset of the fields. If you just want to work on all the fields, you do not need to do anything. If you want to work on only a subset of the fields, right click the Fields node and choose New, Field. Drag the fields you want to work on from the selection window. 6. (Notice that the Dynamic property automatically is set to No when you start adding fields to the Fields node). 7. Repeat step 5 until you have added all the fields you need. 8. Save your new query. To define a sorting 1. Expand the query you want to add a sorting to, and locate the Sorting node. 2. Right-click the Sorting node and choose New, Field from the shortcut menu. Columbus IT Partner Russia, ApS
238
Navision Axapta 3. Select the field you want to sort on by setting the Field property for the sorting. Repeat the previous step for each field you want to add to the sorting. 4. Arrange the fields below the Sorting node, in an order that reflects the desired sorting sequence. MorphX tries to sort the record according to the first field. If a sorting conflict occurs, MorphX uses the second field to resolve the sorting conflict, and so on. 5. Use the property sheet to set the Ordering property to Ascending or Descending, or each field below the Sorting node. 6. If you want to enable AutoSum set the AutoSum property to Yes. 7. If you want MorphX to automatically create a header, set the AutoHeader property to Yes. 8. If you want to use an index which is already defined for the table used as data source, then right click the Sorting node and choose New, Index from the shortcut menu. Use the property sheet to set the Index property to the index you want to use as a sorting. 9. Save the modified query. To define a range 1. Expand the query you want to add a range to, and locate the Range node. 2. Right click the Range node and choose Add for each range you want to define. 3. Use the property sheet to enter the range in the Value property for each field below the Range node. 4. Save the modified query.
Creating relations between embedded data sources When you create a query with embedded data sources, MorphX allows you to use a relation defined between two tables by setting the Relations property on the embedded data source to Yes. However, If there is not a relevant relation between the tables you are using as data source and embedded data source, MorphX allows you to define this relation below the Relations node. To create a relation between a data source and its embedded data source 1. Set the Relations property on the embedded data source to No. 2. Right-click the Relations node for the embedded data source and select New Relation from the shortcut menu. 3. Now you have to define the fields you want to create a relation between. Display the property sheet. 4. Select a field from the outer data source by setting the Field property. 5. Select a field from the embedded data source by setting the RelatedField property. 6. Save your modifications
Setting properties and default options In MorphX you can use properties to determine the characteristics of a query. Every Data Source, Fields, Sorting, and Range node has properties as well. • Query properties. These properties determine the overall behavior of the query. For example, you can determine the form the system should use when interacting with the user. • Data Source properties. These properties control the characteristics of a data source. For example you can determine if it is allowed to modify the query from X++ code at run time. • Field properties. These properties control if the specification of fields is created dynamically by the query system, or specified by the programmer. • Sorting properties. These properties control the sorting you define. For example, you can determine that the sorting should be in ascending order. • Range properties. These properties determine the characteristics of the range specification you have made. For example you can enable or disable the range you have specified. 239
Columbus IT Partner Russia, ApS
Navision Axapta Property
Property exists on...
Use this property to...
Name
Query DataSourceFields Range Embedded DataSource
modify the name of a query, data source, or range
Title
Query
add a heading for this query
Form
Query
determine which form MorphX should display when the query interacts with the user
UserUpdate
Query
determine if the QueryForm should remember its state when it is reopened. If this property is set to Yes, the previous settings are restored
Version
Query
see the version of the query. The Version property is increased every time the query is updated. (Read only)
Company
Query Embedded DataSource
determine from which company to retrieve data
Dataset
DataSourceFields Sorting Range Embedded DataSource
set the table used as data source. Notice that this property can not be modified when a sorting or a range has been defined
Order
DataSourceFields Embedded DataSource
determine how records from this data source should be sorted
FirstOnly
DataSourceFields Embedded DataSource
give the database a hint saying that you only want the first record from the query. This allows some database systems to optimize record retrieval, and thus speed up performance
FirstFast
DataSourceFields Embedded DataSource
give the database a hint saying that you want the first record from the query faster than the following records. This allows some database systems to optimize record retrieval, and thus speed up performance
AllowAdd
DataSourceFields Embedded DataSource
determine if the end user is allowed to add fields to sortings and ranges at run time
OrderMode
DataSourceFields Embedded DataSource
determine if the records should be fetched in Order By or Group By fashion. Used by functions like SUM, AVG and so on
Update
DataSourceFields Embedded DataSource
determine if the query is allowed to update records in the database
Dynamic
Sorting
determine if all the fields in the table in the data source are used or only a subset of them. As default MorphX uses all the fields in the table. If you start to manually add fields to the Fields node, the Dynamic property is automatically set to No
Field
Sorting Range Relations in Embedded DataSource
specify which field to base the sorting on or the field for which you define a range or define which field in the outer data source that should have a relation to a field in the embedded data source
Ordering
Sorting
determine if the records should be sorted in ascending or descending order
Columbus IT Partner Russia, ApS
240
Navision Axapta AutoSum
Sorting
determine if a sub total is printed when the value in this field changes
AutoHeader
Sorting
determine if MorphX should create a header (label) for the data source automatically
Value
Range
specify the range for the retrieved records
Label
Range
specify a label for a range
Status
Range
determine if the end user is allowed to modify a range in the QueryForm (at run time). Possible options are Open, Lock, or Hidden.
Disabled
Range
disable a field in a range specification
FetchMode
Embedded DataSource
determine if the data sources should be related through a 1:1 or a 1:n relation
JoinMode
Embedded DataSource
determine the strategy for how to join the output from an embedded data source. You can create an InnerJoin, OuterJoin, ExistsJoin, or a NoExistsJoin.
Relations
Embedded DataSource
determine if the query system should use the relations defined for tables and Extended Data Types
RelationshipName
Relations in Embedded DataSource
provide a name for the relation you have defined below the Relations node
Table
Relations in Embedded DataSource
see the name of the table used as outer data source
RelatedTable
Relations in Embedded DataSource
see the name of the table used as embedded data source
RelatedField
Relations in Embedded DataSource
define which field in the embedded data source that should have a relation to a field in the outer data source
Using multiple tables in a query One of the most powerful features of a MorphX query is the ability to use field from more than one table. For example, you might want to view a list of sales made by each salesperson in your company. To retrieve this information, you need to combine data from two tables: the Sales and the SalesPerson tables. To create a query based on more than one table, simply add the tables to the DataSource node for your query. When you do this you also specify how the information in the tables are to be joined. In a MorphX query you can use four different kinds of joins between tables. The table below provides an overview of these join types and when to use them. Use this join type
When you want to...
InnerJoin
combine records from two tables whenever there are matching values in a common field.
OuterJoin
join all the records in one table even if the are no matching values in the joined field from the second table. In an inner join only records having a matching value in the joined tables are returned. However, you may want to return records that do not have a corresponding match in the joined table. For example, suppose that you want to retrieve all employees and their respective departments from the Employee table. As long as all employees are assigned to a department, an inner join works. Unfortunately the president of the company does not have a department, and an inner join between the tables will not find him. The solution to this kind of problem is an outer join.
ExistsJoin
combine records from one table whenever there exists a value in a common
241
Columbus IT Partner Russia, ApS
Navision Axapta field in another table. NoExistsJoin
combine records from one table whenever there does not exist a value in a common field in another table.
With an inner join query, MorphX retrieves all the records from one table that have matching records in another table. For example, you can select records that show orders placed by each customer. The query would only select records for customers who placed orders. With an outer join, you can find all customers along with any orders they have placed. You can also find all orders whether or not they have associated customers. In theory there should not be any orders without customers. But this is one of the features of an outer join, it allows you to find information that usually would not be found using an inner join. If you join two tables using an outer join, the query includes all records from one table, and only those records from the other table for which values in the joined fields are equal. The result of a query is empty if no records exist in the other table. ExistsJoins are just like inner joins. The difference is that MorphX only uses the embedded data source as a condition. Thus, the records in the embedded data source are not fetched by the query. The query will only fetch the records in the data source if a match is made with the embedded data source. The NoExistsJoin is the opposite of the ExistsJoin. The query will only fetch the records in the data source if a match with the embedded data source does not exist.
Sequencing of retrieved records When you design a query in the Application Object Tree, MorphX allows you to add several tables to the DataSource nodes. The sequence of the retrieved records highly depends on how the data sources are linked. Example: multiple embedded data sources DataSourceA
DataSourceB
DataSourceC
The above embedding structure causes the records to be fetched in this sequence A1, B1..Bn, C1..Cn, A2, .. Aj, B1..Bn, C1..Cn Example: single embedded data source DataSourceA
DataSourceB
This embedding structure causes the records to be fetched in this sequence A1, B1, A2, B2, A3, B3, .....An, Bn Columbus IT Partner Russia, ApS
242
Navision Axapta
7.3. Using queries from other application objects MorphX provides a number of Query classes, which are used when you want to use queries from other application objects such as forms and reports. MorphX Query classes are divided into Build classes and a Run classes • Build classes are: QueryBuildDynalink
Query,
QueryBuildDataSource,
QueryBuildRange,
QueryBuildLink,
• Run classes are: QueryRun The QueryRun class contains methods such as get, next, changed, and prompt, which all work on a running instance of a query. This means that any modification you make to a query at run time is local to this specific instance of the query, or in other word, the modifications have the same life time as the instance of the query object itself. The Build classes differs from this, as they do not work on a running instance of an object, but rather on the specifications of the objects, that is, on any of the query objects you have defined in the Application Object Tree. If you use a method in a Build class to modify a property for a query object, you actually modify the specification of the query object. This means that the modification will take effect for the instances you run later on.
Using Run classes for Query objects Below you will find some typical examples of how to use the functionality in the QueryRun class
Iterating through a set of selected records Assume that you are using a query to retrieve a number of LedgerTable records and their corresponding LedgerTrans records. To iterate through the records the query has selected, you would write LedgerTable ltable; LedgerTrans ltrans; while (q.next()) { ltable = q.get (TableNum(LedgerTable)); ltrans = q.get (TableNum(LedgerTrans)); // Records are now retrieved from LedgerTable and LedgerTrans }
Checking if a Query has fetched a new record You can use the changed method in the QueryRun class to determine if the a new record has been fetched, that is. You can use this to check if the current record in the query has changed in response to the actions you have made to the query. if (q.changed (TableNum(ltable))) { // New LedgerTable record }
243
Columbus IT Partner Russia, ApS
Navision Axapta ...
Displaying a dialog window Execution of the Prompt member function in the QueryRun class causes a dialog to be displayed. This dialog is actually a MorphX form that is specified through the Form property. You can use the dialog window to let the end user enter information that is used to select records in certain ranges, and so on. if (q.Prompt(TableNum(LedgerTable))) { //User clicked OK } else { // User clicked Cancel }
If the end user clicks the Cancel button in the form, the Prompt method will return FALSE, otherwise TRUE is returned.
Using Build classes for Query objects Below you will find some typical examples of how to use the functionality in the query Build classes
Building and using a new query In the following example you first create a new (named) query, then use the Query class. Then you use the QueryBuildDataSource class to add a new data source to the query you have just created, finally use the QueryBuildRange class to add a range to the data source. //Create the query as a named object in the Application Object tree Query NewQuery = new Query ("MyQuery"); //Add data source QueryBuildDataSource bb = NewQuery.AddDataSource (TableNum(LedgerTable)); //Select a range or records QueryBuildRange br = bb.AddRange (fieldNum(LedgerTable, AccountNum)); br.value ("5000..5500");
You do not need to supply a name for the query as is done above (MyQuery). If you do not specify a name for the query, it will not be shown in the Application Object Tree. The last line above restricts the query to select records in the range from account number 5000 to 5500. Now this query can be found in the Application Object Tree. To retrieve the records specified by the query, you will have to use a Run query, which is created based on the NewQuery object you have just build above. Columbus IT Partner Russia, ApS
244
Navision Axapta //The Query() function makes a copy of the NewQuery. //All modifications are made to this copy QueryRun qr = new QueryRun (NewQuery); r.query().DataSourceNo(1).addRange(fieldNum(LedgerTable, Dimension)); r.query().DataSourceNo(1).range (2).value("MyDepartment") Now the records can be retrieved through the Next() method // Retrieve records if (qr.prompt()) { while (qr.next()) { //Process the data } }
Linking data sources in a hierarchy The data sources you define in a query have a hierarchical structure. The way you build this hierarchy is simply by embedding the data sources in each other. You also have to define a number of relations between each data source and the embedded data source. Assume that you want to make a query that fetches ledger transactions. For each record, that is, for each AccountNum selected in LedgerTable, all the related LedgerTrans records are fetched. This is simply done by embedding a data source containing the LedgerTrans table in an outer data source containing the LedgerTable table. Furthermore you will have to create a relation between the data sources to relate the AccountNum in LedgerTrans with the AccountNum in LedgerTable. //Create a new query in the Application Object Tree Query NewQuery = new Query ("MyQuery"); //Add data source QueryBuildDataSource LedgerTableBlock = NewQuery.AddDataSource (TableNum(LedgerTable)); //Define a range of AccountNumbers QueryBuildRange br = bb.AddRange (fieldNum(LedgerTable, AccountNumb)); br.value ("5000..5500"); //Create link between records in LedgerTable and LedgerTrans QueryBuildDataSource LedgerTransBlock = LedgerTableBlock.AddDataSource(TableNum(LedgerTrans), "Ledger Transactions");
245
Columbus IT Partner Russia, ApS
Navision Axapta LedgerTransBlock.addLink(fieldNum (LedgerTable, AccountNumber), fieldNum(LedgerTrans, AccountNumber));
Queries in forms and reports Forms and reports also use queries.
Queries in a form A query is used to create a link between two forms, for example, between a form displaying records from the LedgerTable, and another form which displays the transactions for the current account. The form displaying the transactions needs a way to determine the transactions related to the current account. This is done through a query. This query is not embedded in a LedgerTable data source, but the same information is made available through a dynamic link. This dynamic link connects the other form to the current record in the first form. You can use the query() method to access the query related to a data source. You can even specify another query by using the query() method. You just have to supply it with the name of the other query (as a parameter in the method call).
Queries in a report A report also uses a query. This query is used for specifying two things: • which records the report is going to print, • the structure of the report.
7.4. Queries and methods MorphX recognizes certain things that occur when you use a query, for example when data is fetched from the database. In response, you can get MorphX to execute X++ code defined in a method associated with the query. The picture below illustrates a query with a number of methods (Init, run, ..., next).
Pic. 7-6 The methods shown above can be thought of as predefined methods that are executed in a specific sequence when you use the query. The bodies of the methods initially only contain a call to super() in MorphX. By adding X++ code to the methods you can change the default behavior of the system. The class declaration lets you declare variables which has scope within the query. Query objects in MorphX have the following methods: Method
Executed when...
Init
a query is run. This causes the query to be initialized.
Run
the query is run from the Application Object Tree.
Prompt
the query is run. The call to Super() activates the QueryForm defined via the Form property for your query.
Columbus IT Partner Russia, ApS
246
Navision Axapta Next
247
the next record in the data source is fetched
Columbus IT Partner Russia, ApS
Navision Axapta
8. Creating Reports 8.1. Reports basics A report lets you present information in your database as a printed document. Use reports to print invoices, or complex summaries. MorphX helps you design reports that present information the way you want. You can use many different design elements, such as labels, data from the database, lines, and graphics created in other programs. The MorphX report engine automatically generates a skeletal report based on the design you specify.
What report are and how they work Use reports to display printed presentations of the information in the tables in your database. When you design the report in the Application Object Tree, you decide which information the report will include. However, notice that reports are not static. Using functionality in the system classes you can modify and change a report at run time. MorphX uses a query to retrieve the information you want to present in the report. The query in a report uses a QueryForm to let the user interact with the query. To make the report generation as easy as possible MorphX provides a Wizard that guides you through the report generation process.
Report components The picture below shows the components of a typical report in the Application Object Tree.
Pic. 8-1 Query and QueryForm The report uses a query to retrieve the information you want to present in the report from the database. The QueryForm is a form that is run before the report is executed. This is how the report interacts with the user at run time. Data sources and links Columbus IT Partner Russia, ApS
248
Navision Axapta A data source corresponds to a table. To retrieve data from more than one table, define multiple data sources within the query. A data source can be embedded inside another data source. When your report uses embedded data sources, you set links (relations) between the data sources to define how the information from the data sources is to be combined. Range Below the Range node, you can add a list of fields. Define a range for each field. For example, you could narrow down the range for AccountNumbers to 1000..2000. When you run a query from the Application Object Tree, the list of fields appearing on the Range tab in the QueryForm corresponds to a default setting defined by the programmer who created the query. However, the standard QueryForm allows the end user to add other fields to this list at run time. Sorting Below the Sorting node, you can also add a list of fields. This lets you define if the records should be sorted in ascending or descending order. When you run a query from the Application Object Tree, the list of fields appearing on the Sorting tab in the QueryForm corresponds to a default setting defined by the programmer who created the query. However, the standard QueryForm allows the end user to add other fields to this list at run time. Methods MorphX recognizes certain events that happen to a report when it is executed. As the picture above illustrates, the report, the query, and most parts of the design have related methods. By modifying the methods, you can change the default behavior of the report. Report designs This is where you define the layout of the report. You can work with designs in MorphX using either an automatic design specification or a customized design. In simple reports, MorphX generates the layout based on a specification you make. However, if you want your report to have a special layout containing company logos, pictures and so on, use a customized design. Report templates A report template can contain sections such as prolog, page header, page footer, epilog, and so on. It can also contain programmable sections. These sections can be added to the design MorphX generates based on your report specification. For example, your template can contain a page header that adds your company logo and a page number to all your pages.
Data source and visual layout There are two steps in creating a report in MorphX. The first step is to define the data source(s) for the report. The second step is to define the visual appearance of the report.
The data source for a report Below the Data Sources node for a report is a query. This query defines which data MorphX should use in the report. The definition of the data source determines: • The tables from which the report will retrieve data • The relationships between embedded data sources • The sorting, and ranges to be imposed on the data • How the data should be grouped • If subtotals should be calculated automatically • X++ statements in the query’s methods The query is built from a number of data sources. The query can contain a sequence of data sources and you can even create hierarchies of data sources by embedding a data source in another data source.
The visual appearance of a report Below the Designs node for a report, you can define one or more designs. Each design can be either 249
Columbus IT Partner Russia, ApS
Navision Axapta • a specification which is used by the system at run time to generate a report, or • a customized design. When using a design specification, MorphX creates the layout of the report when the report is run. The layout is based on the structure of the query specified below the report’s Data Sources node. When you create a customized design, MorphX takes a snapshot of the current state of the design specification. This snapshot is placed below a Design node in the report. A customized design allows the programmer to control all aspects of the layout of the report. A major difference between using a design specification and a customized design, is that if reports are based on a report template, only those with the design specification reflect changes made to the template.
8.2. Creating a report The type of report determines how a report is created in MorphX. Maybe you just want a quick overview of some data in your database. You can also create mailing label reports, to print names and addresses in a format that fits on common mailing labels. You may want to create reports that present your data in an attractive format with pictures, lines, and special fonts. You can use reports for many purposes. MorphX includes a number of features that help you create many types of reports. You can create a report on your own, or have MorphX create a report using a Report Wizard. A Report Wizard speeds up the process of creating a report because it does all the basic work for you. When you use a Report Wizard, it prompts you for information and creates a report based on your answers. Even if you've created many reports, you may want to use a Report Wizard to quickly lay out your report. Then you can switch to the Report Designs node to customize it. If you are going to create reports similar in their graphical layout, you may want to define part of the layout in a report template. A report template contains sections such as prologs, page headers, page footers, epilogs, and programmable sections. When you apply a template to a report, the sections in the template are added to the design MorphX generates. For example, a template can contain a page header that adds a page number to all the pages. You can work with designs in MorphX in one of two ways, using either a design specification, or a customized design. In simple reports use the basic design where you let MorphX generate the layout based on a specification you make. However, if you want your report to have a layout with many details, for example pictures, use a customized design.
Creating a report by using a wizard To create a report using a wizard: • On the Tools menu, click Report wizard in the Development submenu called Wizards. The wizard asks you detailed questions about the record sources, fields, layout, and format you want and creates a report based on your answers. Most of the options have default values that you can choose to accept, or you can modify them according to your needs. Only the selection of a data source is mandatory. These are the wizards steps: 1. In the first dialog, choose whether you would like to see system names or user interface names for tables and fields in the following wizard dialogs. This choice is for the wizard only. When the user subsequently runs the report, user interface names are always displayed. 2. Enter a report name and a heading. The system suggests a report name consisting of your user ID and the string '_Report'. 3. Select the data source that contains the data you want to base your report on. This step is mandatory as a data source is required for a report. The Next button is not available until you have selected a data source. Columbus IT Partner Russia, ApS
250
Navision Axapta Double-clicking a data source name to select, or use the button with the arrow symbol
.
When you have selected one table as a data source, you can choose also to add related tables, for example:
4. Select the fields from your data source that you want to see in your report. Expand the data source name to see the field names. The fields you select appear in your selection order. Use the buttons labeled Up and Down to move fields. 5. Select fields for summation, and define how the sum is to be calculated. The field types you can choose from are integer field, real fields and display methods. 6. Select the fields you want to use for sorting. Making selections in this dialog is optional. However, selecting sorting fields now makes it easier and faster to generate the report. Selections made in the Wizard become the default selections when the user runs the report. 7. Select report sub-headings to be output when a value in a sort field changes. 8. Add group totals. 9. Add report ranges. Like fields for sorting, it is optional whether you want to add default ranges to your report, but doing so now makes report generation easier. 10. Define the layout of your report. Check “Include standard top text” if you want the report system to insert a heading each time a record changes (for example for each new customer account number). Use the option buttons to the right to define layout and orientation. 11. Use the Preview dialog to open the graphical report editor and make layout adjustments, and to see a preview of the report. 12. Click Finish to create and save the report.
Using report templates When you create a report, use a report template to determine its default characteristics. The template contains information about which sections a new blank report contains. It also contains definitions of the layout of each of these parts. A report template can contain a prolog, page header, page footer, epilog, and programmable sections. These sections can be added to the design MorphX generates based on your design specification. For example, your template can contain a page footer that adds a page number to all pages in your report.
251
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 8-2 The basic idea of using a template is simple. Imagine that you have 20 reports for a specific company. All these reports share the same basic layout, and this is where the template comes in. By defining the basic layout once in the template, the same layout can be shared by all 20 reports. If you decide to make a modification to the layout, you only have to make the modification once in the template, and all your 20 reports will automatically inherit this change. Notice that this is only true when using a report based on a design specification. If your report uses a custom design, it does not inherit the changes made to the template, even though you initially based your report on a template. When you created the custom design, MorphX took a snapshot of the template at that time, and copied it to the Design node in your report.
Report sections Sections determine the layout of a report in MorphX. Sections can be defined either by a report template, or directly in the custom design in your report. All the sections can be repeated any number of times. This type of section...
Appears in...
Section can be embedded in Section Group?
Prolog
the beginning of a report. Use it to display items such as a logo, a report title, and current date. The prolog is printed before the page header on the first page of the report.
No
Page Header
the top of every page in a report.
No
Header
the beginning of a new group of records. Use it to display items such as a group name.
Yes
Section Group
the middle of a report. A section group can contain a header, body, or a footer section. Notice that the structure of data sources is reflected in the structure of the section groups.
N/A (Embedded in a body section)
Body
the middle of the report. A body section contains controls or a Section Group. The controls show the actual information from fields in the data sources (tables).
Yes
Footer
the end of a group of records. Use it to display items such as sub totals.
Yes
Page Footer
the bottom of every page in a report. Use to display items, such as page numbers.
No
Epilog
end of the report. Use it to display items such as
No
Columbus IT Partner Russia, ApS
252
Navision Axapta a logo. The epilog is printed just after the page footer on the last page in a report. Programmable Section
Use the programmable section to add any kind of customized information. To activate a programmable section, activate it explicitly with a element.execute() statement.
No
By making the Super() call in the ExecuteSection method conditional you can make the printing of any section conditional.
The example below is a report that contains a number of different sections.
Pic. 8-3 Normally, MorphX takes care of adjusting the size of the sections. However, if you need to, you can adjust the size manually. You can always add and remove sections, and add and remove controls within the sections. On each section in a report design, you can create display methods (methods using the display modifier). Display methods are methods that produce the information to be displayed by the controls in a section. For example, to display a bitmap in a section, create a display method that returns a string that is a path to the location of the bitmap on your disk (Normally this is in the ...\share\include directory). To make a bitmap control display the bitmap, define which display method to use in the DataMethod property for the control.
Creating a new report template A report template consists of a number of sections. Each section defines a certain part of the printed report, such as a prolog, page header, page footer, epilog, or a programmable section. Each of these design components can contain a number of controls to display various types of information. To create a new report template: 1. Expand the Reports node. Right-click the Report Templates node, and choose New 253
Columbus IT Partner Russia, ApS
Navision Axapta 2. Rename the new template. 3. Right-click the new template and choose New. Choose the type of section you want to create from the sub menu. You can create a prolog, page header, page footer, epilog, or a programmable section. If you choose Prolog, MorphX displays
Pic. 8-4 4. In a section, you can add any number of controls to display various types of information. There are several types of controls, and each of them can handle a specific type of data: String, Enum, Integer, Real, Date, Time, Text, Prompt, Shape or Bitmap. To display the company name in the prolog you made in the previous step, right-click the Prolog node and choose String in the shortcut menu. 5. To generate the text to display using the string control, create a display method. Right-click the Methods node below the Prolog node, and choose New Method in the shortcut menu. Modify the method in the X++ editor as follows
Pic. 8-5 6. The above method gets the name of the company by accessing the Name field in the CompanyInformation table. The display modifier allows the result returned from this method to be displayed by the string control. To do this, define where the data is retrieved by setting the DataMethod property to CompanyName. 7. Repeat steps 4 to 6 for each control you want to add to the section. For each display method, remember to use the correct return type. For example, for a bitmap, supply a display method that returns a string containing a path to where MorphX can find the bitmap on your disk. 8. Use the Left, Top, Width, and Height properties to position the controls you add. 9. Use the FaceName property to change the font, font size, and so on. 10. Save the new template.
Creating a report based on a design specification Below you will find a description of the steps required to create a simple report that uses a layout generated by MorphX. The majority of your reports should be created using this method. To define a simple report: 1. Right-click the Reports node in the Application Object Tree, and choose New from the shortcut menu. MorphX creates a new report node. 2. Rename the new report. Columbus IT Partner Russia, ApS
254
Navision Axapta 3. Start by defining the query that is used as a data source for the report. Locate the Query node below the Data Sources node. MorphX displays
Pic. 8-6 4. The query used by the report corresponds to a normal query object. MorphX allows you to work with embedded data sources, define ranges and sorting for the retrieved data. 5. After you have defined which data to display in the report, define the design of the report. Right-click the Report Designs node, and choose New Report Design from the context menu. MorphX displays
Pic. 8-7 6. Use the ReportTemplate property to apply a report template to ReportDesign1. MorphX provides a list of report templates to choose from. A report template can contain definitions of page headers and page footers. Typically, the templates add information such as company logo, the current date, or a page number to the pages in your reports. 7. The AutoDesignSpecs node is where MorphX stores your specification of which fields to display in the report. For each data source in your report query, MorphX generates a list of the fields you want to display in the report. To add a list of fields from each data source, right-click the AutoDesignSpecs node, and select Generate Specs From Query from the shortcut menu. MorphX creates one or more AutoDesignSpecs below the AutoDesignSpecs node (one node for each table in your query). If an AutoDesignSpec already exists from a previous generation, a warning is issued before the existing AutoDesignSpec is overwritten. 8. Specify the field you want to display in the report. Right-click a node below the AutoDesignSpecs node, and choose New, Field from . MorphX displays a selection window of all the fields in the table used as data source. 9. Use drag and drop to choose the fields you want to use in the report. 10. Return to step 8, and repeat the previous steps for all nodes below the AutoDesignSpecs node.
Use View on the AOT shortcut menu to open the visual report designer and see the report layout.
11. Depending on how many fields you want to display, you may need to set the NoOfHeadingLines property on the design specifications. If your report includes many columns, there will not be enough space to print a heading text above each column. MorphX solves this by using more than one line to print the headers. The NoOfHeadingLines property defines how many lines MorphX will use for text headers. 12. MorphX chooses the default font and font size. Modify these using the FaceName and FontSize properties on the field lists. Notice that you can choose to use different font, style, and font sizes for 255
Columbus IT Partner Russia, ApS
Navision Axapta each individual field, that is, each field within a data source can be displayed in its own customized way. 13. Compile and save your modifications.
Creating a report with a custom design Create a custom design to create a report with an advanced graphical design. The first steps in creating a report with a custom design are exactly the same as when you create a report with a basic design. When creating a custom design, the basic idea is to take a snapshot of an AutoDesignSpec, and use this snapshot as a foundation for creating a refined design. You begin exactly as when creating a report with an AutoDesignSpec. When you have specified the data source(s) and a possibly template for your report, MorphX copies this below the Design node. Now you can modify and refine the design as appropriate. To create a report with a customized design 1. We assume that you have already created a report based on design. Right-click the ReportDesign1 node and choose Generate Design. 2. MorphX now takes a snapshot of the design defined below the AutoDesignSpecs node, and if you are using a template in the basic design, also a snapshot of the template. Expand the Design node to view the new design. 3. To view a visual representation of the design, double click the Design node. 4. To modify the positioning, fonts, and so on, modify the Auto settings in the controls’ property sheets. Right-click the controls you want to modify, and choose Properties from the shortcut menu. 5. Save your modifications.
Advanced users may prefer to build reports that are not based on a snapshot of the basic design. Do this by manually adding all the controls you need below the Design node.
Creating a report with multiple designs Reports in MorphX can have more than one design. You can use this to have multiple versions of the same report. For example you could have a report with two designs, where the first design would print as portrait and the second design would print as landscape. To create a report with multiple designs, simply right-click the Designs node for the report, and choose New Report Design from the shortcut menu.
Activating a specific report design When opening a report from the Application Object Tree, by choosing Open from the shortcut menu, the first design is used as default. To select a specific design when activating a report from the Application Object Tree: 1. Expand the Designs node for the relevant report. 2. Right-click the design you want to use, and choose Open from the short cut menu. From X++ use the design method on the ReportRun object to select the design you want to use: Args ArgList = new Args(reportStr(AReportWithMultipleDesigns)); ReportRun rr = new ReportRun (ArgList); rr.design('Report Design1'); //Select the design to be used rr.run();
Columbus IT Partner Russia, ApS
256
Navision Axapta
Using controls to display information from the database MorphX provides a wide range of controls that can be used in the sections in your reports. The controls retrieve the information they display in different ways. Basically a report control retrieves information using one of these methods: Method 1: Through the property that directly sets the value of the control. Method 2: Through the DataMethod property, that is, using a display method. Method 3: Through the Table and DataField properties that specify a table, and a field within that table. Control Type
Data is retrieved as described in method...
String
2 or 3
Enum
2 or 3
Integer
2 or 3
Real
2 or 3
Date
2 or 3
Time
2 or 3
Text
1
Prompt
3
Box
1
Bitmap
1 or 3
Example showing how to use a display method 1. Assume that you want to display a bitmap in your report. Do this by using the Bitmap control. The picture below shows a bitmap control that has been added to the basic design.
Pic. 8-8 2. The picture above also shows a method called ShowCompanyLogo. This method produces a string that describes where MorphX is supposed to find the bitmap that you want to display in your report. The ShowCompanyLogo method is shown below
257
Columbus IT Partner Russia, ApS
Navision Axapta
Pic. 8-9 3. Finally set the DataMethod property for the Bitmap control in the property sheet.
Pic. 8-10
Description of properties for the data source query Property
Modify this property to...
Name
change the name of the query.
Title
change the query’s label.
Form
change the name of the form used for user interaction, for example, entering ranges and sorting.
UserUpdate
give the user permission to update the query.
Interactive
allow the query to open a form for user interaction (for example for specifying a printer). When set to No, the user is not prompted for a file name when directing the report to a file. The file name used is the one returned by the reportViewer::description() method.
AllowCheck
circumvent the table privilege checking.
In addition to these properties, the query has non-modifiable system properties that identify the creator, the creation date, the modification date, and so on.
Defining report orientation When a report is generated, displayed or printed, its orientation is controlled by the Orientation property on the design. When Orientation has been set to... Portrait or Landscape Columbus IT Partner Russia, ApS
The report is printed in the selected mode. 258
Navision Axapta Note: the Axapta property setting overrides the user’s selections in the standard Windows Page Setup dialog. This means that the orientation cannot be changed for print out. Auto
The report is printed in portrait if at all possible. If the margins are exceeded during the system’s automatic rearrange, landscape mode is used instead.
8.3. Printing Reports Printing reports executed on the server Reports executed on the server when running 3-tier, thin client can be printed to printers set up on the client or to printers set up on the server. To control which printers a report executed on the server can be printed on, use these check boxes in the Damgaard Axapta Configuration Utility: • On the Server tab page: Allow clients to use printers on the server. The default is no check mark. • On the Client tab page: Use printers on the server (only possible if server allows it). The default is no check mark. If both options have a check mark, the print dialog that appears when executing a report on the server will allow the user to select a printer on the client. Otherwise the print dialog will allow the user to select a printer on the client. If a report is generated on the server and printed to a printer on the client, the server makes some calls to the client. These calls are made to get information about the page size, the dimension of the fonts used in the report, and about the size of various strings in the report (for example the column headings). These calls are time consuming, so printing to a printer on the server is the faster solution. In a small company where the server has access to the same network printers as the clients, this could be a good choice. If the Axapta Object Server is run by an Application Service Provider, the server will in general not allow clients to use its printers.
Choosing alternative report medium Through the system's standard report interface, report output can be directed to printer, print archive, file, mail recipient, or to screen. The nature of the output is defined through the system's standard dialogs like the query form (ranges, sorting, sums and so on) and the print form (printer and orientation). The sequence in which the system creates the report is transparent to the user and is handled completely by the MorphX report generator. To define the output contents and layout and to have an alternative output medium, for example publishing a report to the web, MorphX offers a hook into the report generator through the system class ReportOutputUser. ReportOutputUser has a vast number of methods that correspond exactly to the methods that are normally activated by the report generator when a report is created. The methods are activated when ReportOutputUser rather than the MorphX report generator handles the report generation. The super() call in the ReportOutputUser methods, though, do not perform any actions. The idea is to tailor-make your report by overriding these methods. In the application, this pattern is used for creating reports to be published on the Web. An example: HTML Web reports In the application, the application class WebReportBase extends the system class ReportOutputUser, and the application class WebReportHTML extends WebReportBase. 259
Columbus IT Partner Russia, ApS
Navision Axapta As the name indicates, WebReportHTML produces HTML reports to be published on the Web.
Pic. 8-11 The Publish method on the WebReportRun application class determines the output medium, the output type, and calls the run method on the ReportRun system class: //previous statements ... pjs.setTarget(printMedium::viewerClass); pjs.viewerType(ReportOutputUserType::HTML); rr.run(); //following statements Because the print medium ClassFactory::createViewer.
is
viewerClass,
the
system's
report
system
now
activates
As the output type is HTML, the case-statement in createViewer activates WebReportHTML. The output type is defined by a system enum with five entries. One of them is HTML as seen in the above example.
Disable printer selection Prevent display of the Print setup dialog Special types of reports - for example checks - you may want to direct to the same printer, and disallow any user selection. To disable the user’s possibility to choose printer, override the prompt method on the report, setting the showDevice parameter to false: public boolean prompt(boolean showCopy = true, boolean showPages = true, boolean showDevice = true, boolean showProperties = true, boolean showPrintTo = true) {
Columbus IT Partner Russia, ApS
260
Navision Axapta boolean ret; ret = super(showCopy, showPages, false, // showDevice showProperties, showPrintTo); return ret; }
Now the user is not presented with the Printer setup dialog when opening a report. Use the report’s property sheet as an alternative to modifying a report method. Set the Interactive property on the report to No to prevent display of the Printer setup dialog. Then leave the prompt method as it is.
Direct output to a specific printer If you want to decide which printer the output should be sent to, use the deviceName method on the PrintJobSettings system class. public void Init() { super(); element.DeviceName("Invoice Printer"); }
Use the methods on the PrintJobSettings class to set all parameters known from the Print setup dialog, as the report contains those methods. You can also use the PrintJobSettings, to which the reportRun can deliver a handle, for more control. An example from the standart application The PrintJobSettings is used in Sales order/Posting/Invoice/Printer setup/Invoice. Here the (each) user chooses the printer once. Afterwards, that setup is used on all of the following invoices - until it is changed. The following components are used to achieve the functionality: in: \Reports\SalesInvoice\Methods\init ... element.unpackPrintjobSettings(salesFormLetter.printerSettingsFormLetter()); ... The printer settings for the report are set using element.unpackPrintjobSettings, it takes a container with the settings, as an argument. in: \Classes\SalesFormLetter\callPrinterSettingsFormletter
261
Columbus IT Partner Russia, ApS
Navision Axapta static boolean callPrinterSettingsFormletter(SalesFormletter salesFormletter) { PrintJobSettings printJobSettings; boolean ok = true; ; printJobSettings = new (salesFormLetter.printerSettingsFormletter()); ok = printJobSettings.printerSettings(formStr(SysPrintForm)); salesFormLetter.updatePrinterSettingsFormletter(printJobSettings.packPrintJobSettings()); return ok; }
The system Class PrintJobSettings is new'ed using the container (earlier settings), The standard Form (SysPrintForm) is run. The new settings are retrieved (as a container) using packPrintJobSettings, and saved for later use in the report, or for further modifications.
Fit to page The system's standard behavior is to scale reports to fit the print page so that all fields from the various report sections can be printed on one line. When the system scales a report, a message to that effect is displayed in the Infolog. To prevent the system from scaling wide reports, use the fitToPage method on the PrintJobSettings system class. Call the method with false as parameter from the prompt method on the relevant report. The method should be called before the super() call. An example public Boolean prompt(Boolean showCopy=TRUE, Boolean showPages=TRUE, Boolean showDevice=TRUE, Boolean showProperties=TRUE, Boolean showPrintTo=TRUE) { Boolean ret; element.printJobSettings().fitToPage(false); ret = super(showCopy, showPages, showDevice, showProperties, showPrintTo); Return ret; }
8.4. Reports and methods MorphX recognizes certain things that occur when you use a report, for example when the report is initialized. In response to these events, you can get MorphX to execute X++ code defined in a method. Columbus IT Partner Russia, ApS
262
Navision Axapta The methods on a report can be divided into three categories: 1. Methods on the report itself 2. Methods in the report’s query 3. Methods in the report design
Methods on a report When you click New on the report shortcut menu to make a new report, a Methods node is created. The purpose of the Methods node is to allow you to add logic to individual reports. Note that whenever possible, you should write your code on the underlying table. Methods written on a table are available to any report that uses that table as the data basis. In terms of re-use and inheritance, the Methods node is only the ''second best' place to add code. The node holds what is called virtual methods, or methods that are implemented in MorphX, but you are allowed to override to change the report's default behavior. In these methods the function call 'super()' results in the activation of MorphX's implementation of the method.
Pic. 8-12 The methods shown above are predefined methods that are executed in a specific sequence when you use the report. The bodies of the methods initially only contain a call to super() in MorphX. By adding X++ code to the methods, you can change the default behavior of the system. The class declaration lets you declare variables, which have scope within the report.
Overview of methods on a report When you run a report, the report automatically activates different methods on itself. This topic describes the methods, when they are run, and how it may be useful to override them. iReport method name
Is executed...
Comment
Finalize
when an instance of the report is no longer needed.
This method performs various cleanup activities. Note: This method is not called automatically but must be called explicitly from your code. Can also be used to release external resources.
Prompt
to prompt the user to select the print medium (paper, screen, print archive, RTF, HTML, ASCII) and other
If the programmer does not want this dialog, the Prompt method may be overridden so that it does not call super(). Note: Do not mistake this method for the method of the same name on a query.
263
Columbus IT Partner Russia, ApS
Navision Axapta information. Init
when a report is created.
Entities proper to the report are defined in the ClassDeclaration.
Run
to run a report.
The non overridden version of this method does five things in sequence: Call Prompt Create a basic design, if it does not exist already Arrange the fields Call Fetch Call Print
Fetch
to fetch records from the database.
The non-overridden version of this method does this by creating a query, opening the query's prompt and fetching the records. Each record found is dispatched to the report formatter by calling the Send method.
Print
to print the report on the selected medium.
If the user has chosen to preview the report, the Print method opens the window containing the report. If the user has chosen to print the report on paper, the Print method does whatever is needed to print out the report. Note: No database access is done here; the records have all been found in the Fetch method, as described above.
Send
to send the records fetched by the query to the body sections in the report.
The Send method is a connection between a report’s query and the visual part of the report. The Send method sends the fetched records to the body sections in the report. The Send method is automatically called by Next each time a record is fetched. All data is sent through the Send method after being fetched by the Fetch method.
SetTarget
by the SysPrintForm when changing print medium.
Use the Target method to select the print medium, or the return value to detect the selected medium.
GetTarget
by the SysPrintForm when changing print medium.
Use the return value to detect the selected medium.
PrinterSettings
when Printer Settings is selected in the shortcut menu or via the SysPrintForm.
Caption
when a report is run.
The Caption method determines the caption for the preview window. By modifying the Caption method, you can change the string shown as caption.
Create
when the progress form is created.
You can modify the ProgressForm method to use a customized form to indicate progress.
ProgressInfo
each time the progress form is to be updated.
The super() call updates the progress form. This method may be overridden to supply another visual indicator of the report evaluation progress.
Columbus IT Partner Russia, ApS
264
Navision Axapta
The Fetch and Send methods The query used to fetch the records to print and the report design are two distinct parts of the report. These two parts only interact dynamically, through the methods as described here. However, the query may refer to the report using the predefined Report variable. If needed, the report can access the query using the Query variable. The Fetch and Send methods are a central part of the report engine in MorphX. The Fetch method fetches the record defined by the report’s query, and the Send method sends the fetched records to the report design.
Modifying the Fetch method on a report The Fetch method is the main loop of a report. The programmer may override the fetch method if there are very special constraints on which records to show. The Fetch method can be modeled in X++ as //Create a new query to fetch the records QueryRun qr = new QueryRun(report); //Open the prompt dialog if(qr.prompt()) { //The user didn't press cancel while(qr.next()) { file = qr.get(file); //For all data sources send(file); } }
If you want to print only records that satisfy some special constraint that is difficult to express as a range in the query, write the code above, and only allow Send to be called if the constraint (expressed as a function by the same name in the example below) is satisfied: while (qr.next()) { file = qr.get(file); //For all data sources if(constraint()) send(file); }
265
Columbus IT Partner Russia, ApS
Navision Axapta
Understanding the Send method on a report A report in MorphX consists of two main parts: the query that defines which data will be in the report, and the report design that defines the layout of the report. The query and the design are connected through the Send method.
Pic. 8-13
Methods on the report design Below each section in your report design is an ExecuteSection method. When Super() in ExecuteSection is executed, the information in the section is printed. In certain situations you may want to control if the information in a section should be printed or not, according to some criteria you define. This is done by making the call to Super() in ExecuteSection conditional. You can also use the ExecuteSection method to hide and show parts of the report design at run time. For each type of field on a report there is a MorphX class based on the ReportControl class, such as ReportRealControl, ReportIntControl, and so on. In these classes, use the hide() and show() methods to hide and show specific fields in your report. To identify a specific field in your report, use either the ControlName(Name) method, or the Control(FieldId, TableId) method in the ReportDesign class. Another common use of the ExecuteSection method is to insert a page break. For example, to insert a page break between the prolog and the following pages. Do this by adding an Element.NewPage() statement after the call to Super() in the ExecuteSection method for the prolog.
Events on reports An event is a specific action that occurs on or with a certain object. Axapta responds to a variety of events: mouse clicks, data changes, reports opening or closing, and many others. Events are usually the result of user action. By adding your own code to one of the system’s methods, or creating methods of your own, you can define your own custom response to an event that occurs to a report. However, in order to know where to add your code, or where to call a method of your own, it is necessary to understand the nature of the methods’ super() calls and the order of events that occur during common report operations like.
Opening a report from the Application Object Tree When you open a report by selecting Open in the short cut menu, the following sequence of events occurs:
Columbus IT Partner Russia, ApS
266
Navision Axapta
Pic. 8-14 1. First the Init method on the report is activated to initialize the report. 2. The Run method on the report is activated. 3. The Prompt method on the report is activated to allow the user to interact with the report. 4. The Fetch method on the report is activated. 5. The Print method on the report is activated.
Events caused by the Fetch method
Pic. 8-15 1. Fetch calls CreateProgressForm to create a form for showing progress. 2. Send is called for each record fetched from the data source. 3. Send calls ProgressInfo to update the progress info form. If another data source is embedded in the data source, for example the CustTrans table inside the CustTable, ProgressInfo is called once more. 4. When all records are sent the Fetch methods returns to the caller.
267
Columbus IT Partner Russia, ApS
Navision Axapta
8.5. Tips
.
Overview of components in a report design Designs
=
{ Design }
Design
=
Sections
Sections
=
{ Prolog | PageHeader | Header | SectionGroup |Footer | PageFooter | Epilog | ProgrammableSection }
Prolog
=
{ ControlList | FieldFromTable }
PageHeader
=
{ ControlList | FieldFromTable }
Header
=
{ ControlList | FieldFromTable }
Footer
=
{ ControlList | FieldFromTable }
PageFooter
=
{ ControlList | FieldFromTable }
Epilog
=
{ ControlList | FieldFromTable }
SectionGroup
=
{ Header | Body | Footer }
ProgrammableSection
=
ControlList
Body
=
{ ControlList | FieldFromTable | SubSection }
ControlList
=
{ String control | Enum control | ...}
FieldFromTable
=
{ Field1 | Field2 | ... | Fieldn }
Printing headers for reports with many columns If your report contains many columns, and you want to display a heading for each of them, use the NoOfHeadingLines property. The integer value you enter in the NoOfHeadingLines property defines how many lines MorphX should use when printing a report. For example if you set the value to three, the headings will be printed as follows:
Pic. 8-16
Sequencing of sections when printing a report Assume that your report design contains three programmable sections, and that the ExecuteSection method for the programmable section number one contains the following: element.execute(2); Columbus IT Partner Russia, ApS
268
Navision Axapta super(); element.execute(3); If you call element.execute(1), the programmable sections prints in the following sequence. Programmable Section-2 Programmable Section-1 Programmable Section-3
Setting font and font size Each user can set up his own default font, and font size for the reports he generates. Click Options... on the Tools menu, and choose font, and font size on the General tab.
Positioning sections relative paper edges These methods support positioning sections relative to paper edges, and positioning controls relative to sections: reportRun::currentYmm100() reportRun::gotoYmm100() reportSection::topMarginAndFrame() reportSection::leftMarginsEtc() reportSection::rightMarginsEtc() reportControl::top100mm() reportControl::top100mmInclBorder() To check the position of sections and controls, you can use these methods: reportRun::rulerCM() reportRun::rulerINCH() A control using one of these methods draws rulers on the current page (and should only be used for test purposes). Please see the report tutorial tutorial_Positioning in the Application Object Tree. The tutorial demonstrates how a control (positionedControl) can be fixed to a given position, and stay there when margins and border thickness change.
Column headings and word wrap Use the ColumnHeadingsStrategy property on report sections to control whether or not you want column headings to word wrap. ColumnHeadingsStrategy can be set to WordWrap or to DisplacedLines. When ColumnHeadingsStrategy is set to WordWrap (the default value), column headings (aaaaaaaa and bbbbbbbb in the example) are word wrapped: Aaaa
Bbbb
Aaaa
Bbbb
------
-------
AAA
BBBB
269
Columbus IT Partner Russia, ApS
Navision Axapta A report heading is adjusted to the length of the fields it is a heading for. This means that the maximum length of a heading is the length of the longest field. However, if the system can avoid wrapping by allowing three additional characters on the heading line, this strategy is used. Due to the fact that a heading rarely has the same number of characters in different languages, identical reports look different in different languages. Headings can be wrapped over a maximum of eight lines. If eight lines are insufficient, the heading is cut off after line number eight. When ColumnHeadingsStrategy is set to DisplacedLines, each coulmn heading displays on one line, and is not divided: aaaa aaaa bbbb bbbb ------ --------
AAA BBB The value of the NoOfHeadingLines property also influences the way a column heading is displayed. The above examples presupposed that the NoOfHeadingLines property has been set to Auto. When NoOfHeadingLines is Auto, and ColumnHeadingsStrategy is WordWrap, the system calculates the number of lines needed to display the column headings. When NoOfHeadingLines is Auto, and ColumnHeadingsStrategy is DisplacedLines, two lines are used if the heading of a control is wider than the width of the control. One line is used if the columnHeading is <= the width of the control, and zero lines are used if none of the controls in the section have a column heading. When the NoOfHeadingLines property has been set to a value other than Auto, headings are wrapped or displaced according to this value.
Missing bitmaps Use the property WarnIfMissing on bitmap controls if the user should be informed that a bitmap in his report is missing. When WarnIfMissing has been set to Yes, a message is written to the InfoLog. The default property setting is No.
Columbus IT Partner Russia, ApS
270
Navision Axapta
9. Creating Menus Menus in MorphX are extremely flexible and can be custom made to suit the exact needs of any company and user. Menus allow you to organize commands so that the end user can find and use them quickly. An Axapta application normally has several menus customized to the individual users' area of responsibility. Typically the person responsible for sales and marketing will have a menu that is radically different from the bookkeeper's menu. Such menus are created and opened from the File menu. The standard application has a default main menu. However, the main menu can be customized to suit the need of the individual company. All menus in Axapta are based on menu items. When you create a menu, you create references to your Menu Items collection. So creating menu items are a prerequisite for creating any menus.
Creating a menu 1. Click New on the Menu node's context menu. This creates a new, empty menu that you must name through its property sheet. 2. Add a menu entry, a submenu, a separator or a menu reference by clicking New and then the relevant command in the menu's context menu. When you click New Menu Item, the system creates a new, empty item. You must use the property sheet to set the MenuItemGroup and MenuItemName properties. MenuItemGroup refers to the group that you have placed your menu item in (Display, Output, or Action), and MenuItemName refers to the application object. Use the Shortcut property to give the menu item a shortcut. Now your menu is ready to be part of a user menu. Click New User Menu on the File menu.
An alternative way of adding a menu item to a menu is to use a drag-and-drop operation.
Description of properties for menus Property
Modify this property to ...
Name
modify the name of the object
Label
alter the name displayed in menus.
FeatureKey
restrict access to the menu.
setCompany
have the system change company when the menu is opened. When set to Yes: each time the menu is activated, the company changes to what it was when the menu was first activated.
CreatedBy
A read-only property that is set by the system. The property gives the name of the user who created the object.
CreationDate
A read-only property that is set by the system. The property gives the date when the object was created.
ChangedBy
A read-only property that is set by the system. The property gives the name of the user who last modified the object.
ChangedDate
A read-only property that is set by the system. The property gives the date when the object was last modified.
ChangedTime
A read-only property that is set by the system. The property gives the time when the object was last changed.
271
Columbus IT Partner Russia, ApS
Navision Axapta LockedBy
A read-only property that is set by the system. The property gives the name of the user who has currently locked the object.
Menu items: What they are and how they work Menu items are a collection of items that can be activated from menus and forms. Each item runs an application object: a form, a report, a class, or a query. You must always create a menu item when you want to activate an application object from a menu or from a form. Menu items represent an additional level of indirection. This means that you never reference an object directly.
Pic. 9-1 The example illustrates the situation when you have four forms, forms A to D, that each have a button to open the same form, form X. These forms do not reference form X directly; rather they reference the menu item that references form X. The advantage of this becomes obvious when you need to change the application so that forms A to D open another application object – this could be a form but it could also be a class, a report, or a query. In such a situation you need modify only the menu item that references form X and all objects that use the menu item are updated automatically. A menu item is created using the Menu Items node in the Application Object Tree.
The Display, Output and Action nodes are categories you can use to have an improved overview of your items that rapidly grow in number (the standard application comprises more than 1000 application objects!). • The Display node typically holds items that are displayed on the screen, typically forms • The Output node typically holds items that generate output, primarily reports • The Action node typically holds items that activate in batch, primarily queries and classes. However, the nodes are identical in structure and you can use them as you wish. They are merely a help facility when structuring your references. Note, though, that the name of a menu item must be unique within a group.
Creating a menu item To create a menu item in the Application Object Tree 1. Locate the menu items subnode that corresponds to the type of item you want to create. The Display node typically holds forms. The Output node typically holds reports. Columbus IT Partner Russia, ApS
272
Navision Axapta The Action node typically holds queries and classes. 2. Use a drag-and-drop operation to move your application object to the Menu Items subnode. The central properties are automatically set. An alternative way… If you prefer, you can also use the New Menu Item command on the shortcut menu. In that case you must enter a suitable name in the new item's Name property and modify the menu item’s Class and Object properties to identify an application object.
Methods on a menu item The table below lists the menu item methods and explains when they are executed. Form control method name
Is executed when ...
Comments
Create
Not activated by the system.
The system does not call the Create method but you can do so explicitly. Create returns an object of the same type as the one the menu item activates (for example a form). The idea is that you can modify the application object before running it.
CanCall
Not activated by the system.
The super() call checks whether it is valid to activate the menu item. Use this method to add you own checks.
Description of properties for menu items Property
Modify this property to ...
Name
modify the name of the object.
Label
alter the name displayed in menus and on buttons.
HelpText
create a help string for the menu item.
Class
choose another object type (form, report, query etc.)
Object
choose an object from object type given by the Class property.
Parameters
enter text as parameter to the Object.
EnumTypeParameter
choose an enumerated type as parameter to the Object.
RunOn
choose whether the menu item should be executed on the client, the server or where it is called from. Note The menu item is constructed, and methods called on it at the tier specified in the property sheet for the menu item. The RunOn property decides where the application object is executed only when the application object activated by the menu item has its own RunOn property set to Called from. A form is instantiated and run on the client since the FormRun class always runs on the client. A report is instantiated and run as specified by the menu item’s RunOn property since the ReportRun class always runs where called from. A class' main method is run as specified by its modifier. The class itself is instantiated as specified by its RunOn property. The
273
Columbus IT Partner Russia, ApS
Navision Axapta instantiation might happen in the main method. This means that the property is the most interesting for reports. FeatureKey
be able to restrict access to the menu item. In conjunction with NeededAccessLevel, this property is used to set access to Axapta’s menu.
NeededAccessLevel
define the minimum access required if the menu item is to appear on a menu. In conjunction with FeatureKey, this property is used to set access to Axapta’s menu.
MultiSelect CreationDate
A read-only property that is set by the system. The property gives the date when the object was created.
CreatedBy
A read-only property that is set by the system. The property gives the name of the user who created the object.
ChangedDate
A read-only property that is set by the system. The property gives the date when the object was last modified.
ChangedTime
A read-only property that is set by the system. The property gives the time when the object was last changed.
LockedBy
A read-only property that is set by the system. The property gives the name of the user who has currently locked the object.
When you use the Parameters or EnumParameter properties the system cannot generate compile errors if you should have made for example a type mismatch in your code. Such errors will cause runtime errors.
EnumParameter and EnumTypeParameter EnumTypeParameter and EnumParameter are typically used when one form is used in several different situations. On the basis of the value of the EnumParameter you might for example disable a button. This means that when you have several different menu items, you can make the same form behave differently in different circumstances. PriceDiscGroup from the standard application is an example of such use. The form PriceDiscGroup is included three times in the Display menu item group but with three different EnumParameter values. In the form's Init method a case-structure checks the value and the form is created accordingly.
Activating a menu item from your X++ code To execute a menu item from your X++ code you use the MenuFunction system class. This is illustrated in the example below that is from the LedgerJournalTrans table. The actual code extract is from the formSettlement method. Line
Boolean formSettlement() {
1.
FormRun formRun;
2.
Args args = new Args();
3.
boolean end = false; ; if (!this.AccountNum) throw error(“@SYS25989”);
Columbus IT Partner Russia, ApS
274
Navision Axapta 4.
args.record(this);
5.
switch (this.accountType) {
6.
case (LedgerJournalACType::Cust):
7.
formRun = new Menufunction(Identifierstr(CustOpenTrans),MenuItemType::Display).create(Args);
8. 9.
break;
10.
case (LedgerJournalACType::Vend):
11.
formRun = new Menufunction(Identifierstr(VendOpenTrans),MenuItemType::Display).create(args);
12. 13.
break;
14.
default:
15.
end = true; }
16.
if (! end) {
17.
formRun.wait();
18.
formRun.wait(); } return end; }
An explanation of the code Line 4
Generates parameters.
Line 6+10
Performs a test on the type of journal.
Line 7+11
Creates a menu item based on the result of the test.
Line 12+17
275
Identifierstr(CustOpenTrans)
identifierstr is a built-in function. It returns a string.
MenuItemType:: Displaytool
Sets the menu item group to be Display.
create(Args)
The create method adds any menu item specific parameters. These parameters are Parameters EnumTypeParameter and EnumParameter.
Actives the menu item that has just been created.
Columbus IT Partner Russia, ApS
Navision Axapta
Activating a class from a menu item If you define a method on a class with the following profile void static main (args _args) you can activate it from a menu item. One of the class methods can subsequently instantiate and run the class.
Columbus IT Partner Russia, ApS
276