How to convert UPC-A to zero-compressed UPC-E

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).

public string ConvertUPCAToUPCE(string UPCa)
{
   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.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Reddit
  • StumbleUpon
  • TwitThis

2 Responses to “How to convert UPC-A to zero-compressed UPC-E”

  1. Dustin Says:

    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.

  2. james Says:

    That makes perfect sense. Code updated, tests passed, committed. Thanks!

Leave a Reply