Consultancy and Programming
Advice, tips, techniques and downloads for Visual Foxpro developers.
If your application processes UK postcodes, you'll need an effective way of validating them. Postcodes in the UK do much more than speed the mail. They are widely used to link individuals to various types of geographical, demographic and marketing data, and it's especially important that they are recorded and processed accurately.
Unlike with US zip codes, you can't download a simple text file containing all known postcodes for use in validation routines. The official Postcode Address File (PAF) contains around 27 million codes, and is subject to strict copyright and licensing controls. The only practical way to access it is by purchasing specialised address management software, and this is inevitably an expensive option.
However, UK postcodes follow strict formatting rules. If you don't have access to the PAF, you can at least check that the postcodes in your application follow these rules. In this article, we offer a VFP function that does just that. (For an equivalent SQL Server function, see Parsing and validating UK postcodes in SQL Server.)
The formatting rules for postcodes appear complex at first, but are in fact straightforward. Essentially, every postcode consists of two elements, separated by a space. The outward part of the code comes first, then the space, then the inward part of the code. So, in the postcode RG6 1WG (which happens to be that of Microsoft's UK headquarters), RG6 is the outward code and 1WG is the inward code.
The inward code always consists of exactly one digit followed by exactly two letters. Furthermore, the letters C, I, K, M, O and V never appear in the inward code (because they are easily confused with digits).
As for the outward code, this consists of either one or two letters, followed by either one or two digits. The letters represent the 124 UK postal areas (RG, for example, is Reading), while the digits indicate the districts within the areas. Most of the postal areas have two letters, but eight of them are represented by a single letter (e.g. G for Glasgow).
As an exception, a few central London postcodes have an additional letter after the district. Thus, SW1A is the outward code for parts of Westminster (SW1A 2AA, for example, is the prime minister's postcode).
To summarise, all valid postcodes match one of the following patterns (where A represents a letter, 9 a digit):
|A9 9AA||M1 1BA|
|A99 9AA||N12 1UD|
|AA9 9AA||EH9 4UA|
|AA99 9AA||RG6 1WG|
|A9A 9AA||W1A 1NA|
|AA9A 9AA||SW1A 1HQ|
There are a very few postcodes that don't follow the above rules, but most applications can safely ignore these. They include special codes for UK dependent territories (FIQQ 1ZZ for the Falkland Islands, for instance) and the code GIR 0AA, which is used by the National Girobank. Our VFP function disregards these special cases.
Remember, our postcode validation function only checks that the code is in the correct format. A code might pass this test but still not be a genuine postcode. To determine whether a postcode actually exists, you would need to access the Postcode Address File. (But even that wouldn't be a perfect check, as the PAF is never completely up to date; postcodes are constantly being added, and existing premises are occasionally re-coded.)
You can improve the accuracy of the validation by checking the first one or two letters against a lookup table of the 124 postal areas (which can be found at www.upu.int/post_code/en/countries/GBR.pdf). If you do, keep in mind that the list of postal areas is itself subject to change - albeit infrequently - so be prepared to update the lookup table when necessary.
Here then is our FoxPro function for checking the validity of a UK postcode. Feel free to copy and paste it into your application. To use it, simply call the CheckPostcode function, passing the postcode as a parameter. The function will return .T. if the code passes the test, .F. otherwise.
FUNCTION CheckPostcode * Checks that a UK postcode is syntactically valid. * The code must be all caps, and must include a space * between the inward and outward portions (multiple * spaces are allowed). LPARAMETERS tcCode LOCAL lcTest, lcInLetters, lcInward, lcOutward tcCode = ALLTRIM(tcCode) * Check for the space IF SUBSTR(tcCode, LEN(tcCode)-3, 1) <> " " RETURN .F. ENDIF * Create a string in which all the capital letters * in the code are represented as A, all the digits * as 9, and all other characters remain unchanged. lcTest = ; CHRTRAN(tcCode, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", ; REPLICATE("A", 26)) lcTest = ; CHRTRAN(lcTest, "0123456789", ; REPLICATE("9", 10)) * Separate out the test string into outward and * inward portions lcOutward = ALLTRIM(LEFT(lcTest, LEN(tcCode)-4)) lcInward = RIGHT(lcTest, 3) * The inward portion must be in the format 9AA IF lcInward <> "9AA" RETURN .F. ENDIF * Certain letters disallowed in the inward portion lcInLetters = RIGHT(tcCode, 2) IF lcInLetters <> CHRTRAN(lcInLetters, "CIKMOV", "") RETURN .F. ENDIF * The outward portion must be in one of the * following formats: * A9, AA9, A99, AA99, A9A, AA9A IF NOT INLIST(lcOutward, ; "A9", "AA9", "A99", "AA99", "A9A", "AA9A") RETURN .F. ENDIF RETURN .T. ENDFUNC
As well as being a useful function in its own right, the above code neatly demonstrates a simple form of pattern matching. Rather than using a complex DO CASE construct to check the various combinations of string length and character values, we reduce the submitted postcode to a simple pattern in which letters are represented as As, digits as 9s, and all other characters (including spaces) are left unchanged. It then become an easy matter to test the code against a list of valid patterns.
This form of pattern matching can be applied to many other types of validation. Even if you never need to check UK postcodes, we hope you'll find the technique useful for other tasks.
Mike Lewis Consultants Ltd. March 2006.
FoxStuff is maintained by Mike Lewis Consultants Ltd. as a service to the VFP community. Feel free to download and use any code or components, and to pass around copies of the articles (but please do not remove our copyright notices or disclaimers).
The information given on this site has been carefully checked and is believed to be correct, but no legal liability can be accepted for its use. Do not use code, components or techniques unless you are satisfied that they will work correctly in your applications.
© Copyright Mike Lewis Consultants Ltd.