EAN generátor   zodpovězená otázka

VB.NET

Zdravím, měl bych prosbu o jednu radu. Vytvořil jsem takový generátor ean kódů dle jeho standardů. Ve skladu totiž máme produkty které nemají vlastní ean a jelikož při fakturaci je zdlouhavé tyto produkty dohledávat, tak jsem si řekl že jim eany vytvořím aby se při fakturaci mohla používat čtečka.

Stále jsem přemýšlel jak EANy generovat a přišel jsem na toto řešení, akorát mě příjde ten kód možná zbytečně dlouhý, ale nevím jak ho zjednodušit pokud by to tedy šlo, ale myslím že kvůli výpočtům níže to nejspíše ani nepůjde.

Tento kód plánuju přiřadit akci Click na tlačítko ve formuláři detailu produktu. Výsledný ean kód se pak zobrazí v TextBoxu a uloží do příslušného sloupce tabulky.


Dim a As Integer
Dim b As Integer
Dim c As Integer
Dim d As Integer
Dim e As Integer
Dim f As Integer
Dim g As Integer
Dim h As Integer
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim l As Integer

Dim subSuma As Integer
Dim subSumb As Integer
Dim subSumc As Integer

Dim rounding As Integer

Dim controlNumber As Integer

Dim EAN As String
'generovani 12 nahodnych cisel pro EAN, prvni tri jsou kod zeme puvodu
a = 5
b = 9
c = 0
d = Int(Rnd * 10)
e = Int(Rnd * 10)
f = Int(Rnd * 10)
g = Int(Rnd * 10)
h = Int(Rnd * 10)
i = Int(Rnd * 10)
j = Int(Rnd * 10)
k = Int(Rnd * 10)
l = Int(Rnd * 10)

subSuma = a + c + e + g + i + k 'soucet vsech lichych cisel
subSumb = (b + d + f + h + j + l) * 3 'soucet vsech sudych cisel a vynasobeni cislem 3
subSumc = (subSuma + subSumb) 'soucet vysledku lichych cisel a vysledku sudych cisel
rounding = Round((subSumc + 4.95) / 10, 0) * 10 'zaokrouhleni nahoru na desitky vysledku promenne subSumc
'vypocet kontrolniho cisla pro EAN
controlNumber = rounding - subSumc 'odecteni souctu vysledku lichyh a sudych cisel od zaokrouhleneho cisla. Vysledek je vzdy jednomistne cislo
'konecne poskladani vygenerovaneho ean kodu
EAN = a & b & c & d & e & f & g & h & i & j & k & l & controlNumber

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ani bych neviděl problém v délce kódu, spíš bych měl strach z možnosti přiřazení jednoho EAN více položkám.

Nevím jak je sklad velký a kolik položeke je bez EAN, ale vidím tu problém kolize jednoho EAN:

1) mezi více položkami s vlastním přiřazením EAN - než náhodné číslo, spíše bych použil přírůstkové číslování 0...N až pro 10 tis. položek

2) vlastní přiřazený EAN kód již může být přířazen u položky jiného výrobce - pravděpodobně nutnost spolupráce s GS1CZ pro přiřazení vyhrazené části EAN

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Položek je ve skladu zatím cca okolo 3000 z toho svůj vlastní EAN má jem malá hrstka produktů - max 30-50. Také jsem se obával přiřazení stejného EAN, ale to bych nejspíše vyřešil tak, že v databazy bych příslušný sloupec s EAN kody udělal tak aby v něm byli pouze unikátní hodnoty. Bude se spíše jednat o interní EAN, který budou pouze v interní databazy. Například na shopu se vůbec uvádět nebude, tam se uvádějí produktové kódy.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

proc to musi byt nahodna cisla? Kdyz je stejne budu ukladat v databazi, neni pak lepsi rovnou pouzit autonumer.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Psal jsem 1. příspěvek bez přihlášení :-(

Unikátnosti EAN rozumím.

Pokud přiřadíte vlastní EAN, nějakému výrobku, tak může nastat to, že nově přidávaná položka s existujícím EAN(od výrobce) bude mít EAN shodný s položkou s EAN přiděleným Interně.

Ještě jsem o tom přemýšlel a napadlo mě:

1) použít kód země, který neexistuje (někde jsem zahlédl seznam - analýza kódů zemí, zda je seznam souvislý nebo náhodný)

2) další čísla řešit inkrementálně

předpokládané důvody:

zemí bude přibývat hodně málo, spíše žádné, takže by nemělo dojít ke kolizi EAN s již existujícím

inkrementální řešení dalších čísel - stačí uchovávat poslední číslo, nebo z DB vytáhnou počet položek s kódem neexistující země

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Také jsme nad tím přemýšlel a myslím že nejelegantnější řešení bude udělat první tři čísla které identifikují zemi původu na nějakou neexistující.

do budoucna se předejde spousty problémům. Například kdyby se do skladu přidalo zboží které by mělo shodný EAN s vygenerovaným EAN kódem které je již ve skladě.

Seznam prvních třech čísel EAN kódů zemí mám, takže nebude problém dohledat neexistující.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak jsem kód malinko upravil. Použil jsem pro EAN první tři čísla která nejsou žádné zemi přidělena "999", nyní by již neměl být problém v tom aby se nevyskytl stejný EAN kód produktu který má iž svůj vlastní. Na konec jsem ještě přidal řádek pro zapsaní do textboxu.

Dim a As Integer
Dim b As Integer
Dim c As Integer
Dim d As Integer
Dim e As Integer
Dim f As Integer
Dim g As Integer
Dim h As Integer
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim l As Integer

Dim subSuma As Integer
Dim subSumb As Integer
Dim subSumc As Integer

Dim rounding As Integer

Dim controlNumber As Integer

Dim EAN As String
'generovani 12 nahodnych cisel pro EAN, prvni tri jsou kod zeme puvodu
a = 9
b = 9
c = 9
d = Int(Rnd * 10)
e = Int(Rnd * 10)
f = Int(Rnd * 10)
g = Int(Rnd * 10)
h = Int(Rnd * 10)
i = Int(Rnd * 10)
j = Int(Rnd * 10)
k = Int(Rnd * 10)
l = Int(Rnd * 10)

subSuma = a + c + e + g + i + k 'soucet vsech lichych cisel
subSumb = (b + d + f + h + j + l) * 3 'soucet vsech sudych cisel a vynasobeni cislem 3
subSumc = (subSuma + subSumb) 'soucet vysledku lichych cisel a vysledku sudych cisel
rounding = Round((subSumc + 4.95) / 10, 0) * 10 'zaokrouhleni nahoru na desitky vysledku promenne subSumc
'vypocet kontrolniho cisla pro EAN
controlNumber = rounding - subSumc 'odecteni souctu vysledku lichyh a sudych cisel od zaokrouhleneho cisla. Vysledek je vzdy jednomistne cislo
'konecne poskladani vygenerovaneho ean kodu
EAN = a & b & c & d & e & f & g & h & i & j & k & l & controlNumber
TextBox1.Text = CSTr(EAN)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak po delší době jsem se dostal k pokračování řešení generování EAN. Díky prvním třem číslům neexistující země jsem zamezil případný konflikt stejného EAN který již je používan výrobcem.

Po testování jsem ale narazil na problém se kterým moc nevím jak dál. Otevřu formulář, ve gterém se generování provádí. Vygeneruju například 20 EAN kódů k 20 produktům, které EAN nemají. Uzavřu formulář, zavřu program. Když program opět zapnu a chci vygenerovat další nové EAN pro nové produkty hned u prvního mi to vygeneruje EAN který již existuje (byl generován již minule). Mohl by někdo poradit jak kód upravit aby například při detekci stejného EAN generoval dál než nevygeneruje EAN který zatím neexistuje? Děkuji za rady.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nepoužívejte funkci Rnd, ale třídu Random.

Dim r As New Random
d = r.Next(10)

Generovat další kód, když vygenerujete už existující EAN, na to byste měl přijít sám.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jak vygenerovat, to problém není, problém je, zjistit zda-li již existuje na to by chtělo nějaký cyklus, ale s těmi mi to zatím moc nejde.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Napsal jsem to asi takhle:

Imports System.Text

Module Module1
    Sub Main()
        For i As Integer = 0 To 50
            Console.WriteLine(GenerateEAN())
        Next

        Console.ReadKey()

    End Sub

    Dim rnd As New Random
    Public Function GenerateEAN() As String
        Static eans As New List(Of String)
        Dim EanNumbers(11) As Integer
        EanNumbers(0) = 9
        EanNumbers(1) = 9
        EanNumbers(2) = 9
        Dim subSuma, subSumb, subSumc, rounding, controlNumber As Integer
        For i As Integer = 3 To 11
            EanNumbers(i) = rnd.Next(11)
        Next

        For i As Integer = 0 To 11
            If i Mod 2 > 0 Then
                subSuma += EanNumbers(i)
            Else
                subSumb += EanNumbers(i)
            End If
        Next

        subSumb = subSumb * 3
        subSumc = subSuma + subSumb
        rounding = Math.Round((subSumc + 4.95) / 10, 0) * 10
        controlNumber = rounding - subSumc

        Dim sb As New StringBuilder
        For i As Integer = 0 To 11
            sb.Append(EanNumbers(i))
        Next
        sb.Append(controlNumber)

        Dim ret As String = sb.ToString()
        If (eans.Contains(ret)) Then
            Return GenerateEAN()
        End If
        eans.Add(ret)

        Return ret
    End Function
End Module

Jde o to, že funkce Rnd() není zrovna nejideálnější. Tohle nevygeneruje stejné EAN v rámci jednoho spuštění programu, je zde určitá šance že se občas vytvoří stejný EAN při dalším spuštění. Řešením by potom bylo například ukládat si obsah Listu eans do souboru a při každém spuštění jej načíst.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Vymyslel jsem ještě jednu variantu:

Dim Index As Integer
Dim vysledek As Integer
Index = Me.KodProduktu

    Select Case Index
        
    Case Is < 10
    vysledek = Index
    Case Is < 95
    vysledek = Round(Index / 10)
    Case Is < 195
    vysledek = Round((Index - 100) / 10)
    Case Is < 295
    vysledek = Round((Index - 200) / 10)
    Case Is < 395
    vysledek = Round((Index - 300) / 10)
    Case Is < 495
    vysledek = Round((Index - 400) / 10)
    Case Is < 595
    vysledek = Round((Index - 500) / 10)
    Case Is < 695
    vysledek = Round((Index - 600) / 10)
    Case Is < 795
    vysledek = Round((Index - 700) / 10)
    Case Is < 895
    vysledek = Round((Index - 800) / 10)
    Case Is < 995
    vysledek = Round((Index - 900) / 10)
    Case Else
    End Select


    Dim a As Integer
    Dim b As Integer
    Dim c As Integer
    Dim d As Integer
    Dim e As Integer
    Dim f As Integer
    Dim g As Integer
    Dim h As Integer
    Dim i As Integer
    Dim j As Integer
    Dim k As Integer
    Dim l As Integer
    
    Dim subSuma As Integer
    Dim subSumb As Integer
    Dim subSumc As Integer
    
    Dim rounding As Integer
    
    Dim controlNumber As Integer
    
    Dim EAN As String
    Dim EANTab As String

    a = 9
    b = 9
    c = 9
    d = Int(rnd * 10)
    e = Int(rnd * 10)
    f = vysledek
    g = Int(rnd * 10)
    h = Int(rnd * 10)
    i = Int(rnd * 10)
    j = Int(rnd * 10)
    k = Int(rnd * 10)
    l = Int(rnd * 10)
    
    subSuma = a + c + e + g + i + k 'soucet vsech lichych cisel
    subSumb = (b + d + f + h + j + l) * 3 'soucet vsech sudych cisel a vynasobeni cislem 3
    subSumc = (subSuma + subSumb) 'soucet vysledku lichych cisel a vysledku sudych cisel
    rounding = Round((subSumc + 4.95) / 10, 0) * 10 'zaokrouhleni nahoru na desitky vysledku promenne subSumc
    'vypocet kontrolniho cisla pro EAN
    controlNumber = rounding - subSumc 'odecteni souctu vysledku lichyh a sudych cisel od zaokrouhleneho cisla. Vysledek je vzdy jednomistne cislo
    'konecne poskladani vygenerovaneho ean kodu
    EAN = a & b & c & d & e & f & g & h & i & j & k & l & controlNumber 'EAN s kontrolni cislici

Funguje to vlastně tak, že se vezme unikátní index produktu, vytvoří se z něj jednomístné číslo, to se umístí na jednu pozici v ean kodu. Tim dojde i jinému výsledku kontrolní číslice celého kódu. Myslím, že tím jsem pravděpodobnost vygenerování stejného EAN velice zmenšil.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jak jsem již psal dříve, generování EAN pomocí náhodných čísel je zbytečná komplikace. V podstatě neustálá kontrola zda již není EAN vygenerován. Pokud by bylo generování inkrementální, v nastavení by se ukládal poslední generovaný EAN nebo jeho část bez uvedení kódu státu a tato hodnota by se pouze načetla při spuštění aplikace. Popřemýšlejte o tom.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Určitě by to bylo lepší řešení, ale v programování jsem zatím velice mírně pokročilý začátečník, a tato metoda by pro mne byla zatím nad mé sily.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ještě mě napadla jedna možná jednodužší varianta řešení generování EAN kódů:

Dim Id As Integer
Dim DefaultNumber As Integer
Dim EanNumber As Integer
Dim FirstNumber As Integer
Dim FinalEan As String

Id = Me.KodProduktu
DefaultNumber = 013579024
FirstNumber = 999

EanNumber = DefaultNumber + Id

FinalEan = FirstNumber & EanNumber

Jednoduchý princim k defaultnímu číslu se přičte unikátní číslo indexu produktu. Ale problém, jak vypočítat kontrolní číslici? Napadá někoho něco?:)

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback