web-dev-qa-db-fra.com

Comment puis-je valider un UPC ou code EAN?

J'ai besoin d'une fonction C # .NET pour évaluer si un code à barres saisi ou numérisé est un numéro d'article valide Global (UPC ou EAN).

barcode check digit

Le dernier chiffre d'un numéro de code à barres est un chiffre de contrôle d'ordinateur qui permet de s'assurer que le code à barres est correctement composé. Calculateur de chiffre de contrôle GTIN

19
Zack Peterson
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;
}
21
Zack Peterson

GS1 US publie l’algorithme de calcul du chiffre de contrôle pour GTIN dans un document PDF (supprimé le lien en constante évolution).

Le code suivant utilise linq pour vérifier le dernier chiffre des codes à barres GTIN: GTIN-8, GTIN-12 (UPC), GTIN-13 (EAN) et 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
Luciano Carvalho

Les solutions ci-dessus calculent le chiffre de contrôle et le comparent au chiffre donné, en ignorant le fait qu'il est conçu pour être validé de manière beaucoup plus simple.

  1. Multipliez tous les chiffres, y compris le chiffre de contrôle , par 3 ou 1 et somme.
  2. Vérifiez si la somme est un multiple de 10

Basé sur la réponse de 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;
}
12
AlexDev

EAN de longueur variable

    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 };
    }

MODIFIER

Le projet pour lequel je construisais ce code est maintenant opérationnel - il fait partie d'une base de données et d'outils complète de codes à barres - et comprend un validateur de codes à barres en vrac (100 dans un lot pour les utilisateurs non reg, 10 000 pour les inscrits) - https: //blinked.in/tools/validator

5
null loop

J'ai eu un problème similaire et Google m'a amené à cette page. Je devais calculer le chiffre de contrôle pour un grand nombre de codes à barres pour un programme de génération d'étiquettes. J'ai d'abord commencé avec une variante de la réponse de Luciano Carvalho ci-dessus, mais j'étais un peu curieux de savoir comment transformer la chaîne en un personnage en un. Je pensais pouvoir améliorer un peu les performances.

Veuillez noter que la validation est en dehors de cette fonction. Cette fonction est davantage conçue pour la vitesse, car je génère un grand nombre de codes à barres.

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
user2748023
    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
Dan Dwire
/// <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;
}

Cas de test:

    [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
Mitch

J'ai trouvé ce paquet Nuget: https://www.nuget.org/packages/ProductCodeValidator/

Le code dans github est: https://github.com/ThomasPe/ProductCodeValidator .

Voici comment l'utiliser:

using ProductCodeValidator;

bool IsValidEAN(string EAN)
{
    return EanValidator.IsValidEan(testEan));
}
1
Otávio Larrosa

Je suis conscient que la question se situe dans le contexte de .net/C #. Néanmoins, j'ai atterri sur cette page en cherchant une réponse à la même question, mais dans un contexte Groovy.

Puisque j'ai réussi à utiliser les informations de cette page pour trouver une réponse à mon propre problème, j'ai pensé partager le résultat.
Surtout les réponses de AlexDev, Zack Peterson et Mitch m'ont été utiles.

/*
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
Tex

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

probablement pas le plus efficace mais espérons que cela aide ..

0
Ben Russell