This Tutorial is available to download from the downloads page, there are two versions one for the GB localised version of Dynamics NAV and the other for the worldwide version, in the download you will find the NAV objects and the tutorial in PDF format
Scenario
We have a requirement in from the Finance Director at Cronus UK, the sales team have been inputting some post codes wrongly, which has caused the company some embarrassment, after the recent upgrade from Navision version 3.70 to Dynamics, further development of the system, must have the least impact on the upgrade path, so there must be no heavy development, there are however a few objects spare in the Customers number range we may use these, any integration must be done within Dynamics, the use of external resources to create wrapper’s will not be allowed, it has been hard to maintain control of the required custom objects, as new equipment has been purchased, and new software installed, we have been tasked with finding a solution, there is only a small budget so the package should be basic, enter the postcode, and return the street, city, county, we do not need to be able to look up organisations or verify exact door numbers, the sales staff will enter these, we have decided to use AFD Postcode® to fulfil the requirement and have installed the sample software which will give us enough to test our modifications.
Analysis
There are quite a few places where we might want to have a post code lookup, Customer, Vendor, Ship to Address, Banks, and we can’t do any heavy modifications because of the cost of upgrades, the best option for us is to have the code at the form level, a little icon like we use for telephone and email, this means that we do not have to touch the C/AL Code on the post code fields.
We will need a table to act as a buffer, there can be many properties with the same post code, we will need to show these, so the sales staff can choose, how can we find out if the user has the software on their PC, we cannot add a field to the user “AFD User”, as often the users change desks, so it will need to be at the workstation level, where we need to check, so we will install the software on each PC at the default location, we can look to see if the dll exists, this is crude but it will should work for us.
We also need to think about what variances there may be, corporate and personal, then the various address types, like “the old mill”, “flat B”, “Central Tower” etc.
So we will allow up to four input fields to construct the address.
- Organisation – this will be the Company or Persons name and go into the Name fields
- Property Name – Name or a Number like Old Stable or 23 or Flat C, 34
- Property No - If we have a Property Name we will add any other numbers here
- Postcode - this has to be able to find part and whole postcodes for looking up.
We can do this project with just 3 objects and a button, and the process flow will be something like this example, for a new customer.
Input the new Customers name or organisation into the name field, in the address field the address name or number, and then we can use the address 2 field if we need it, last we will enter the post code, when we press the button icon, the Customer record gets passed into a codeunit, this loads our four fields into a temporary table, we then open a new form with this table, transfer the information from our temporary record to variables and delete or temporary record, then lookup the postcode, regardless of how many matches we find we will always get the user to confirm the details, then select an address from the list, or do another search if needed, when the user selects OK on the form, we will return the record back to the codeunit and update the customer, so we have just the three objects, table, form and codeunit we are not counting the button as an object. When we are finished we will have learned two valuable skills, running forms on temporary tables and using automation objects, we will have some objects that are almost halfway to a solution, if you want to complete the solution you will need to add error checking for the dll, and the functions for the other address records.
In this tutorial it is assumed that you have installed the evaluation copy of AFD Postcode® and that you are familiar with the following, creating and coding of forms tables and codeunits, if you are unsure how to create functions and set properties with in the Dynamics development environment, then you should start with “Tutorial 1” as this takes you through several of the steps required in this tutorial, any areas not covered in the first tutorial will be explained, in summary detail.
The Table
Using the Cronus UK database we create a table based on the standard address format, we have increased some of the field sizes to match the ADF returned field sizes, and save it as 99999 AFD Address Buffer

This table required no code as it is only used to store information on temporary bases, and there are a number of tables like this, “Invt. Posting Buffer” and “Invoice Post. Buffer”, are two of the tables used in the Sales and Purchase posting codeunits
The Form
Create a form and add these variables

AddArray: Properties – Dimensions – 4
TempAddBuffer: Properties – Temporary – Yes
AFDPcode:
|  | This automation object exposes the class methods and properties, and we will be using a selection of these in this tutorial, the methods are the functions that will find and search for the postcodes data for the user entered string. The properties class returns a results set of error codes and the address elements, there are a number of other elements like the grid references, and we will be returning the STD code as well as our address. |
Layout your form as below:

The Address fields: Properties - Editable – No
Table box Properties - Editable – No and Name - Tablebox
Address count: Properties - SourceExpr - TempAddBuffer.COUNTAPPROX
Save the form.
Coding the form
View the forms code and enter the following:
Form - OnFindRecord(Which : Text[1024]) : Boolean
TempAddBuffer := Rec;
IF NOT TempAddBuffer.FIND(Which) THEN
EXIT(FALSE);
Rec := TempAddBuffer;
EXIT(TRUE);
For the OnNextRecord section add a local variable, select the section, then View the C/AL Locals add the variable CurrentSteps type Integer
Form - OnNextRecord(Steps : Integer) : Integer
TempAddBuffer := Rec;
CurrentSteps := TempAddBuffer.NEXT(Steps);
IF CurrentSteps <> 0 THEN
Rec := TempAddBuffer;
EXIT(CurrentSteps);
I found the code structure on the navigate form 344, this uses a temporary record to display results, and our form is the same and uses some of this code.
Next we will create three functions,
This function just checks for a numeric value.
Name = IsNumeric – Parameter = Value Text 60 – Return Value = Boolean Variable – AddProperty = Integer
IsNumeric(Value : Text[60]) : Boolean
EXIT(EVALUATE(AddProperty,Value));
Our second function updates the form based on the returned record set, if we have none or one matching record then we do not need to show our table box, if we have many records then the user can choose, which record they want to use.
Name = UpdateAfterFindRecords – Parameter = None – Return Value = None
Properties – Local - Yes
UpdateAfterFindRecords()
RecExists := TempAddBuffer.FIND('-');
CurrForm.UPDATE(FALSE);
IF RecExists THEN BEGIN
IF TempAddBuffer.COUNTAPPROX > 1 THEN BEGIN
CurrForm.TableBox.VISIBLE(TRUE);
CurrForm.Address.ACTIVATE;
CurrForm.UPDATE(FALSE);
END ELSE
CurrForm.TableBox.VISIBLE(FALSE);
END ELSE
CurrForm.TableBox.VISIBLE(FALSE);
Our Last function does all the work finds the records and updates the form, and the way it works is it tries to find a match for the input string, failing to find a match it then moves on to search and returns a list of addresses.
Name = SearchPostCode – Parameter = None – Return Value = Boolean
Properties – Local - Yes
SearchPostCode() : Boolean
//Checks if there is a string to lookup
IF AddArray[4] = '' THEN
EXIT;
//If the automation object is not initialized then create it
IF ISCLEAR(AFDPcode) THEN
CREATE(AFDPcode);
//Initialize our variables
RecNo := 0;
TempAddBuffer.DELETEALL;
//Try to find a match by postcode
AFDPcode.FastFind(AddArray[4]);
//If it has succeeded then a 0 is returned if it failed then search
IF AFDPcode.Result <> 0 THEN
AFDPcode.DoSearch();
//If we have one or more matches add them to our table
IF AFDPcode.Result = 0 THEN BEGIN
REPEAT
RecNo := RecNo + 1;
TempAddBuffer.INIT;
TempAddBuffer."No." := RecNo;
TempAddBuffer.Name := AddArray[1];
TempAddBuffer.Address := AFDPcode.Street;
TempAddBuffer."Address 2" := AFDPcode.Locality;
TempAddBuffer.City := AFDPcode.Town;
TempAddBuffer.County := AFDPcode.County;
TempAddBuffer."Post Code" := AFDPcode.Postcode;
TempAddBuffer.STD := AFDPcode.STDCode;
//If user has Input property Name and Property Number
IF (AddArray[2]<>'')AND(AddArray[3]<>'')THEN BEGIN
IF ((STRLEN(TempAddBuffer.Address))+
(STRLEN(AddArray[3]))+2)< 50 THEN BEGIN
IF IsNumeric(COPYSTR(AddArray[3],STRLEN(AddArray[3])))THEN
TempAddBuffer."Address 2" := STRSUBSTNO('%1 %2',AddArray[3],TempAddBuffer.Address)
ELSE
TempAddBuffer."Address 2" := STRSUBSTNO('%1, %2',AddArray[3],TempAddBuffer.Address);
TempAddBuffer.Address := AddArray[2];
END ELSE BEGIN
TempAddBuffer."Name 2" := AddArray[2];
TempAddBuffer."Address 2" := TempAddBuffer.Address;
TempAddBuffer.Address := AddArray[3];
END;
END;
//If user has Input Property Number only
IF (AddArray[2]<>'')AND(AddArray[3]='')THEN BEGIN
IF ((STRLEN(TempAddBuffer.Address))+
(STRLEN(AddArray[2]))+2)< 50 THEN BEGIN
IF IsNumeric(COPYSTR(AddArray[2],STRLEN(AddArray[2])))THEN
TempAddBuffer.Address := STRSUBSTNO('%1 %2',AddArray[2],TempAddBuffer.Address)
ELSE
TempAddBuffer.Address := STRSUBSTNO('%1, %2',AddArray[2],TempAddBuffer.Address);
END ELSE BEGIN
TempAddBuffer."Address 2" := TempAddBuffer.Address;
TempAddBuffer.Address := AddArray[2];
END;
END;
//Note: that here we set a maximum retrieval of 100 records
TempAddBuffer.INSERT;
UNTIL (AFDPcode.GetNextRecord < 0) OR (RecNo = 1000)
END;
Rec := TempAddBuffer;
UpdateAfterFindRecords;
This deals with the different input scenarios, we will test them later.
This code can now be added
Form - OnOpenForm()
//f we have passed in a tempory record use the values to search
IF FIND('-')THEN BEGIN
AddArray[1]:= Name;
AddArray[2]:= Address;
AddArray[3]:= "Address 2";
AddArray[4]:= "Post Code";
//Now we can delete our calling record
DELETEALL;
//Find our record set and insert it
SearchPostCode;
END;
//Update our form
UpdateAfterFindRecords;
Code for the Search button:
Search - OnPush()
SearchPostCode;
Codeunit
This will be similar to the Format Address codeunit, except that instead of getting an address array back we get a record with the address added.
Create a new Codeunit and add a variable tempAddBuffer – Record - Address Buffer
Add a new function Name - findAddress with these parameters and variable and the following Properties - Local –Yes


Add another function CustFindAddress
Parmeter - Var – Customer Record - Customer
This function receives the Customer record and passes it’s fields to findAddress
custFindAddress(VAR Customer : Record Customer)
WITH Customer DO BEGIN
// Not a Local Customer so Get Out
IF Customer."Country Code" <> '' THEN
EXIT;
findAddress(Name,"Name 2",Address,"Address 2",City,County,"Post Code");
EXIT;
END;
findAddress(VAR Name : Text[50];VAR Name2 : Text[50];VAR Address : Text[50];VAR Address2 : Text[50];VAR City : Text[30];VAR County : Te
IF postCode = '' THEN
EXIT;
tempAddBuffer.DELETEALL;
//Add the fields here to pass to our form to populate the AddArray
tempAddBuffer.INIT;
tempAddBuffer."No." := RecNo;
tempAddBuffer.Name := Name;
tempAddBuffer.Address := Address;
tempAddBuffer."Address 2" := Address2;
tempAddBuffer."Post Code" := postCode;
tempAddBuffer.INSERT;
//Run our form with the temporary record transfer the fields if selected
IF FORM.RUNMODAL(FORM::"AFD Postcode",tempAddBuffer) = ACTION::LookupOK THEN BEGIN
Name := tempAddBuffer.Name;
Name2 := tempAddBuffer."Name 2";
Address := tempAddBuffer.Address;
Address2 := tempAddBuffer."Address 2";
City := tempAddBuffer.City;
County := tempAddBuffer.County;
postCode := tempAddBuffer."Post Code";
END;
Save your work and we are nearly done
Last object to change is the Customer Card form 21, here we are going to add a button to do a search the for the post code based on our input, we need to add a new button just next to the post code field, with the lookup search icon


View the code for the button and add a
Local variable AFDPostcodeMgnt – Codeunit – AFD Postcode Management
Now all we need is the following code
- OnPush()
// Cronus 21/05/2006 Adeptris
AFDPostcodeMgnt.custFindAddress(Rec);
CurrForm.UPDATE;
So let’s look at the results, AFD Evaluation copy has a limited amount of data which does not expire, so we can test our different scenarios
We have company Name – Premises Name and a number

Result

If we have only the house number then it is input into Address field

300 Record matches with the partial postcode of B5, we could have a maximum 1000
#
That’s it for our different input scenarios

Conclusion
This is not a ready to use solution, to develop it further; you need to add the different functions in the AFD Postcode Management codeunit for Vendor, Bank, Ship-To etc:
On our form you need code to see if AFD is installed it can be as simple as
IF NOT EXISTS(c:\Windows\System32\postcode.dll)THEN
EXIT;
For the AFD Error trapping a variable ErrorText and a box on the form, then in the code just add the following after the calls to the dll.
ErrorText := AFDPcode.ResultText;
The best way to learn Dynamics coding is to get in and have a look, this solution has used 3 objects, and the upgrade path is simple, drop the button back on the forms.
Please use the feedback section on my website www.adeptris.com and let me know how you found this tutorial, so I cam make the next one better.

'AFD', 'AFD POSTCODE', 'ZIPADDRESS', and the Flying Envelope Device are Registered Trade Marks of ZipAddress Ltd. 'ROBOT' Technology is protected by Patent No GB2369699.
All other trade marks acknowledged.
AFD Products are subject to a License Agreement and include a data license for one computer, renewable annually
DOCUMENT COPYRIGHT
The authors that contributed to this Adeptris.com tutorial are delighted to share their work with others.
Please recognize the hard work and integrity of our contributing authors by giving them appropriate credit and citing references on any material that you share with others.
Permission is granted to reproduce this material in whole or in part for educational purposes only (not-for-profit beyond cost of reproduction) provided that the authors receive acknowledgement and this notice is included:
Any additions or changes to these materials must be pre-approved by the author.
NOTE: On most Adeptris.com documents Author Access information is placed at the bottom of the document