Como valido um código UPC ou EAN?

Preciso de uma função C#. NET para avaliar se um código de barras tipado ou digitalizado é um número válido da rubrica do comércio global (UPC ou EAN).

barcode check digit

o último algarismo de um número de código de barras é um algarismo de controlo informático que garante a composição correcta do código de barras. calculadora de algarismos de verificação do GTIN

Author: Zack Peterson, 2012-04-13

11 answers

public static bool IsValidGtin(string code)
{
    if (code != (new Regex("[^0-9]")).Replace(code, ""))
    {
        // is not numeric
        return false;
    }
    // pad with zeros to lengthen to 14 digits
    switch (code.Length)
    {
        case 8:
            code = "000000" + code;
            break;
        case 12:
            code = "00" + code;
            break;
        case 13:
            code = "0" + code;
            break;
        case 14:
            break;
        default:
            // wrong number of digits
            return false;
    }
    // calculate check digit
    int[] a = new int[13];
    a[0] = int.Parse(code[0].ToString()) * 3;
    a[1] = int.Parse(code[1].ToString());
    a[2] = int.Parse(code[2].ToString()) * 3;
    a[3] = int.Parse(code[3].ToString());
    a[4] = int.Parse(code[4].ToString()) * 3;
    a[5] = int.Parse(code[5].ToString());
    a[6] = int.Parse(code[6].ToString()) * 3;
    a[7] = int.Parse(code[7].ToString());
    a[8] = int.Parse(code[8].ToString()) * 3;
    a[9] = int.Parse(code[9].ToString());
    a[10] = int.Parse(code[10].ToString()) * 3;
    a[11] = int.Parse(code[11].ToString());
    a[12] = int.Parse(code[12].ToString()) * 3;
    int sum = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10] + a[11] + a[12];
    int check = (10 - (sum % 10)) % 10;
    // evaluate check digit
    int last = int.Parse(code[13].ToString());
    return check == last;
}
 20
Author: Zack Peterson, 2012-04-13 15:17:50

O GS1 US publica o algoritmo de cálculo de dígitos de controlo para o GTIN em um documento PDF (removeu o link em constante mudança).

O seguinte código utiliza o linq para verificar o último algarismo dos códigos de barras de GTIN: GTIN-8, GTIN-12 (UPC), GTIN-13 (EAN) e GTIN-14 (ITF-14).

private static Regex _gtinRegex = new System.Text.RegularExpressions.Regex("^(\\d{8}|\\d{12,14})$");
public static bool IsValidGtin(string code)
{
    if (!(_gtinRegex.IsMatch(code))) return false; // check if all digits and with 8, 12, 13 or 14 digits
    code = code.PadLeft(14, '0'); // stuff zeros at start to garantee 14 digits
    int[] mult = Enumerable.Range(0, 13).Select(i => ((int)(code[i] - '0')) * ((i % 2 == 0) ? 3 : 1)).ToArray(); // STEP 1: without check digit, "Multiply value of each position" by 3 or 1
    int sum = mult.Sum(); // STEP 2: "Add results together to create sum"
    return (10 - (sum % 10)) % 10 == int.Parse(code[13].ToString()); // STEP 3 Equivalent to "Subtract the sum from the nearest equal or higher multiple of ten = CHECK DIGIT"
}
 17
Author: Luciano Carvalho, 2014-09-07 21:02:08

As soluções acima calculam o algarismo de controlo e comparam-no com o algarismo dado, ignorando o facto de ser concebido para ser validado de uma forma muito mais simples.

  1. multiplicar todos os algarismos, incluindo o algarismo de controlo , por 3 ou 1 e somar.
  2. Verifique se a soma é um múltiplo de 10
Baseado na resposta do Luciano:
private static Regex _gtinRegex = new Regex("^(\\d{8}|\\d{12,14})$");
public static bool IsValidGtin(string code)
{
    if (!(_gtinRegex.IsMatch(code))) return false;
    code = code.PadLeft(14, '0');
    int sum = code.Select((c,i) => (c - '0')  * ((i % 2 == 0) ? 3 : 1)).Sum();
    return (sum % 10) == 0;
}
 10
Author: AlexDev, 2014-01-22 10:57:23

Comprimento variável EANs

    public static bool IsValidEan13(string eanBarcode)
    {
        return IsValidEan(eanBarcode, 13);
    }

    public static bool IsValidEan12(string eanBarcode)
    {
        return IsValidEan(eanBarcode, 12);
    }

    public static bool IsValidEan14(string eanBarcode)
    {
        return IsValidEan(eanBarcode, 14);
    }

    public static bool IsValidEan8(string eanBarcode)
    {
        return IsValidEan(eanBarcode, 8);
    }

    private static bool IsValidEan(string eanBarcode, int length)
    {
        if (eanBarcode.Length != length) return false;
        var allDigits = eanBarcode.Select(c => int.Parse(c.ToString(CultureInfo.InvariantCulture))).ToArray();
        var s = length%2 == 0 ? 3 : 1;
        var s2 = s == 3 ? 1 : 3;
        return allDigits.Last() == (10 - (allDigits.Take(length-1).Select((c, ci) => c*(ci%2 == 0 ? s : s2)).Sum()%10))%10;
    }

    [Test]
    [TestCaseSource("Ean_13_TestCases")]
    public void Check_Ean13_Is_Valid(string ean, bool isValid)
    {
        BlinkBuilder.IsValidEan13(ean).Should().Be(isValid);
    }

    private static IEnumerable<object[]> Ean_13_TestCases()
    {
        yield return new object[] { "9781118143308", true };
        yield return new object[] { "978111814330", false };
        yield return new object[] { "97811181433081", false };
        yield return new object[] { "5017188883399", true };
    }

    [Test]
    [TestCaseSource("Ean_8_TestCases")]
    public void Check_Ean8_Is_Valid(string ean, bool isValid)
    {
        BlinkBuilder.IsValidEan8(ean).Should().Be(isValid);
    }

    private static IEnumerable<object[]> Ean_8_TestCases()
    {
        yield return new object[] { "12345670", true };
        yield return new object[] { "12345679", false };
        yield return new object[] { "55432214", true  };
        yield return new object[] { "55432213", false };
        yield return new object[] { "55432215", false };
    }

Editar

O projecto para o qual eu estava a construir este código está agora a funcionar-faz parte de uma base de dados abrangente de códigos de barras e conjunto de ferramentas-e inclui um validador de código de barras a granel (100 num lote para utilizadores não reg, 10 000 para registados) - https://blinked.in/tools/validator

 5
Author: null loop, 2013-05-03 16:10:16
/// <summary>
/// Validates a GTIN (UPC/EAN) using the terminating check digit
/// </summary>
/// <param name="code">the string representing the GTIN</param>
/// <returns>True if the check digit matches, false if the code is not 
/// parsable as a GTIN or the check digit does not match</returns>
public static bool IsValidGtin(string code)
{
    if (string.IsNullOrWhiteSpace(code))
        return false;
    if (code.Length != 8 && code.Length != 12 && code.Length != 13 
        && code.Length != 14)
        // wrong number of digits
        return false;

    int sum = 0;
    for (int i = 0; i < code.Length - 1 /* do not include check char */; i++)
    {
        if (!char.IsNumber(code[i]))
            return false;

        var cchari = (int)char.GetNumericValue(code[i]);
        // even (from the right) characters get multiplied by 3
        // add the length to align right
        if ((code.Length + i) % 2 == 0)
            sum += cchari * 3;
        else
            sum += cchari;
    }

    // validate check char
    char checkChar = code[code.Length - 1];
    if (!char.IsNumber(checkChar))
        return false;

    int checkChari = (int)char.GetNumericValue(checkChar);
    return checkChari == (10 - (sum % 10)) % 10;
}

Casos de teste:

    [TestMethod()]
    public void IsValidGtinTest_Valid()
    {
        string[] valid = new[] {
            "085126880552",
            "0085126880552",
            "00085126880552",
            "0786936226355",
            "0719852136552"
        };
        foreach (var upc in valid)
            Assert.IsTrue(IdentifierUtilities.IsValidGtin(upc), upc);
    }

    [TestMethod()]
    public void IsValidGtinTest_Invalid()
    {
        string[] invalid = new[] {
            "0058126880552",
            "58126880552",
            "0786936223655",
            "0719853136552",
            "",
            "00",
            null,
            "123456789123456789123456789",
            "1111111111111"
        };
        foreach (var upc in invalid)
            Assert.IsFalse(IdentifierUtilities.IsValidGtin(upc), upc);
    }
 1
Author: Mitch, 2013-06-11 22:01:02
    private bool ValidateCheckDigit()
    {

        Int32 _num = 0;
        Int32 _checkdigit = 0;

        for (int i = 0; i < CurrentUpcInfo.UpcCode.Length; i++)
        {
            if (i % 2 == 0)
            {
                _num += (3 * Convert.ToInt32(CurrentUpcInfo.UpcCode.Substring(i, 1)));
            }
            else
            {
                _num += Convert.ToInt32(CurrentUpcInfo.UpcCode.Substring(i, 1));
            }

        }
        _num = Math.Abs(_num) + 10;  // in case num is a zero
        _checkdigit = (10 - (_num % 10)) % 10;


        if (Convert.ToInt32(CurrentUpcInfo.Checkdigit) == _checkdigit)
            return true;

        return false;

    }
 1
Author: Dan Dwire, 2013-08-29 13:09:27
Tive um problema semelhante e o google trouxe-me a esta página. Eu precisava calcular o dígito de verificação para um grande número de códigos de barras para um programa de geração de etiquetas. Eu comecei com uma variação da resposta de Luciano Carvalho acima, mas eu estava um pouco curioso sobre o lançamento da corda para um char para um int. Suspeitei que poderia melhorar um pouco o desempenho.

Por favor, note que a validação está a acontecer fora desta função. Esta função é construída mais para a velocidade desde que estou gerando um grande número de códigos de barras.

int CalculateCheckDigit(ulong label)
{
    int sum = 0;
    bool isEven=true;
    while(label>0)
    {
        if(isEven)
            sum += (int)(label % 10) * 3;
        else
            sum += (int)(label % 10) * 1;
        isEven = !isEven;
        label /= 10;
    }

    return (10 - (sum % 10)) % 10;
}
 1
Author: user2748023, 2014-02-14 16:33:54
Estou ciente de que a questão está no contexto da. NET/C#. no entanto, aterrei nesta página à procura de resposta à mesma pergunta, mas num contexto fixe.

Uma vez que eu realmente consegui usar a informação nesta página para chegar a uma resposta para o meu próprio problema, eu pensei que eu iria compartilhar o resultado.
Especialmente as respostas do AlexDev, Zack Peterson e Mitch foram úteis para mim.
/*
Check digit calculation is based on modulus 10 with digits in an odd
position (from right to left) being weighted 1 and even position digits
being weighted 3. 
For further information on EAN-13 see:
Wikipedia - European Article Number: http://en.wikipedia.org/wiki/International_Article_Number_%28EAN%29
Implementation based on http://stackoverflow.com/questions/10143547/how-do-i-validate-a-upc-or-ean-code
Tests can be found there too
*/
boolean isValidEan(String code){
  returnValue = false
  if (code ==~ /\d{8}|\d{12,14}/){ //Matches if String code contains 8, 12, 13 or 14 digits
    assert [8,12,13,14].contains(code.size())
    code = code.padLeft(14, '0')
    assert code.size() == 14
    int sum = 0
    code.eachWithIndex{ c, i ->
      sum += c.toInteger() * ((i % 2 == 0) ? 3 : 1)
    }
    returnValue = sum % 10 == 0
  }
  return returnValue
}
 0
Author: Tex, 2015-07-14 11:09:31

Def check_digit ():

        users_gtin=raw_input("enter first seven digits of gtin ")

        gtin_seven_digits=unicode(users_gtin)


        if len(gtin_seven_digits) == 7 and gtin_seven_digits.isnumeric():
            ck = ((((int(gtin_seven_digits[0])) + (int(gtin_seven_digits[2])) + (int(gtin_seven_digits[4])) + (int(gtin_seven_digits[6])))*3) + ((int(gtin_seven_digits[1])) + (int(gtin_seven_digits[3])) + (int(gtin_seven_digits[5])))) %10
            final_ck = 10-ck

            if final_ck == 10:
                final_ck=0
                print "Is your check digit",final_ck,"?"

            else:
                print "Is your check digit",final_ck,"?"

        else:
            print "please try typing an seven digit number"
            check_digit()


        choice=raw_input("enter (a) to restart or press anything other than the letter  a  to end this program <<<< ").upper()


        if choice == "A":
            check_digit()

Check_digit ()

Provavelmente não é o mais eficiente, mas espero que ajude..
 0
Author: Ben Russell, 2016-01-20 18:09:53

Encontrei este pacote Nuget: https://www.nuget.org/packages/ProductCodeValidator/

O código no github é: https://github.com/ThomasPe/ProductCodeValidator.

Aqui está como usá-lo:

using ProductCodeValidator;

bool IsValidEAN(string EAN)
{
    return EanValidator.IsValidEan(testEan));
}
 0
Author: Otávio Larrosa, 2018-08-16 20:06:04
private void button1_Click(object sender, EventArgs e)
{
    string code = textBox1.Text;
    string sBarcode = string.Empty;
    sBarcode = IsValidGtin(code);
    lblBarCode.Text = sBarcode;
}
public static string IsValidGtin(string code)
{

    //if (code != (new Regex("[^0-9]")).Replace(code, ""))
    //{
    //    // is not numeric
    //    return false;
    //}
    // pad with zeros to lengthen to 14 digits
    switch (code.Length)
    {
        case 2:
            code = code + "000000000";
            break;
        case 3:
            code = code + "00000000";
            break;
        case 4:
            code = code + "0000000";
            break;
        case 5:
            code = code + "000000";
            break;
        case 6:
            code = code + "00000";
            break;
        case 7:
            code = code + "0000";
            break;
        case 8:
            code = code + "000";
            break;
        case 9:
            code = code + "00";
            break;
        case 10:
            code = code + "0";
            break;
        case 11:
            break;
        case 12:
            code = code.Substring(0, 11);
            break;
        //default:
        // wrong number of digits
        //  return false;
    }
    // calculate check digit
    int[] a = new int[12];
    a[0] = int.Parse(code[0].ToString()) * 3;
    a[1] = int.Parse(code[1].ToString());
    a[2] = int.Parse(code[2].ToString()) * 3;
    a[3] = int.Parse(code[3].ToString());
    a[4] = int.Parse(code[4].ToString()) * 3;
    a[5] = int.Parse(code[5].ToString());
    a[6] = int.Parse(code[6].ToString()) * 3;
    a[7] = int.Parse(code[7].ToString());
    a[8] = int.Parse(code[8].ToString()) * 3;
    a[9] = int.Parse(code[9].ToString());
    a[10] = int.Parse(code[10].ToString()) * 3;
    //a[11] = int.Parse(code[11].ToString());
    //a[12] = int.Parse(code[12].ToString()) * 3;
    int sum = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10];
    string check = Convert.ToString((10 - (sum % 10)));
    // evaluate check digit
    // int last = int.Parse(code[13].ToString());
    // return check == last;
    code = code + check;
    return code;
}
 -3
Author: Harsh, 2012-10-10 22:04:08