Here is a function for your grids (and UX components with a change or two) to automatically lookup and verify address and add the 9 digit zip code. It is a modification of a process that I found on www.learnalpha.com about an article that Jay Talbott had written. Thank you Jay!

For grid use, add a button under the address fields called 'Address Verify'. Then set up an Ajax Callback function called PostOffice that is called when you click the button. Then add the following function to the Xbasic Functions.

You will probably have to rename field names in this function to reflect the actual field names in your grid. This function will also get the county for the address. If you don't have that field in your table, then be sure to rem out that line in the function.
The nice thing about this is that the user only needs to enter the street address, city and state. This function will return and fill in or correct the street address, city, state and 9 digit zip code. It means that you will get the proper street address formatted in post office format and the proper zip code. If you enter in 3222 E Kristal for example, it will return 3222 E Kristal Way and fill in the field for you. It also checks for basic errors and for multiple addresses. What I mean by multiple addresses is this. Say you put in an address of 5225 N Central, Phoenix, AZ. You will get that error message. That address is composed of several suites, so it is telling you that you need to include the suite number in the address field in order for the post office to process it. That is particularly useful when people forget to give you that piece of information or the suite or apartment number is incorrect.

Hope you find it useful.

Mike


function PostOffice as c (e as p)
'change the next 3 lines as needed to match your actual field names
vc_address1 = alltrim(e._currentRowDataNew.addr2)
vc_city = alltrim(e._currentRowDataNew.city)
vc_state = alltrim(e._currentRowDataNew.state)
vc_zip = ""
vc_zip4 = ""
vc_county = ""
error = ""


'debug(1)
'the url = must be on one line, not 2 as shown here
url = "https://tools.usps.com/go/ZipLookupResultsAction!input.action?resultMode=1&companyName=&address1=" +vc_address1 + "&address2=&city=" + vc_city + "&state=" + vc_state + "&urbanCode=&postalCode=&zip=" + vc_zip
result=http_get_page2(url,.f.)


scanner=stringscanner.create(result)


'check for muliple unit error
scanner.SkipToString("Several addresses matched the information you")
scanner.SkipOverString(" ")
error = scanner.ScantoString("you didn't")
if error = "Several addresses matched the information you provided. Perhaps " then
PostOffice = "alert('" + js_escape("Several addresses matched the information you provided. Perhaps you didn't enter a street number or the building has mulitple units.") + "');"
end
end if




'Start over to check for next error
scanner.reset()
'Check for invalid address
scanner.SkipToString("Unfortunately, this address wasn't found.")
error = scanner.ScanToString(".")
if error = "Unfortunately, this address wasn't found" then
PostOffice = "alert('This address cannot be found in the Post Office database, please check the spelling and try again.');"
end
end if




'Start over to check for next error
scanner.reset()
'Check for invalid address
scanner.SkipToString("The address you provided is not recognized")
error = scanner.ScanToString("by")
if error = "The address you provided is not recognized" then
PostOffice = "alert('This address cannot be found in the Post Office database, please check the address and try again.');"
end
end if




'Start over to retrieve address info
scanner.reset()


scanner.SkipToString("<!-- Begin zip-lookup-result-container-single.jsp-->")


scanner.SkipToString("address1")
scanner.SkipOverString("&nbsp;")
scanner.SkipToString("range"")
scanner.SkipOverString("range">")
vc_address1 = scanner.ScanToString("</")


scanner.SkipToString("class="city")
scanner.SkipOverString("&nbsp;")
scanner.SkipToString("range"")
scanner.SkipOverString("range">")
vc_city = scanner.ScanToString("</" )


scanner.SkipToString("class="state" )
scanner.SkipOverString("&nbsp;")
scanner.SkipToString("range"")
scanner.SkipOverString("range">")
vc_state = scanner.ScanToString("</" )


scanner.SkipToString("class="zip"" )
scanner.SkipOverString("&nbsp;")
scanner.SkipToString("style=""")
scanner.SkipOverString("style=""")
scanner.SkipOverString(">")
vc_zip = scanner.ScanToString("</" )


scanner.SkipToString("class="zip4"" )
scanner.SkipOverString("class="zip4"")
scanner.SkipOverString(">")
vc_zip4 = scanner.ScanToString("</" )


scanner.SkipToString("County</dt>" )
scanner.SkipToString("<dd")
scanner.SkipOverString("<dd")
scanner.SkipOverString(">")
vc_county = scanner.ScanToString("</" )


vc_zip = vc_zip + "-" + vc_zip4

'change the next 5 lines as needed to reflect your actual field names
e._set.addr2.value = vc_address1
e._set.city.value = vc_city
e._set.state.value = vc_state
e._set.zip.value = vc_zip
e._set.county.value = vc_county
PostOffice = ""


end function