Zipinfoplus statement

It looks like the Post Office has changed their website, so Zip code lookup no longer works. It may be a while before I can get around to figuring it out and updating the zipinfoplus statement.

I am having trouble posting the address to the USPS site to get the Zip Code information. If anyone can help with this, I think this can be resolved quickly.

What does “posting the address” mean in this context?

What I need to know is how to input the address to the webpage to get to the result: the corrected address and Zip+4.

The address of the form, and also the address of the response when I submitted it was

https://tools.usps.com/go/ZipLookupAction_input#zipCodeByAddress

The input tags for the 5 fields were

<input id="tCompany" name="tCompany" tabindex="0" type="text" class="form-control" placeholder="" maxlength="38"/>
<input id="tAddress" name="tAddress" tabindex="0" type="text" class="form-control" placeholder="123 Main Street" data-error="Please enter an address."required maxlength="38"/>
<input id="tApt" name="tApt" tabindex="0" type="text" class="form-control" placeholder="" maxlength="38" />
<input id="tCity" name="tCity" tabindex="0" type="text" class="form-control" placeholder="City" data-error="Please enter a city." required maxlength="50"/>
<select id="tState" name="tState"  class="form-control dropdown" data-required-error="Please select a state." required>

I haven’t tried writing a procedure to post that. I hope it helps.

It appears that this URL will return the zip+4 info, but not the county or carrier route. I did some poking around the USPS web site but so far I have not found a page that will look up that information. Perhaps USPS no longer provides that info?

The Address Info Wizard in Panorama 6 still returns the county. I might be able to find the Carrier Route somewhere, but I have not poked around enough to be certain.

I just tried it and it worked for me once, then it stopped working. Put some debug code in and discovered that the post office was denying access. I think that’s why that old URL isn’t being used any more in the Panorama X version.

Carrier Route is returned about line 1555, County about line 1565, but I cannot figure out how to post the data yet.

You must be accessing a completely different URL than I am, I don’t see that data at all.

I could be. It is https://tools.usps.com/go/ZipLookupAction!input.action#zipCodeByAddress

This may or may not help with some clarity on this issue.

Using this page:
https://tools.usps.com/go/ZipLookupAction!input.action#zipCodeByAddress https://tools.usps.com/go/ZipLookupAction!input.action#zipCodeByAddress

If I enter 14900 Shell Point Blvd, Fort Myers, FL, the post office displays a down arrow to the right of the address where they display the zip code.

Using that down arrow, we can then see the other hidden info that does not typically display. The additional data does now show the Carrier Route and County. It is the same URL but the additional data must be accessed either through the tags or through manual manipulation of the down arrow and visually seeing it. They are merely hiding it until the user asks to see it. The data is back there already though.

Yes, the problem is inputting the address to check from Panorama. Once that is done, I should be able to scrape out all that good stuff.

Can we presume that ZipInfoPlus is still a work in progress?

I think I have it:

/*
<PROCEDUREINFO>
  <DESCRIPTION>
  This statement queries the web to obtain information about a zip code.
  </DESCRIPTION>
  <PARAMETER NAME=ADDRESS1 TYPE=TEXT>First line of address.</PARAMETER>
  <PARAMETER NAME=ADDRESS2 TYPE=TEXT>Second line of address (optional).</PARAMETER>
  <PARAMETER NAME=CITY TYPE=TEXT>Name of city.</PARAMETER>
  <PARAMETER NAME=STATE TYPE=TEXT>Two letter state abbreviation.</PARAMETER>
  <PARAMETER NAME=ZIP5 TYPE=TEXT>Five digit zip code (optional).</PARAMETER>
  <PARAMETER NAME=ZIPPLUSINFO TYPE=TEXT>This returns a dictionary (see GETDICTIONARYVALUE) with information about this zipcode.
  The dictionary will contains one or more of the values listed below.<p>
  "ADDRESS" - Corrected street address
  "CITY" - This is the primary name of the city associated with this address.<p>
  "STATE" - Two letter abbreviation of the state this address is in.<p>
  "ZIP9" - Nine digit zip code.<p>
  "COUNTY" - Name of the county associated with this address.<p>
  "CARRIERROUTE" - Name of the carrier route associated with this zip code.<p>
  </PARAMETER>
<EXAMPLES>
This example checks an address in the database to see if it is correct.
If it is completely invalid, an error message is displayed.
If it is not formatted correctly by USPS rules, the database is corrected.<p>
local zinfo,correctAddress<br>
zipinfoplus Address,"",City,State,Zip,zinfo<br>
correctAddress=getdictionaryvalue(zinfo,"ADDRESS")<br>
if correctAddress=""<br>
	message "Address is not valid!"<br>
	rtn<br>
endif<br>
if correctAddress=Address rtn endif<br>
Address=correctAddress</EXAMPLES>
</PROCEDUREINFO>
*/


local Page,Page1,Address1,Address2,City,State,County,Zip,CarrierRoute,zig,ziga,zipinfoplus,Adurl


Address1=parameter(1)
Address2=parameter(2)
City=parameter(3)
State=parameter(4)
Zip=parameter(5)
if datatype("Zip") notmatch "text"
	Zip=str(Zip)
endif
Adurl = 'https://www.zip-codes.com/search.asp?fld-address='+replace(Address1 +sandwich(" ",Address2,"")," ","+")+'&fld-city2='+replace(City," ","+") +'&fld-state2='+ replace(State," ","+") +'&srch=Find+ZIP%2B4'


loadurl Page1,Adurl

//displaydata Page1

Page = strip(tagdata(Page1,'<div style="font-size: 22px; text-align:center; padding-bottom:50px; padding-top:30px;">','</div>',1))
//displaydata Page

zipinfoplus=""

setdictionaryvalue zipinfoplus,"ADDRESS",strip(textbefore(Page,"<br>"))
setdictionaryvalue zipinfoplus,"CITY",strip(tagdata(Page,'<br>',',',1))
setdictionaryvalue zipinfoplus,"STATE",tagdata(Page,', ','&nbsp',1)
setdictionaryvalue zipinfoplus,"ZIP9",tagdata(Page,'<span style="color:#FF0000;">','</span>',1)

setdictionaryvalue zipinfoplus,"COUNTY",strip(replace(tagdata(Page1,'<dt>County</dt>','</dd>',1),"<dd>",""))
setdictionaryvalue zipinfoplus,"CARRIERROUTE",tagdata(tagdata(Page1,'<dt>Carrier Route</dt>','</dd>',1),'<dd>',' ',1)

setparameter 6,zipinfoplus

rtn

I did have a problem that arose from a carriage return where there should not have been one, so I suggest substituting
Adurl = strip9’https://www.zip-codes.com/search.asp?fld-address=’+replace(Address1 +sandwich(" “,Address2,”")," “,”+")+’&fld-city2=’+replace(City," “,”+") +’&fld-state2=’+ replace(State," “,”+") +’&srch=Find+ZIP%2B4’)

Your 2nd post has a ‘9’ where a ‘(’ should have been.

I’m not clear how you are intending others to make use of this but this is what I did to try it out.

I pasted your procedure into a new db and named the procedure ‘A ZipInfoPlus’. I created a field named ‘Response’.

I created a 2nd procedure with this text…

Local LCorrectedAddress

Call 'A ZipInfoPlus',"303 Placentia","Suite 200","Fullertoon","CA","92832",LCorrectedAddress

Response = LCorrectedAddress

When I ran the above procedure, this is what was in the ‘Response’ field…

˛ADDRESSˇ303 N PLACENTIA AVE STE 200˛/ADDRESSˇ˛CITYˇFULLERTON˛/CITYˇ˛STATEˇCA˛/STATEˇ˛ZIP9ˇ92831-4401˛/ZIP9ˇ˛COUNTYˇ˛/COUNTYˇ˛CARRIERROUTEˇ˛/CARRIERROUTEˇ

It did correct the lack of a directional indicator (‘N’) and added the street suffix.
It did correct the incorrect spelling of the city.
It did correct the zip code.

It did not return the County
It did not return the Carrier Route

The response needs cleanup of extraneous text.

I am not seeing any purpose for the ‘zig’, ‘ziga’ local variables in your procedure.

Where you declared the local variables, I would suggest using names that would obviously not conflict with a users field naming. ie. LPage, LPage1, LAddress1, etc.

You are correct, I did not shift the 9. It should be:
Adurl = strip(’https://www.zip-codes.com/search.asp?fld-address=’+replace(Address1 +sandwich(" “,Address2,”")," “,”+")+’&fld-city2=’+replace(City," “,”+") +’&fld-state2=’+ replace(State," “,”+") +’&srch=Find+ZIP%2B4’)

As for the rest, I never had anything about the carrier route or the county when I first got the statement to work. It may not have worked earlier, when I could still scrape the USPS site. I do not claim it works now, although it would be possible to add the county, I think.

Please note that I have not been able to figure out how to post addresses to the USPS Zip Code site, so this uses another website, and all I wanted to do was to be able to check addresses, which it does, more or less. I think it still has problems with the Address2, just as the USPS site does: it has to be something that is recognized as a legitimate address extension: Apartment, Suite, etc. or abbreviations thereof.

There is a lot of extraneous stuff there. Feel free to edit it out. In Panorama X, all of the descriptive stuff at the beginning can be cut out.

I admit this is not ideal, but it is something that works for now. Eventually, we might be able to get a better version, but that would require registering with the USPS, which is free. This is the best that I can do.

To make it work in Panorama 6, paste it into the source in the Custom Statements Wizard. In X, use the Open View… menu to find it, choosing “+Libraries”, and paste it there. Remember to save after you paste.

I think what he had in mind was that you would modify the copy of this code that already comes with Panorama X. There was a forum post some time ago about how to modify library code that comes with Panorama. But what you did will also work.

It did not return the County
It did not return the Carrier Route

The web site Bruce is using doesn’t return that information.

The response needs cleanup of extraneous text.

That is what a dictionary looks like in Panorama 6. You can access the individual components with the getdictionaryvalue( function.

No, that doesn’t matter. As long as that procedure itself doesn’t need to access any fields in a database, which of course it doesn’t, it doesn’t matter whether the local variable names conflict with field names or not. The scope of these variables is only in this procedure, so it won’t affect the ability to access database fields in any other code. Now with fileglobal, windowglobal or global variables you have to be more careful about avoiding conflicts, especially global variables since they could potentially conflict with fields or variables in any open database.

As it turns out, I can do County:

/*
<PROCEDUREINFO>
  <DESCRIPTION>
  This statement queries the web to obtain information about a zip code.
  </DESCRIPTION>
  <PARAMETER NAME=ADDRESS1 TYPE=TEXT>First line of address.</PARAMETER>
  <PARAMETER NAME=ADDRESS2 TYPE=TEXT>Second line of address (optional).</PARAMETER>
  <PARAMETER NAME=CITY TYPE=TEXT>Name of city.</PARAMETER>
  <PARAMETER NAME=STATE TYPE=TEXT>Two letter state abbreviation.</PARAMETER>
  <PARAMETER NAME=ZIP5 TYPE=TEXT>Five digit zip code (optional).</PARAMETER>
  <PARAMETER NAME=ZIPPLUSINFO TYPE=TEXT>This returns a dictionary (see GETDICTIONARYVALUE) with information about this zipcode.
  The dictionary will contains one or more of the values listed below.<p>
  "ADDRESS" - Corrected street address
  "CITY" - This is the primary name of the city associated with this address.<p>
  "STATE" - Two letter abbreviation of the state this address is in.<p>
  "ZIP9" - Nine digit zip code.<p>
  "COUNTY" - Name of the county associated with this address.<p>
  </PARAMETER>
<EXAMPLES>
This example checks an address in the database to see if it is correct.
If it is completely invalid, an error message is displayed.
If it is not formatted correctly by USPS rules, the database is corrected.<p>
local zinfo,correctAddress<br>
zipinfoplus Address,"",City,State,Zip,zinfo<br>
correctAddress=getdictionaryvalue(zinfo,"ADDRESS")<br>
if correctAddress=""<br>
	message "Address is not valid!"<br>
	rtn<br>
endif<br>
if correctAddress=Address rtn endif<br>
Address=correctAddress</EXAMPLES>
</PROCEDUREINFO>
*/


local Page,Page1,Address1,Address2,City,State,County,Zip,zipinfoplus,Adurl


Address1=parameter(1)
Address2=parameter(2)
City=parameter(3)
State=parameter(4)
Zip=parameter(5)
if datatype("Zip") notmatch "text"
	Zip=str(Zip)
endif
Adurl = strip('https://www.zip-codes.com/search.asp?fld-address='+replace(Address1 +sandwich(" ",Address2,"")," ","+")+'&fld-city2='+replace(City," ","+") +'&fld-state2='+ replace(State," ","+") +'&srch=Find+ZIP%2B4')


loadurl Page1,Adurl

//displaydata Page1

Page = strip(tagdata(Page1,'<div style="font-size: 22px; text-align:center; padding-bottom:50px; padding-top:30px;">','</div>',1))
//displaydata Page

zipinfoplus=""

setdictionaryvalue zipinfoplus,"ADDRESS",strip(textbefore(Page,"<br>"))
setdictionaryvalue zipinfoplus,"CITY",strip(tagdata(Page,'<br>',',',1))
setdictionaryvalue zipinfoplus,"STATE",tagdata(Page,', ','&nbsp',1)
setdictionaryvalue zipinfoplus,"ZIP9",tagdata(Page,'<span style="color:#FF0000;">','</span>',1)

setdictionaryvalue zipinfoplus,"COUNTY",strip(replace(tagdata(Page,'<br><i>County: ','</i>',1),"<dd>",""))
setdictionaryvalue zipinfoplus,"CARRIERROUTE",tagdata(tagdata(Page1,'<dt>Carrier Route</dt>','</dd>',1),'<dd>',' ',1)

setparameter 6,zipinfoplus

rtn