1. #1
    Membre du Club
    Profil pro
    Inscrit en
    mars 2006
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2006
    Messages : 330
    Points : 61
    Points
    61

    Par défaut Processus inverse d'une fonction de decodage d'un code-barre

    Bonjour à tous,

    dans le cadre de mon boulot, un collègue avez créé un bout de code qui nous permettez à partir d'un code-barre de nos produits de retrouver différentes informations comme:
    - l'identifiant produit
    - le type de flacon
    - le numéro de lot
    - le numéro de flacon
    - la date de péremption

    par exemple de CB suivant "!328>P|%72046191" donne:

    - l'identifiant produit: E21
    - le type de flacon: 4
    - le numéro de lot: 72046191
    - le numéro de flacon: 707
    - la date de péremption: 01/02/2018

    Jusque là pas de problème.

    Par contre ce collègue n'est plus parmi nous et nous souhaiterions modifier son code pour faire l'inverse. A savoir, à partir des différentes infos (ID produit, type de flacon ect..) recréer le CB.

    C'est là ou cela se complique car mes connaissance en C# ne sont pas d'un niveau avancé et je vois pas trop comment faire (surtout la conversion des formules "mathématique").

    Ci dessous la fonction que je souhaite "inverser":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    public void convertReagentOrCtrCalBarcode(string sBarCode)
            {         
                int length = sBarCode.Length;
                int num = 0;
                double num2 = 0.0;
                DateTime time = default(DateTime);
                string text = "";
                string text2 = "";
     
                text2 = string.Concat(new string[]
    	{
    		text2,
    		", Barcode: ",
    		sBarCode,
    		", len: ",
    		length.ToString()
    	});
                int num3 = length;
     
     
                            rsLotId = sBarCode.Substring(8, 8);
                            for (int i = 0; i < length - 8; i++)
                            {
                                int num4 = "!#$%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`|}~".IndexOf(sBarCode[i]);
     
                                num2 += (double)num4 * Math.Pow((double)"!#$%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`|}~".Length, (double)(length - 8 - i - 1));
                            }
                            text = num2.ToString().PadLeft(14, '0');
                            text2 = text2 + ", barcode: " + text;
                            text2 = text2 + ", lot: " + rsLotId;
                            string text3 = "01";
                            string text4 = text.Substring(num, 2);
     
                            num += 2;
                            string text5 = text.Substring(num, 2);
                            text5 = "20" + text5;
                            num += 2;
     
                            time = new DateTime(int.Parse(text5), int.Parse(text4), int.Parse(text3));
                            time = time.AddMonths(1);
                            rlExpiryDate = Convert.ToInt32(ConvertToUnixTimestamp(time));
     
                            string text6 = text.Substring(num, 5);
                            num += 5;
                            string text7 = int.Parse(text6).ToString("X4");
     
                            rsManufNbr = text7.Substring(0, 3);
                            rcVialType = text7[3];
                            riVesselNumber = int.Parse(text.Substring(num, 5));
     
     
                            label1.Text = rsManufNbr.ToString();
                            label2.Text = rsLotId.ToString();
                            label3.Text = riVesselNumber.ToString();
                            label4.Text = rcVialType.ToString();
                            label5.Text = time.ToString();
     
     
     
            }
    Merci pour votre aide.

  2. #2
    Rédacteur/Modérateur

    Avatar de Jean-Philippe André
    Homme Profil pro
    Developpeur VBA migrant tranquillement vers C# et VB.Net =]
    Inscrit en
    juillet 2007
    Messages
    12 375
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Canada

    Informations professionnelles :
    Activité : Developpeur VBA migrant tranquillement vers C# et VB.Net =]
    Secteur : Finance

    Informations forums :
    Inscription : juillet 2007
    Messages : 12 375
    Points : 27 316
    Points
    27 316

    Par défaut

    Salut,

    une piste de lecture pour repliquer sous C# ce qu'on peut faire avec VBA :
    http://domi2.developpez.com/tutoriel.../codes-barres/
    Pas de question technique par MP, je ne réponds pas

    Apprendre à programmer avec Access 2016

    Pensez à consulter la FAQ Excel et la FAQ Access

    Derniers tutos
    Excel et les paramètres régionaux
    Les fichiers Excel binaires : xlsb,

    Autres tutos

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    mars 2006
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2006
    Messages : 330
    Points : 61
    Points
    61

    Par défaut

    Salut

    Merci pour le lien mais cela ne va pas m'aider... en tout cas pour le moment. En effet, sur ton lien il s'agit de de créer le CB à partir d'une chaine de caractère, or dans mon cas je cherche à creer cette chaine de caractère.

    En effet, les différentes infos (lot ect...) sont codés dans la chaîne de caractère finale et ce que je cherche a faire c'est créer la chaine de caractères à partir des différents éléments (lot ect...) et là il s'agit de codage pur.... avec la création de la fonction inverse de celle indiqué dans mon premier message... et là je vois bien le principe mais cela dépasse mes compétences.

    En tout cas merci d'avoir répondu

  4. #4
    Rédacteur/Modérateur

    Avatar de Jean-Philippe André
    Homme Profil pro
    Developpeur VBA migrant tranquillement vers C# et VB.Net =]
    Inscrit en
    juillet 2007
    Messages
    12 375
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Canada

    Informations professionnelles :
    Activité : Developpeur VBA migrant tranquillement vers C# et VB.Net =]
    Secteur : Finance

    Informations forums :
    Inscription : juillet 2007
    Messages : 12 375
    Points : 27 316
    Points
    27 316

    Par défaut

    La nomenclature de codage est quelque chose que tu peux decider, par exemple
    A_B_C_D
    A/B/C/D
    voire meme
    A_B/C_D
    et bien sur un encodage
    A'B'C'D'
    du coup la facon dont tu agences les donnees en amont te permet de determiner la facon dont tu liras les donnees en aval.

    Ici on cherchera donc a determiner a partir du decodage de l'information, l'encodage qui sera a faire

    par exemple de CB suivant "!328>P|%72046191" donne:

    - l'identifiant produit: E21
    - le type de flacon: 4
    - le numéro de lot: 72046191
    - le numéro de flacon: 707
    - la date de péremption: 01/02/2018
    Autant le numero de lot apparait clairement, autant les autres informations sont encodees. Quel algorithme utilises tu pour le decoder ?
    Pas de question technique par MP, je ne réponds pas

    Apprendre à programmer avec Access 2016

    Pensez à consulter la FAQ Excel et la FAQ Access

    Derniers tutos
    Excel et les paramètres régionaux
    Les fichiers Excel binaires : xlsb,

    Autres tutos

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    mars 2006
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2006
    Messages : 330
    Points : 61
    Points
    61

    Par défaut

    L'algorithme est le suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    public void convertReagentOrCtrCalBarcode(string sBarCode)
            {         
                int length = sBarCode.Length;
                int num = 0;
                double num2 = 0.0;
                DateTime time = default(DateTime);
                string text = "";
                string text2 = "";
     
                text2 = string.Concat(new string[]
    	{
    		text2,
    		", Barcode: ",
    		sBarCode,
    		", len: ",
    		length.ToString()
    	});
                int num3 = length;
     
     
                            rsLotId = sBarCode.Substring(8, 8);
                            for (int i = 0; i < length - 8; i++)
                            {
                                int num4 = "!#$%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`|}~".IndexOf(sBarCode[i]);
     
                                num2 += (double)num4 * Math.Pow((double)"!#$%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`|}~".Length, (double)(length - 8 - i - 1));
                            }
                            text = num2.ToString().PadLeft(14, '0');
                            text2 = text2 + ", barcode: " + text;
                            text2 = text2 + ", lot: " + rsLotId;
                            string text3 = "01";
                            string text4 = text.Substring(num, 2);
     
                            num += 2;
                            string text5 = text.Substring(num, 2);
                            text5 = "20" + text5;
                            num += 2;
     
                            time = new DateTime(int.Parse(text5), int.Parse(text4), int.Parse(text3));
                            time = time.AddMonths(1);
                            rlExpiryDate = Convert.ToInt32(ConvertToUnixTimestamp(time));
     
                            string text6 = text.Substring(num, 5);
                            num += 5;
                            string text7 = int.Parse(text6).ToString("X4");
     
                            rsManufNbr = text7.Substring(0, 3);
                            rcVialType = text7[3];
                            riVesselNumber = int.Parse(text.Substring(num, 5));
    Pour info la taille de la chaine de caractère (sBarCode) fait 16 dans le cas de nos CB.

    On voit que les 8 derniers caractères correspondent au numéro de lot et qu'avec les 8 premiers caractères, on retrouve les autres infos (date d'expiration ect...).
    C'est cette partie qui me pose soucis, notamment la boucle "for" avec le calcul de num2.

    Je vois pas trop comment m'y prendre pour faire le processus inverse.

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juin 2007
    Messages
    396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : juin 2007
    Messages : 396
    Points : 612
    Points
    612

    Par défaut

    Avec une fonction écrite en petit chinois ça va être compliqué ; ma suggestion serait de te créer quelques tests unitaires pour éviter les régressions puis de tenter de réécrire la fonction de décodage avec des noms de variable significatifs jusqu'à ce quelle devienne compréhensible.

    Edit : je trouve quand même curieux qu'il y ait une fonction de décodage mais pas d'encodage ; comment sont générés ces codes barre ?

  7. #7
    Membre chevronné

    Homme Profil pro
    Responsable déploiement (SCCM, AirWatch, AMP)
    Inscrit en
    juillet 2014
    Messages
    1 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, AirWatch, AMP)
    Secteur : Transports

    Informations forums :
    Inscription : juillet 2014
    Messages : 1 121
    Points : 2 080
    Points
    2 080

    Par défaut

    Bonjour, il manque la méthode "ConvertToUnixTimestamp" et si tu as aussi "ConvertFromUnixTimestamp"

    Ton CB à toujours le même nombre de caractères ?
    Son format est il toujours semblable ?
    Est ce un critère que conception que le CB ne soit pas réversible ou l'est il ?

  8. #8
    Membre chevronné

    Homme Profil pro
    Responsable déploiement (SCCM, AirWatch, AMP)
    Inscrit en
    juillet 2014
    Messages
    1 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, AirWatch, AMP)
    Secteur : Transports

    Informations forums :
    Inscription : juillet 2014
    Messages : 1 121
    Points : 2 080
    Points
    2 080

    Par défaut

    Je remonte l’algorithme jusqu’à num2 ligne 29 et après il y a ce fameux calcul dont tu parlais.

    Je te pose ton code que j'ai simplifié en partant de certaine affirmation et le début de ma méthode.
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
            public static void ReverseconvertReagentOrCtrCalBarcode()
            {
                int riVesselNumber = 707;
                char rcVialType = '4';
                string rsManufNbr = "E21";
                DateTime time = new DateTime(2018, 01, 02);
     
                string text_0_2 = time.ToString("MM");
                string text_2_2 = time.ToString("yy");
                string text_4_5 = int.Parse(rsManufNbr + rcVialType.ToString(), System.Globalization.NumberStyles.HexNumber).ToString().PadLeft(5, '0'); // Reverse ToString("X4") : E214 -> 57876
                string text_9_5 = riVesselNumber.ToString().PadLeft(5, '0');
     
                double num2 = Convert.ToDouble(text_0_2 + text_2_2 + text_4_5 + text_9_5); // num2 = 1185787600707
     
                int length = 16;
                for (int i = length - 9; i >= 0 ; i--)
                {
                    double exposant = (double)(length - 8 - i - 1);
                    // Todo ;-)
                }
            }
     
            public static void convertReagentOrCtrCalBarcode(string sBarCode)
            {
                int length = sBarCode.Length;
                double num2 = 0.0D;
     
                string rsLotId = sBarCode.Substring(8, 8);
                for (int i = 0; i < length - 8; i++)
                {
                    int num4 = "!#$%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`|}~".IndexOf(sBarCode[i]);
                    double exposant = (double)(length - 8 - i - 1);
                    num2 += (double)num4 * Math.Pow(64D, exposant);
     
                    // i = 0, num2 = 0.0
                    // i = 1, num2 = 1168231104512
                    // i = 2, num2 = 1185410973696
                    // i = 3, num2 = 1185780072448
                    // i = 4, num2 = 1185787412480
                    // i = 5, num2 = 1185787596800
                    // i = 6, num2 = 1185787600704
                    // i = 7, num2 = 1185787600707
                }
     
                string text = num2.ToString().PadLeft(14, '0'); 
     
                string textDay = "01";
                string textMonth = text.Substring(0, 2);
                string textYear = "20" + text.Substring(2, 2);
                DateTime time = new DateTime(int.Parse(textYear), int.Parse(textMonth), int.Parse(textDay)).AddMonths(1);
     
                string tmp = text.Substring(4, 5);
                string text7 = int.Parse(text.Substring(4, 5)).ToString("X4");
     
                string rsManufNbr = text7.Substring(0, 3);
                char rcVialType = text7[3];
                int riVesselNumber = int.Parse(text.Substring(9, 5));
            }

  9. #9
    Membre chevronné

    Homme Profil pro
    Responsable déploiement (SCCM, AirWatch, AMP)
    Inscrit en
    juillet 2014
    Messages
    1 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, AirWatch, AMP)
    Secteur : Transports

    Informations forums :
    Inscription : juillet 2014
    Messages : 1 121
    Points : 2 080
    Points
    2 080

    Par défaut

    Voici l'opération inverse.

    Je pense qu'il vaudrait mieux transmettre un objet qui valide le bon format de chaque données.
    La longueur du CB à l'air assez figé tout comme la longueur de strCharList
    On dirait un système d'encodage malléable sans l'être vraiment. Bref, j'aurais fait autrement les calculs sauf si c'est juste pour brouiller les pistes , car il pourrais être plus lisible comme le mien !?

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
            static void Main(string[] args)
            {
                /*
                A noter que :
                 idProd et typeFlacon doivent être des caractères hexadécimales valides
                 idProd ne doit pas dépasser 3 caractères
                 lotNumero ne doit pas dépasser 8 caractères
                 flaconNumero ne doit pas dépasser 5 caractères
                 Les dates permises sont entre 2001 et 2099 compris (codé sur les 2 derniers digits)
                 Le jour de la date n'est pas encodé
                 Il semble que l'encodage des dates est au format "UnixTimestamp" (non gérée)
                */
                string CB = ReverseconvertReagentOrCtrCalBarcode("E21", '4', 72046191, 707, new DateTime(2018, 01, 02)); // CB = !328>P|%72046191
            }
     
     
            public static string ReverseconvertReagentOrCtrCalBarcode(string idProd, char typeFlacon, int lotNumero, int flaconNumero, DateTime datePeremption, string strCharList = "!#$%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`|}~")
            {
     
                int riVesselNumber = flaconNumero;
                char rcVialType = typeFlacon;
                string rsManufNbr = idProd;
                DateTime time = datePeremption;
                int rsLotId = lotNumero;
     
                string CB = "";
     
                string text_0_2 = time.ToString("MM");
                string text_2_2 = time.ToString("yy");
                string text_4_5 = int.Parse(rsManufNbr + rcVialType.ToString(), System.Globalization.NumberStyles.HexNumber).ToString().PadLeft(5, '0'); // Reverse ToString("X4") : E214 -> 57876
                string text_9_5 = riVesselNumber.ToString().PadLeft(5, '0');
     
                double num2 = Convert.ToDouble(text_0_2 + text_2_2 + text_4_5 + text_9_5); // num2 = 1185787600707
     
                int length = 16;
                for (int i = 0; i < length - 8; i++)
                {
                    double pow = Math.Pow((double)strCharList.Length, (double)(length - 8 - i - 1));
                    int count = (int) (num2 / pow);
                    num2 -= (double) (count * pow);
                    CB += strCharList[count];
                }
     
                CB += rsLotId.ToString().PadLeft(8, '0');
                return CB;
            }

    PS : Il y a peut être d'autres contraintes dont je n'ai pas conscience

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    mars 2006
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2006
    Messages : 330
    Points : 61
    Points
    61

    Par défaut

    Salut,

    Merci beaucoup pour ton aide c'est super sympa. Ta solution est parfaite, il y a juste une petite subtilité sur le numéro de flacon. En fait on peut monter à 5 caractère pour celui-ci (dans le descriptif tu parles de 3 caracteres mais dans le code montes bien à 5 caractères dans ton padleft)

    Pour ma part, j'avais bidouillé de mon côté et je j'étais arrivé à recréer le num2. Il me resté à passer de num2 au CB final.

    ps: pour tes remarques:
    - oui les longueurs des CB sont fixes (18 caractères)
    - pour la date, c'est bien un format unix mais j'ai reussi à bidouiller pour faire ce que je souhaitais.

    dans mon cas, je vais adapter ton modèle qui est nettement plus lisible que le code d'origine. En fait ce que je vais faire, c'est permettre de créer des CB à partir des différentes infos. Je vais donc faire une interface pour saisir celles-ci en fonction de leurs contraintes.

    Encore merci

  11. #11
    Membre chevronné

    Homme Profil pro
    Responsable déploiement (SCCM, AirWatch, AMP)
    Inscrit en
    juillet 2014
    Messages
    1 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, AirWatch, AMP)
    Secteur : Transports

    Informations forums :
    Inscription : juillet 2014
    Messages : 1 121
    Points : 2 080
    Points
    2 080

    Par défaut

    Oui bien vu pour le numéro de flacon, j'ai tenter d’identifier les contraintes car il y en a il y a eu un raté.

    Le code de décodage de CB peut être simplifié aussi. Si on part sur des tailles fixe encore plus.
    Bref, tu as le code de base tu va pouvoir adapter as ta sauce.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Etude inverse d'une fonction : xj=F(y,xi)
    Par elmoukrie dans le forum MATLAB
    Réponses: 0
    Dernier message: 25/04/2017, 21h31
  2. Réponses: 10
    Dernier message: 23/05/2016, 21h44
  3. processus qui appel une fonction
    Par gastoncs dans le forum C
    Réponses: 4
    Dernier message: 03/05/2012, 12h06
  4. Opération inverse d'une fonction
    Par fadiese_1 dans le forum Delphi
    Réponses: 6
    Dernier message: 26/12/2006, 19h53
  5. Connaitre le processus qui appelle une fonction API
    Par RazielReaver dans le forum API, COM et SDKs
    Réponses: 9
    Dernier message: 28/05/2006, 14h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo