Calculating a UPS Shipment Number From a Tracking Number

I may be the only person who ever needs to calculate a UPS Shipment Number. The project I’m working on requires me to create this value for a custom commerical invoice.

The format of the shipment number is

123X59M7CH

and the tracking number format is

1Z 123X56 66 2075 4864

Sort of the same … but not. The first part of the shipment number is your account number. That was -easy-. Second part, a bit more involved. Turns out, that this number is generated using base26 encoding. Base26 is rarely used but it is here. I’ve put together a custom tag which does the conversion for you. Just pass it a tracking number.

<cfset trackingNum=”1Z 123X56 66 2075 4864″>
<cf_base26Encoder trackingNum=”#trackingNum#” output=”shipNum”>
<cfoutput>ShipmentNumber:#shipNum#</cfoutput>

——save code below as base26Encoder.cfm ——
<CFPARAM NAME=”attributes.trackingNum” DEFAULT=”string”>
<CFIF NOT isDefined(“attributes.trackingNum”)>
<CFTHROW MESSAGE=’Error in custom Tag <B></B>:<BR>Attribute trackingNum not found’>
</CFIF>
<CFIF attributes.trackingNum eq “”>
<CFTHROW MESSAGE=’Error in custom Tag <B></B>:<BR>Attribute trackingNum can not be empty’>
</CFIF>
<!— UPS Tracking Number Anatomy
1st 2 digits – Lead numbers
next 5 – Acct Number
next 2 – service class
next 7 tracking number
last digit – check digit
—>
<cfscript>
//remove any spaces
tN1 = replace(attributes.trackingNUm,” “, “”,”all”);
//get the tracking number and check digit
tN = right(tN1,8);
//strip the check digit
tN = left(tN,7);
//get the account number
aNum = replace(replace(left(tN1,7), tN, “”),”1Z”, “”);
//do the base26 calculations based on UPS requirements
//discard remainders so use int()
p1 = int(tN/26^4);
p2 = int((tN-(p1*26^4))/26^3);
p3 = int((tN-(p1*26^4)-(p2*26^3))/26^2);
p4 = int((tN-(p1*26^4)-(p2*26^3)-(p3*26^2))/26);
p5 = int((tN-(p1*26^4)-(p2*26^3)-(p3*26^2)-(p4*26)));
//set up conversion lists
l1 = “0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25”;
l2 = “3,4,7,8,9,B,C,D,F,G,H,J,K,L,M,N,P,Q,R,S,T,V,W,X,Y,Z”;
l3 = p1 & “,” & p2 & “,” & p3 & “,” & p4 & “,” & p5;
</cfscript>
<cfset sNum = “”>
<!— loop through our base26 numbers, find in l1 and get corresponding value from l2 —>
<cfloop list=”#l3#” index=”x”>
<cfset v= listgetat(l2,listFind(l1,x))>
<cfset sNum = snum & v>
</cfloop>
<CFSET “caller.#attributes.output#” = aNUm&sNUm>
Hope someone else finds this useful.

Newspaper Columns Using CFscript and CSS

Someone asked me how to break up a text block into 3 columns (like a newspaper). While this isn’t necessarily the best way to format a webpage (scroll down, scroll up, scroll down ), it is a familiar format.

Thanks to a neat little cfscript function from theLazyCoder, it turns out to be fairly simple.

The code takes a block of text courtesy the Lore Ipsum Generator and chops it up into 3 sections for your page. You could simply use left mid and right but you would get words that were cut off in the middle. Using the fullLeft function we get the closest full word to the end of each column and then we just subtract the previous section using replace. For the third column, we replace both the first and second column text.

For a 7 in tall page using default font size, 950 characters seems to fit about right.

col1 = fullLeft(mytext,950); //get the full word closest to 950 chars
col2 = fullleft(replace(mytext,col1,””),950); //get the full word closest to 950 chars – the chars in col1
col3 = fullleft(replace(mytext,col1 & col2,””),950); //get the full word closest to 950 chars – the chars in col1 and col2

Once we’ve broken it up this way we can simply apply a little newspaper-ish CSS and you’ve got 3 columns justified with gutters.

Limitations:

Doesn’t deal with multiple pages

Doesn’t allow for handling characters when there are more than the 3 columns allow

The Code

<cfset myText = “Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nunc non sem. Curabitur nunc lectus, consequat non, consectetuer non, gravida ut, ante. Integer faucibus molestie risus. Vestibulum consectetuer blandit risus. Pellentesque id nulla. Phasellus sem. Donec sit amet urna ac nunc fringilla aliquam. Nulla venenatis congue felis. Etiam molestie tortor eu risus. In at tortor. Ut eget mauris. In non erat eu urna gravida ornare.
Curabitur leo sem, tincidunt sed, suscipit eu, congue eu, sem. Mauris tincidunt nisl sed leo. Nullam eget dolor non mi feugiat vestibulum. Pellentesque orci. Sed purus. Vestibulum tempus, ante pellentesque dapibus blandit, quam felis hendrerit enim, egestas molestie elit magna ut pede. Cras in quam non nulla lobortis rutrum. Nam sollicitudin adipiscing risus. Etiam quis urna. Ut et orci. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aenean arcu mi, aliquam sed, laoreet in, vulputate sed, ante. Suspendisse sagittis ipsum rutrum ipsum. Quisque urna. Maecenas id lectus.
Suspendisse lobortis lacus ut tortor. Quisque tincidunt mauris et arcu. Morbi justo nunc, malesuada ac, suscipit in, convallis at, nibh. Morbi accumsan erat ac urna. Sed gravida. Phasellus tristique. Donec volutpat dictum turpis. Nam vel ante. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed eu odio facilisis mi ornare interdum. Curabitur quam mauris, cursus sed, ultrices a, tincidunt eget, enim. Morbi in nunc sed ipsum sagittis commodo. Curabitur augue. In mattis nibh eu arcu. Donec mattis metus non tortor. Nulla et erat. Ut tempor. Aliquam tincidunt urna porttitor augue. Ut elit augue, suscipit a, pulvinar et, porta et, lacus.
Proin felis purus, ornare nec, auctor vel, adipiscing ac, ligula. Nam faucibus tristique justo. Nunc tristique metus vel quam. Vestibulum ultrices massa a sapien. Praesent sit amet diam vitae elit vestibulum facilisis. Maecenas pretium massa a sem. Vestibulum lobortis. Nulla arcu arcu, laoreet eget, scelerisque non, dapibus vitae, sem. Sed tempus, sapien id consectetuer lacinia, dolor elit aliquet diam, in malesuada nulla lacus eget erat. Vestibulum consectetuer sapien a felis. Curabitur et erat a neque laoreet rutrum. Curabitur ac leo ut purus dapibus dignissim. Ut tincidunt, urna eget interdum ultrices, enim urna sollicitudin leo, nec tincidunt ligula mi sed ipsum. Maecenas imperdiet massa quis neque. Ut vel lectus id magna malesuada imperdiet. Ut nec quam. Aliquam enim lorem, luctus at, fermentum et, tempor at, neque. Integer in enim sit amet lorem auctor viverra.
Etiam vitae elit. Integer bibendum augue tincidunt dui. Sed semper consectetuer dui. Pellentesque volutpat egestas nunc. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
“>

<cfscript>
col1 = fullLeft(mytext,950);
col2 = fullleft(replace(mytext,col1,””),950);
col3 = fullleft(replace(mytext,col1 & col2,””),950);

//fullLeft function from: http://thelazycoder.com/1/2007/07/53.Full-Left-Word-Count-with-Whole-Words.cfm
function fullLeft(str, count) {
if (not refind(“[[:space:]]”, str) or (count gte len(str)))
return Left(str, count);
else if(reFind(“[[:space:]]”,mid(str,count+1,1))) {
return left(str,count);
} else {
if(count-refind(“[[:space:]]”, reverse(mid(str,1,count)))) return Left(str, (count-refind(“[[:space:]]”, reverse(mid(str,1,count)))));
else return(left(str,1));
}
}
</cfscript>
<cfoutput>
<div style=”width:2in;padding:5px;height:7in;overflow:hidden;top:50px;position:absolute;text-align:justify;”>
#col1#
</div>
<div style=”width:2in;padding:5px;height:7in;overflow:hidden;left:2.5in;position:absolute;top:50px;text-align:justify;”>
#col2#
</div>
<div style=”width:2in;padding:5px;height:7in;overflow:hidden;left:4.875in;position:absolute;top:50px;text-align:justify;”>
#col3#
</div>
</cfoutput>