Universal Product Codes (UPCs) should be a very straight-forward topic. You give a product a number and that is the end of the story. Unfortunately it turns out to be a bit more complicated than that.
There is a great (well I guess that’s subjective) page on Wikipedia that does an excellent job explaining all the variations: Universal Product Codes. There are 14, 13, 12, 11, 10, 8, and 6 digit types of UPCs. There is also an interesting algorithm to convert from a fairly standard 12-digit UPC-A code into a zero-compressed UPC-E. This is a most uninteresting fact. Until the day comes when you actually have to convert some of these codes.
Here is some C# code to:
- Convert UPC-A codes to UPC-E
- Convert UPC-E codes to UPC-A
- Calculate check digits
If google brought you here because you need these conversions then bask is it’s yucky goodness! If not, then just move right along (basically it’s a cup with dirt in it).
{
string UPCe = "";
//Must be 12 digits
if (UPCa.Length != 12)
{
return "";
}
string mfg = UPCa.Substring( 1, 5);
string prod = UPCa.Substring(6, 5);
if ((mfg.Substring(2) == "000") || (mfg.Substring(2) == "100") ||(mfg.Substring(2) == "200") )
{
// 0 XXNNN0 0XX000-00NNN + check
// 1 XXNNN1 0XX100-00NNN + check
// 2 XXNNN2 0XX200-00NNN + check
UPCe = mfg.Substring(0, 2) + prod.Substring(2, 3) + mfg.Substring(2, 1);
}
else if (mfg.Substring(3,2) == "00")
{
// 3 XXXNN3 0XXX00-000NN + check
UPCe = mfg.Substring(0,3) + prod.Substring(3,2) + "3";
}
else if (mfg.Substring(4, 1) == "0")
{
// 4 XXXXN4 0XXXX0-0000N + check
UPCe = mfg.Substring(0, 4) + prod.Substring(4,1) + "4";
}
else
{
// 5 XXXXX5 0XXXXX-00005 + check
// 6 XXXXX6 0XXXXX-00006 + check
// 7 XXXXX7 0XXXXX-00007 + check
// 8 XXXXX8 0XXXXX-00008 + check
// 9 XXXXX9 0XXXXX-00009 + check
UPCe = mfg + prod.Substring(4);
}
return UPCe;
}
public string ConvertUPCEToUPCA(string UPCe)
{
//Must be 12 digits
if (UPCe.Length != 6)
{
return "";
}
string mfg = "";
string prod = "";
switch (UPCe.Substring(5, 1))
{
case "0":
mfg = "0" + UPCe.Substring(0, 2) + "000";
prod = "00" + UPCe.Substring(2, 3);
break;
case "1":
mfg = "0" + UPCe.Substring(0, 2) + "100";
prod = "00" + UPCe.Substring(2, 3);
break;
case "2":
mfg = "0" + UPCe.Substring(0, 2) + "200";
prod = "00" + UPCe.Substring(2, 3);
break;
case "3":
mfg = "0" + UPCe.Substring(0, 3) + "00";
prod = "000" + UPCe.Substring(3, 2);
break;
case "4":
mfg = "0" + UPCe.Substring(0, 4) + "0";
prod = "0000" + UPCe.Substring(4, 1);
break;
default:
mfg = "0" + UPCe.Substring(0, 5);
prod = "0000" + UPCe.Substring(5, 1);
break;
}
return mfg + prod + CalculateCheckDigit(mfg + prod);
}
//In the UPC-A system, the check digit is calculated as follows:
//
// 1. Add the digits in the odd-numbered positions (first, third, fifth, etc.) together and multiply by three.
// 2. Add the digits in the even-numbered positions (second, fourth, sixth, etc.) to the result.
// 3. Find the result modulo 10 (i.e. the remainder when the result is divided by 10).
// 4. If the result is not zero, subtract the result from ten.
//
private string CalculateCheckDigit(string upc)
{
int check = 0;
char[] chars = upc.ToCharArray();
// process string from right to left
Array.Reverse(chars);
for (int i =0;i<chars.Length;i++)
{
if ((i % 2)!= 0)
{
// even
check += int.Parse(chars[i].ToString());
}
else
{
// odd
check += (3 * int.Parse(chars[i].ToString()));
}
}
check = check % 10;
if (check != 0)
{
check = 10 - check;
}
return check.ToString();
}
Update: CheckDigit right to left processing.

May 13th, 2009 at 2:20 pm
Good article.
Small note though, the right most digit is always considered an odd digit in a UPC Code. Your function works because you you only allow UPC-A codes to be inputted for the CalculateCheckDigit function. Removing the length check and starting from the right ( with the right most digit being odd ), would allow you to calculate the check digit for EAN, UPCA, and GSI..
Just a thought.
May 15th, 2009 at 8:11 am
That makes perfect sense. Code updated, tests passed, committed. Thanks!