[Excel-VBA] Base de données --> Formulaire

Résolu
alecomte Messages postés 37 Statut Membre -  
alecomte Messages postés 37 Statut Membre -
Bonjour tout le monde,

Tout d'abord j'espère avoir posté mon sujet dans la bonne catégorie, sinon je vous prie de m'en excuser.

J'ai créé un formulaire (UserForm1) sous VBA pour Excel.
Ce formulaire contient des textbox, combobox, checkbox et cases d'option.
Il me permet de remplir une base de données clients sous Excel en récupérant
-le contenu de mes textbox et combobox ;
-les captions des checkbox (plusieurs choix possibles) ou cases d'option (un seul choix possible).

Je cherche maintenant à créer un deuxième formulaire (UserForm2 et copie du UserForm1 pour faire la manipulation inverse :

1) Je demande à l'utilisateur de sélectionner la première cellule de n'importe quelle ligne dans la base de données. Cette cellule contient le nom d'un client pour lequel j'ai rempli le formulaire. Les cellules à droite de celle du nom correspondent donc aux différents champs du formulaire que j'ai rempli (textbox, combobox, checkbox et cases d'option).

2) Je voudrais pouvoir charger le UserForm2 rempli en fonction des données dans le tableau. Ainsi les bonnes checkbox seront cochées, les textbox remplies et les bonnes cases d'option cochées.

3) Je vais modifier des données et les ré-enregistrer à la place des précédentes sur la même ligne du tableau afin d'éviter les doublons.

Voici mon problème :

Je n'arrive pas à comparer le contenu des cellules de mon tableau avec les captions de mes checkbox.
Si le contenu de la cellule est identique au caption d'une ou plusieurs checkbox, il faut cocher les checkbox en question.

Même raisonnement pour les boutons d'option, je souhaiterais comparer le contenu de la cellule aux captions des cases d'option et sélectionner la bonne.

Enfin je voudrais pouvoir ré-enregistrer le contenu du UserForm2 sur la même ligne de mon tableau Excel en remplacement des valeurs précédentes.

Voici une trame de code que j'ai effectuée mais qui ne fonctionne pas; si vous pouvez m'aider ?

Pour le moment la macro demande de sélectionner une ligne.
Ensuite j'essaie de récupérer le contenu d'une cellule associée à une frame avec plusieurs checkbox et de cocher les bonnes checkbox.

Private Sub UserForm_Initialize()
'la macro se lance à l'ouverture du formulaire

'Sélection de la cellule du client auquel on souhaite apporter des modifications
Dim macellule As Range
Dim i As Byte

Set macellule = Application.InputBox("Sélectionnez la cellule avec le nom du client.", "Sélection de cellules", Type:=8)

'Remplir les checkbox
Dim cible As String
cible = "A,B,C,D"

'A B C D correspondent aux captions des checkbox

'ici j'ai essayé plusieurs syntaxe de code :

'If Not InStr(cible, macellule.Offset(0, 2)) = 0 Then
'If Not InStr(macellule.Offset(0, 2), cible) = 0 Then
If InStr(macellule.Offset(0, 2), cible) > 0 Then

With Me.frame1
For i = 6 To 10
'If .Controls("CheckBox" & i).Caption = cible Then
'If .Controls("CheckBox" & i).Caption = macellule.Text Then
If .Controls("CheckBox" & i).Caption = macellule Then
.Controls("CheckBox" & i).Value = True
End If
Next i
End With
End If

End Sub

Voilà j'espère avoir été clair dans mon problème.
Un grand merci à ceux qui se pencheront dessus :)

14 réponses

  1. Heliotte Messages postés 1561 Statut Membre 92
     
    Bonsoir alecomte,
    Le but est donc de remplir le UserForm depuis le tableau sur le Feuil2 du classeur Excel : fait
    les retours à la ligne Chr(10) me posent problème : c'est normal .. je suis à la version 2003, donc, pour moi, un retour de ligne, ce n'est chr(10) mais plutôt "vbcrlf" !! à retenir !
    Private Sub UserForm_Initialize()
        'L'idée est de REMPLIR LE FORMULAIRE DEPUIS LA BASE DE DONNEES
        Dim macellule As Range
        ' sélection de la feuille où se trouve les clients "Feuil2"
        Worksheets("Feuil2").Activate
        'Sélection de la cellule du client auquel on souhaite apporter des modifications
        Set macellule = Application.InputBox("Sélectionnez la cellule avec le nom du client.", _
                                             "Sélection de cellules", _
                                             Type:=8)
        If (macellule = "") Then UserForm_Initialize
        '
        ' remplir le formulaire
        With ComboBox1
            .Clear
            .AddItem macellule
            If ComboBox1.ListCount >= 1 Then
                .ListIndex = 0
            End If
        End With
        ' raisons
        CheckBox6.Value = IIf(InStr(1, macellule.Offset(0, 1), "A", vbTextCompare) > 0, True, False)
        CheckBox7.Value = IIf(InStr(1, macellule.Offset(0, 1), "B", vbTextCompare) > 0, True, False)
        CheckBox8.Value = IIf(InStr(1, macellule.Offset(0, 1), "C", vbTextCompare) > 0, True, False)
        CheckBox9.Value = IIf(InStr(1, macellule.Offset(0, 1), "D", vbTextCompare) > 0, True, False)
        ' sexe
        OptionButton7.Value = IIf(macellule.Offset(0, 2) = "Homme", True, False)
        OptionButton8.Value = IIf(macellule.Offset(0, 2) = "Femme", True, False)
        '
    End Sub
    2
    1. alecomte Messages postés 37 Statut Membre 9
       
      Super merci !!

      Du coup je voudrais vous exposer 3 autres soucis que je rencontre svp ?


      Pour commencer, voici le nouveau fichier obtenu grâce à ton aide :
      https://www.cjoint.com/?BLkaGRE1C3j


      Sur mon fichier d'origine, j'ai 2 formulaires :
      - le premier UserForm1 rempli le tableau
      - le deuxième UserForm2 sert à modifier des données (en chargeant les données du tableau vers la base de données grâce à ton code précédant notamment :)

      Voici les différents problèmes que je souhaiterais résoudre :




      souci 1) Dans le UserForm1

      J'ai un code qui doit me permettre de récupérer les noms des clients dans le tableau Excel et les intégrer dans une ComboBox1: ça j'ai trouvé mais....

      Mais je voudrais trier les noms dans la ComboBox1 par ordre alphabétique
      et là ma macro ne fonctionne pas.

      Par ailleurs sur le UserForm1, j'ai un bouton qui me permet de transférer les données dans le tableau, en l'occurrence le nom du client.
      Je voudrais que la ComboBox1 se mette à jour avec le nom du nouveau client toujours par ordre alphabétique.

      Mon code ne fonctionne pas. Mais si tu trouves l'erreur je suis preneur :)




      souci 2) Tu remarqueras que j'ai ajouté une ComboBox2 "fréquence" sur les deux formulaires.

      Dans le UserForm1, la ComboBox2 offre un certain nombre d'options.

      Je voudrais que lorsqu'on charge le UserForm2, les options soient toutes présentes dans la ComboBox2 mais que la fréquence présente dans le tableau Excel soit sélectionnée par défaut (puisqu'on charge les données depuis le tableau).




      souci 3) A l'ouverture du UserForm2, (UserForm2 Initialize)
      on demande de sélectionner une cellule avec le nom du client auquel on souhaite apporter les modifications.
      Donc cela nécessite de modifier les données du formulaire puis, via un bouton sur le formulaire,
      de lancer une macro qui va aller modifier les données.

      Private Sub CommandButton1_Click()
      'comment référencer ici macellule sélectionnée dans la macro UserForm_Initialize ?
      End Sub

      Seulement est-il possible de référencer dans cette macro le nom de la cellule qu'on est allé sélectionner dans la macro précédente (UserForm2 Initialize) afin d'apporter les modifications souhaitées sur la même ligne du tableau Excel ?



      Merci encore pour ton aide !!
      0
    2. alecomte Messages postés 37 Statut Membre 9
       
      Pour le souci 3)
      j'ai pensé autrement à refaire une recherche dans le tableau

      Set Recherche = Sheets("Feuil2").Columns("A").Find(Me.ComboBox1)
      If Not Recherche Is Nothing Then

      'FIXER LA CELLULE où le nom du client à été trouvé COMME CELLULE DE DÉMARRAGE pour les modifications et ensuite je modifie toutes les colonnes avec la fonction Offset

      mais dans ce cas-là : comment fixer la cellule comme cellule de "démarrage" ?

      Merci :)
      0
    3. alecomte Messages postés 37 Statut Membre 9
       
      toujours pour le souci 3)
      on doit pouvoir utiliser

      Set Recherche = Sheets("Feuil2").Columns("A").Find(Me.ComboBox1)
      If Not Recherche Is Nothing Then
      Recherche.Address = Me.ComboBox1

      puis ActiveCell.Offset ...
      0
    4. alecomte Messages postés 37 Statut Membre 9
       
      souci 2 = résolu
      0
  2. alecomte Messages postés 37 Statut Membre 9
     
    Nouveau souci sur mon fichier :

    J'ai quatre formulaires.
    Et sur les quatre je voudrais utiliser une même macro pour enregistrer.

    J'ai tapé ma macro sur un des modules du projet

    Sub enregistrer ()
    ...
    End Sub

    Et sur mes quatre formulaires, j'ai ajouté un bouton "Enregistrer" avec
    un macro associée :

    Sub enregistrer_Click ()
    Call enregistrer
    End Sub

    Seulement Excel me renvoie

    "Erreur de compilation :
    Utilisation incorrecte de la propriété"

    Et je ne comprends pas ce qui ne fonctionne pas.
    Au départ la macro figurait dans le module du UserForm1 et elle fonctionnait parfaitement. Et je précise qu'elle ne fait appelle à aucune variable définie dans le module de mon UserForm !

    Merci de votre aide
    1
    1. Heliotte Messages postés 1561 Statut Membre 92
       
      Sub enregistrer () 
      ... 
      End Sub

      Essaie en "Public Sub Enregistrer, mais logiquement ce n'est pas la cause .. Je rechercherai ce soir

      Edit:
      Nom du bouton "Enregistrer" .. Nom de la procédure "Enregistrer"
      Moi, compilateur, le prend lequel ?
      0
  3. Heliotte Messages postés 1561 Statut Membre 92
     
    Bonjour alecomte,
    Pour y voir plus clair, ce serait bien que tu dépose ton fichier sur un site de dépôt, tel que https://www.cjoint.com/ en prenant garde de supprimer toutes données sensible !
    Puis, tu nous met le lien dans ton prochain message en soulignant les questions !
    Merci
    0
  4. alecomte Messages postés 37 Statut Membre 9
     
    Pour info, le bouton sur la feuil1 me servira à lancer le formulaire (mais ça je sais le programmer ;)
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. alecomte Messages postés 37 Statut Membre 9
     
    Bonjour Heliotte*

    Il semble que mon premier message ne soit pas passé.

    Donc voici le lien https://www.cjoint.com/?BLjoUkvp1Fd

    Le but est donc de remplir le UserForm depuis le tableau sur le Feuil2 du classeur Excel

    Pour l'instant j'ai essayé de cocher les cases checkbox associées aux données dans la colonne "raisons".
    J'ai plus détaillé les macros dans le fichier en téléchargement ci-avant.

    J'ai fait plusieurs essais de code mais les retours à la ligne Chr(10) me posent problème.

    Merci pour ton aide
    0
  7. Heliotte Messages postés 1561 Statut Membre 92
     
    Bonjour alecomte,

    J'ai fait un certain nombre de choses, surtout pour l'UserForm2
    Teste-le et rapporte-moi tes prochain souhaits.

    Essaie d'être un peu plus précis et concis, merci.
    Pour la précision, parles des objets tel qu'ils sont. Exemple tu dis "bases de données .. en fait tu parles de la feuille .. on ne peut pas appeler cela une base de données.

    Il faut savoir qu'une base de données est faites, en règle générale de plusieurs "tables" .. une feuille est une table .. donc, pas une base de données, merci.

    Ah oui, j'oubliais le principal ! Le classeur, version 2003, se trouve ici : http://cjoint.com/12dc/BLklruMuPYG.htm
    0
  8. alecomte Messages postés 37 Statut Membre 9
     
    Bonjour Heliotte,
    Alors oui c'est presque ça.

    Problème1 : tri alphabétique sans tenir compte des majuscules/minuscules

    Actuellement la comboBox1 des noms de clients fait un tri alphabétique mais en tenant compte des caractères majuscules et minuscules ; par exemple :

    AnThoNy
    ONG Frederic
    Vincent
    XENA
    alex
    henri
    marie

    Je voudrais avoir :

    alex
    AnThoNy
    henri
    marie
    ONG Frederic
    Vincent
    XENA

    Donc les noms avec l'orthographe saisie exactement.
    Donc je suppose que ça exclut l'utilisation des fonctions UCase, LCase, NProper etc. ?

    Problème2 : avec la ligne de code des cases d'option

    Supposons qu'au lieu d'avoir le choix entre deux sexes (Homme et Femme), je veuille rajouter une troisième case d'option "Troisième sexe".

    Quelles sont les modifications à opérer sur cette ligne (sous-jacente au UserForm2) ?

    MaCellule.Offset(0, 2) = IIf(OptionButton7.Value = True, "Homme", "Femme")

    car je ne pense pas que je puisse avoir :

    MaCellule.Offset(0, 2) = IIf(OptionButton7.Value = True, "Homme", "Femme","Troisième sexe")

    Merci !
    0
  9. Heliotte Messages postés 1561 Statut Membre 92
     
    Re-plusieurs_fois bonjour alecomte,

    Problème 1 : c'est très simple. Dans le module "Module1", après "Option Explicit", tu écris "Option Compare Text" et là .. miracle .. l'ordre alphabétique se réalise sans tenir compte des minuscules/majuscules.

    Problème 2 : D'abord, le toisième sexe est "Ange" .. trève de plaisanterie. Si il y a plus que deux éléments, il est plus élégant d'utiliser un "If/Else/EndIf" ou un "Select Case". Cela donnerais quelque chose comme Non Fonctionnel:
    Select Case (OptionButton7.Value) 
     Case = True 
      MaCellule.Offset(0, 2) = "Homme" 
     Case = False 
      MaCellule.Offset(0, 2) = "Femme" 
     Case = NiTrueNiFalse 
      MaCellule.Offset(0, 2) = "Ange" 
    End Select

    J'ai pris cet exemple qui ne fonctionnera jamais car un "OptionButton" n'a que 2 états "True" ou "False", mais fonctionnerais super bien pour un TextBox, et il faudrait écrire:
    Select Case (Val(TextBox1.Text)) 
     Case = 1 
      MaCellule.Offset(0, 2) = "Homme" 
     Case = 2 
      MaCellule.Offset(0, 2) = "Femme" 
     Case = 3 
      MaCellule.Offset(0, 2) = "Ange" 
     Case Else 
      MaCellule.Offset(0, 2) = "néant" 
    End Select

    Résumé : je pense que tout est ok maintenant !
    edit: faute d'orthographe
    0
  10. alecomte Messages postés 37 Statut Membre 9
     
    Oui je pense que tout est ok grâce à toi.
    Je vais finaliser mon fichier et je te dirai si je rencontre d'autres problèmes.
    En attendant je clôture le topic.
    Et je te dis vraiment un grand MERCI ! :)
    0
    1. Heliotte Messages postés 1561 Statut Membre 92
       
      Tout le plaisir est pour moi,
      @ très bientôt alors .. bonne programmation,
      Heliotte
      0
  11. Heliotte Messages postés 1561 Statut Membre 92
     
    Comment appelles-tu les UserForm .. du code
    0
  12. alecomte Messages postés 37 Statut Membre 9
     
    Pardon, c'est une erreur, sur mon code j'ai bien
    Public Sub enregistrer
    mais on peut le remplacer par Public Sub sauvegarder pour une meilleure lisibilité.

    Par contre je crois que par défaut Sub = Public Sub (sauf précision en Private Sub)

    Pour les formulaires, je les appelle simplement :
    UserForm1
    UserForm2
    UserForm3
    UserForm4
    (Enfin je fais bien sûr ici allusion à la propriété Name et non pas Caption.)

    Mais je crois voire où tu m'emmènes :
    j'avais bien pensé à les appelés en faisant

    Dans mon module :

    Public Sub sauvegarder (Usf as Userform)
    ...
    End Sub

    et dans les boutons de mes formulaires par exemple :

    Sub enregistrer_Click (UserForm1)
    Call enregistrer (UserForm1)
    End Sub

    Mais ici je veux enregistrer tout le classeur (et non pas seulement le formulaire ; ce qui semble impossible en fait)
    donc je ne vois pas l'utilité de référencer les UserForm en variables ?
    (Ceci je n'ai pas essayé mais je ne saisis pas la logique dans ce cas ?)
    0
  13. Heliotte Messages postés 1561 Statut Membre 92
     
    Public Sub ou Private Sub : une bonne pratique, sinon c'est pris pour de la négligence, manque de rigueur !

    Oui, quand uniquement "Sub", elle est publique.

    On attaque le morceau !
    Pour chaque UserForm:
    Option Explicit
    Private HandleUF&
    '
    Private Sub UserForm_Initialize()
        Const WS_MAXIMIZEBOX& = &H10000, _
            WS_MINIMIZEBOX& = &H20000, GWL_STYLE& = -16&
        HandleUF = FindWindow(vbNullString, Me.Caption)
        SetWindowLong HandleUF, GWL_STYLE, _
            GetWindowLong(HandleUF, GWL_STYLE) Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX
        BaseUFProc = SetWindowLong(HandleUF, GWL_WNDPROC, BaseUFProc)
    End Sub
    '
    Private Sub UserForm_Terminate()
        SetWindowLong HandleUF, GWL_WNDPROC, BaseUFProc
    End Sub
    '
    Private Sub Enregistrer_Click()
        Call EnregistrerX
        Unload Me
    End Sub

    Dans un module:
    Option Explicit
    
    Public Declare Function FindWindow& _
        Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName$, ByVal lpWindowName$)
    
    Public Declare Function GetWindowLong& _
        Lib "user32" Alias "GetWindowLongA" _
        (ByVal hwnd&, ByVal nIndex&)
    
    Public Declare Function SetWindowLong& _
        Lib "user32" Alias "SetWindowLongA" _
        (ByVal hwnd&, ByVal nIndex&, ByVal dwNewLong&)
    
    Private Declare Function EnableWindow& _
        Lib "user32" _
        (ByVal hwnd&, ByVal fEnable&)
    
    Private Declare Function CallWindowProc& _
        Lib "user32" Alias "CallWindowProcA" _
        (ByVal lpPrevWndFunc&, ByVal hwnd&, ByVal Msg&, ByVal wParam&, ByVal lParam&)
    
    Public Const GWL_WNDPROC& = -4&, WM_SYSCOMMAND& = &H112&
    
    Public BaseUFProc&, BaseXLProc&, AncState&
    
    Function UFProc&(ByVal hwnd&, ByVal uMsg&, ByVal wParam&, ByVal lParam&)
        Dim HwndXL&
        Const SC_MINIMIZE& = &HF020&
        If uMsg = WM_SYSCOMMAND Then
                If wParam = (SC_MINIMIZE And &HFFF0&) Then
                    HwndXL = FindWindow("XLMAIN", Application.Caption)
                    EnableWindow HwndXL, True
                    UserForm1.Hide
                    AncState = Application.WindowState
                    Application.WindowState = xlMinimized
                    BaseXLProc = SetWindowLong(HwndXL, GWL_WNDPROC, AddressOf XLProc)
                    UFProc = 1&
                    Exit Function
                End If
        End If
        UFProc = CallWindowProc(BaseUFProc, hwnd, uMsg, wParam, lParam)
    End Function
    
    
    Function XLProc&(ByVal hwnd&, ByVal uMsg&, ByVal wParam&, ByVal lParam&)
        Const SC_MAXIMIZE& = &HF030&, _
            SC_RESTORE& = &HF120&, SC_CLOSE& = &HF060&
        If uMsg = WM_SYSCOMMAND Then
                If wParam = (SC_MAXIMIZE And &HFFF0&) Or wParam = (SC_RESTORE _
                    And &HFFF0&) Or wParam = SC_CLOSE Then
                    SetWindowLong hwnd, GWL_WNDPROC, BaseXLProc
                    Application.WindowState = AncState
                    UserForm1.Show
                    XLProc = 1&
                    Exit Function
                End If
        End If
        XLProc = CallWindowProc(BaseXLProc, hwnd, uMsg, wParam, lParam)
    End Function
    '
    Public Sub EnregistrerX()
        ActiveWorkbook.Save
        MsgBox "Enregistrement effectué !", vbInformation, "Etat de la procédure ""Sauvegarder"" !"
    End Sub
    Voilà !
    0
  14. alecomte Messages postés 37 Statut Membre 9
     
    Merci pour ta réponse, je regarde ça et je te tiens au courant ;)
    0
  15. alecomte Messages postés 37 Statut Membre 9
     
    Encore une fois, ça me convient très bien. T'es au top ;)
    0