Question code VBA

Bonjour,

Je construit actuellement un fichier pour me constituer une BDD fournisseur selon mes besoins. (je débute en VBA, j'y connaissais rien il y a 3 jours)

Tout fonctionne dans le formulaire, y compris l'envoi d'infos dans la BDD.

Je cherche depuis un moment une solution pour un élément sur lequel je suis bloqué, mais je trouve pas.

Concrètement :

J'ai un formulaire avec une liste de champs.

J'ai fait en sorte quand quand on clique sauvegarder, ce soit injecté dans la BDD

Ensuite, une fois que ça fonctionnait, j'ai fait en sorte que si le fournisseur existait déjà, ses infos soient re-remplies dans le formulaire dès qu'il était écrit (exéc. after update du champ).

Le code ci-dessous fonctionne sur le fait que tout le formulaire se complète si un fournisseur est existant. Je peux modifier le contenu et sauvegarder et le champ de la BDD est bien écrasé avec les nouvelles données.

Là ou ça pose soucis, c'est la création d'un nouveau fournisseur. Si je tape un nouveau nom, dès que je passe à la case après le nom du fournisseur, il me met une erreur 91. L'erreur est ciblée sur cette ligne "If fournisseur_existant = TextBox_nom_fournisseur.Value Then"

Merci d'avance

Private Sub TextBox_nom_fournisseur_AFTERUPDATE()

Dim fournisseur_existant As Object, ligne_fournisseur_existant As Integer
'Je recherche si le fournisseur existe dans la BDD
Set fournisseur_existant = Worksheets("BD_FOUR").Range("A:A").Find(what:=TextBox_nom_fournisseur)
'Dernière ligne BDD
ligne_insertion = Sheets("BD_FOUR").Range("A65000").End(xlUp).Row + 1

For ligne_fournisseur_existant = 2 To ligne_insertion
If fournisseur_existant = TextBox_nom_fournisseur.Value Then
'Si existant, alors on recherche le numéro de ligne
ligne_fournisseur_existant = fournisseur_existant.Row
'on donne ce numéro de ligne au label pour permettre un rec par écrasement des datas
Label_num_fournisseur = ligne_fournisseur_existant

MsgBox ligne_fournisseur_existant & fournisseur_existant

        TextBox_telephone.Value = Format(Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 2), "0# ### ## ##")
        TextBox_contact_commercial.Value = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 3)
        TextBox_franco.Value = Format(Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 4), "##0 €")
        TextBox_gsm.Value = Format(Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 5), "0### ## ## ##")
        TextBox_notes.Value = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 6)
        CheckBox_lundi.Value = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 11)
        CheckBox_mardi.Value = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 12)
        CheckBox_mercredi.Value = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 13)
        CheckBox_jeudi.Value = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 14)
        CheckBox_vendredi.Value = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 15)
        CheckBox_samedi.Value = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 16)
        CheckBox_dimanche.Value = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 17)
        CheckBox_tous_les_jours.Value = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 18)
        ComboBox_lundi.ListIndex = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 19)
        ComboBox_mardi.ListIndex = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 20)
        ComboBox_mercredi.ListIndex = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 21)
        ComboBox_jeudi.ListIndex = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 22)
        ComboBox_vendredi.ListIndex = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 23)
        ComboBox_samedi.ListIndex = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 24)
        ComboBox_dimanche.ListIndex = Sheets("BD_FOUR").Cells(ligne_fournisseur_existant, 25)

End If
Exit For
Next

End Sub

Bonsoir,

Essayer ce code non testé (éviter de répéter n fois le même nom de feuille)

Private Sub TextBox_nom_fournisseur_AFTERUPDATE()
    Dim sh_four As Worksheet
    Dim fournisseur_existant As Object
    Dim ligne_fournisseur_existant As Long, ligne_insertion As Long

    'Assignation feuille fournisseurs
    Set sh_four = Sheets("BD_FOUR")

    'Je recherche si le fournisseur existe dans la BDD
    ligne_fournisseur_existant = 0: ligne_insertion = 0
    Set fournisseur_existant = sh_four.Range("A:A").Find(what:=TextBox_nom_fournisseur)
    If Not fournisseur_existant Is Nothing Then
        ligne_fournisseur_existant = fournisseur_existant.Row
    Else
        'Dernière ligne BDD
        ligne_insertion = sh_four.Range("A65000").End(xlUp).Row + 1
    End If

    If ligne_fournisseur_existant > 0 Then
        'on donne ce num?ro de ligne au label pour permettre un rec par écrasement des datas
        Label_num_fournisseur = ligne_fournisseur_existant
        MsgBox ligne_fournisseur_existant & fournisseur_existant

        TextBox_telephone.Value = Format(sh_four.Cells(ligne_fournisseur_existant, 2), "0# ### ## ##")
        TextBox_contact_commercial.Value = sh_four.Cells(ligne_fournisseur_existant, 3)
        TextBox_franco.Value = Format(sh_four.Cells(ligne_fournisseur_existant, 4), "##0 ?")
        TextBox_gsm.Value = Format(sh_four.Cells(ligne_fournisseur_existant, 5), "0### ## ## ##")
        TextBox_notes.Value = sh_four.Cells(ligne_fournisseur_existant, 6)
        CheckBox_lundi.Value = sh_four.Cells(ligne_fournisseur_existant, 11)
        CheckBox_mardi.Value = sh_four.Cells(ligne_fournisseur_existant, 12)
        CheckBox_mercredi.Value = sh_four.Cells(ligne_fournisseur_existant, 13)
        CheckBox_jeudi.Value = sh_four.Cells(ligne_fournisseur_existant, 14)
        CheckBox_vendredi.Value = sh_four.Cells(ligne_fournisseur_existant, 15)
        CheckBox_samedi.Value = sh_four.Cells(ligne_fournisseur_existant, 16)
        CheckBox_dimanche.Value = sh_four.Cells(ligne_fournisseur_existant, 17)
        CheckBox_tous_les_jours.Value = sh_four.Cells(ligne_fournisseur_existant, 18)
        ComboBox_lundi.ListIndex = sh_four.Cells(ligne_fournisseur_existant, 19)
        ComboBox_mardi.ListIndex = sh_four.Cells(ligne_fournisseur_existant, 20)
        ComboBox_mercredi.ListIndex = sh_four.Cells(ligne_fournisseur_existant, 21)
        ComboBox_jeudi.ListIndex = sh_four.Cells(ligne_fournisseur_existant, 22)
        ComboBox_vendredi.ListIndex = sh_four.Cells(ligne_fournisseur_existant, 23)
        ComboBox_samedi.ListIndex = sh_four.Cells(ligne_fournisseur_existant, 24)
        ComboBox_dimanche.ListIndex = sh_four.Cells(ligne_fournisseur_existant, 25)
    End If

    If ligne_insertion > 0 Then

    End If

End Sub

Génial ! Ca fonctionne, un grand merci pour ton aide ! J'ai pu un peu raccourcir le code sans empêcher un bon fonctionnement.

J'ai deux-trois petites questions pour être sûr de bien comprendre la procédure :

Le fait de redonner la feuille sheets("BD_FOUR") en variable sh_four a-t-elle une utilité en VBA à part éclaircir le code?

Ensuite,

If Not fournisseur_existant Is Nothing Then
    ligne_fournisseur_existant = fournisseur_existant.Row
    Else
    derniere_ligne = sh_four.Range("A65000").End(xlUp).Row + 1
    End If

Si je comprends bien, dans le formule, si le fournisseur existant n'est PAS FAUX, le then donne la solution s'il est existant, c'est bien ça?

Et dernière question : y a-t-il une astuce pour simplifier le code au niveau des checkbox & combobox. Comme on voit, j'en ai une pour chaque jour de la semaine. J'ai déjà essayé avec une fonction array de nommer jours=array(...) et avec une boucle for de simplifier en indiquant checkbox_jours.value mais ça n'a jamais fonctionné. Pas d'autre choix que de laisser ces checkbox ligne par ligne? (pour le moment, ça va, mais le jour où il y a 50 checkbox ça pourrait être compliqué)

Grand merci

Le fait de redonner la feuille sheets("BD_FOUR") en variable sh_four a-t-elle une utilité en VBA à part éclaircir le code?

1-Elle éclaircit le code

2- Elle évite des erreurs de référence à cette feuille qui au vu du nombre de fois où elle est répétée, pourrait être mal libellée : sheets("BD_FOU") par exemple

3- Elle simplifie toute modification ultérieure du nom de la feuille

Si je comprends bien, dans le formule, si le fournisseur existant n'est PAS FAUX, le then donne la solution s'il est existant, c'est bien ça?

si le fournisseur existant n'est pas NON TROUVÉ, le "then" donne l'instruction à appliquer.

Et dernière question : y a-t-il une astuce pour simplifier le code au niveau des checkbox & combobox. Comme on voit, j'en ai une pour chaque jour de la semaine. J'ai déjà essayé avec une fonction array de nommer jours=array(...) et avec une boucle for de simplifier en indiquant checkbox_jours.value mais ça n'a jamais fonctionné. Pas d'autre choix que de laisser ces checkbox ligne par ligne? (pour le moment, ça va, mais le jour où il y a 50 checkbox ça pourrait être compliqué)

Bien sûr.

Le plus simple est d'insérer vos TextBox et ComboBox dans un cadre (Frame) que vous nommeriez "Jours". Si vos TextBox et ComboBox font partie de ce "Frame", alors vous pouvez utliser la boucle suivante :

    Dim ctrl As Control

    For Each ctrl In Me.Jours.Controls
        If TypeOf ctrl Is MSForms.CheckBox Then ctrl.Value
        If TypeOf ctrl Is MSForms.ComboBox Then ctrl.Value
    Next ctrl

NB : Me est l'objet représentant votre UserForm.

A noter que Me est toujours l'objet représentant un UserForm dans le code associé à celui-ci, mais qu'il est également l'objet représentant une feuille dans le code associé à cette dernière.

Ok, top, un grand merci pour vos réponses !!

Supposant que je crée un frame nomé frame_test, comment procédre à l'enregistrement des checkbox dans la BDD?

J'ai tenté ceci, mais ça ne fonctionne pas (ça suppose un cumul des différentes valeurs des checkbox dans une seule case de la BDD)

Private Sub CommandButton_enregistrer_Click()

  Dim ctrl As Control

    For Each ctrl In Me.Frame_test.Controls
        If TypeOf ctrl Is MSForms.CheckBox Then ctrl.Value
    Next ctrl

    Sheets("BD_PROD").Cells(3, 1) = ctrl.Value

Unload Me

End Sub

Et, est-ce que cela peut aussi fonctionner avec un multipage qui contient les différentes checkbox sans devoir remettre un frame en plus? (on ferait donc référence à page_test à la place de frame_test)

Bonjour,

Essayer ce code

    Dim ctrl As Control
    Dim j As Integer

    j = 11
    For Each ctrl In Me.Frame_test.Controls
        If TypeOf ctrl Is MSForms.CheckBox Then
            Sheets("BD_PROD").Cells(3, j) = ctrl.Value
            j = j + 1
        End If
    Next ctrl

Et, est-ce que cela peut aussi fonctionner avec un multipage qui contient les différentes checkbox sans devoir remettre un frame en plus? (on ferait donc référence à page_test à la place de frame_test)

Non. Car le contrôle Multipage ne possède la propriété "Controls". Il faut remettre un frame.

Ca fonctionne, merci beaucoup

Du coup ca me créer les variables VRAI / FAUX sur plusieurs colonnes.

Mais dans le sens inverse, quand je dois recharger toutes les datas dans mon formulaire si le nom tapé est existant, y a-t-il une solution pour le faire sans indiquer à nouveau chaque check box ligne par ligne (un peu comme la formule donnée à l'instant, en sens inverse?)

Private Sub TextBox_nom_produit_AFTERUPDATE()

Dim sh_prod As Worksheet
Dim produit_existant As Object
Dim ligne_produit_existant As Long, 

Set sh_prod = Sheets("BD_PROD")

'Je recherche si le fournisseur existe dans la BDD
Set produit_existant = sh_prod.Range("F:F").Find(what:=TextBox_nom_produit, LookAt:=xlWhole)
    If Not produit_existant Is Nothing Then
    ligne_produit_existant = produit_existant.Row
    End If

'on lance le test pour voir s'il y a un four existant. Si pas, rdv après le else
If ligne_produit_existant > 0 Then

'+++++++++PAGE 1
ComboBox_departement.ListIndex = sh_prod.Cells(ligne_produit_existant, 1)
TextBox_code_ean.Value = sh_prod.Cells(ligne_produit_existant, 2)
ComboBox_fournisseur.ListIndex = sh_prod.Cells(ligne_produit_existant, 3)
TextBox_code_fournisseur.Value = sh_prod.Cells(ligne_produit_existant, 4)
ComboBox_classification.ListIndex = sh_prod.Cells(ligne_produit_existant, 5)
TextBox_nom_produit.Value = sh_prod.Cells(ligne_produit_existant, 6)
TextBox_min_achat.Value = sh_prod.Cells(ligne_produit_existant, 7)
TextBox_quantite.Value = sh_prod.Cells(ligne_produit_existant, 8)
ComboBox_poids.ListIndex = sh_prod.Cells(ligne_produit_existant, 9)
TextBox_prix_achat.Value = sh_prod.Cells(ligne_produit_existant, 10)

End If
End Sub

Et autre question. Ce code a pour le moment pour but de chercher dans la DB si le produit existe. Pour le moment, il insère s'il est écrit exactement pareil. J'aurais pu mettre XlPart dans le FIND, mais ça risque de me mettre n'importe quoi.

Mais à l'inverse, si je dois créer un article Fusilli et que Fusillis existe déjà dans la DB, il ne va pas me le trouver.

Est-ce techniquement faisable d'avoir une fenêtre qui s'ouvre si le terme cherché existe en valeur proche (et si oui, moyen de définir les paramètre de ce qu'on entend par valeur proche ?), et si c'est le cas, est-ce possible d'avoir la possibilité de sélectionné le produit désiré dans la fenêtre pour le charger dans l'userform? (par ex, si j'ai le choix entre Fusilli, Fusilli à la tomate, Fusilli nature, Fusilli à l'oeuf)

Grand merci d'avance

Bonjour,

Tout d'abord pour la clarté et bonne lecture du code, il est bon de l'indenter correctement comme ci-dessous :

Private Sub TextBox_nom_produit_AFTERUPDATE()
    Dim sh_prod As Worksheet
    Dim rech_prod As String
    Dim produit_existant As Object
    Dim ligne_produit_existant As Long

    Set sh_prod = Sheets("BD_PROD")

    'Je recherche si le fournisseur existe dans la BDD
    Set produit_existant = sh_prod.Range("F:F").Find(what:=rech_prod, LookAt:=xlWhole)
    If Not produit_existant Is Nothing Then
        ligne_produit_existant = produit_existant.Row
    End If

    'on lance le test pour voir s'il y a un four existant. Si pas, rdv apr?s le else
    If ligne_produit_existant > 0 Then

        '+++++++++PAGE 1
        ComboBox_departement.ListIndex = sh_prod.Cells(ligne_produit_existant, 1)
        TextBox_code_ean.Value = sh_prod.Cells(ligne_produit_existant, 2)
        ComboBox_fournisseur.ListIndex = sh_prod.Cells(ligne_produit_existant, 3)
        TextBox_code_fournisseur.Value = sh_prod.Cells(ligne_produit_existant, 4)
        ComboBox_classification.ListIndex = sh_prod.Cells(ligne_produit_existant, 5)
        TextBox_nom_produit.Value = sh_prod.Cells(ligne_produit_existant, 6)
        TextBox_min_achat.Value = sh_prod.Cells(ligne_produit_existant, 7)
        TextBox_quantite.Value = sh_prod.Cells(ligne_produit_existant, 8)
        ComboBox_poids.ListIndex = sh_prod.Cells(ligne_produit_existant, 9)
        TextBox_prix_achat.Value = sh_prod.Cells(ligne_produit_existant, 10)

    End If

End Sub

Mais dans le sens inverse, quand je dois recharger toutes les datas dans mon formulaire si le nom tapé est existant, y a-t-il une solution pour le faire sans indiquer à nouveau chaque check box ligne par ligne (un peu comme la formule donnée à l'instant, en sens inverse?)

Oui, il existe une solution de même type mais qui nécessite un préalable dans la définition de vos Combobox/ TextBox pour établir un lien avec l'entête de la colonne de votre BDD.

Exemple:

 TextBox_code_fournisseur.Value = sh_prod.Cells(ligne_produit_existant, 4)

Si l'entête de la colonne 4 de votre BDD a pour valeur "Code fournisseur", alors mettre cette valeur dans la propriété "Tag" de votre contrôle TextBox_code_fournisseur.

En supposant que l'entête des colonnes de votre BDD se trouve à la ligne 1 de votre feuille, vous pouvez alors utiliser la boucle suivante :

    Dim ctrl As Control
    Dim j As Integer
    Dim sh_four As Worksheet

    Set sh_four = Sheets("BD_PROD")
    For Each ctrl In Me.Frame_test.Controls
        If TypeOf ctrl Is MSForms.TextBox Then
            If ctrl.Tag <> Empty Then
                j = sh_four.Rows(1).Find(ctrl.Tag).Column
                ctrl.Value = sh_four.Cells(3, j)
             End If
        End If
    Next ctrl
 

Est-ce techniquement faisable d'avoir une fenêtre qui s'ouvre si le terme cherché existe en valeur proche (et si oui, moyen de définir les paramètre de ce qu'on entend par valeur proche ?), et si c'est le cas, est-ce possible d'avoir la possibilité de sélectionné le produit désiré dans la fenêtre pour le charger dans l'userform? (par ex, si j'ai le choix entre Fusilli, Fusilli à la tomate, Fusilli nature, Fusilli à l'oeuf)

Une solution simple pourrait être :

    
    Dim sh_prod As Worksheet
    Dim rech_prod As String
    Dim produit_existant As Object
    Dim ligne_produit_existant As Long

    Set sh_prod = Sheets("BD_PROD")

    'limite la recherche au premier mot du produit (séparé par espace)
    rech_prod = Split(TextBox_nom_produit, " ")(0)
    'Je recherche si le fournisseur existe dans la BDD
    Set produit_existant = sh_prod.Range("F:F").Find(what:=rech_prod, LookAt:=xlWhole)
    If Not produit_existant Is Nothing Then
        ligne_produit_existant = produit_existant.Row[
    End If

Bonjour Thev

Merci de votre retour. Voici le nouveau code suite aux commentaires ;

Private Sub TextBox_nom_produit_AFTERUPDATE()

Dim sh_prod As Worksheet
Dim rech_prod As String
Dim produit_existant As Object
Dim ligne_produit_existant As Long
Dim ctrl As Control
Dim colonne_checkbox_saison As Integer

Set sh_prod = Sheets("BD_PROD")

rech_prod = Split(TextBox_nom_produit, " ")(0)

'Je recherche si le fournisseur existe dans la BDD
Set produit_existant = sh_prod.Range("F:F").Find(what:=rech_prod, LookAt:=xlWhole)
    'Si jamais la ligne n'existe pas, ça bloque, ajoute de if not
    If Not produit_existant Is Nothing Then
    'recherche le numéro de ligne
    ligne_produit_existant = produit_existant.Row
    End If

'on lance le test pour voir s'il y a un four existant. Si pas, rdv après le else
If ligne_produit_existant > 0 Then

'+++++++++PAGE 1
ComboBox_departement.ListIndex = sh_prod.Cells(ligne_produit_existant, 1)
TextBox_code_ean.Value = sh_prod.Cells(ligne_produit_existant, 2)
ComboBox_fournisseur.ListIndex = sh_prod.Cells(ligne_produit_existant, 3)
TextBox_code_fournisseur.Value = sh_prod.Cells(ligne_produit_existant, 4)
ComboBox_classification.ListIndex = sh_prod.Cells(ligne_produit_existant, 5)
TextBox_nom_produit.Value = sh_prod.Cells(ligne_produit_existant, 6)
TextBox_min_achat.Value = sh_prod.Cells(ligne_produit_existant, 7)
TextBox_quantite.Value = sh_prod.Cells(ligne_produit_existant, 8)
ComboBox_poids.ListIndex = sh_prod.Cells(ligne_produit_existant, 9)
TextBox_prix_achat.Value = sh_prod.Cells(ligne_produit_existant, 10)

 '+++++++++PAGE 2 CHECKBOX SAISONS  
For Each ctrl In Me.Frame_saison.Controls
    If TypeOf ctrl Is MSForms.TextBox Then
        If ctrl.Tag <> Empty Then
            colonne_checkbox_saison = sh_prod.Rows(1).Find(ctrl.Tag).Column
            ctrl.Value = sh_prod.Cells(ligne_produit_existant, colonne_checkbox_saison)
            End If
    End If
Next ctrl

End If
End Sub

Le but de l'ajout de code était de re-cocher les cases des saisons pour un produit qui existe déjà dont les saisons ont déjà été cochées. J'ai compris la mécanique du morceau de code, mais ça ne fonctionne pas. Où Ai-je fait une erreur? J'ai essayé également en remplacant MSForms.textbox par .checkbox mais ça ne change rien.

Autre chose concernant la formule SPLIT pour recherche produit. Je ne comprends pas ce qu'apporte la formule par rapport à ce qui était fait avant ? On est toujours sur une recherche du terme du nom produit, et ça fonctionnait déjà avec find, n'est ce pas un doublon?

Le but était ici de :

  • J'ouvre mon formulaire pour ajouter un nouveau produit dans lequel il y a une série d'infos à compléter (nom produit, fournisseur, saison, prix, ...
  • Je tape le nom de mon nouveau produit. S'il existe dans la BDD, toutes les infos sont rechargées dans l'entiereté du formulaire (ce qui fonctionne jusqu'à présent, sauf pour les checkbox)
  • Ce qu'il me manque, et que je voudrais si possible c'est que si je tape "Fusilli", mais que ce terme exact n'existe pas dans la BDD mais bien des termes dérivés comme "Fusilli nature", "Fusilli aux oeufs",..., c'est qu'un écran s'ouvre (userform? Msgbox?) indiquant une message qui dit qu'il y a des produits prochent qui existe, et que j'aie la possibilité de cliquer sur un de ces termes proches pour le charger dans mon userform dans le champ nom produit

Grand merci d'avance

Le but de l'ajout de code était de re-cocher les cases des saisons pour un produit qui existe déjà dont les saisons ont déjà été cochées. J'ai compris la mécanique du morceau de code, mais ça ne fonctionne pas. Où Ai-je fait une erreur? J'ai essayé également en remplacant MSForms.textbox par .checkbox mais ça ne change rien.

1- S'il s'agit de Checkbox, il faut tester que le contrôle est de type CheckBox, donc :

If TypeOf ctrl Is MSForms.CheckBox Then

2- Pour cocher vos Checkbox, il faut que la valeur de votre cellule de BDD soit égale à 1 ou VRAI

Après, sans extrait de votre classeur joint, difficile d'en dire plus.

Autre chose concernant la formule SPLIT pour recherche produit. Je ne comprends pas ce qu'apporte la formule par rapport à ce qui était fait avant ? On est toujours sur une recherche du terme du nom produit, et ça fonctionnait déjà avec find, n'est ce pas un doublon?

Non.

Le Split avait pour objet de ne retenir que le premier mot de votre produit. Si le produit était "Fusili tomate", alors rech_prod = "Fusili".

Mais je vois que ce n'est pas votre demande. Donc je vais vous proposer autre chose.

Dernier point

Votre code n'est toujours pas indenté correctement, les décalages relatifs aux IF ne sont pas faits :

    rech_prod = Split(TextBox_nom_produit, " ")(0)

    'Je recherche si le fournisseur existe dans la BDD
    Set produit_existant = sh_prod.Range("F:F").Find(what:=rech_prod, LookAt:=xlWhole)
        'Si jamais la ligne n'existe pas, ça bloque, ajoute de if not
        If Not produit_existant Is Nothing Then
            'recherche le numéro de ligne
            ligne_produit_existant = produit_existant.Row
        End If

    'on lance le test pour voir s'il y a un four existant. Si pas, rdv après le else
    If ligne_produit_existant > 0 Then

        '+++++++++PAGE 1
        ComboBox_departement.ListIndex = sh_prod.Cells(ligne_produit_existant, 1)
        TextBox_code_ean.Value = sh_prod.Cells(ligne_produit_existant, 2)
        ComboBox_fournisseur.ListIndex = sh_prod.Cells(ligne_produit_existant, 3)
        TextBox_code_fournisseur.Value = sh_prod.Cells(ligne_produit_existant, 4)
        ComboBox_classification.ListIndex = sh_prod.Cells(ligne_produit_existant, 5)
        TextBox_nom_produit.Value = sh_prod.Cells(ligne_produit_existant, 6)
        TextBox_min_achat.Value = sh_prod.Cells(ligne_produit_existant, 7)
        TextBox_quantite.Value = sh_prod.Cells(ligne_produit_existant, 8)
        ComboBox_poids.ListIndex = sh_prod.Cells(ligne_produit_existant, 9)
        TextBox_prix_achat.Value = sh_prod.Cells(ligne_produit_existant, 10)

         '+++++++++PAGE 2 CHECKBOX SAISONS
        For Each ctrl In Me.Frame_saison.Controls
            If TypeOf ctrl Is MSForms.TextBox Then
                If ctrl.Tag <> Empty Then
                    colonne_checkbox_saison = sh_prod.Rows(1).Find(ctrl.Tag).Column
                    ctrl.Value = sh_prod.Cells(ligne_produit_existant, colonne_checkbox_saison)
                    End If
            End If
        Next ctrl

    End If

Merci de votre retour.

Les valeurs des CTRL de checkbox sont bien de type Vrai ou faux, mais ça ne charge pas non plus..

Voici le fichier ci-joint

Grand merci d'avance

Le but de l'ajout de code était de re-cocher les cases des saisons pour un produit qui existe déjà dont les saisons ont déjà été cochées. J'ai compris la mécanique du morceau de code, mais ça ne fonctionne pas. Où Ai-je fait une erreur?

1- tester le contrôle de type CheckBox

If TypeOf ctrl Is MSForms.CheckBox Then

2- Pour faire référence au nom de colonne de votre BDD, vous avez utilisé la propriété "Caption" de votre contrôle et non la propriété "Tag". Donc la boucle doit être ainsi

        For Each ctrl In Me.Frame_saison.Controls
            If TypeOf ctrl Is MSForms.CheckBox Then
                If ctrl.Caption <> Empty Then
                    colonne_checkbox_saison = sh_prod.Rows(1).Find(ctrl.Caption).Column
                    ctrl.Value = sh_prod.Cells(ligne_produit_existant, colonne_checkbox_saison)
                End If
            End If
        Next ctrl

Ce qu'il me manque, et que je voudrais si possible c'est que si je tape "Fusilli", mais que ce terme exact n'existe pas dans la BDD mais bien des termes dérivés comme "Fusilli nature", "Fusilli aux oeufs",..., c'est qu'un écran s'ouvre (userform? Msgbox?) indiquant une message qui dit qu'il y a des produits prochent qui existe, et que j'aie la possibilité de cliquer sur un de ces termes proches pour le charger dans mon userform dans le champ nom produit

ci-jointe une proposition avec l'affichage conditionnel d'une Combobox supplémentaire.

Encore un grand merci de votre retour !

Top pour les check box qui doivent être rechargée, ça fonctionne, un grand merci .

Concernant l'ajout du champ en combobox de recherche produit, c'est le résultat de recherche que je cherche, merci beaucoup. Par contre,

  • Je vois que que si je tape le terme exact, alors la liste n'apparait pas. Pour cette option, s'il y a plus d'un terme proche, alors ce serait bien que la liste apparaisse. Dans le fichier produit exemple, si je cherche tomate, il faut que les autres sortes de tomates apparaissent (ce qui n'est pas le cas). Par contre si je cherche "pois chiches", alors rien d'autre ne dois apparaitre.
  • Est-ce faisable, au lieu d'avoir un combobox, d'avoir à la place une fenêtre qui s'ouvre, qui montre les références qui existent (de préférence pas en combobox, mais de manière à ce que tous les termes soient visible dans devoir appuyer sur des flèches ou autre), et qu'au clic ou double clic dessus, ça sélectionne la référence (avec bien sûr la possibilité de ne pas choisir une des références

Merci d'avance

Bonjour,

Une nouvelle version qui devrait correspondre à votre demande.

En sus, j'ai réalisé des ajustements à votre code pour le rendre plus clair et logique.

Génial, un grand merci pour votre aide Thev !

Je vais parcourir le fichier, il y aura certainement qques questions qui risque de suivre

Grand merci & bon samedi

Hello

J'ai pu parcourir le code, et j'ai quelques questions pour être certain de bien tout comprendre

Concernant la simplification du code :

  • Je vois que les variables telles que sh_prod & sh_four ont été déclarées en début de module, hors sub. Ca permet de les rendre valide pour tout le code de l'userform si je comprend bien?
  • Pas possible de déclarer des variables de type dernière ligne? C'est toujours la même variable dans tout le fichier, mais je dois à chaque fois la réécrire à chaque nouveau sub.
    Ca soulagerait le code de pouvoir la déclarer une fois pour toute. Je vois aussi que une fois que sh_prod a été déclaré dans initialize, il n'y a plus de set par la suite. Le déclarer une fois dans le premier sub (initialize) est suffisant? (est-ce la manière de faire du coup?)
  • Et je déclare pas toujours toutes les variables en dim. Quel est le risque de ne pas les déclarer dans un fichier?

Concernant le code d'initialize :

Partie COMBOBOX DEPARTEMENT

Est-ce que faire un .clear avec la combobox avant de déclarer la liste a une utilité? Je vois que ça fonctionne sans.

PARTIE COMBOBOX FOURNISSEUR

Je vois qu'on est passé de derniere_ligne à un with... en with. Est-ce que ça a un meilleur fonctionnement dans le code que la manière que j'avais utilisé (.end.row)?

Concernant la fonction "liste_triée_sans_doublons", je présume que c'est un module préconcu qui fonctionne avec n'importe quel fichier. Il suffit de copier tel que le module pour l'utiliser ailleurs?

Si je comprends bien, ce module est un module générique qui permet de faire une liste qui contient aucun doublons, et qui en plus est triée de A à Z et de Z à A, c'est bien ça?

Concernant le Sub Recherche produit :

Je vois que c'est dans cette partie que l'on définit la recherche sur les valeurs proches du produit.

Si maintenant je voulais afficher dans le cadre qui s'affiche , en plus d'un nom du produit certaines autres variables liées au produit (par ex : nom fournisseur + prix), quelle serait la procédure?

Quelle est la partie du code qui fait qu'une fois le choix fait dans la listbox produit, celui ci s'affiche dans la case?

Une sélection est-elle imaginable au double clic sur le produit?

Concernant la combobox nom produit :

Est-ce que cette partie de code a encore une utilité vu la nouvelle méthode de recherche? (si oui, où est cette combobox, je ne la vois pas)

Private Sub ComboBox_nom_produit_Change()
    If Me.ComboBox_nom_produit = Empty Then Exit Sub

    Me.TextBox_nom_produit.Value = Me.ComboBox_nom_produit.Value
    TextBox_nom_produit_AFTERUPDATE
    Me.ComboBox_nom_produit.Visible = False

End Sub

Questions pour améliorer le code :

Lorsque l'on choisit un fournisseur (j'ai changé le Private Sub Combobox_fournisseur_afterupdate() par change()) , une possibilité d'ouvrir l'userform fournisseur s'affiche grace à un commandbutton "...". Le but de ce commandbuton est de pouvoir éditer les infos existantes sur le fournisseur.

Quand je clique dessus, le cadre s'ouvre. J'ai essayé différente manière de faire en sorte que le cadre fournisseur s'ouvre, mais que dans le textbox nom fournisseur (du userform_fournisseur qui s'ouvre) soit affiché le nom qui a été mis dans la combolist (du userform_produit), mais j'ai dû mal à arriver au résultat escompté.

Et les seules fois où j'y suis plus ou moins arrivé, le remplissage des autres champs d'un fournisseur existant (numéro tel, franco, ...) ne se faisaient plus, alors que quand j'ouvre l'userform en direct, il reconnait les fournisseurs existants et met à jour les données.

Un tout grand merci d'avance

Bonne fin de dimanche

Concernant la simplification du code :

Je vois que les variables telles que sh_prod & sh_four ont été déclarées en début de module, hors sub. Ca permet de les rendre valide pour tout le code de l'userform si je comprend bien?

Tout à fait

Pas possible de déclarer des variables de type dernière ligne? C'est toujours la même variable dans tout le fichier, mais je dois à chaque fois la réécrire à chaque nouveau sub.

C'est une possibilité. Mais il faut être attentif au "sub" qui va alimenter cette variable de façon à ce que sa valeur soit toujours la bonne pour les autres "sub" de votre UserForm.

Je vois aussi que une fois que sh_prod a été déclaré dans initialize, il n'y a plus de set par la suite. Le déclarer une fois dans le premier sub (initialize) est suffisant? (est-ce la manière de faire du coup?)

Il s'agit non pas de la déclarer (instruction Dim) mais de lui assigner sa valeur. Le sub (initialize) s'exécute toujours avant l'affichage du UserForm et c'est suffisant pour toutes les valeurs de variable qui resteront les mêmes pour tous les "Sub" du UserForm.

Et je déclare pas toujours toutes les variables en dim. Quel est le risque de ne pas les déclarer dans un fichier?

1- Le risque, c'est des résultats inattendus de votre code. Vous n'avez aucun contrôle de la bonne orthographe de votre variable. Une variable est utilisée plusieurs fois et si elle est une fois mal orthographiée, elle sera considérée comme une nouvelle variable et vous aurez un résultat inattendu.

2- Une variable non déclarée est toujours de type "Variant" et n'apporte aucune aide pour contrôler une instruction lors de son écriture ou de son exécution.

Exemple 1

Si vous déclarez une variable objet de type Worksheet, Range, ou autre classe, vous verrez apparaître à l'écriture en tapant le "." juste derrière cette variable, les propriétés et méthodes correspondantes, ce qui facilite l'écriture et réduit les erreurs.

Exemple 2

Si vous déclarez une variable numérique "i " de type Integer, cette instruction :

i = "a"

générera une erreur à l'exécution.

Concernant le code d'initialize :

Est-ce que faire un .clear avec la combobox avant de déclarer la liste a une utilité? Je vois que ça fonctionne sans.

Oui, si on utilise la méthode ".Additem " pour charger la Combobox, non, si on utilise la propriété ".List" qui en fait intègre le ".Clear"

Je vois qu'on est passé de derniere_ligne à un with... en with. Est-ce que ça a un meilleur fonctionnement dans le code que la manière que j'avais utilisé (.end.row)?

Votre instruction pour déterminer la dernière ligne n'est pas standard pour toute version d'Excel, même si elle suffisante pour votre cas:

derniere_ligne = sh_four.Range("A65000").End(xlUp).Row

Elle devrait être :

derniere_ligne = sh_four.Cells(Rows.Count, "A").End(xlUp).Row

Le code que j'ai utilisé n'a pas de meilleur fonctionnement mais pour moi, il est plus clair à la lecture : plage de la colonne A, débutant en A3 pour le nombre de lignes non vides de la colonne. Si votre précédent code vous parait plus clair, alors réutilisez-le.

Concernant la fonction "liste_triée_sans_doublons", je présume que c'est un module préconcu qui fonctionne avec n'importe quel fichier. Il suffit de copier tel que le module pour l'utiliser ailleurs?

Si je comprends bien, ce module est un module générique qui permet de faire une liste qui contient aucun doublons, et qui en plus est triée de A à Z et de Z à A, c'est bien ça?

C'est un fait une fonction que j'ai moi-même développée car c'est besoin récurrent dans les UserForm pour charger ceratines Combobox. Ce module est donc parfaitement réutilisable pour toute plage relative à la colonne ou la ligne d'une feuille.

Concernant le Sub Recherche produit :

Je vois que c'est dans cette partie que l'on définit la recherche sur les valeurs proches du produit.

Si maintenant je voulais afficher dans le cadre qui s'affiche , en plus d'un nom du produit certaines autres variables liées au produit (par ex : nom fournisseur + prix), quelle serait la procédure?

1- agrandir la largeur de la ListBox et passer son nombre de colonnes à 3 (propriété : ColumnCount)

2- à partir du code actuel, renseigner pour chaque ligne de la ListBox, les 2 colonnes supplémentaires, via la propriété List(i,j) où i et j sont respectivement la ligne et la colonne avec départ à 0.

Exemple de code

    If dic_liste_produits.Count > 1 Then
        With UserForm_liste_produits
            With .ListBox_produits
                tb = dic_liste_produits.Items
                For Each produit In dic_liste_produits.keys
                    .AddItem (produit)
                    ligne_produit_existant = dic_liste_produits(produit)
                    .List(.ListCount - 1, 1) = sh_prod.Cells(ligne_produit_existant, 3)
                    .List(.ListCount - 1, 2) = sh_prod.Cells(ligne_produit_existant, 10)
                Next produit
            End With
            .Show

            With .ListBox_produits
                If .ListIndex > -1 Then ligne_produit_existant = dic_liste_produits(.Value)
            End With

        End With

Quelle est la partie du code qui fait qu'une fois le choix fait dans la listbox produit, celui ci s'affiche dans la case?

Via le remplissage de votre variable : ligne_produit_existant

            With .ListBox_produits
                If .ListIndex > -1 Then ligne_produit_existant = dic_liste_produits(.Value)
            End With

Une sélection est-elle imaginable au double clic sur le produit?

Bien sûr, puisque cet événement est disponible pour une ListBox.

Concernant la combobox nom produit :

Est-ce que cette partie de code a encore une utilité vu la nouvelle méthode de recherche? (si oui, où est cette combobox, je ne la vois pas)

Private Sub ComboBox_nom_produit_Change()
    If Me.ComboBox_nom_produit = Empty Then Exit Sub

    Me.TextBox_nom_produit.Value = Me.ComboBox_nom_produit.Value
    TextBox_nom_produit_AFTERUPDATE
    Me.ComboBox_nom_produit.Visible = False

End Sub

Non puisque cette Combobox a été supprimée en 2ème version.

Questions pour améliorer le code :

Lorsque l'on choisit un fournisseur (j'ai changé le Private Sub Combobox_fournisseur_afterupdate() par change()) , une possibilité d'ouvrir l'userform fournisseur s'affiche grace à un commandbutton "...". Le but de ce commandbuton est de pouvoir éditer les infos existantes sur le fournisseur.

Quand je clique dessus, le cadre s'ouvre. J'ai essayé différente manière de faire en sorte que le cadre fournisseur s'ouvre, mais que dans le textbox nom fournisseur (du userform_fournisseur qui s'ouvre) soit affiché le nom qui a été mis dans la combolist (du userform_produit), mais j'ai dû mal à arriver au résultat escompté.

Et les seules fois où j'y suis plus ou moins arrivé, le remplissage des autres champs d'un fournisseur existant (numéro tel, franco, ...) ne se faisaient plus, alors que quand j'ouvre l'userform en direct, il reconnait les fournisseurs existants et met à jour les données.

1- Modifier ainsi le code du UserForm Produit (Me étant l'objet représentant le UserForm associé au code)

Private Sub CommandButton_fournisseur_Click()
    Me.Hide
    UserForm_fournisseur.Show
    Me.Show

End Sub

2- Une solution est d'utiliser la collection UserForms qui contient les formulaires chargés en mémoire. Modifier ainsi le code de votre UserForm Fournisseur

Private Sub UserForm_Initialize()
    Dim USF_appelant

    If UserForms.Count > 1 Then
        Set USF_appelant = UserForms(0)
        Me.TextBox_fournisseur = USF_appelant.ComboBox_fournisseur.Value
    End If

    'On insère les données dans les combobox
Rechercher des sujets similaires à "question code vba"