Zip Code Sorting
Posted in 1995
It was recently requested of me to modify a label printing program
we've had around for a long time (possibly even version 1.0). We have
a client that does bulk mailings once or twice a year and they want to
take advantage of special rates for sorting by zip code. I've written
a few functions that satisfy the request but I can see potential for
improvement and increased functionality. So, if any of you would care
to play with this --- here it is.
I've made note of some possible enhancements on the other end of
the included code.
Here is a short bit of the output:
#####
Loose Letters for 89119 to 89130 (2 pieces)
Loose Letters for 90000 (2 pieces)
Bundle (5 digits) for 90001 (52 pieces)
Bundle (5 digits) for 90002 (20 pieces)
Bundle (5 digits) for 90003 (39 pieces)
Bundle (5 digits) for 90004 (38 pieces)
Bundle (5 digits) for 90005 (30 pieces)
Bundle (5 digits) for 90006 (54 pieces)
Bundle (5 digits) for 90007 (22 pieces)
Bundle (5 digits) for 90008 (19 pieces)
Loose Letters for 90010 (5 pieces)
Bundle (5 digits) for 90011 (106 pieces)
Bundle (3 digits) for 90012 to 90014 (12 pieces)
Bundle (5 digits) for 90015 (16 pieces)
Bundle (5 digits) for 90016 (25 pieces)
Bundle (5 digits) for 90017 (14 pieces)
Bundle (5 digits) for 90018 (30 pieces)
Bundle (5 digits) for 90019 (36 pieces)
Bundle (5 digits) for 90020 (22 pieces)
Sack (5 digits) for 90021 (130 pieces)
##############
These variables are defined statically:
ziparr array[1000] of record
zipcode char(5),
zipend char(5),
bundle_flg char(1),
cntr smallint
end record,
arr_cntr smallint,
sacrec record
stzip char(5),
endzip char(5),
cntr smallint,
sacktype char(2)
end record,
sack_flag char(1),
bundle_rec record
stzip char(5),
endzip char(5),
cntr smallint,
bundletype char(2)
end record,
bundle_flag char(1)
The value for zipcode is feed to this function by the part of the
program feeding the actual label report...
#############################
FUNCTION zip_counter(zipcode)
#############################
define
zipcode char(5)
if length(zipcode) = 5 then else return end if
if arr_cntr = 0 then # establish the first array record
let arr_cntr = 1
let ziparr[arr_cntr].zipcode = zipcode
let ziparr[arr_cntr].cntr = 1
return
end if
if zipcode = ziparr[arr_cntr].zipcode then
let ziparr[arr_cntr].cntr = ziparr[arr_cntr].cntr + 1
else
let arr_cntr = arr_cntr + 1
let ziparr[arr_cntr].zipcode = zipcode
let ziparr[arr_cntr].cntr = 1
end if
end function
############
######################
FUNCTION zip_report()
######################
define
n smallint,
zip3 char(3),
tmprec record
snum integer,
start_zip char(5),
end_zip char(5),
cntr smallint,
sack_type char(2)
end record
create temp table zipsacks
(
snum serial,
start_zip char(5),
end_zip char(5),
cntr smallint,
sack_type char(2) # 5S, 3S, 5B, 3B, LL, MS
)
for n = 1 to arr_cntr
if ziparr[n].cntr >= 125 then # 5 digit sack all by itself ...
# Need to test for pre-existing (unfinished sacks) ...
if ziparr[n].zipcode[1,3] <> sacrec.stzip[1,3] then
call test_sack()
end if
insert into zipsacks values (0,ziparr[n].zipcode, "", ziparr[n].cntr, "5S")
continue for
end if
if ziparr[n].cntr >= 10 then # 5 digit bundle ...
# need to test for pre-existing bundles ...
call test_bundle()
call build_sack(ziparr[n].zipcode, ziparr[n].cntr) returning sack_flag
if sack_flag = "Y" then # sack needs to be created (record doesn't fit)
insert into zipsacks values
(0,sacrec.stzip, sacrec.endzip, sacrec.cntr, sacrec.sacktype)
initialize sacrec.* to null
call build_sack(ziparr[n].zipcode, ziparr[n].cntr) returning sack_flag
end if
insert into zipsacks values (0, ziparr[n].zipcode, "", ziparr[n].cntr, "5B")
initialize bundle_rec.* to null
continue for
end if
call build_bundle(ziparr[n].zipcode, ziparr[n].cntr) returning bundle_flag
if bundle_flag = "Y" then # bundle needs to be created (record doesn't fit)
insert into zipsacks values
(0, bundle_rec.stzip, bundle_rec.endzip, bundle_rec.cntr,
bundle_rec.bundletype)
if bundle_rec.bundletype = "LL" then
else
call build_sack(bundle_rec.stzip, bundle_rec.cntr) returning sack_flag
if sack_flag = "Y" then # sack needs to be created (record doesn't fit)
insert into zipsacks values
(0, sacrec.stzip, bundle_rec.endzip, sacrec.cntr, sacrec.sacktype)
initialize sacrec.* to null
call build_sack(bundle_rec.stzip, bundle_rec.cntr) returning sack_flag
end if
end if
initialize bundle_rec.* to null
call build_bundle(ziparr[n].zipcode, ziparr[n].cntr) returning bundle_flag
end if
end for
call test_sack()
start report zipreport to "zipcount.out"
declare sack_curs cursor for select * from zipsacks
order by zipsacks.snum
open sack_curs
while true
fetch sack_curs into tmprec.*
if sqlca.sqlcode then exit while end if
case
when tmprec.sack_type = "5S"
call five_sack(tmprec.start_zip, tmprec.cntr)
when tmprec.sack_type = "5B"
call five_bundle(tmprec.start_zip, tmprec.cntr)
when tmprec.sack_type = "3S"
call three_sack(tmprec.start_zip, tmprec.end_zip, tmprec.cntr)
when tmprec.sack_type = "3B"
call three_bundle(tmprec.start_zip, tmprec.end_zip, tmprec.cntr)
when tmprec.sack_type = "MS"
call misc_sack(tmprec.start_zip, tmprec.end_zip, tmprec.cntr)
when tmprec.sack_type = "LL"
call loose_letters(tmprec.start_zip, tmprec.end_zip, tmprec.cntr)
end case
end while
close sack_curs
finish report zipreport
end function
############
report zipreport (a_line)
define
a_line char(80)
output
top margin 0
left margin 0
format
on every row
print a_line
end report
#################################
FUNCTION five_sack(zipcode, cntr)
#################################
define
rpt_line char(80),
zipcode char(5),
cntr smallint
output to report zipreport("")
let rpt_line = "Sack (5 digits) for ", zipcode, " (",
cntr using "<<<<<<", " pieces)"
output to report zipreport (rpt_line)
output to report zipreport("")
end function
############
###################################
FUNCTION five_bundle(zipcode, cntr)
###################################
define
rpt_line char(80),
zipcode char(5),
cntr smallint
let rpt_line = "Bundle (5 digits) for ", zipcode, " (",
cntr using "<<<<<<", " pieces)"
output to report ziprep