I'm currently working on a windows form in VS2010 that is supposed to create UPC-A for new part numbers and store them in a database. So far I'm still trying to get the pieces together and I'm having issues with calculating the check digit. I came up with the following two scenarios:
Scenario 1: Do the calculation the way we currently do it in Excel:
string value = uPCDataSet.UPC.Rows[uPCDataSet.UPC.Rows.Count - 1]["UPCNumber"].ToString();
string manCode = value.Substring(1, 5);
string prodCode = value.Substring(7, 5);
int first = Math.Abs(Convert.ToInt32(value));
while (first >= 10)
first /= 10;
int chkDigitSubtotal;
string UPCNumber = first + manCode + prodCode;
chkDigitSubtotal = Convert.ToInt32((UPCNumber.Substring(1, 1)) + (UPCNumber.Substring(3, 1)) +
(UPCNumber.Substring(5, 1)) + (UPCNumber.Substring(7, 1)) + (UPCNumber.Substring(9, 1)) +
(UPCNumber.Substring(11, 1)));
chkDigitSubtotal = (3 * chkDigitSubtotal) + Convert.ToInt32((UPCNumber.Substring(2, 1)) +
(UPCNumber.Substring(4, 1)) + (UPCNumber.Substring(6, 1)) + (UPCNumber.Substring(8, 1)) +
(UPCNumber.Substring(10, 1)));
string chkDigit = ((300 - chkDigitSubtotal).ToString()).Substring(12, 1);
When I run this code, I get an error "Value was either too large or too small for an Int32". I don't understand why since "value" is a varchar
with 12 characters (they are all numbers).
Scenario 2: I found a code snipped online. This code works, but gives me the wrong check digit. I'm using a UPC that we calculated using your Excel sheet:
string value = "606891001678"; //valid UPC with check digit
string UPCBody = value.Substring(0, 11);
int sum = 0;
bool odd = true;
for (int i = value.Length - 1; i >= 0; i--)
{
if (odd == true)
{
int tSum = Convert.ToInt32(value[i].ToString()) * 2;
if (tSum >= 10)
{
string tData = tSum.ToString();
tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString());
}
sum += tSum;
}
else
sum += Convert.ToInt32(value[i].ToString());
odd = !odd;
}
int result = (((sum / 10)+1) *10) - sum;
result = result % 10;
MessageBox.Show(UPCBody + " & " + result);
In this example the check digit obviously should be 8, but it returns 2. I've spent pretty much all day on this and could use some advice. Why am I getting the error on the first scenario and why am I getting a different check digit in the second scenario from what it should be?
Thanks in advance for your help!
Chris
EDIT:
I deleted two previous edits since the code was flawed in a sense that I didn't get the correct results. I found out that we use Azalea barcodes and they have their own method of calculating the check digit (see ChkDigitSubtotal). So the below code works and gives me the correct check digit for my scenario. I think this code will work up to chkDigitSubtotal for all UPC-A calculations. Thanks to Harrison for his great guidance and resourceful answer!
string value = uPCDataSet.UPC.Rows[uPCDataSet.UPC.Rows.Count - 1]
["UPCNumber"].ToString();
long chkDigitOdd;
long chkDigitEven;
long chkDigitSubtotal;
string UPCNumber = value.Substring(0, 11);
chkDigitOdd = Convert.ToInt64(UPCNumber.Substring(0, 1)) +
Convert.ToInt64(UPCNumber.Substring(2, 1)) + Convert.ToInt64(UPCNumber.Substring(4, 1))
+ Convert.ToInt64(UPCNumber.Substring(6, 1)) + Convert.ToInt64(UPCNumber.Substring(8,
1)) + Convert.ToInt64(UPCNumber.Substring(10, 1));
chkDigitOdd = (3 * chkDigitOdd);
chkDigitEven = Convert.ToInt64(UPCNumber.Substring(1, 1)) +
Convert.ToInt64(UPCNumber.Substring(3, 1)) + Convert.ToInt64(UPCNumber.Substring(5, 1))
+ Convert.ToInt64(UPCNumber.Substring(7, 1)) + Convert.ToInt64(UPCNumber.Substring(9,
1));
chkDigitSubtotal = (300-(chkDigitEven + chkDigitOdd));
string chkDigit = chkDigitSubtotal.ToString();
chkDigit = chkDigit.Substring(chkDigit.Length - 1, 1);
Based on what I'm reading on wikipedia your doing the calculation incorrectly in the first example.
String.Substring
+String.Subtring
or "1" + "1" = "11". You are looking for 1+1=2. You need to convert each substring to int prior to adding.+ Operator (C# Reference)
String.Substring
is 0 based so you are missing theString.Substring(0,1)
for your even digitsString.Substring Method
string chkDigit = ((300 - chkDigitSubtotal).ToString()).Substring(12, 1);
You are attempting to take a
Substring
from the 12th 0 based character, or 13th character for a length of 1. However, the value of chkDigitSubtotal will not be that large/long.As far as your error, As Golden Dragon states in his answer your are converting a 12 characcter string to a number, which won't fit into an
Int32
and you should use a long.goes to
I would check your calculation is actually functioning logically in the previous steps first.
Update
In your edit 2 it looks like your last line has the variables around the
% operator
reversed. You want to take the remainder of 109 divided by 10 (which is 9) and your code takes the remainder of 10 divided by 109 (which is 0) So change.to
Now 10 - 9 = 1 which is your checkDigit.