Introduction

The AFD Common API provides full access to the AFD API for all our products. The API is easy to use and quick to implement, while balancing that with providing full flexibility. This enables you to rapidly develop using the API with practically any development environment to provide the data that you require. All AFD products provide rapid lookup and search functionality allowing you to implement address management solutions and provide bank data, account and card validation.

Our address management products are fully interchangeable with the Common API, meaning that you can include the name and all address fields in your integration even if you are only using our lowest level Postcode product. Your integration will then function fully with our Postcode Plus or Names & Numbers product should you, or your customer, wish to upgrade in the future. Similarly if you only develop for one product now, it’s easy to add fields and features from another later without having to learn a whole new API.

To make life as easy as possible, the AFD Common API comes with a Wizard which will generate sample projects and code for the major development environments. The AFD Common API is also backed up by our free customer support services. You can visit our website at www.afd.co.uk/support for full developer support with using our API.

Getting Started

We recommend that for the most rapid development and to help you know where to start that you use our API Wizard to generate a sample project for your development environment. If your environment is not one that is listed, then select one that is closest to your own and use that as a basis for your coding. By looking at a sample project you can get a look and feel for how the API works and what you can do with it and you can easily copy and paste the code from that into your own and adapt it to meet your needs. Our sample projects work in the way that your own application is most likely to work, but also keep code to an absolute minimum, whilst being well commented, so that you can transfer the code with ease. The API Wizard also provides the code to go into a module or class in your application with all our API declarations and constants included which you can copy and paste into your own application. The code for lookup and search functionality is also provided and can be similarly copied and pasted.

Standard API

General Declarations

Type or Structure

All code calling the Common API will need to include a module, class, or header and cpp file (depending on the environment) which includes the declarations required to use the AFD Common API. This file can be included in any project and contains all you need to easily use the full functionality of the API in accordance with your needs.

This code will start with a type or structure declaration which contains all the fields for the product type that you are integrating. This will take account of options you may have selected, for example the address format. By providing all available fields you can easily see the data which may be available and take advantage of it. You should always note that not all fields may return data for all underlying products and not all fields are searchable. For a list of the fields available in each product and to find out which ones are searchable please refer to the appropriate appendix:

  • Appendix A – Address Management Fields
  • Appendix B – BankFinder Fields
  • Appendix C – Nearest Fields

While we would recommend that you keep all fields present, should you wish to thin this out, you can remove any unwanted fields, as long as you also remove them from the field specification string described below.

VB Type returning only basic Address fields and fields necessary for lookup and result retrieval:
Type afdAddressData
    Lookup As String * 255
    Name As String * 120
    Organisation As String * 120
    Property As String * 120
    Street As String * 120
    Locality As String * 70
    Town As String * 30 
    Postcode As String * 10
    PostcodeFrom As String * 8 
    Key As String * 255
    List As String * 512
End Type
C++ Structure returning only basic Address fields and fields necessary for lookup and result retrieval:
struct afdAddressData {
    char Lookup[256];
    char Name[121];
    char Organisation[121];
    char Property[121];
    char Street[121];
    char Locality[71];
    char Town[31];
    char Postcode[11];
    char PostcodeFrom[9];
    char Key[256];
    char List[513];
    afdAddressData(){     // constructor - zero the contents
        clear();
    }
    void clear(){
        memset(this,'\0',sizeof(*this));
    }
};
Note that the C++ declaration has fields one character larger than the VB one as we are allowing for the addition of a null terminator.  The C++ structure also has code to clear the structure negating the need for an additional method to do this.

Function Declaration

Next comes the function declaration which is used to perform all operations with the Common API. This is the AFDData function, found in the afddata.dll (or afddata64.dll for 64-bit systems). It has the following parameters:

DataName (String)
Operation (Long)
tData (Any)
    fields to use to lookup and return results.

The function returns a long which is the result code. This will be >= 0 if the function is successful, or < 0 in the case of an error (constants for this are described below).

Example VB Declaration for AFDData:
Public Declare Function AFDData Lib "afddata.dll" (ByVal dataName As String, ByVal operation As Long, tData As Any) As Long
Example C++ Declaration for AFDData:
long __stdcall AFDData(char* dataName, long operation, char* tData);
typedef long(__stdcall *AFDDATA)(char* dataName, long operation, char* tData);

Field Specification String

A field specification string is described next, this will vary between the different product types (Address Management, BankFinder and Nearest). Its purpose is to tell the Common API the product type in use and the fields required as well as any additional options. It is a string in the following format:

{Data Name}@{Options}<{Refiner Options}>{{International}}@{Field List}

{Data Name} will be one of the following:

Address Address Management Products
BankFinder AFD BankFinder
Nearest* Nearest Integration
List Functions to list the alias localities for any address as well as retrieving lists of possible field values (Names & Numbers and TraceMaster only).
Grids Grid Reference related utility functions
Email Email utility function
String - Deprecated String utility functions

*With Nearest this will be followed by your database details in the following format:

Nearest:{DBType}:{DBName}:{UID}:{PWD}:{SQL}:{Primary}

Where:

DBType The type of database, O=ODBC, A=Access, P=Paradox, X=Xbase
DBName The DSN or database file name (should contain > in place of :)
UID Any user name needed to connect to the database (ODBC Only)
PWD Any password needed to connect to the database (ODBC Only)
SQL The SQL string to use to query the data (N/A for FoxPro/Xbase)
Primary The Primary Key field

{Options} - One or more of the following options can be used as required:

  • U – Specifies that the structure passed is in Unicode (Wide Bytes)
  • L – Specifies that list items should not contain a Tab. Tabs are useful as they help align results correctly with each other, however some environments have list boxes which do not support these and so this option allows them to be omitted.
  • X – Specifies that Null Terminators should be used rather than space padded values (particularly useful in languages such as C/C++)
  • F – Specifies that Individual Fields will be retrieved from the Common API rather than a structure – see Appendix I for more information.
  • G - Specifies that approximate grid references for the locality or town of the address will be supplied for any location which does not contain a grid reference for that postcode (for example some non-geographical addresses, Isle of Man and Channel Islands etc.).
  • R - Specifies that Royal Mail Postzon grid references are used in-preference to GeoRef grid references.

{Field List} – A list of fields and there lengths to retrieve. (See Appendix A, B or C as appropriate for a list of the possible fields). These are each specified in the following format:

{Field Name 1}:{Field Length 1}@...{Field Name n}:{Field Length n}

Where

  • {Field Name x} – Specifies the name of the field

  • {Field Length x} – Specifies the length of the field

Example:

Example VB Declaration for the Field Specification string matching the VB type previously given:
Public Const afdFieldSpec = "Address@@Lookup:255@Name:120@Organisation:120@Property:120@Street:120@Locality:70@Town:30@Postcode:10@PostcodeFrom:8@Key:255@List:512"
Example C++ Declaration for the Field Specification string matching the C++ structure previously given:
static char afdFieldSpec[2048] = "Address@LX@Lookup:256@Name:121@Organisation:121@Property:121@Street:121@Locality:71@Town:31@Postcode:11@PostcodeFrom:9@Key:256@List:513";

Note that when using Nearest the GBGridE, GBGridN, and List fields also specify the name of the field in your database table to use for that field in pointed brackets, e.g.

GBGridE<GridE>:10@GBGridN<GridN>:10@List<Miles, Title>:10

{Refiner Options}

Refiner API users can also add a set of advanced cleaning options, if they are required, to the end of the options portion of the field specification string, enclosing them in pointed brackets, e.g. <0AS>>

The options supported are as follows: (Please see the main Refiner manual for more detail regarding each of these options)

  • 0 - Specifies the default cleaning mode where the address is fully cleaned
  • 1 - Specifies that the postcode should be verified only
  • 2 – Specifies that only full matches should be returned
  • 3 – Uses Attach Mode only (fields are returned based on the postcode)
  • N – Use non-separated fields (Useful for databases where fields are not seperated, e.g. the street and town are entered on the same line with no comma etc. between them)
  • A – No Ambiguous Matches (do not return list of addresses to choose from if the address cannot be uniquely matched)
  • S – No Suggested Matches (do not return a suggested match along with the original address if the address cannot be matched but there is a possible unique match)
  • U – Assume the Postcode is correct (this option allows less reliable matching on the assumption that the postcode is correct if the address cannot otherwise be verified. In Attach mode this allows a property and postcode to be matched)
  • T – Give Ambiguous Matches in Preference to Street Level (if an address cannot be uniquely matched to an individual property the original property information is normally retained, this option gives the ambiguous addresses to choose from instead).
  • P – Match PO Box Last (Some PO Box addresses contain some Street address information too even though the address is meant for a PO Box. If you wish Refiner to try and match it to a street address first then select this option).
  • L – Retain Alias Localities (If the address is matched using an alias locality this will be retained in the address – Alias Localities are not normally retained as they are not required for the address to be deliverable).
  • O – Do not move data to Organisation (Normally Refiner will put additional address data for street level only matches in the property field unless they look like an Organisation or there is already a property. Specifying this option ensures Refiner never returns such data in the Organisation field - useful if you are not going to use the Organisation field returned).
  • W – Do not use the Default DPS (if an address is not matched to a full Delivery Point Record, a default of 9Z is assigned which can still be used for printing bar codes etc., if you do not wish this to be used then use this option)
  • F – Do not use Field Placement (By default if an address cannot be matched Refiner attempts to format the address correctly on return, if you would rather it was left “as-is” then use this option.

Function Type Constants

Next a set of constants are defined which specify the lookup and search operations available. The DLL supports the following operations:

Constant Value Description
AFD_POSTCODE_LOOKUP 0 Carries out a standard postcode (or zipcode) lookup from the data specified in the Lookup field. (Not BankFinder)
AFD_POSTCODE_PROPERTY_LOOKUP 1 Carries out a lookup based on a postcode or combination of property name/number and a postcode. (Address Management Only)
AFD_MULTIPLE_FASTFIND_LOOKUP 1 Like a FastFind lookup for Nearest but where a specified locality or town matches multiple locations the user is presented with a list to choose from. (Nearest Only)
AFD_FASTFIND_LOOKUP 2 Full fast-find functionality, allowing either a postcode or an address portion to be entered to find the address.
AFD_SEARCH 3 Reverse search, set fields to specify reverse search criteria. (See Appendix A for details of which fields are searchable in which products). Fields not searchable will be ignored if specified.
AFD_RETRIEVE_RECORD 4 Retrieves a previous record from a lookup/search. Useful when you add items to a list box, using the List field and then wish to retrieve the item the user clicks on. Set the Key field to use this operation with the value of the Key field that was returned from the original lookup/search for the record you want.
AFD_ACCOUNT_VALIDATE 5 Used to validate a supplied sortcode and account number (BankFinder only)
AFD_CARD_VALIDATE 6 Used to validate a supplied card number and optional expiry date (BankFinder only)
AFD_CLEAN 7 Used to clean an address (requires a Refiner API license)
AFD_GET_NEXT 32 Should be specified with any of the lookup or search operations for subsequent calls to obtain the next matching result (END_OF_SEARCH,-6, will be returned if there are no further results to return).
AFD_LIST_BOX 64 Specify with any of the lookup/search operations if you wish the DLL to display a listbox for you rather than having to use your own in the case of multiple results. Calls to AFD_GET_NEXT are not needed in this case as the API will only return the result the user selects.
AFD_SHOW_ERROR 128 Set this option if you require the DLL to display any error message (e.g. if no results are found) to the user itself.
Example VB Constant Declarations:
Public Const AFD_POSTCODE_LOOKUP = 0
Public Const AFD_POSTCODE_PROPERTY_LOOKUP = 1
Public Const AFD_MULTIPLE_FASTFIND_LOOKUP = 1
Public Const AFD_FASTFIND_LOOKUP = 2
Public Const AFD_SEARCH = 3
Public Const AFD_RETRIEVE_RECORD = 4
Public Const AFD_ACCOUNT_VALIDATE = 5
Public Const AFD_CARD_VALIDATE = 6
Public Const AFD_CLEAN = 7
Public Const AFD_GET_NEXT = 32
Public Const AFD_LIST_BOX = 64
Public Const AFD_SHOW_ERROR = 128
Example C++ Constant Declarations:
// Function Type Constants
#define AFD_POSTCODE_LOOKUP 0
#define AFD_POSTCODE_PROPERTY_LOOKUP 1
#define AFD_MULTIPLE_FASTFIND_LOOKUP 1
#define AFD_FASTFIND_LOOKUP 2
#define AFD_SEARCH 3
#define AFD_RETRIEVE_RECORD 4
#define AFD_ACCOUNT_VALIDATE 5
#define AFD_CARD_VALIDATE 6
#define AFD_CLEAN 7
#define AFD_GET_NEXT 32
#define AFD_LIST_BOX 64
#define AFD_SHOW_ERROR 128

Skip Constants – UK Address Management Only

For address management products skip constants are provided next which can be added to the operation parameter for calls to the AFDData function to skip records, for example to return the first record on a postcode only.

The available options are as follows:

Constant Value Description
AFD_NO_SKIP 0 Default – all matching records are returned
AFD_ADDRESS_SKIP 512 Only the first record per address (e.g. first listed resident) is returned. Only has any effect in Names & Numbers.
AFD_POSTCODE_SKIP 1024 Only the first record per postcode is returned.
AFD_SECTOR_SKIP 1536 Only the first record in each postcode sector is returned. (A postcode sector is the portion of the postcode before the space plus the first digit after it, e.g. B11 1 is a sector).
AFD_OUTCODE_SKIP 2048 Only the first record per Outcode is returned. The Outcode is the portion of the postcode before the space, e.g. B11.
AFD_POST_TOWN_SKIP 2560 Only the first record per Post Town, e.g. Birmingham is returned.
AFD_POSTCODE_AREA_SKIP 3072 Only the first record per Postcode Area is returned. A Postcode Area is the letters at the start of the postcode, e.g. B11 1AA is in Postcode Area B, IM8 is in Postcode Area IM.
Example VB Constant Declarations:
Public Const AFD_NO_SKIP = 0
Public Const AFD_ADDRESS_SKIP = 512
Public Const AFD_POSTCODE_SKIP = 1024
Public Const AFD_SECTOR_SKIP = 1536
Public Const AFD_OUTCODE_SKIP = 2048
Public Const AFD_POST_TOWN_SKIP = 2560
Public Const AFD_POSTCODE_AREA_SKIP = 3072
Example C++ Constant Declarations:
// Function Type Constants
#define AFD_NO_SKIP 0
#define AFD_ADDRESS_SKIP 512
#define AFD_POSTCODE_SKIP 1024
#define AFD_SECTOR_SKIP 1536
#define AFD_OUTCODE_SKIP 2048
#define AFD_POST_TOWN_SKIP 2560
#define AFD_POSTCODE_AREA_SKIP 3072

Clearing System Constants – BankFinder Only

The clearing system constants allows you to restrict the results that come back to those which are solely on the UK (BACS) Clearing System or the Irish (IPSO Clearing System), or both systems. Obviously if you are only able to clear through the UK clearing system you should specify this to return results for the UK system only. This constant should be added to the operation parameter for calls to the AFDData function.

The available options are as follows:

Constant Value Description
AFD_BOTH_CLEARINGS 0 Default – all matching records are returned
AFD_UK_CLEARING 512 Only records on the UK (BACS) Clearing System are returned
AFD_IRISH_CLEARING 1024 Only records on the Irish (IPSO) Clearing System are returned
Example VB Constant Declarations:
Public Const AFD_BOTH_CLEARINGS = 0
Public Const AFD_UK_CLEARING = 512
Public Const AFD_IRISH_CLEARING = 1024
Example C++ Constant Declarations:
// Function Type Constants
#define AFD_BOTH_CLEARINGS 0
#define AFD_UK_CLEARING 512
#define AFD_IRISH_CLEARING 1024

Success Code Constants

These specify the possible success codes returned from any API function:

Constant Value Description
AFD_RECORD_BREAK 0 The search/lookup has not completed but may take some time and so is returning to give the user the option to cancel a long search.
AFD_SUCCESS 1 The function was successful and a matching record has been returned.
AFDSUCCESS
NO_VALIDATION 2 This applies only to Bankfinder account number validation and indicates that the function was successful and the account number should be taken as valid. However, as account numbers on this sortcode cannot be validated you may wish to double check it is correct.

Error Code Constants

These specify the possible errors returned from any API function:

Constant Value Description
AFD_ ERROR_INVALID_FIELDSPEC -1 The field specification string specified is invalid. This shouldn’t be returned under normal circumstances.
AFD_ ERROR_NO_RESULTS_FOUND -2 No records matching your lookup or search criteria were found.
AFD_ERRORINVALID
... _RECORD_NUMBER -3 The record number provided (e.g. when re-retrieving an item from a list box) is invalid.
AFD_ERROR_OPENING_FILES -4 An error occurred attempting to open the AFD data files. Check they are correctly installed.
AFD_ERROR_FILE_READ -5 An error occurred reading the data. Likely to be due to corrupt data so software may need to be re-installed.
AFD_ERROR_END_OF_SEARCH -6 End of Search (when the last result has already been called off – indicates there are no more results to return).
AFD_DATA_LICENSE_ERROR -7 Indicates there is an error with the product registration. Normally due to it having expired. Run the Welcome program to re-register the software.
AFD_ERRORCONFLICTING
.. _SEARCH_PARAMETERS -8 Occurs if you attempt to search for a Name and Organisation at the same time. Also occurs with Postcode Plus if the UDPRN field is searched for at the same time as any other field.
AFD_USER_CANCELLED -99 Indicates that the user clicked the cancel button if the DLL internal list box was used.

The following fields apply to BankFinder validation operations only

AFD_ERROR_SORTCODE_NOT_FOUND -12 The sort code specified for an account number validation does not exist.
AFD_ERROR_INVALID_SORTCODE -13 The sortcode specified for an account number validation is invalid.
AFD_ERROR_INVALID_ACCOUNT_NUMBER -14 The account number specified for an account number validation is invalid.
AFD_ERROR_INVALID_ROLL_NUMBER -21 The sort code and account number given are for a building society account which also requires a roll number for account credits. No roll number has been supplied or is incorrect for this building society.
AFD_ERROR_INVALID_IBAN -22 The International Bank Account Number provided is in an invalid format
AFD_ERROR_UNRECOGNISED_COUNTRY -23 The IBAN provided contains a country that is not recognised as valid
AFD_ERROR_IBAN_MISMATCH -24 Both an IBAN and Account Number was provided and these details do not match.
AFD_ERROR_INVALID_EXPIRY -15 The expiry date specified for a card validation is invalid.
AFD_ERROR_CARD_EXPIRED -16 The card has expired
AFD_ERROR_INVALID_CARD_NUMBER -18 The card number specified for a card validation is invalid.
AFD_ERROR_VISA_ATM_ONLY -19 The card number specified is a Visa card which can be used in an ATM only.
AFD_ERRORUNRECOGNISED
.. _CARD_TYPE -20 While the card number appears to be a valid one, the card is not of any of the known types and is therefore unlikely to be acceptable for payment.
Example VB Constant Declarations:
Public Const AFD_ERROR_INVALID_FIELDSPEC = -1
Public Const AFD_ERROR_NO_RESULTS_FOUND = -2
Public Const AFD_ERROR_INVALID_RECORD_NUMBER = -3
Public Const AFD_ERROR_OPENING_FILES = -4
Public Const AFD_ERROR_FILE_READ = -5
Public Const AFD_ERROR_END_OF_SEARCH = -6
Public Const AFD_ERROR_DATA_LICENSE_ERROR = -7
Public Const AFD_ERROR_CONFLICTING_SEARCH_PARAMETERS = -8
Public Const AFD_USER_CANCELLED = -99
Example C++ Constant Declarations:
#define AFD_ERROR_INVALID_FIELDSPEC -1
#define AFD_ERROR_NO_RESULTS_FOUND -2
#define AFD_ERROR_INVALID_RECORD_NUMBER -3
#define AFD_ERROR_OPENING_FILES -4
#define AFD_ERROR_FILE_READ -5
#define AFD_ERROR_END_OF_SEARCH -6
#define AFD_ERROR_DATA_LICENSE_ERROR -7
#define AFD_ERROR_CONFLICTING_SEARCH_PARAMETERS -8
#define AFD_USER_CANCELLED -99

Refiner Status Code Constants

Refiner clean operations return a cleaning constant >= 100 or <= -100 which indicates the status of the cleaning operation. These constants are as follows:

Constant Value Description
AFD_ REFINER_PAF_MATCH 100 Address verified from Postcode and matches a record in PAF identically.
AFD_REFINER_POSTCODE_MATCH 200 Address verified from the Postcode and matches a record in PAF with some correction.
AFD_REFINER_CHANGED_POSTCODE 201 Address verified from a postcode which was substituted due to a Royal Mail recoding and now matches a record in PAF.
AFD_REFINER_ASSUMEPOSTCODE
CORRECT 202 Match was made with the Assume Postcode Correct option enabled only and the address could only be verified on the assumption that the postcode was correct.
AFD_REFINER_ASSUMECHANGED
POSTCODE_CORRECT 203 Match was made with the Assume Postcode Correct option enabled and the address could only be verified on the assumption that the postcode was correct after a Royal Mail recoding change.
AFD_REFINER_ASSUMEPOSTCODE
ADDED_PROPERTY 204 Match was made with the Assume Postcode Correct option enabled and the address could only be verified on the assumption that the postcode was correct and the property was added in.
AFD_REFINER_ASSUMECHANGED
POSTCODE_ADDED_PROPERTY 205 Match was made with the Assume Postcode Correct option enabled and the address could only be verified on the assumption that the postcode was correct after a Royal Mail recoding change and the property was added in.
AFD_REFINER_FULL_DPS_MATCH 300 Address verified to PAF with some correction, looking wider than just the specified Postcode.
AFD_REFINER_FULL_DPS_MATCHNO
ORG 301 Address verified to PAF with ambiguous organisation which was not in the original address so has been omitted.
AFD_REFINER_FULL_DPSMATCH
LIMITED 302 Match was made with the Assume Postcode Correct option enabled and the Address was verified to PAF to a more limited degree.
AFD_REFINER_STREET_MATCH 400 Address verified to Street Level, i.e. the property was not on PAF, but a unique match to the street was identified on a single postcode.
AFD_REFINER_NO_MATCH_FOUND -101 No Match Found - Refiner has been unable to match this record.
AFD_REFINER_AMBIGUOUS_POSTCODE -102 Ambiguous Postcode Match - Refiner has matched this record to Street Level but cannot determine which is the correct Postcode and so has presented each of the possibilities.
AFD_REFINER_SUGGEST_RECORD -103 Suggested Match. Refiner has given a possibility that this address could match to as it is unique but there was not enough to be certain of a correct match.
AFD_REFINER_AMBIGUOUS_MATCH -104 Ambiguous Match. Refiner has given several possibilities that this address could match to.
AFD_REFINERINTERNATIONAL
ADDRESS -105 This address was detected as being an International Address and therefore cannot be cleaned as data is only present for cleaning UK, Channel Isles and Isle of Man addresses.
AFD_REFINER_NO_RECORD_DATA -106 No record data was supplied. Refiner cannot clean this address as no address data was given.
Example VB Constant Declarations:
Public Const AFD_REFINER_PAF_MATCH = 100
Public Const AFD_REFINER_POSTCODE_MATCH = 200
Public Const AFD_REFINER_CHANGED_POSTCODE = 201
Public Const AFD_REFINER_ASSUME_POSTCODE_CORRECT = 202
Public Const AFD_REFINER_ASSUME_CHANGED_POSTCODE_CORRECT = 203
Public Const AFD_REFINER_ASSUME_POSTCODE_ADDED_PROPERTY = 204
Public Const AFD_REFINER_ASSUME_CHANGED_POSTCODE_ADDED_PROPERTY = 205
Public Const AFD_REFINER_FULL_DPS_MATCH = 300
Public Const AFD_REFINER_FULL_DPS_MATCH_NO_ORG = 301
Public Const AFD_REFINER_FULL_DPS_MATCH_LIMITED = 302
Public Const AFD_REFINER_STREET_MATCH = 400
Public Const AFD_REFINER_NO_MATCH_FOUND = -101
Public Const AFD_REFINER_AMBIGUOUS_POSTCODE = -102
Public Const AFD_REFINER_SUGGEST_RECORD = -103
Public Const AFD_REFINER_AMBIGUOUS_MATCH = -104
Public Const AFD_REFINER_INTERNATIONAL_ADDRESS = -105
Public Const AFD_REFINER_NO_RECORD_DATA = -106
Example C++ Constant Declarations:
#define AFD_REFINER_PAF_MATCH 100
#define AFD_REFINER_POSTCODE_MATCH 200
#define AFD_REFINER_CHANGED_POSTCODE 201
#define AFD_REFINER_ASSUME_POSTCODE_CORRECT 202
#define AFD_REFINER_ASSUME_CHANGED_POSTCODE_CORRECT 203
#define AFD_REFINER_ASSUME_POSTCODE_ADDED_PROPERTY 204
#define AFD_REFINER_ASSUME_CHANGED_POSTCODE_ADDED_PROPERTY 205
#define AFD_REFINER_FULL_DPS_MATCH 300
#define AFD_REFINER_FULL_DPS_MATCH_NO_ORG 301
#define AFD_REFINER_FULL_DPS_MATCH_LIMITED 302
#define AFD_REFINER_STREET_MATCH 400
#define AFD_REFINER_NO_MATCH_FOUND -101
#define AFD_REFINER_AMBIGUOUS_POSTCODE -102
#define AFD_REFINER_SUGGEST_RECORD -103
#define AFD_REFINER_AMBIGUOUS_MATCH -104
#define AFD_REFINER_INTERNATIONAL_ADDRESS -105
#define AFD_REFINER_NO_RECORD_DATA -106

AFDErrorText Function

This is a helper function that the Wizard will generate, which will convert an error code (return value less than zero) to a message which explains the error. This makes it easy to simply use this function to obtain text to display in the case of an error. Text is included for each of the error codes listed in the Error Code Constants section above.

AFD RefinerCleaningText Function

This is a helper function that the Wizard will generate, which will convert a return code from the Common API when using the AFD_CLEAN option to a message which explains the error. This makes it easy to simply use this function to obtain text to display in the case of an error. Text is included for each of the error codes listed in the Refiner Status Code Constants section above. Please note that this function is only useful if you are using Refiner API functionality with the appropriate license.

Clear Function

The wizard also generates a helper function to clear the AFD Type or Structure, which you should call prior to carrying out an operation using the API. This is either called ClearAFDAddressData or ClearAFDBankData for Address Management products and BankFinder respectively. The differing names allow these to co-exist in the same module if desired when using both products.

Note: This does not apply to C++ code as they include a clear function in the structure declaration itself.

afdInitDLL

Where necessary, e.g. in C++ a function is also included which will load the DLL and locate the AFDData function:

List Functions – Address Management Only

With Postcode Plus, Names & Numbers and TraceMaster products you can obtain the alias localities for any address or postcode if required. These are non-postally required localities held by Royal Mail which can or may be included on an address if desired. An example of this would be including Wimbledon for an address in London. You should note that these are stored at postal sector level (e.g. SW19 1) and there are often multiple entries for an address so a locality being returned does not mean it is necessarily the best one for the particular address you are viewing.

For Names & Numbers and TraceMaster products only it is also possible to obtain a list of possible values for most fields, e.g. all the Mailsort codes present, business descriptions, etc. You can also specify the start value of the field, e.g. return all surnames present starting with “Smith”.

When using International data you can also use the List functions to obtain a list of all available countries (names or ISO codes).

To use these functions an AFDListData structure should be declared containing the following fields:

Field Name Length Description Lookup 255 In the case of retrieving an alias locality this should be the postcode or key of the address to obtain the alias localities for.

In the case of Names & Numbers or TraceMaster lists this should either be blank to retrieve the full list, or contain the value you wish entries to start with. List 255 Each matching locality name or list entry is returned, in turn, into this field. Product 40 Optional: Would indicate the product used if desired.

A afdListFieldSpec string should also be declared and works as described in section 4.1.3.

The constants you can use with this function to specify the list operation you wish to perform are as follows:

Constant Value Description
AFD_LIST_ALIAS_LOCALITY 0 Returns all alias localities for the sector that the specified postcode or key resides in.
The following are applicable when using International data only:
AFD_LIST_COUNTRY_ISO 3 Will return the ISO codes of all available countries.
AFD_LIST_COUNTRY 4 Will return the names of all available countries.
The following are applicable to Names & Numbers and TraceMaster Products Only:
These all return a list of all entries of the data item specified in the data.
Setting the lookup parameter will restrict matches to only those items starting with the specified string.
AFD_LIST_FORENAME 10 Returns Forenames (first names).
AFD_LIST_SURNAME 11 Returns Surnames
AFD_LIST_ORGANISATION 12 Returns Organisations
AFD_LIST_PROPERTY 13 Returns Properties
AFD_LIST_STREET 14 Returns Streets
AFD_LIST_LOCALITY 15 Returns Localities
AFD_LIST_TOWN 16 Returns Postal Towns
AFD_LIST_COUNTY 17 Returns Counties (This includes Postal, Traditional and Administrative County names)
AFD_LIST_MAILSORT_CODE 18 Returns Mailsort codes
AFD_LIST_URBAN_RURAL_CODE 19 Returns Urban Rural Codes
AFD_LIST_URBAN_RURAL_NAME 20 Returns Urban Rural Names
AFD_LIST_WARD_CODE 21 Returns Ward Codes
AFD_LIST_WARD_NAME 22 Returns Ward Names
AFD_LIST_CONSTITUENCY 23 Returns Constituencies
AFD_LIST_EER_CODE 24 Returns EER Codes (European Electoral Region Codes)
AFD_LIST_EER_NAME 25 Returns EER Names
AFD_LIST_AUTHORITY_CODE 26 Returns Local / Unitary Authority Codes
AFD_LIST_AUTHORITY 27 Returns Authority Names
AFD_LIST_LEA_CODE 28 Returns LEA Codes (Local Education Authority)
AFD_LIST_LEA_NAME 29 Returns LEA Names
AFD_LIST_TV_REGION 30 Returns TV Regions
AFD_LIST_NHS_CODE 31 Returns NHS Codes
AFD_LIST_NHS_NAME 512 Returns NHS Names
AFD_LIST_NHS_REGION_CODE 513 Returns NHS Region Codes
AFD_LIST_NHS_REGION_NAME 514 Returns NHS Region Names
AFD_LIST_PCT_CODE 515 Return CCG Codes
AFD_LIST_PCT_NAME 516 Return CCG Names
AFD_LIST_CENSATION_CODE 517 Returns Censation Codes
AFD_LIST_AFFLUENCE 518 Returns Censation Affluence Codes with descriptions
AFD_LIST_LIFESTAGE 519 Returns Censation Lifestage Codes with descriptions
AFD_LIST_ADDITIONAL_CENSUS_INFO 520 Returns Censation Additional Information with descriptions.
AFD_LIST_HOUSEHOLD_COMPOSITION 521 Returns Household composition codes with descriptions.
AFD_LIST_BUSINESS 522 Returns Business descriptions
AFD_LIST_SIZE 523 Returns Company Size catagories
AFD_LIST_SIC_CODE 524 Returns SIC Codes
AFD_LIST_COUNCIL_TAX_BAND 525 Returns Council Tax Bands
AFD_LIST_CONSTITUENCY_CODE 528 Returns Constituency Codes
AFD_LIST_SUB_COUNTRY_NAME 529 Returns Sub Country Names
AFD_LIST_DEVOLVED_CONSTITUENCY_CODE 531 Returns Devolved Constituency Codes
AFD_LIST_DEVOLVED_CONSTITUENCY_NAME 532 Returns Devolved Constituency Names
Example VB Constant Declarations for List Functions:
Public Const AFD_LIST_ALIAS_LOCALITY = 0
Public Const AFD_LIST_COUNTRY_ISO = 3
Public Const AFD_LIST_COUNTRY = 4
Public Const AFD_LIST_FORENAME = 10
Public Const AFD_LIST_SURNAME = 11
Public Const AFD_LIST_ORGANISATION = 12
Public Const AFD_LIST_PROPERTY = 13
Public Const AFD_LIST_STREET = 14
Public Const AFD_LIST_LOCALITY = 15
Public Const AFD_LIST_TOWN = 16
Public Const AFD_LIST_COUNTY = 17
Public Const AFD_LIST_MAILSORT_CODE = 18
Public Const AFD_LIST_URBAN_RURAL_CODE = 19
Public Const AFD_LIST_URBAN_RURAL_NAME = 20
Public Const AFD_LIST_WARD_CODE = 21
Public Const AFD_LIST_WARD_NAME = 22
Public Const AFD_LIST_CONSTITUENCY = 23
Public Const AFD_LIST_EER_CODE = 24
Public Const AFD_LIST_EER_NAME = 25
Public Const AFD_LIST_AUTHORITY_CODE = 26
Public Const AFD_LIST_AUTHORITY = 27
Public Const AFD_LIST_LEA_CODE = 28
Public Const AFD_LIST_LEA_NAME = 29
Public Const AFD_LIST_TV_REGION = 30
Public Const AFD_LIST_NHS_CODE = 31
Public Const AFD_LIST_NHS_NAME = 512
Public Const AFD_LIST_NHS_REGION_CODE = 513
Public Const AFD_LIST_NHS_REGION_NAME = 514
Public Const AFD_LIST_PCT_CODE = 515
Public Const AFD_LIST_PCT_NAME = 516
Public Const AFD_LIST_CENSATION_CODE = 517
Public Const AFD_LIST_AFFLUENCE = 518
Public Const AFD_LIST_LIFESTAGE = 519
Public Const AFD_LIST_ADDITIONAL_CENSUS_INFO = 520
Public Const AFD_LIST_HOUSEHOLD_COMPOSITION = 521
Public Const AFD_LIST_BUSINESS = 522
Public Const AFD_LIST_SIZE = 523
Public Const AFD_LIST_SIC_CODE = 524
Public Const AFD_LIST_COUNCIL_TAX_BAND = 525
Example C++ Constant Declarations for List Functions:
// Function Type Constants
#define AFD_LIST_ALIAS_LOCALITY 0
#define AFD_LIST_COUNTRY_ISO 3
#define AFD_LIST_COUNTRY 4
#define AFD_LIST_FORENAME 10
#define AFD_LIST_SURNAME 11
#define AFD_LIST_ORGANISATION 12
#define AFD_LIST_PROPERTY 13
#define AFD_LIST_STREET 14
#define AFD_LIST_LOCALITY 15
#define AFD_LIST_TOWN 16
#define AFD_LIST_COUNTY 17
#define AFD_LIST_MAILSORT_CODE 18
#define AFD_LIST_URBAN_RURAL_CODE 19
#define AFD_LIST_URBAN_RURAL_NAME 20
#define AFD_LIST_WARD_CODE 21
#define AFD_LIST_WARD_NAME 22
#define AFD_LIST_CONSTITUENCY 23
#define AFD_LIST_EER_CODE 24
#define AFD_LIST_EER_NAME 25
#define AFD_LIST_AUTHORITY_CODE 26
#define AFD_LIST_AUTHORITY 27
#define AFD_LIST_LEA_CODE 28
#define AFD_LIST_LEA_NAME 29
#define AFD_LIST_TV_REGION 30
#define AFD_LIST_NHS_CODE 31
#define AFD_LIST_NHS_NAME 512
#define AFD_LIST_NHS_REGION_CODE 513
#define AFD_LIST_NHS_REGION_NAME 514
#define AFD_LIST_PCT_CODE 515
#define AFD_LIST_PCT_NAME 516
#define AFD_LIST_CENSATION_CODE 517
#define AFD_LIST_AFFLUENCE 518
#define AFD_LIST_LIFESTAGE 519
#define AFD_LIST_ADDITIONAL_CENSUS_INFO 520
#define AFD_LIST_HOUSEHOLD_COMPOSITION 521
#define AFD_LIST_BUSINESS 522
#define AFD_LIST_SIZE 523
#define AFD_LIST_SIC_CODE 524
#define AFD_LIST_COUNCIL_TAX_BAND 525

Utility Declarations – Address Management Only

These utility functions are not necessary for core address or bank validation functionality, but provide additional functionality that may be useful in your application. For full details of what these functions can do please refer to section 4.7 of this document.

String Utility Declarations – Depreciated and Unsupported

These are provided for compatibility with existing applications which may depend on them but for new developments we would recommend you use in-built functions which are included with most modern development environments. For the String Utility functions an AFDStringData structure is declared, containing the fields specified in Appendix E of this manual for String functions. An afdStringFieldSpec is also declared and works in the same way as the general field specification string documented earlier in this section. The following operation constants are also defined which are used to specify the string operation you wish to perform:

Constant Value Description
AFD_ STRING_SEARCH_REPLACE 0 All occurrences in the string specified in the Lookup field of the string specified in the Search field are replaced with the string in the Replace field.
AFD_STRING_SEARCH_REPLACE_CASE 1 This is the same as AFD_STRING_SEARCH_REPLACE but is case sensitive.
AFD_STRING_CAPITALISE 2 This corrects the capitalisation of the string specified in the Lookup field. For example ‘commercial STREET’ would become ‘Commercial Street’.
AFD_STRING_CLEAN_LINE 3 This cleans the string specified in the Lookup field by removing spurious characters that should not be in an address line, e.g. a trailing comma.
AFD_STRING_CHECK_POSTCODE 4 This checks if the string specified in the Lookup field looks like a postcode.
AFD_STRING_CLEAN_POSTCODE 5 This cleans the postcode specified in the Lookup field to tidy up the postcode specified.
AFD_STRING_ABBREVIATE_COUNTY 6 This provides the Royal Mail Approved county abbreviation for the county specified in the Lookup field if one exists.
VB Declarations for String Utility Functions:
Public Type AFDStringData
  Lookup As String * 255
  Outcode As String * 4
  Incode As String * 3
  Search As String * 255
  Replace As String * 255
End Type
Public Const afdStringFieldSpec = "String@@Lookup:255@Outcode:4@Incode:3@Search:255@Replace:255"
Public Const AFD_STRING_SEARCH_REPLACE = 0
Public Const AFD_STRING_SEARCH_REPLACE_CASE = 1
Public Const AFD_STRING_CAPITALISE = 2
Public Const AFD_STRING_CLEAN_LINE = 3
Public Const AFD_STRING_CHECK_POSTCODE = 4
Public Const AFD_STRING_CLEAN_POSTCODE = 5
Public Const AFD_STRING_ABBREVIATE_COUNTY = 6
C++ Declarations for String Utility Declarations:
struct afdStringData {
  char Lookup[256];
  char Outcode[5];
  char Incode[4];
  char Search[256];
  char Replace[256];
  afdStringData(){     // constructor - zero the contents
    clear();
  }
  void clear(){
    memset(this,'\0',sizeof(*this));
  }
};
static char afdStringFieldSpec[2048] = "String@LX@Lookup:256@Outcode:5@Incode:4@Search:256@Replace:256";
#define AFD_STRING_SEARCH_REPLACE 0
#define AFD_STRING_SEARCH_REPLACE_CASE 1
#define AFD_STRING_CAPITALISE 2
#define AFD_STRING_CLEAN_LINE 3
#define AFD_STRING_CHECK_POSTCODE 4
#define AFD_STRING_CLEAN_POSTCODE 5
#define AFD_STRING_ABBREVIATE_COUNTY 6

Grid Utility Declarations (UK Address Management Only)

For the Grid Utility functions an AFDGridData structure is declared, containing the fields specified in Appendix E of this manual for Grid functions. An afdGridFieldSpec is also declared and works in the same way as the general field specification string documented earlier in this section. The following operation constants are also defined which are used to specify the grid operation you wish to perform:

Constant Value Description
AFD_GRID_CONVERT 512 Converts a GB or NI based grid reference, or latitude and longitude value to all other grid reference types and latitude and longitude values. (This uses a 1m resolution (6 digit). Using a constant of 0 rather than 512 uses 5 digit grids).
AFD_GRID_LOOKUP_LOCATION 513 Looks up a town, locality, or partial postcode specified in the Lookup field and provides an approximate grid reference for the location if a match is found (returns multiple results if there are multiple matches for this location). (This uses a 1m resolution (6 digit). Using a constant of 1 rather than 513 uses 5 digit grids).
AFD_GRID_DISTANCE 514 Calculates the distance between a pair of grid references or latitude and longitude values specified. (This uses a 1m resolution (6 digit). Using a constant of 2 rather than 514 uses 5 digit grids).
VB Declarations for Grid Utility Functions:
Public Type AFDGridData
  Lookup As String * 255
  GBGridE As String * 10
  GBGridN As String * 10
  NIGridE As String * 10
  NIGridN As String * 10
  Latitude As String * 10
  Longitude As String * 10
  TextualLatitude As String * 15
  TextualLongitude As String * 15
  Km As String * 6
  Miles As String * 6
  GBGridEFrom As String * 10
  GBGridNFrom As String * 10
  NIGridEFrom As String * 10
  NIGridNFrom As String * 10
  LatitudeFrom As String * 10
  LongitudeFrom As String * 10
  TextualLatitudeFrom As String * 15
  TextualLongitudeFrom As String * 15
End Type
Public Const afdGridFieldSpec = "Grid@@Lookup:255@GBGridE:10@GBGridN:10@NIGridE:10@NIGridN:10@Latitude:10@Longitude:10@TextualLatitude:15@TextualLongitude:15@Km:6@Miles:6@GBGridEFrom:10@GBGridNFrom:10@NIGridEFrom:10@NIGridNFrom:10@LatitudeFrom:10@LongitudeFrom:10@TextualLatitudeFrom:15@TextualLongitudeFrom:15"
Public Const AFD_GRID_CONVERT = 512
Public Const AFD_GRID_LOOKUP_LOCATION = 513
Public Const AFD_GRID_DISTANCE = 514
C++ Declarations for Grid Utility Declarations:
struct afdGridData {
  char Lookup[256];
  char GBGridE[11];
  char GBGridN[11];
  char NIGridE[11];
  char NIGridN[11];
  char Latitude[11];
  char Longitude[11];
  char TextualLatitude[16];
  char TextualLongitude[16];
  char Km[7];
  char Miles[7];
  char GBGridEFrom[11];
  char GBGridNFrom[11];
  char NIGridEFrom[11];
  char NIGridNFrom[11];
  char LatitudeFrom[11];
  char LongitudeFrom[11];
  char TextualLatitudeFrom[16];
  char TextualLongitudeFrom[16];
  afdGridData(){     // constructor - zero the contents
    clear();
  }
  void clear(){
    memset(this,'\0',sizeof(*this));
  }
};
static char afdGridFieldSpec[2048] = "Grid@@Lookup:256@GBGridE:11@GBGridN:11@NIGridE:11@NIGridN:11@Latitude:11@Longitude:11@TextualLatitude:16@TextualLongitude:16@Km:7@Miles:7@GBGridEFrom:11@GBGridNFrom:11@NIGridEFrom:11@NIGridNFrom:11@LatitudeFrom:11@LongitudeFrom:11@TextualLatitudeFrom:16@TextualLongitudeFrom:16";
#define AFD_GRID_CONVERT 512
#define AFD_GRID_LOOKUP_LOCATION 513
#define AFD_GRID_DISTANCE 514

Email Utility Declarations

For the Email Utility function an AFDEmailData structure is declared, containing the fields specified in Appendix E of this manual for Email functions. An afdEmailFieldSpec is also declared and works in the same way as the general field specification string documented earlier in this section. The following operation constants are also defined which are used to specify the level of email validation that you wish to perform:

Constant Value Description
AFD_EMAIL_FULL 0 Full email validation including live domain lookup
AFD_EMAIL_FORMAT 2 Validate email addres format is correct only
AFD_EMAIL_TLD 3 Validate email format is correct and the top level domain exists
AFD_EMAIL_LOCAL 4 Validate email format, top level domain and for well known domains carry out additional checks of the local portion of the address
VB Declarations for Email Utility Functions:
Public Type AFDEmailData
  Email As String * 255
End Type
Public Const afdEmailFieldSpec = "Email@@Email:255"
Public Const AFD_EMAIL_FULL = 0
Public Const AFD_EMAIL_FORMAT = 2
Public Const AFD_EMAIL_TLD = 3
Public Const AFD_EMAIL_LOCAL = 4
C++ Declarations for Email Utility Declarations:
struct afdEmailData {
  char Email[256];
  afdEmailData(){     // constructor - zero the contents
    clear();
  }
  void clear(){
    memset(this,'\0',sizeof(*this));
  }
};
static char afdEmailFieldSpec[2048] = "Email@@Email:256";
#define AFD_EMAIL_FULL = 0
#define AFD_EMAIL_FORMAT = 2
#define AFD_EMAIL_TLD = 3
#define AFD_EMAIL_LOCAL = 4

Lookup Function

The most commonly used function across our product range is the Lookup function. By entering a single string the user can find the results matching there lookup criteria.

With our address management products three lookup types are provided which you specify as the operation parameter in a call to AFDData:

Operation Constant Functionality
AFD_FASTFIND_LOOKUP This method is the most flexible, enabling the user to lookup an address simply by entering the postcode, or by using search criteria such as “Commercial Street, Birmingham” to quickly find matching records.
AFD_POSTCODE_PROPERTY_LOOKUP This method allows the user to type in any postcode (or zipcode) and, optionally, include optional property information to find a match. For example “304, B11 1AA”. When full fastfind functionality is not required using this operation can prevent erroneous input causing long searches.
AFD_POSTCODE_LOOKUP The user can type in any postcode (or zipcode), e.g. “B11 1AA” and obtain the results for that postcode. Only full correct postcodes are accepted. This is useful when you only want a postcode lookup, for example if you are looking up a list of postcodes to obtain grid references.

Similarily with Nearest, three lookup types are also provided (although they differ slightly due to the nature of the product):

Operation Constant Functionality
AFD_FASTFIND_LOOKUP This method is the most flexible, enabling the user to find the nearest simply by entering the postcode, or by entering a locality or town name, or a partial postcode.
AFD_MULTIPLE_FASTFIND_LOOKUP This is similar to AFD_FASTFIND_LOOKUP, except that where a locality or town is given which has multiple matches the user will be presented with a list of locations to choose from to then lookup to find the Nearest.
AFD_POSTCODE_LOOKUP The user can type in any postcode, e.g. “B11 1AA” and obtain the Nearest records to that postcode. Only full correct postcodes are accepted.

With BankFinder the only option available is AFD_FASTFIND_LOOKUP which allows you to find a bank using a sort code, postcode or other criteria quickly.

To carry out a lookup you will first need to declare an instance of the AFD structure you have declared in your general declarations module or class (see Section 4.1).

You will then need to set the Lookup parameter to the postcode or fast find string that you wish to look up.

If you are using International data you should also set the CountryISO or Country field to specify the country to carry out the lookup for.

If you are using Nearest you should also set the MaxRecords parameter to indicate the maximum number of records to return and the Miles or Km parameter to specify the maximum distance to return. Using low values for these options speeds up the lookup.

You then call the AFDData function with the following three parameters:

  1. The Field Specification String (as detailed in Section 4.1)
  2. The operation constant you require (one of the 3 above)
  3. The instance of the structure or type that you declared.

If you would prefer not to use your own list box in your application, you may wish to add to the operation constant the AFD_LIST_BOX option. This causes the DLL to display a list box for you returning the record that the user selects, rather than returning all matching records to your application. This is only suitable for desktop applications as it displays the list box on-screen. Similarly adding AFD_SHOW_ERROR causes the DLL to display any error message to the user itself.

Should you wish to use one of the skip options in Address Management, for example returning the first record per sector only you can also add any of the Skip constants listed in the declarations (see Section 4.1).

When using BankFinder you may wish to add the clearing system you wish to restrict records to as well. Using AFD_UK_CLEARING restricts records to those on the UK (BACS) clearing system only. Using AFD_IRISH_CLEARING restricts records to those on the Irish (IPSO) clearing system only. If you can only clear through the UK system it is important to use the AFD_UK_CLEARING constant.

The AFDData function will return a negative value (less than zero) in the case of an error. Unless you have used the AFD_SHOW_ERROR option to ask the DLL to present any error to the user, you should display an error for the user before aborting the lookup. The AFDErrorText function will help you obtain a string which can be useful for displaying to the user to describe the error.

In the case of Address Management products the PostcodeFrom field of the structure or type will be set if a postcode was looked up which has changed following a Royal Mail recoding. The lookup will complete using the new postcode (found in the Postcode field), however you may wish to display a message notifying the user of this.

If the return value from the AFDData function is AFD_SUCCESS then a matching result has been returned and you can access the fields in the structure or type instance supplied to obtain full details for it. Included in this is a List property that can be used to provide a formatted item for adding to a list box to allow the user to select the desired option if desired. The Key property should also be stored as this allows quick retrieval of the record should it be selected using the ListFetch method described in Section 4.4.

If you have specified the AFD_LIST_BOX option then the user will have selected the required item and you can access the fields in the supplied structure or type instance and the lookup is complete.

Otherwise, you will have retrieved the first record which you can add to a list box if desired. If the return value was AFD_RECORD_BREAK then no result has yet been returned but the lookup is taking some time (would not occur with a postcode or property, postcode lookup) and so the user is being given the chance to cancel.

To retrieve the rest of the records you should call the AFDData function as above repeatedly with the same operation code as before, but adding the AFD_GET_NEXT constant to it to obtain subsequent records. These can be added to a list box as above or processed as required. You should call AFDData in a lookup to retrieve these records allowing the user to cancel the lookup should it take some time or they realise they have entered something incorrectly.

Example VB code for an Address Management Lookup:
  Dim details As AFDAddressData
  Dim retVal As Long
  Static running As Boolean
  ' Prevent corruption of list box from button being clicked twice
  If running Then Exit Sub
  running = True
  ' Replace lstResult with the name of your list box for the results
  With lstResult
  ' Clear out any existing items in the list
  .Clear
  ' Reset Cancel flag
  cancelFlag = False
  ' Set the lookup
  details.Lookup = txtLookup.Text ' Change txtLookup to your lookup entry textbox
  ' Carry out the lookup (no need to alter the line below, unless you want to add a sector skip option - see constants)
  retVal = AFDData(afdFieldSpec, AFD_FASTFIND_LOOKUP + AFD_SECTOR_SKIP, details)
  ' Abort with Message if error or user cancelled
  If retVal < 0 Then
    MsgBox AFDErrorText(retVal)
    running = False
    Exit Sub
  End If
  ' Display any changed postcode if applicable
  If Trim(details.PostcodeFrom) <> "" Then
    MsgBox "Postcode has changed from " + Trim(details.PostcodeFrom) + " to " + Trim(details.Postcode)
  End If
  ' Now add matching records to the list box
  Do While retVal >= 0
    If retVal <> AFD_RECORD_BREAK Then
      ' Add the item to the list box with hidden key at the end
      .AddItem details.List + details.Key
    End If
    ' Give user the chance to cancel and allow list box to update
    DoEvents
    ' Check if user cancelled
    If cancelFlag Then
      MsgBox "Lookup Cancelled"
      running = False
      Exit Sub
    End If
    retVal = AFDData(afdFieldSpec, AFD_GET_NEXT + AFD_FASTFIND_LOOKUP, details)
  Loop
  ' Check results have been returned
  If .ListCount = 0 Then
    MsgBox "No Results Found"
  Else
    .ListIndex = 0 ' Select First item in the list
  End If
  End With
  running = False
Example C++ Code For an Address Management Lookup (Visual C++)
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  static bool running = false;
  afdAddressData details;
  char listItem[2055];
  char msgTxt[255];
  long retVal;
  CListBox* listBox;
  MSG msg;
  // Check if we are already running to prevent crossing over items in the listbox
  if (running) return;
  running = true;
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Replace m_lstResult with the name given to a variable assigned to your list box control for the results
  listBox = &m_lstResult;
  // Clear out any existing items in the list
  listBox->ResetContent();
  // Reset Cancel flag
  cancelFlag = false;
  // Update Data so we can read the lookup variable
  UpdateData(TRUE);
  // Set the lookup
  strcpy(details.Lookup, m_txtLookup); // Change this to your lookup entry textbox value variable
  // Carry out the lookup (no need to alter the line below, unless you want to add a sector skip option - see constants)
  retVal = (afdData)(afdFieldSpec, AFD_FASTFIND_LOOKUP, (char*)&details);
  // Abort with Message if error or user cancelled
  if (retVal < 0) {
    AFDErrorText(retVal, msgTxt);
    MessageBox(msgTxt, "Error", 0);
    running = false;
    return;
  }
  // Display any changed postcode if applicable
  if (details.PostcodeFrom[0] != '\0') {
    strcpy(msgTxt, "Postcode has changed from ");
    strcat(msgTxt, details.PostcodeFrom);
    strcat(msgTxt, " to ");
    strcat(msgTxt, details.Postcode);
    MessageBox(msgTxt, "Changed Postcode", 0);
  }
  // Now add matching records to the list box
  while (retVal >= 0) {
    if (retVal != AFD_RECORD_BREAK) {
      // make up list item with hidden key at the end
      strncpy(listItem, details.List, sizeof(details.List));
      strncpy(listItem + sizeof(details.List), details.Key, sizeof(details.Key));
      listItem[sizeof(details.List) + sizeof(details.Key)] = '\0';
      // Add the item to the list box
      listBox->AddString(listItem);
    }
    // Give user the chance to cancel and allow list box to update
    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    // Check if user cancelled
    if (cancelFlag) {
      MessageBox("Search Cancelled", "Cancelled", 0);
      return;
    }
    retVal = (afdData)(afdFieldSpec, AFD_GET_NEXT + AFD_FASTFIND_LOOKUP, (char*)&details);
  }
  // Check results have been returned
  if (listBox->GetCount() == 0)
    MessageBox("No Results Found", "Error", 0);
  else {
    listBox->SetCurSel(0); // Select First item in the list
    OnSelchangeLstResult(); // Set this to your list change method to simulate selecting the first list item
  }
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;
  running = false;

Search Function

The search function allows records to be located by searching using specific fields rather than a general lookup string. It allows any of the Fields to be searched that are specified as being searchable for the AFD product that you are using in Appendix A (for Address Management products) or Appendix B (for BankFinder). All fields in your database are searchable in the case of Nearest.

To carry out a search you will first need to declare an instance of the AFD structure you have declared in your general declarations module or class (see Section 4.1).

You will then need to set the fields that you wish to search on to the criteria that you wish to use. Note that if you specify a field that is not searchable in the product that you are using it will be ignored.

If you are using International data you should also set the CountryISO or Country field to specify the country to carry out the lookup for.

You then call the AFDData function with the following three parameters:

  1. The Field Specification String (as detailed in Section 4.1)
  2. The operation code (AFD_SEARCH constant)
  3. The instance of the structure or type that you declared.

If you would prefer not to use your own list box in your application, you may wish to add to the operation constant the AFD_LIST_BOX option. This causes the DLL to display a list box for you returning the record that the user selects, rather than returning all matching records to your application. This is only suitable for desktop applications as it displays the list box on-screen. Similarly adding AFD_SHOW_ERROR causes the DLL to display any error message to the user itself.

Should you wish to use one of the skip options in Address Management, for example returning the first record per sector only you can also add any of the Skip constants listed in the declarations (see Section 4.1).

When using BankFinder you may wish to add the clearing system you wish to restrict records to as well. Using AFD_UK_CLEARING restricts records to those on the UK (BACS) clearing system only. Using AFD_IRISH_CLEARING restricts records to those on the Irish (IPSO) clearing system only. If you can only clear through the UK system it is important to use the AFD_UK_CLEARING constant.

The AFDData function will return a negative value (less than zero) in the case of an error. Unless you have used the AFD_SHOW_ERROR option to ask the DLL to present any error to the user, you should display an error for the user before aborting the lookup. The AFDErrorText function will help you obtain a string which can be useful for displaying to the user to describe the error.

If the return value from the AFDData function is AFD_SUCCESS then a matching result has been returned and you can access the fields in the structure or type instance supplied to obtain full details for it. Included in this is a List property that can be used to provide a formatted item for adding to a list box to allow the user to select the desired option if desired. The Key property should also be stored as this allows quick retrieval of the record should it be selected using the ListFetch method described in Section 4.4.

If you have used the M and T options in the field specification to return all records at once from the API then you will have all matching records in the array you specified so the search is complete. If you have specified the AFD_LIST_BOX option then the user will have selected the required item and so you can access the fields in the supplied structure or type instance and the search is complete.

Otherwise, you will have retrieved the first record which you can add to a list box if desired. If the return value was AFD_RECORD_BREAK then no result has yet been returned but the search is taking some time (would not occur with a postcode or property, postcode lookup) and so the user is being given the chance to cancel.

To retrieve the rest of the records you should call the AFDData function as above repeatedly with the same operation code as before, but adding the AFD_GET_NEXT constant to it to obtain subsequent records. These can be added to a list box as above or processed as required. You should call AFDData in a lookup to retrieve these records allowing the user to cancel the lookup should it take some time or they realise they have entered something incorrectly.

Example VB code for an Address Management Search:
  Dim details As AFDAddressData
  Dim retVal As Long
  Static running As Boolean
  ' Prevent corruption of list box from button being clicked twice
  If running Then Exit Sub
  running = True
  ' Replace lstResult with the name of your list box for the results
  With lstResult
  ' Clear out any existing items in the list
  .Clear
  ' Reset Cancel flag
  cancelFlag = False
  ' Clear Structure
  ClearAFDAddressData details
  ' Set the fields you wish to search on (look at the other properties of the structure)
  details.Organisation = txtSearchOrganisation.Text
  details.Property = txtSearchProperty.Text
  details.Street = txtSearchStreet.Text
  details.Locality = txtSearchLocality.Text
  details.Town = txtSearchTown.Text
  details.Postcode = txtSearchPostcode.Text
  ' Carry out the search (no need to alter the line below, unless you want to add a sector skip option - see constants)
  retVal = AFDData(afdFieldSpec, AFD_SEARCH + AFD_SECTOR_SKIP, details)
  ' Abort with Message if error or user cancelled
  If retVal < 0 Then
    MsgBox AFDErrorText(retVal)
    running = False
    Exit Sub
  End If
  ' Now add matching records to the list box
  Do While retVal >= 0
    If retVal <> AFD_RECORD_BREAK Then
      ' Add the item to the list box with hidden key at the end
      .AddItem details.List + details.Key
    End If
    DoEvents
    If cancelFlag Then
      MsgBox "Search Cancelled"
      running = False
      Exit Sub
    End If
    retVal = AFDData(afdFieldSpec, AFD_GET_NEXT + AFD_SEARCH, details)
  Loop
  ' Check results have been returned
  If .ListCount = 0 Then
    MsgBox "No Results Found"
  Else
    .ListIndex = 0 ' Select First item in the list
  End If
  End With
  running = False
Example C++ Code For an Address Management Search (Visual C++)
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  static bool running = false;
  afdAddressData details;
  char listItem[2055];
  char msgTxt[255];
  long retVal;
  CListBox* listBox;
  MSG msg;
  // Check if we are already running to prevent crossing over items in the listbox
  if (running) return;
  running = true;
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Replace m_lstResult with the name given to a variable assigned to your list box control for the results
  listBox = &m_lstResult;
  // Clear out any existing items in the list
  listBox->ResetContent();
  // Reset Cancel flag
  cancelFlag = false;
  // Update Data so we can read the search variables
  UpdateData(TRUE);
  // Set the search parameters (look at the other properties of the structure)
  strcpy(details.Organisation, m_txtSearchOrganisation);
  strcpy(details.Property, m_txtSearchProperty);
  strcpy(details.Street, m_txtSearchStreet);
  strcpy(details.Locality, m_txtSearchLocality);
  strcpy(details.Town, m_txtSearchTown);
  strcpy(details.Postcode, m_txtSearchPostcode);
  // Carry out the search (no need to alter the line below, unless you want to add a sector skip option - see constants)
  retVal = (afdData)(afdFieldSpec, AFD_SEARCH, (char*)&details);
  // Abort with Message if error or user cancelled
  if (retVal < 0) {
    if (retVal != 99) { // User Cancelled
      AFDErrorText(retVal, msgTxt);
      MessageBox(msgTxt, "Error", 0);
      return;
    }
    running = false;
    return;
  }
  // Now add matching records to the list box
  while (retVal >= 0) {
    if (retVal != AFD_RECORD_BREAK) {
      // make up list item with hidden key at the end
      strncpy(listItem, details.List, sizeof(details.List));
      strncpy(listItem + sizeof(details.List), details.Key, sizeof(details.Key));
      listItem[sizeof(details.List) + sizeof(details.Key)] = '\0';
      // Add the item to the list box
      listBox->AddString(listItem);
    }
    // Give user the chance to cancel and allow list box to update
    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    // Check if user cancelled
    if (cancelFlag) {
      MessageBox("Search Cancelled", "Cancelled", 0);
      return;
    }
    retVal = (afdData)(afdFieldSpec, AFD_GET_NEXT + AFD_SEARCH, (char*)&details);
  }
  // Check results have been returned
  if (listBox->GetCount() == 0)
    MessageBox("No Results Found", "Error", 0);
  else {
    listBox->SetCurSel(0); // Select First item in the list
    OnSelchangeLstResult(); // Set this to your list change method to simulate selecting the first list item
  }
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;
  running = false;

List Fetch Function

Unless you are using the DLL’s internal list box (i.e. specified the AFD_LIST_BOX constant at the time of your lookup or search) you may well have added each of the results from a lookup or search to a list box from which the user will select the required result. To retrieve the record they select you should use the Key Field which will have been returned with each result, and which you should have stored with the list items.

To fetch the record, you will first need to declare an instance of the AFD structure you have declared in your general declarations module or class (see Section 4.1). You should then set the Key Field to the value returned for the list item the user has selected.

If you are using International data you should also set the CountryISO or Country field to specify the country to carry out the lookup for.

You then call the AFDData function with the following three parameters:

  1. The Field Specification String (as detailed in Section 4.1)
  2. The operation code (AFD_RETRIEVE_RECORD constant)
  3. The instance of the structure or type that you declared.

The AFDData function will return a negative value (less than zero) in the case of an error. It is unlikely that an error will occur at this stage, unless your key was in some way corrupted, but for completeness you can use the AFDErrorText function to help you obtain a string which can be useful for displaying to the user to describe the error.

You will now have the requested record and can use any of the fields in the structure to display or otherwise process the record details as desired.

You should note that with Nearest and the Multiple Fastfind Lookup operation if a location is returned you will obtain a Key starting “LOC:” followed by a grid reference. This should be looked up as a new lookup to get the Nearest results rather than retrieving a record.

Example VB code to fetch an item selected in the list for Address Management products:
  Dim details As AFDAddressData
  Dim pos As Long, retVal As Long
  ' Replace lstResult with the name of your list box for the results
  With lstResult
  ' Check a valid item is selected
  If .ListIndex = -1 Then
    MsgBox "No Item Selected"
    Exit Sub
  End If
  ' Set DLL parameters to retrieve the selected record
  details.Key = Mid(lstResult, 513) ' Replace lstResult with the name of your list box for the results
  ' Finished with the list box
  End With
  ' Carry out the lookup (no need to alter the line below, unless you want to add a sector skip option - see constants)
  retVal = AFDData(afdFieldSpec, AFD_RETRIEVE_RECORD, details)
  ' Abort with Message if error or user cancelled
  If retVal < 0 Then
    MsgBox AFDErrorText(retVal)
    Exit Sub
  End If
  ' Now Assign required fields to your application
  ' These are any of the members of the details. type (Use Trim to remove whitespace)
  txtName.Text = Trim(details.Name)
  txtOrganisation.Text = Trim(details.Organisation)
  txtProperty.Text = Trim(details.Property)
  txtStreet.Text = Trim(details.Street)
  txtLocality.Text = Trim(details.Locality)
  txtTown.Text = Trim(details.Town)
  txtPostcode.Text = Trim(details.Postcode)
Example C++ code to fetch an item selected in the list for Address Management products (Visual C++):
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  afdAddressData details;
  bool foundSel = false;
  long retVal;
  CListBox* listBox;
  char lstStr[2055];
  char msgTxt[255];
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Replace m_lstResult with the name given to a variable assigned to your list box control for the results
  listBox = &m_lstResult;
  // Set DLL parameters to retrieve the selected record
  listBox->GetText(listBox->GetCurSel(), lstStr);
  strncpy(details.Key, lstStr + sizeof(details.List), sizeof(details.Key));
  // Carry out the lookup (no need to alter the line below, unless you want to add a sector skip option - see constants)
  retVal = (afdData)(afdFieldSpec, AFD_RETRIEVE_RECORD, (char*)&details);
  // Abort with Message if error
  if (retVal < 0) {
    AFDErrorText(retVal, msgTxt);
    MessageBox(msgTxt, "Error", 0);
    return;
  }
  // Now Assign required fields to your application
  // These are any of the members of the details. structure
  m_txtName = details.Name;
  m_txtOrganisation = details.Organisation;
  m_txtProperty = details.Property;
  m_txtStreet = details.Street;
  m_txtLocality = details.Locality;
  m_txtTown = details.Town;
  m_txtPostcode = details.Postcode;
  // Update Fields
  UpdateData(FALSE);
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;

Account Number Validation – BankFinder Only

This function provides the ability to validate a sort code and account number. This checks that the account number is valid for the branch of the bank which the sortcode belongs to. This does not guarantee that the account number exists or sufficient funds exist for any transaction, but greatly cuts down on errors due to incorrectly entered numbers. The function will also translate any non-standard account numbers (e.g. a 10-digit account number).

To carry out a validation, you will first need to declare an instance of the AFDBankData structure you have declared in your general declarations module or class (see Section 4.1). You should then set the SortCode and AccountNumber Fields to the sort code and account number that you wish to validate (or instead the IBAN if validating an account number in that International standardised format). Optionally with Building Society credits you may also require a Roll Number.

You then call the AFDData function with the following three parameters:

  1. The Field Specification String (as detailed in Section 4.1)
  2. The operation code (AFD_ACCOUNT_VALIDATE constant)
  3. The instance of the structure or type that you declared.

If you would prefer the DLL to display any error message that may occur to the user, rather than having to display this yourself, you should add the AFD_SHOW_ERROR constant to the operation parameter. This is only suitable for desktop applications as it displays any error message on-screen.

You may also need to add the clearing system you wish to restrict records to as well. Using AFD_UK_CLEARING restricts records to those on the UK (BACS) clearing system only. Using AFD_IRISH_CLEARING restricts records to those on the Irish (IPSO) clearing system only. If you can only clear through the UK system it is important to use the AFD_UK_CLEARING constant.

The AFDData function will return a negative value (less than zero) in the case of an error. Unless you have used the AFD_SHOW_ERROR option to ask the DLL to present any error to the user, you should display an error for the user before aborting the lookup. The AFDErrorText function will help you obtain a string which can be useful for displaying to the user to describe the error.

Otherwise the account number is valid and you should use the SortCode, AccountNumber and TypeOfAccount fields returned in the supplied type or structure instance to process the account number (and optionally roll number with some building societies) as they may be updated should account number translation have been necessary.

If the return value is AFD_SUCCESS then the account number has been validated, if the return value is AFD_SUCCESS_NO_VALIDATION then account numbers on this sortcode cannot be validated and so the number should still be treated as valid. This return code is provided so you can carry out an additional check on the account number, e.g. asking a customer on the phone to repeat it, checking it has been entered from a paper form correctly etc. if you wish to do so.

If you are processing account numbers on both clearing systems and wish to check which one the branch at which the account number that was entered resides on, you can do this by checking the value of the ClearingSystem field:

Clearing System Field Value Meaning
United Kingdom (BACS) The branch at which this account is held is on the UK clearing system
Ireland (IPSO) The branch at which this account is held is on the Irish Payment Services Organisation Clearing System
Both UK and Irish The branch at which this account is held is on both the UK and Irish clearing systems. The actual account may only clear through one of these systems but it is not possible to determine which one so you should clarify that with the customer.

Should you also wish to check the branch details match those that the customer has supplied, check the transaction types allowed at this branch, or obtain the address to use for this branch (may not be the branch physical location) then you can carry out a lookup for the sortcode (see Section 4.1) to obtain the branch information.

Example VB code to validate an account number:
  Dim details As AFDBankData
  Dim retVal As Long
  ' Set the Sort Code and Account Number
  details.SortCode = txtValidateSortcode.Text ' Change txtValidateSortCode to your sortcode entry textbox
  details.AccountNumber = txtValidateAccountNo.Text ' Change txtValidateAccountNo to your account number entry textbox
  ' Carry out the validation (you can change the AFD_BOTH_CLEARINGS option to AFD_UK_CLEARING or AFD_IRISH_CLEARING as desired)
  retVal = AFDData(afdBankFieldSpec, AFD_ACCOUNT_VALIDATE + AFD_BOTH_CLEARINGS, details)
  ' Abort with Message if error
  If retVal < 0 Then
    MsgBox AFDErrorText(retVal)
    Exit Sub
  End If
  ' Display validation result - with details to submit for payment - note non-standard account number's will be translated
  MsgBox "Account Number Valid: " + vbCrLf + vbCrLf + "Sortcode: " + Trim(details.SortCode) + vbCrLf + "Account Number: " + Trim(details.AccountNumber) + vbCrLf + "Type of Account Code: " + Trim(details.TypeOfAccount) + vbCrLf + "Clearing System: " + Trim(details.ClearingSystem)
Example C++ code to validate an account number (Visual C++):
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  afdBankData details;
  char msgTxt[255];
  long retVal;
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Update Data so we can read the sortcode and account number variables
  UpdateData(TRUE);
  // Set the Sort Code and Account Number
  strcpy(details.SortCode, m_txtValidateSortcode); // Change this to your sort code textbox value variable
  strcpy(details.AccountNumber, m_txtValidateAccountNo); // Change this to your account number textbox value variable
  // Carry out the validation (you can change the AFD_BOTH_CLEARINGS option to AFD_UK_CLEARING or AFD_IRISH_CLEARING as desired)
  retVal = (afdData)(afdBankFieldSpec, AFD_ACCOUNT_VALIDATE + AFD_BOTH_CLEARINGS, (char*)&details);
  // Abort with Message if error or user cancelled
  if (retVal < 0) {
    AFDErrorText(retVal, msgTxt);
    MessageBox(msgTxt, "Error", 0);
    return;
  }
  // Display validation result - with details to submit for payment - note non-standard account number's will be translated
  strcpy(msgTxt, "Account Number Valid:\n\nSortcode: ");
  strcat(msgTxt, details.SortCode);
  strcat(msgTxt, "\nAccount Number: ");
  strcat(msgTxt, details.AccountNumber);
  strcat(msgTxt, "\nType of Account Code: ");
  strcat(msgTxt, details.TypeOfAccount);
  strcat(msgTxt, "\nClearing System: ");
  strcat(msgTxt, details.ClearingSystem);
  MessageBox(msgTxt, "Validation Successful", 0);
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;

Card Number Validation – BankFinder Only

This function provides the ability to validate a card number, and optionally check that an expiry date indicates that the card is in-date. This checks that the card number is a valid one for the type of card and can indicate the card type. This does not guarantee that the card exists or that a transaction will be authorized, but greatly cuts down on errors due to incorrectly entered numbers.

To carry out a validation, you will first need to declare an instance of the AFDBankData structure you have declared in your general declarations module or class (see Section 4.1). You should then set the CardNumber and, if you wish, the ExpiryDate Fields for the card that you wish to validate.

You then call the AFDData function with the following three parameters:

  1. The Field Specification String (as detailed in Section 4.1)
  2. The operation code (AFD_CARD_VALIDATE constant)
  3. The instance of the structure or type that you declared.

If you would prefer the DLL to display any error message that may occur to the user, rather than having to display this yourself, you should add the AFD_SHOW_ERROR constant to the operation parameter. This is only suitable for desktop applications as it displays any error message on-screen.

The AFDData function will return a negative value (less than zero) in the case of an error. Unless you have used the AFD_SHOW_ERROR option to ask the DLL to present any error to the user, you should display an error for the user before aborting the lookup. The AFDErrorText function will help you obtain a string which can be useful for displaying to the user to describe the error.

Otherwise the card number is valid. If you wish to determine the card type, the CardType field will hold this information.

Example VB code to validate a card number:
  Dim details As AFDBankData
  Dim retVal As Long
  ' Set the Card Number and Expiry Date (Optional)
  details.CardNumber = txtValidateCardNo.Text ' Change txtValidateCardNo to your card number entry textbox
  details.ExpiryDate = txtValidateExpiry.Text ' Change txtValidateExpiry to your expiry date entry textbox
  ' Carry out the validation (you can change the AFD_BOTH_CLEARINGS option to AFD_UK_CLEARING or AFD_IRISH_CLEARING as desired)
  retVal = AFDData(afdBankFieldSpec, AFD_CARD_VALIDATE, details)
  ' Abort with Message if error
  If retVal < 0 Then
    MsgBox AFDErrorText(retVal)
    Exit Sub
  End If
  ' Display validation result
  MsgBox "Card Valid: " + Trim(details.CardType)
Example C++ code to validate a card number (Visual C++):
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  afdBankData details;
  char msgTxt[255];
  long retVal;
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Update Data so we can read the card number and expiry date variables
  UpdateData(TRUE);
  // Set the Card Number and Expiry date (Optional)
  strcpy(details.CardNumber, m_txtValidateCardNo); // Change this to your card number textbox value variable
  strcpy(details.ExpiryDate, m_txtValidateExpiry); // Change this to your expiry date textbox value variable
  // Carry out the validation (no need to alter the line below)
  retVal = (afdData)(afdBankFieldSpec, AFD_CARD_VALIDATE, (char*)&details);
  // Abort with Message if error or user cancelled
  if (retVal < 0) {
    AFDErrorText(retVal, msgTxt);
    MessageBox(msgTxt, "Error", 0);
    return;
  }
  // Display validation result
  strcpy(msgTxt, "Card Valid: ");
  strcat(msgTxt, details.CardType);
  MessageBox(msgTxt, "Validation Successful", 0);
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;

List Functions – Address Management Only

With Postcode Plus, Names & Numbers and TraceMaster products you can use the list functions to obtain a list of alias localities for the postcode sector that a postcode or result is contained in. These are non-postally required localities held by Royal Mail which can or may be included on an address if desired. An example of this would be including Wimbledon for an address in London. You should note that these are stored at postal sector level (e.g. SW19 1) and there are often multiple entries for an address so a locality being returned does not mean it is necessarily the best one for the particular address you are viewing.

For Names & Numbers and TraceMaster products only it is also possible to obtain a list of possible values for most fields, e.g. all the Mailsort codes present, business descriptions, etc. You can also specify the start value of the field, e.g. return all surnames present starting with “Smith”.

When using International data you can also use the List functions to obtain a list of all available countries (names or ISO codes).

To carry out a list operation, you first need to declare an instance of the AFDListData structure you have declared in your general declarations module or class (see Section 4.1). For an alias locality lookup, you should then set the Lookup field to the postcode or record key that you wish to lookup the alias localities for. When retrieving field lists from Names & Numbers you can set this to specify that only entries starting with your specified string are returned (this is essential for long lists like surname to be useful, but is generally not so useful with shorter lists like Household Composition).

The operation parameter passed to the AFDData function determines the List function carried out:

Constant Description
AFD_LIST_ALIAS_LOCALITY Returns all alias localities for the sector that the specified postcode or key resides in.
The following are applicable when using International data only:
AFD_LIST_COUNTRY_ISO Will return the ISO codes of all available countries.
AFD_LIST_COUNTRY Will return the names of all available countries.
The following are applicable to Names & Numbers and TraceMaster Products Only:
These all return a list of all entries of the data item specified in the data
Setting the lookup parameter will restrict matches to only those items starting with the specified string.
AFD_LIST_FORENAME Returns Forenames (first names).
AFD_LIST_SURNAME Returns Surnames
AFD_LIST_ORGANISATION Returns Organisations
AFD_LIST_PROPERTY Returns Properties
AFD_LIST_STREET Returns Streets
AFD_LIST_LOCALITY Returns Localities
AFD_LIST_TOWN Returns Postal Towns
AFD_LIST_COUNTY Returns Counties (This includes Postal, Traditional and Administrative County names)
AFD_LIST_MAILSORT_CODE Returns Mailsort codes
AFD_LIST_URBAN_RURAL_CODE Returns Urban Rural Codes
AFD_LIST_URBAN_RURAL_NAME Returns Urban Rural Names
AFD_LIST_WARD_CODE Returns Ward Codes
AFD_LIST_WARD_NAME Returns Ward Names
AFD_LIST_CONSTITUENCY Returns Constituencies
AFD_LIST_EER_CODE Returns EER Codes (European Electoral Region Codes)
AFD_LIST_EER_NAME Returns EER Names
AFD_LIST_AUTHORITY_CODE Returns Local / Unitary Authority Codes
AFD_LIST_AUTHORITY Returns Authority Names
AFD_LIST_LEA_CODE Returns LEA Codes (Local Education Authority)
AFD_LIST_LEA_NAME Returns LEA Names
AFD_LIST_TV_REGION Returns TV Regions
AFD_LIST_NHS_CODE Returns NHS Codes
AFD_LIST_NHS_NAME Returns NHS Names
AFD_LIST_NHS_REGION_CODE Returns NHS Region Codes
AFD_LIST_NHS_REGION_NAME Returns NHS Region Names
AFD_LIST_PCT_CODE Return PCT Codes
AFD_LIST_PCT_NAME Return PCT Names
AFD_LIST_CENSATION_CODE Returns Censation Codes
AFD_LIST_AFFLUENCE Returns Censation Affluence Codes with descriptions
AFD_LIST_LIFESTAGE Returns Censation Lifestage Codes with descriptions
AFD_LIST_ADDITIONAL_CENSUS_INFO Returns Censation Additional Information with descriptions.
AFD_LIST_HOUSEHOLD_COMPOSITION Returns Household composition codes with descriptions.
AFD_LIST_BUSINESS Returns Business descriptions
AFD_LIST_SIZE Returns Company Size catagories
AFD_LIST_SIC_CODE Returns SIC Codes
AFD_LIST_COUNCIL_TAX_BAND Returns Council Tax Bands

You then call the AFDData function with the following three parameters:

  1. The List Field Specification String (as detailed in Section 4.1)
  2. The operation code (See above for options).
  3. The instance of the structure or type that you declared.

If you would prefer not to use your own list box in your application, you may wish to add to the operation constant the AFD_LIST_BOX option. This causes the DLL to display a list box for you returning the record that the user selects, rather than returning all matching list records to your application. This is only suitable for desktop applications as it displays the list box on-screen. Similarly adding AFD_SHOW_ERROR causes the DLL to display any error message to the user itself.

The AFDData function will return AFD_SUCCESS for most operations or AFD_NO_RESULTS_FOUND if there were no matching list items. Other errors may be returned if the product is not correctly licensed (i.e. AFD_ERROR_OPENING_FILES, AFD_ERROR_FILE_READ, or AFD_DATA_LICENSE_ERROR). So, unless you have used the AFD_SHOW_ERROR option to ask the DLL to present any error to the user, you may wish to call AFDErrorText in these circumstances to obtain a string to display to the user describing the error.

If the return value from the AFDData function is AFD_SUCCESS then a matching result has been returned and you can access the fields in the structure or type instance supplied to obtain full details for it. The resulting string will be found in the List Field of the structure.

If you have specified the AFD_LIST_BOX option then the user will have selected the required item and you can access the selected result in the List Field of the structure.

Otherwise, you will have retrieved the first record. To retrieve the rest of the records you should call the AFDData function as above repeatedly with the same operation code as before, but adding the AFD_GET_NEXT constant to it to obtain subsequent records. These can be added to a list box as above or processed as required.

Example VB code for a List operation to retrieve alias localities:
  Dim details As AFDListData
  Dim retVal As Long
  Static running As Boolean
  ' Prevent corruption of list box from button being clicked twice
  If running Then Exit Sub
  running = True
  ' Replace lstResult with the name of your list box for the results
  With lstResult
  ' Clear out any existing items in the list
  .Clear
  ' Reset Cancel flag
  cancelFlag = False
  ' Set the lookup
  details.Lookup = txtLookup.Text ' Change txtLookup to the postcode or record key you wish to lookup
  ' Carry out the lookup (Can alter the operation to retrieve N&N list items if desired)
  retVal = AFDData(afdFieldSpec, AFD_LIST_ALIAS_LOCALITY, details)
  ' Abort with Message if error or user cancelled
  If retVal < 0 Then
    MsgBox AFDErrorText(retVal)
    running = False
    Exit Sub
  End If
 ' Now add matching records to the list box
  Do While retVal >= 0
    ' Add the item to the list box with hidden key at the end
.AddItem Trim(details.List)
' Give user the chance to cancel and allow list box to update
    DoEvents
    ' Check if user cancelled
    If cancelFlag Then
      MsgBox "Lookup Cancelled"
      running = False
      Exit Sub
    End If
    retVal = AFDData(afdFieldSpec, AFD_GET_NEXT + AFD_LIST_ALIAS_LOCALITY, details)
  Loop
  ' Check results have been returned
  If .ListCount = 0 Then
    MsgBox "No Results Found"
  Else
    .ListIndex = 0 ' Select First item in the list
  End If
  End With
  running = False
Example C++ Code For an Address Management Lookup (Visual C++)
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  static bool running = false;
  afdListData details;
  char listItem[2055];
  char msgTxt[255];
  long retVal;
  CListBox* listBox;
  MSG msg;
  // Check if we are already running to prevent crossing over items in the listbox
  if (running) return;
  running = true;
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Replace m_lstResult with the name given to a variable assigned to your list box control for the results
  listBox = &m_lstResult;
  // Clear out any existing items in the list
  listBox->ResetContent();
  // Reset Cancel flag
  cancelFlag = false;
  // Update Data so we can read the lookup variable
  UpdateData(TRUE);
  // Set the lookup
  strcpy(details.Lookup, m_txtLookup); // Change this to the postcode or record key you wish to lookup
  // Carry out the lookup (Can alter the operation to retrieve N&N list items if desired)
  retVal = (afdData)(afdFieldSpec, AFD_LIST_ALIAS_LOCALITY, (char*)&details);
  // Abort with Message if error or user cancelled
  if (retVal < 0) {
    AFDErrorText(retVal, msgTxt);
    MessageBox(msgTxt, "Error", 0);
    running = false;
    return;
  }
  // Now add matching records to the list box
  while (retVal >= 0) {
// make up list item
strncpy(listItem, details.List, sizeof(details.List));
    listItem[sizeof(details.List)] = '\0';
    // Add the item to the list box
    listBox->AddString(listItem);
    // Give user the chance to cancel and allow list box to update
    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    // Check if user cancelled
    if (cancelFlag) {
      MessageBox("Search Cancelled", "Cancelled", 0);
      return;
    }
    retVal = (afdData)(afdFieldSpec, AFD_GET_NEXT + AFD_LIST_ALIAS_LOCALITY, (char*)&details);
  }
  // Check results have been returned
  if (listBox->GetCount() == 0)
    MessageBox("No Results Found", "Error", 0);
  else {
    listBox->SetCurSel(0); // Select First item in the list
    OnSelchangeLstResult(); // Set this to your list change method to simulate selecting the first list item
  }
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;
  running = false;

String Utility Functions – Depreciated and Unsupported

These are provided for compatibility with existing applications which may depend on them but for new developments we would recommend you use in-built functions which are included with most modern development environments.

To carry out a string operation, you will first need to declare an instance of the AFDStringData structure you have declared in your general declarations module or class (see Section 4.1). You should then set the Lookup Field to the string that you wish to clean. If you wish to carry out a Search and Replace operation then you should also set the Search and Replace fields to the appropriate strings.

The operation parameter passed to the AFDData function determines the String operation which is carried out, and this should be one of the following:

Constant Description
AFD_ STRING_SEARCH_REPLACE All occurrences in the string specified in the Lookup field of the string specified in the Search field are replaced with the string in the Replace field.
AFD_STRING_SEARCH_REPLACE_CASE This is the same as AFD_STRING_SEARCH_REPLACE but is case sensitive.
AFD_STRING_CAPITALISE This corrects the capitalisation of the string specified in the Lookup field. For example ‘commercial STREET’ would become ‘Commercial Street’.
AFD_STRING_CLEAN_LINE This cleans the string specified in the Lookup field by removing spurious characters that should not be in an address line, e.g. a trailing comma.
AFD_STRING_CHECK_POSTCODE This checks if the string specified in the Lookup field looks like a postcode.
AFD_STRING_CLEAN_POSTCODE This cleans the postcode specified in the Lookup field to tidy up the postcode specified.
AFD_STRING_ABBREVIATE_COUNTY This provides the Royal Mail Approved county abbreviation for the county specified in the Lookup field if one exists.

You then call the AFDData function with the following three parameters:

  1. The String Field Specification String (as detailed in Section 4.1)
  2. The operation code (See above for options).
  3. The instance of the structure or type that you declared.

The AFDData function will return AFD_SUCCESS for most operations. If you are using AFD_STRING_CLEAN_POSTCODE then AFD_NO_RESULTS_FOUND will be returned if the string does not look like a postcode. For AFD_STRING_ABBREVIATE_COUNTY the constant AFD_NO_RESULTS_FOUND will also be returned if there is no Royal Mail approved abbreviation available for the specified county name.

The resulting string will be found in the Lookup Field of the structure. When using the AFD_STRING_CLEAN_POSTCODE function the Outcode and Incode portions of the postcode (portion before and after the space) will also be avaliable in the separate Outcode and Incode Fields.

Example VB code for a Search/Replace String Operation:
  Dim details As AFDStringData
  Dim retVal as Long 
  ' Set the Lookup, Search and Replace parameters
  details.Lookup = txtLookup.Text ' Change txtLookup.Text to your string entry textbox
  details.Search = txtSearch.Text ' Change txtSearch.Text to your search entry textbox
  details.Replace = txtReplace.Text ' Change txtReplace.Text to your replace textbox
  ' Carry out the String operation
  retVal = AFDData(afdStringFieldSpec, AFD_STRING_SEARCH_REPLACE, details)
  ' Check if success
  If retVal >= 0 Then
    ' details.Lookup holds the updated string
  End If
Example C++ code for a Search/Replace String Operation (Visual C++):
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  afdStringData details;
  long retVal;
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Update Data so we can read the lookup, search and replace variables
  UpdateData(TRUE);
  // Set the String to lookup, and the string to Search for and Replace with
  strcpy(details.Lookup, m_txtLookup); // Change this to your string textbox value variable
  strcpy(details.Search, m_txtSearch); // Change this to your search textbox value variable
  strcpy(details.Replace, m_txtReplace); // Change this to your replace textbox value variable
  // Carry out the String operation
  retVal = (afdData)(afdStringFieldSpec, AFD_STRING_SEARCH_REPLACE, (char*)&details);
  // Check if success
  if (retVal >= 0) {
    // details.Lookup holds the updated string
  }
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;

Grid Utility Functions – UK Address Management Only

These functions are used to carry out operations related to grid references and latitude and longitude values. You can convert between GB and Irish based grid references and also convert to and from latitude and longitude values. The facility to convert a value in kilometers to miles and vice-versa, return an approximate grid reference for a location and also calculate the distance between two geographical locations is also included.

To carry out a grid operation, you will first need to declare an instance of the AFDGridData structure you have declared in your general declarations module or class (see Section 4.1).

The operation parameter passed to the AFDData function determines the String operation which is carried out, and this should be one of the following:

Constant Value Description
AFD_GRID_CONVERT 512 Converts a GB or NI based grid reference, or latitude and longitude value to all other grid reference types and latitude and longitude values. You should set the location in the Fields of your structure or type instance, for example set the GBGridE and GBGridN fields and the function will return the NIGridE and NIGridN variants along with the latitude and longitude values etc. (This uses a 1m resolution (6 digit). Using a constant of 0 rather than 512 uses 5 digit grids).
AFD_GRID_LOOKUP_LOCATION 513 Looks up a town, locality, or partial postcode specified in the Lookup field and provides an approximate grid reference and latitude and longitude values for the location if a match is found. Can return multiple records if the location is ambiguous. (This uses a 1m resolution (6 digit). Using a constant of 1 rather than 513 uses 5 digit grids).
AFD_GRID_DISTANCE 514 Calculates the distance between a pair of grid references or latitude and longitude values specified. You will need to set a grid or latitude and longitude value in both the normal fields and those prefixed with “From” to find the distance in both Miles and Km. (This uses a 1m resolution (6 digit). Using a constant of 2 rather than 514 uses 5 digit grids).

You then call the AFDData function with the following three parameters:

  1. The Grid Field Specification String (as detailed in Section 4.1)
  2. The operation code (See above for options).
  3. The instance of the structure or type that you declared.

The AFDData function will return AFD_SUCCESS on success. If the operation fails, for example a location looked up does not exist or a grid reference specified is out of range then AFD_NO_RESULTS_FOUND will be returned.

You can then read the resulting grid reference, latitude and longitude values, or Km and Miles values as appropriate for the operation you have carried out and the data that you require.

Example VB code for converting a GB based grid reference:
  Dim details As AFDGridData
  Dim retVal as Long 
  ' Set the GBGridE and GBGridN parameters
  details.GBGridE = "406600" ' Change 406600 to the grid easting value you wish to convert
  details.GBGridN = "286500" ' Change 286500 to the grid northing value you wish to convert
  ' Carry out the Grid operation
  retVal = AFDData(afdGridFieldSpec, AFD_GRID_CONVERT, details)
  ' Check if success
  If retVal >= 0 Then
    ' Other elements of details hold converted values, e.g. Latitude and Longitude
  End If
Example C++ code for converting a GB based grid reference (Visual C++):
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  afdGridData details;
  long retVal;
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Set the GBGridE and GBGridN parameters
  strcpy(details.GBGridE, "406600"); // Change 406600 to the grid easting value you wish to convert
  strcpy(details.GBGridN, "286500"); // Change 286500 to the grid northing value you wish to convert
  // Carry out the Grid operation
  retVal = (afdData)(afdGridFieldSpec, AFD_GRID_CONVERT, (char*)&details);
  // Check if success
  if (retVal >= 0) {
    // Other elements of details hold converted values, e.g. Latitude and Longitude
  }
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;

Email Utility Function

This function is used to carry out validation of an email address. This verifies that the address is in the correct format for an email address and also that the domain exists to help minimise errors in data entry.

To carry out an email operation, you will first need to declare an instance of the AFDEmailData structure you have declared in your general declarations module or class (see Section 4.1).

The operation parameter passed to the AFDData function determines the level of validation which is carried out, and this should be one of the following:

Constant Value Description
AFD_EMAIL_FULL 0 Full email validation including live domain lookup
AFD_EMAIL_FORMAT 2 Validate email addres format is correct only
AFD_EMAIL_TLD 3 Validate email format is correct and the top level domain exists
AFD_EMAIL_LOCAL 4 Validate email format, top level domain and for well known domains carry out additional checks of the local portion of the address

You then call the AFDData function with the following three parameters:

  1. The Email Field Specification String (as detailed in Section 4.1)
  2. The operation code (See above for options).
  3. The instance of the structure or type that you declared.

The AFDData function will return AFD_SUCCESS on success. If the operation fails, for example the email address format is not valid then AFD_NO_RESULTS_FOUND will be returned.

Example VB code for validating an email address:
  Dim details As AFDEmailData
  Dim retVal as Long 
  ' Set the Email parameter
  details.Email = "support@afd.co.uk" ' Change support@afd.co.uk to the email address you wish to validate
  ' Carry out the Email operation
  retVal = AFDData(afdEmailFieldSpec, AFD_EMAIL_FULL, details)
  ' Check if success
  If retVal >= 0 Then
    ' Email address is valid
  End If
Example C++ code for validating an email address (Visual C++):
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  afdEmailData details;
  long retVal;
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Set the GBGridE and GBGridN parameters
  strcpy(details.Email, "support@afd.co.uk"); // Change support@afd.co.uk to the email address you wish to validate
  // Carry out the Email operation
  retVal = (afdData)(afdEmailFieldSpec, AFD_GRID_CONVERT, (char*)&details);
  // Check if success
  if (retVal >= 0) {
    // Email Address is Valid
  }
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;

Clean Function – UK Address Management Only

Requires a Refiner API License

The clean function allows an address, for example from a database, to be cleaned, i.e. where possible matched to Postcode Plus and therefore given a correct deliverable address.

To clean an address will first need to declare an instance of the AFD structure you have declared in your general declarations module or class

You will then need to set address fields in your structure to specifiy the address to be cleaned. These do not need to match up to the actual fields, for example if you have Address Line 1, Address Line 2, Address Line 3 and Postcode in your database you could set these to Property, Street, Locality and Postcode fields in the structure and they will be cleaned and returned in the correct named fields when matched. Note that if you set any non-address fields they will be ignored (Please see Appendix G for the list of fields that Refiner will use).

You then call the AFDData function with the following three parameters:

  1. The Field Specification String (as detailed in Section 4.1)
  2. The operation code (AFD_CLEAN constant)
  3. The instance of the structure or type that you declared.

The AFDData function will return a negative value (less than zero) in the case where an address cannot be fully matched. This could be because the address was unmatchable, International, or an ambiguous result was found (see Section 4.1.9 for details of these return codes). An address will still be returned as this will include the address with Field Placement correction which you can use if you desire.

Where the function returns a positive value (greater than zero) this means that the address has been uniquely matched. You may still like to examine the return value as this will give details as to the level to which the address was matched (see Section 4.1.9 for details of these return codes). Many other fields are also avaliable with additional (non-address data) which you may require.

In the case of an ambiguous or suggested result (return code is -102, -103, or -104) the first address returned from the function will be the original address with field placement. For non-batch processes you may wish to present a list of addresses for the user to choose from and in this case you can continue to call the AFDData function as above repeatedly with the same operation code as before, but adding the AFD_GET_NEXT constant to it to obtain subsequent records. These can be added to a list box as above or processed as required. You should call AFDData in a lookup to retrieve these records allowing the user to cancel the lookup should it take some time or they realise they have entered something incorrectly.

Example VB code to clean an Address:
  Dim details As AFDAddressData
  Dim retVal as Long 
  ' Replace lstResult with the name of your list box if you wish to display ambiguous results
  With lstResult
  ' Clear out any existing items in the list
  .Clear
  ' Clear Structure
  ClearAFDAddressData details
  ' Set the fields to specify the address that you wish to clean
  details.Organisation = txtSearchOrganisation.Text
  details.Property = txtSearchProperty.Text
  details.Street = txtSearchStreet.Text
  details.Locality = txtSearchLocality.Text
  details.Town = txtSearchTown.Text
  details.Postcode = txtSearchPostcode.Text
  ' Clean the Address
  retVal = AFDData(afdFieldSpec, AFD_CLEAN, details)
  ' Show the resulting address
  ' These are any of the members of the details. type (Use Trim to remove whitespace)
  txtName.Text = Trim(details.Name)
  txtOrganisation.Text = Trim(details.Organisation)
  txtProperty.Text = Trim(details.Property)
  txtStreet.Text = Trim(details.Street)
  txtLocality.Text = Trim(details.Locality)
  txtTown.Text = Trim(details.Town)
  txtPostcode.Text = Trim(details.Postcode)
  ' Show Cleaning Status
  Msgbox AFDRefinerCleaningText(retVal)
  ' If ambiguous then add matching records to the list box for user selection
  '  - This is optional and not normally useful for batch processes
  If retVal = AFD_REFINER_AMBIGUOUS_POSTCODE Or retVal = AFD_REFINER_AMBIGUOUS_MATCH Or retVal = AFD_REFINER_SUGGEST_RECORD Then
    Do While retVal <> AFD_ERROR_END_OF_SEARCH
      ' Add the item to the list box with hidden key at the end
      .AddItem details.List + details.Key
      retVal = AFDData(afdFieldSpec, AFD_GET_NEXT  + AFD_CLEAN, details)
    Loop
  End If
  End With
Example C++ Code to clean an address (Visual C++)
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  afdAddressData details;
  char listItem[2055];
  char msgTxt[255];
  long retVal;
  CListBox* listBox;
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Replace lstResult with the name of your list box if you wish to display ambiguous results
  listBox = &m_lstResult;
  // Clear out any existing items in the list
  listBox->ResetContent();
  // Update Data so we can read the search variables
  UpdateData(TRUE);
  // Set the fields to specify the address that you wish to clean
  strcpy(details.Organisation, m_txtSearchOrganisation);
  strcpy(details.Property, m_txtSearchProperty);
  strcpy(details.Street, m_txtSearchStreet);
  strcpy(details.Locality, m_txtSearchLocality);
  strcpy(details.Town, m_txtSearchTown);
  strcpy(details.Postcode, m_txtSearchPostcode);
  // Clean the Address
  retVal = (afdData)(afdFieldSpec, AFD_CLEAN, (char*)&details);
  // Show the resulting address
  // These are any of the members of the details. structure
  m_txtName = details.Name;
  m_txtOrganisation = details.Organisation;
  m_txtProperty = details.Property;
  m_txtStreet = details.Street;
  m_txtLocality = details.Locality;
  m_txtTown = details.Town;
  m_txtPostcode = details.Postcode;
  // Update Fields
  UpdateData(FALSE);
  // Show Cleaning Status
  AFDRefinerCleaningText(retVal, msgTxt);
  MessageBox(msgTxt, "Cleaning Status", 0);
  // If ambigious then add matching records to the list box for user selection
  //  - This is optional and not normally useful for batch processes
  if ((retVal == AFD_REFINER_AMBIGUOUS_POSTCODE) || (retVal == AFD_REFINER_AMBIGUOUS_MATCH) || (retVal == AFD_REFINER_SUGGEST_RECORD)) {
    while (retVal != AFD_ERROR_END_OF_SEARCH) {
      // make up list item with hidden key at the end
      strncpy(listItem, details.List, sizeof(details.List));
      strncpy(listItem + sizeof(details.List), details.Key, sizeof(details.Key));
      listItem[sizeof(details.List) + sizeof(details.Key)] = '\0';
      // Add the item to the list box
      listBox->AddString(listItem);
      retVal = (afdData)(afdFieldSpec, AFD_GET_NEXT + AFD_CLEAN, (char*)&details);
    }
  }
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;

Other Features

Selecting TraceMaster Datasets

AFD Names & Numbers TraceMaster includes historic datasets for Address Management Data going back to 1998. These provide previous year’s electoral rolls and business data. Lookup and Search operations function as described in sections 4.2 and 4.3 of this documentation function with TraceMaster in the same way as with all other products.

By default these operations will operate using the Current (latest) dataset. However to use a historic dataset simply specify the dataset name (year) in the DataSet Field of the AFDData structure. The product will automatically carry out your Lookup or Search operation using the specified dataset.

To retrieve records from all datasets, you can call the AFDData function in a loop specifying each dataset in turn.

Determining the Product in Use

When integrating with Address Management products the same code will work with any of our Address Management products (AFD Postcode, AFD Postcode Plotter, AFD Postcode Plus, AFD Names & Numbers and AFD Names & Numbers TraceMaster).

It is not normally necessary to determine which product has been used as you can integrate with one, e.g. Names & Numbers and the user can use any of our address management products – they will just have less data returned depending on the product they have. However, if for any reason, such as disabling/enabling features of your product - you can use the Product field if you wish to determine which product the user has and that has been used by the Common API.

Note that in the case of multiple address management products being installed the AFD Common API will use the highest level product available. For example, AFD Names & Numbers would be used in preference to AFD Postcode.

The Product field will contain one of the following values depending on the product being used:

  • AFD Postcode
  • AFD Postcode Plotter
  • AFD Postcode Plus
  • AFD Names & Numbers
  • AFD Names & Numbers TraceMaster

Note that when carrying out a BankFinder operation AFD BankFinder will always be the product name returned.

Using Welsh Data in Postcode Plus

Welsh data is available for Postcode Plus on request. It works alongside the existing English language PAF data and provides Welsh language equivalents for streets, localities and towns in Wales were such equivalents are available.

To obtain address details using the Welsh variant simply set the DataSet property of the address structure to “Welsh” prior to making your call to the API. Any operation including lookup’s, searches and retrieving records can be done using either dataset. Note that the data returned when using either dataset will be the same if no Welsh language alternative is available.

You can also retrieve the same record in both Welsh and English simply by calling the API to retrieve the record once with the DataSet property set to an empty string (or English if you prefer) and once set to “Welsh”. For example, if you carry out a lookup for a postcode, as specified in Section 4.2 of this documentation, and add the items to a list box, when the user selects an item from the list you can retrieve the same address in both Welsh and English language variants by using the List Fetch operation described in Section 4.4 twice for the same record, once with the DataSet parameter set to Welsh and once with it not set.

Example VB code to fetch an item selected in the list in both English and Welsh:
  Dim details As AFDAddressData
  Dim welshDetails As AFDAddressData
  Dim pos As Long, retVal As Long
  ' Replace lstResult with the name of your list box for the results
  With lstResult
  ' Check a valid item is selected
  If .ListIndex = -1 Then
    MsgBox "No Item Selected"
    Exit Sub
  End If
  ' Set DLL parameters to retrieve the selected record
  details.Key = Mid(lstResult, 513) ' Replace lstResult with the name of your list box for the results
  ' We will want the same record in Welsh too
  welshDetails.Key = details.Key
  ' Finished with the list box
  End With
  ' Set DataSet to Welsh for welshDetails
  details.DataSet = ""
  welshDetails.DataSet = "Welsh"
  ' Carry out the lookup for English language data and then Welsh language data
  retVal = AFDData(afdFieldSpec, AFD_RETRIEVE_RECORD, details)
  retVal = AFDData(afdFieldSpec, AFD_RETRIEVE_RECORD, welshDetails)
  ' Abort with Message if error
  If retVal < 0 Then
    MsgBox AFDErrorText(retVal)
    Exit Sub
  End If
  ' Now Assign required fields to your application
  ' These are any of the members of the details. type (Use Trim to remove whitespace)
  txtEnglishName.Text = Trim(details.PostalCounty)
  txtEnglishOrganisation.Text = Trim(details.AbbreviatedPostalCounty)
  txtEnglishProperty.Text = Trim(details.OptionalCounty)
  txtEnglishStreet.Text = Trim(details.AbbreviatedOptionalCounty)
  txtEnglishLocality.Text = Trim(details.TraditionalCounty)
  txtEnglishTown.Text = Trim(details.AdministrativeCounty)
  txtEnglishPostcode.Text = Trim(details.Postcode)
  txtWelshName.Text = Trim(welshDetails.PostalCounty)
  txtWelshOrganisation.Text = Trim(welshDetails.AbbreviatedPostalCounty)
  txtWelshProperty.Text = Trim(welshDetails.OptionalCounty)
  txtWelshStreet.Text = Trim(welshDetails.AbbreviatedOptionalCounty)
  txtWelshLocality.Text = Trim(welshDetails.TraditionalCounty)
  txtWelshTown.Text = Trim(welshDetails.AdministrativeCounty)
  txtWelshPostcode.Text = Trim(welshDetails.Postcode)
Example C++ code to fetch an item selected in the list for Address Management products (Visual C++):
  HINSTANCE afdDLL = (HINSTANCE)NULL;
  AFDDATA afdData = (AFDDATA)NULL;
  afdAddressData details;
  afdAddressData welshDetails;
  bool foundSel = false;
  long retVal;
  CListBox* listBox;
  char lstStr[2055];
  char msgTxt[255];
  // Load DLL
  if (!afdInitDLL(&afdDLL, &afdData)) {
    MessageBox("Error Loading afddata.dll", "Error", 0);
    return;
  }
  // Replace m_lstResult with the name given to a variable assigned to your list box control for the results
  listBox = &m_lstResult;
  // Set DLL parameters to retrieve the selected record
  listBox->GetText(listBox->GetCurSel(), lstStr);
  strncpy(details.Key, lstStr + sizeof(details.List), sizeof(details.Key));
  // We will want the same record in Welsh too
  strncpy(welshDetails.Key, details.Key, sizeof(details.Key));
  ' Set DataSet to Welsh for welshDetails
  strcpy(details.DataSet, "");
  strcpy(welshDetails.DataSet, "Welsh");
  // Carry out the lookup for English language data and then Welsh language data
  retVal = (afdData)(afdFieldSpec, AFD_RETRIEVE_RECORD, (char*)&details);
  retVal = (afdData)(afdFieldSpec, AFD_RETRIEVE_RECORD, (char*)&welshDetails);
  // Abort with Message if error
  if (retVal < 0) {
    AFDErrorText(retVal, msgTxt);
    MessageBox(msgTxt, "Error", 0);
    return;
  }
  // Now Assign required fields to your application
  // These are any of the members of the details. structure
  m_txtEnglishName = details.Name;
  m_txtEnglishOrganisation = details.Organisation;
  m_txtEnglishProperty = details.Property;
  m_txtEnglishStreet = details.Street;
  m_txtEnglishLocality = details.Locality;
  m_txtEnglishTown = details.Town;
  m_txtEnglishPostcode = details.Postcode;
  m_txtWelshName = welshDetails.Name;
  m_txtWelshOrganisation = welshDetails.Organisation;
  m_txtWelshProperty = welshDetails.Property;
  m_txtWelshStreet = welshDetails.Street;
  m_txtWelshLocality = welshDetails.Locality;
  m_txtWelshTown = welshDetails.Town;
  m_txtWelshPostcode = welshDetails.Postcode;
  // Update Fields
  UpdateData(FALSE);
  // free DLL instance
  FreeLibrary(afdDLL);
  afdDLL = (HINSTANCE)NULL;

DX Member Data

DX Members can have access to DX data from within Postcode Plus and the Common API. This enables you to lookup and search for DX addresses just as you can do with Royal Mail postal addresses. Uniquely, the Common API also allows you to easily identify DX addresses associated with a PAF address to route your mail through a DX member's box wherever possible resulting in savings over Royal Mail.

If you run the Wizard to generate a code sample with DX data installed declarations will be included for the DXNumber (10 characters), DXExchange (30 characters) and DXProfession (30 Characters). You can also manually add these to your field specification string and structure. Postcode Everywhere users will automatically have these fields returned in the XML if they have the DX data installed.

Fast-find functionality works with DX data as well as postal data. For example, as well as looking up a postcode you can also carry out a fast-find for a DX number and searching for an organisaiton name with fast-find will search both postal and DX data. This allows you to easily combine your lookup’s. When searching you can either search the standard postal fields or specify the DX Number, organisation, exchange or profession to search theDX data instead. (If you only want to specify one set of search fields in your application then placing DX followed by the DX number in the normal street field will work too – town can then be used to specify the exchange if desired).

When results are returned following any lookup or search if the address is also a DX Member the DXNumber, DXExchange and DXProfession fields will also be returned to indicate this. You can format a DX address as follows for printing:

<Organisation>      e.g.    Pannone LLP
DX <DXNumber>           DX 14314
<DXExchange>            MANCHESTER

See Appendix K for a current list of available DX Professions and Exchanges.

Appendicies

For our full list of appendicies please download the full Common API Manual