IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Processus inverse d'une fonction de decodage d'un code-barre [Débutant]


Sujet :

C#

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

    Informations forums :
    Inscription : Mars 2006
    Messages : 362
    Points : 64
    Points
    64
    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
    Développeur VBA/C#/VB.Net/Power Platform
    Inscrit en
    Juillet 2007
    Messages
    14 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur VBA/C#/VB.Net/Power Platform
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2007
    Messages : 14 593
    Points : 34 250
    Points
    34 250
    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/
    Cycle de vie d'un bon programme :
    1/ ça fonctionne 2/ ça s'optimise 3/ ça se refactorise

    Pas de question technique par MP, je ne réponds pas

    Mes ouvrages :
    Apprendre à programmer avec Access 2016, Access 2019 et 2021

    Apprendre à programmer avec VBA Excel
    Prise en main de Dynamics 365 Business Central

    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
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 362
    Points : 64
    Points
    64
    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
    Développeur VBA/C#/VB.Net/Power Platform
    Inscrit en
    Juillet 2007
    Messages
    14 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur VBA/C#/VB.Net/Power Platform
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2007
    Messages : 14 593
    Points : 34 250
    Points
    34 250
    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 ?
    Cycle de vie d'un bon programme :
    1/ ça fonctionne 2/ ça s'optimise 3/ ça se refactorise

    Pas de question technique par MP, je ne réponds pas

    Mes ouvrages :
    Apprendre à programmer avec Access 2016, Access 2019 et 2021

    Apprendre à programmer avec VBA Excel
    Prise en main de Dynamics 365 Business Central

    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
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 362
    Points : 64
    Points
    64
    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 chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 896
    Points : 1 912
    Points
    1 912
    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
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 183
    Points : 5 754
    Points
    5 754
    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
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 183
    Points : 5 754
    Points
    5 754
    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
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 183
    Points : 5 754
    Points
    5 754
    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
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 362
    Points : 64
    Points
    64
    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
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 183
    Points : 5 754
    Points
    5 754
    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, 20h31
  2. Réponses: 10
    Dernier message: 23/05/2016, 20h44
  3. processus qui appel une fonction
    Par gastoncs dans le forum C
    Réponses: 4
    Dernier message: 03/05/2012, 11h06
  4. Opération inverse d'une fonction
    Par fadiese_1 dans le forum Delphi
    Réponses: 6
    Dernier message: 26/12/2006, 18h53
  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, 13h56

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