[access vba] modifier une requete

Bonjour,

J'apprivoise tranquillement access. Je me suis fais un formulaire ou je choisi les critères afin de modifier ma requete. Ensuite j'ouvre l'état correspondant. Par contre, les criteres ne sont pas seulement dans la clause where, car j'ai plusieurs select imbriqué, si seulement dans la clause where, j'envoie le critère lors de l'ouverture de l'état, mais comment faire pour changer d'autres parties dans ma requete avant d'ouvrir mon état? Recordset? si oui, comment?

Merci beaucoup de bien vouloir me donner des pistes!

51 réponses

  • Votes
  • Date
  • Date décroissante
Résumé de la discussion

La problématique porte sur la modification dynamique d'une requête Access depuis un formulaire avant l'ouverture d'un état, en gérant des critères imbriqués qui échappent à une simple clause WHERE. Plusieurs solutions passent par la construction d'une chaîne SQL dynamique, le stockage dans une QueryDef et la mise à jour du SQL via ChangeRequeteDef, puis l'ouverture du formulaire lié. En pratique, les champs du formulaire alimentent des variables utilisées dans le SQL (ex. MonChamps), avec des événements AfterUpdate déclenchant la mise à jour et l'ordre Table → Requête → Formulaire. Pour la mise à l'épreuve, tester sur une copie, vérifier le typage des champs (notamment les dates) et consolider les chaînes SQL étape par étape évite les erreurs.

Bobot (l’IA à votre service)
  1. Bonjour,

    suggestion :

    Créer un requête type de ce que vous souhaité avoir comme résultat :

    ex, passer en mode SQL :

    soit une requête [ SELECT * FROM tabClients WHERE (((tabClients.Acronyme) Like "zzz*")); ]

    l'objectif étant de décomposer la requête en chaines de caractères :

    Dim Chaine As String

    Chaine = Chaine = "SELECT * FROM tabClients WHERE (((" & MonChamps & ") Like" & """" & "zzz*" & """" & "));"

    ici, la variable [ MonChamps ] peut provenir de n'importe où [ Zone de texte, liste déroulante, etc ...

    ensuite on valide la mise à jour de la requête avec :

    If (ChangeRequeteDef("MaRequeteType", Chaine)) Then
    DoCmd.OpenForm "MonFormulaire", acNormal, "", "[Acronyme]", , acNormal
    End If

    dans la ligne du IF, on utilise ici une fonction qui est la suivante :
    Public Function ChangeRequeteDef(ChaineRequete As String, ChaineSQL As String) As Boolean
        
        Dim Definition As Variant
        
        If ((ChaineRequete = "") Or (ChaineSQL = "")) Then
            ChangeRequeteDef = False
        Else
            Set Definition = CurrentDb.QueryDefs(ChaineRequete)
            Definition.SQL = ChaineSQL
            Definition.Close
            RefreshDatabaseWindow
            ChangeRequeteDef = True
        End If
        
    End Function
    '
    


    Lupin
    1. bonjour
      en fait j'ai rien compri a ce ke tu a di mais c est exactement ske je voudrais faire donc si t encore dans le coin sa peu m interesser merki
  2. Bonjour,

    Peux tu m'expliquer comment on crée un formulaire qui permet de modifier une requete ?

    Merci beaucoup
    1. Bonjour,

      Oui je suis pas loin, toutefois je dois vous avouer que j'ai du mal avec le langage sms !

      La langue française n'est-elle pas à ce point riche qu'elle ne mérite d'être écorché à ce point.

      Lupin
      1. je suis desole mais j'ai un clavier sans accent deja et j'ai pris une tres mauvaise habitude autant pour moi
        En fait ce serait pour savoir comment faire dans un langage plus simple voila
    2. re :

      Bon je veux bien refaire le parcours.

      Alllons pas à pas !

      As-tu un formuliare qui pointe sur une requête, qui elle-même pointe sur une table ?

      Si une telle requête existe, peux-tu le voir en mode SQL ?

      Si oui, fias-en un copier coller ici .

      Lupin
      1. Je suis pas sur que ce soit ce que tu voule mais voila

        Refmaintenance Numlicence_cle Fin_garantie Fin_extension
        G_BLE_1 30/01/2007
        G_CET 03/01/2007
        G_UCP 12/06/2007
        G_GEM 22/05/2007
        G_DEN 09/10/2007
        G_TUN 18/10/2007
        G_GE_01 29/12/2007
        G_SIN 13/12/2007
        G_ARA 15/12/2007
        EG_BLE_1 30/01/2007 30/01/2008
        EG_CET 03/01/2007 03/01/2008
        EG_DEN 09/10/2007 09/10/2008

        Dans critere en mode creation j'ai un intervalle de dates: >#01/01/2007# Et <#01/01/2008#
        et je voudrais pouvoir changer ces dates a partir d un formulaire quelconque
        1. oups j avais pas vu le "mode SQL" avant et ca je sais pas faire!
      2. re :

        lorsque tu es en mode création, utilise le premier bouton de la barre d'outils pour accéder au mode SQL.

        lorsque tu passe la souris sur le bouton un info-bulle [ Affichage ] apparaît.

        en utilisant la liste déroulante de ce bouton, tu auras le mode SQL.

        tu obtiendra quelque chose comme :

        SELECT *
        FROM tabClients
        WHERE (((tabClients.Acronyme) Like "zzz*"));

        Lupin
        1. Exact ca me donne ca:
          SELECT [Maintenance].[Refmaintenance], [Maintenance].[Numlicence_cle], [Maintenance].[Fin_garantie], [Maintenance].[Fin_extension]
          FROM Maintenance
          WHERE ((([Maintenance].[Fin_garantie])>#1/1/2007# And ([Maintenance].[Fin_garantie])<#1/1/2008#));
          merci rien que pour ca, ca va beaucoup m'aider mais tu pourras continuer!
      3. re :

        maintenant, l'idée est de recomposer la requète SQL dans une chaine de caractères :

        ex.:

        Sub Test()
        
        'SELECT [Maintenance].[Refmaintenance], [Maintenance].[Numlicence_cle], [Maintenance].[Fin_garantie], [Maintenance].[Fin_extension]
        'FROM Maintenance
        'WHERE ((([Maintenance].[Fin_garantie])>#1/1/2007# And ([Maintenance].[Fin_garantie])<#1/1/2008#));
        
            Dim ChaineSQL As String, Critere1 As String, Critere2 As String
            
            Critere1 = "#1/1/2007#" ' Pourrait provenir de n'importe où, variable, textbox, etc ...
            Critere2 = "#1/1/2008#"
            
            ChaineSQL = "SELECT [Maintenance].[Refmaintenance], [Maintenance].[Numlicence_cle], [Maintenance].[Fin_garantie], [Maintenance].[Fin_extension]"
            ChaineSQL = ChaineSQL & " " & "FROM Maintenance "
            ChaineSQL = ChaineSQL & "WHERE ((([Maintenance].[Fin_garantie])>" & Critere1 & " "
            ChaineSQL = ChaineSQL & "And ([Maintenance].[Fin_garantie])<" & Critere2 & "));"
            
            If (ChangeRequeteDef("nom_de_la_requete", ChaineSQL)) Then
                DoCmd.OpenForm "formulaire_Specifique", acNormal, "", "[Acronyme]", , acNormal
            End If
            
            
        End Sub
        '
        


        Lupin
        1. Et j'ecris tout dans cette fenetre alors c'est bien ca?
          (Car c'est la premiere fois que je vois ca!)
          1. re :

            non, ce texte n'est pas a écrire dans la fenêtre du mode SQL !

            c'est du code VBA qui va s'accrocher sur un formulaire, sur un bouton, sur une liste déroulante, etc ...

            Dans mon exemple, plaçons un formulaire maitre et un formulaire secondaire.

            dans le formulaire maitre, on place 2 textbox pour inscrire les dates de sélection

            sur chacun des textboxs on place une procédure évènementiel

            Private Sub tbxDateDebut_AfterUpdate()
            
                 If ((tbxDateDebut.Text <> "") and ( tbxDateFin.Text <> "" ))
                      ' On reconstruit la chaine SQL avec les paramètres des 2 textbox
                      ' On modifie la requète
                      ' On ouvre le sous-formulaire qui pointe sur la requête que l'on vien de modifié.
                 End IF
            End Sub
            '
            

            Lupin
            1. Donc deja j'espere que tu as le temps car je ne comprends pas vite!
              Ensuite elles sont ou les textboxs et enfin formulaire secondaire=sous-formulaire?
              Je pense qu'apres ca ira mieux
              1. re :

                bon alors nous serons deux car je n'explique pas toujours bien ma pensée.

                ce qui est évident pour moi ne l'est pas forcément pour toi et vice-versa :-)

                oui sous-formulaire = formulaire secondaire

                les textboxs ne sont qu'un exemple.

                je cite (message 7) :

                Dans critere en mode creation j'ai un intervalle de dates: >#01/01/2007# Et <#01/01/2008#
                et je voudrais pouvoir changer ces dates a partir d un formulaire quelconque

                tu crées 2 textboxs pour saisir ces valeurs :

                ensuite tu y ajoute le code comme soumis :

                Private Sub tbxDateDebut_AfterUpdate()
                
                    Dim ChaineSQL As String, Critere1 As String, Critere2 As String
                
                     If ((tbxDateDebut.Text <> "") And (tbxDateFin.Text <> "")) Then
                
                        Critere1 = Me.tbxDateDebut.Text
                        Critere2 = Me.tbxDateFinal.Text
                        
                        ChaineSQL = "SELECT [Maintenance].[Refmaintenance], [Maintenance].[Numlicence_cle], [Maintenance].[Fin_garantie], [Maintenance].[Fin_extension]"
                        ChaineSQL = ChaineSQL & " " & "FROM Maintenance "
                        ChaineSQL = ChaineSQL & "WHERE ((([Maintenance].[Fin_garantie])>" & Critere1 & " "
                        ChaineSQL = ChaineSQL & "And ([Maintenance].[Fin_garantie])<" & Critere2 & "));"
                        
                        If (ChangeRequeteDef("nom_de_la_requete", ChaineSQL)) Then
                            DoCmd.OpenForm "formulaire_Specifique", acNormal, "", "[Champs]", , acNormal
                        End If
                    
                     End If
                     
                End Sub
                '
                
                


                Lupin
                1. Justement je crois que mon plus gros probleme ce sont ces textboxs ou l'on met ces formules,
                  ce sont les "modules"(la page ou il y a table, formulaire, macros.......) ou c'est autre chose?
              2. re :

                dis moi,

                le nom de(s) table(s)
                le nom de(s) requète(s)
                le nom de(s) formulaire(s)

                Lupin
                1. Pour l instant tout ce qui est concerne:
                  les tables: Maintenance, Machine, Logiciel
                  les requetes: R_Maintenance, R_Machine, R_Logiciel
                  le formulaire (vide): Tri_dates
                  1. re :

                    disons que le formulaire Tri_dates est le formulaire principal, sur ce formulaire tu places 2 textboxs.

                    tu crées une quatrième requête partiel du style que celle que tu as soumis
                    en lui donnant un autre nom [ nom_de_la_requete dans la procédure ] :

                    SELECT [Maintenance].[Refmaintenance], [Maintenance].[Numlicence_cle], [Maintenance].[Fin_garantie], [Maintenance].[Fin_extension]
                    FROM Maintenance
                    WHERE ((([Maintenance].[Fin_garantie])>#1/1/2007# And ([Maintenance].[Fin_garantie])<#1/1/2008#));

                    maintenant tu crées un second formulaire qui pointe sur la requête partiel avec le visuel souhaité.
                    donne un nom significatif à ce second formulaire

                    maintenant, sur les 2 textboxs en mode création, fenêtre des propriétés, onglet évènement

                    ligne après MAJ, choisir Procédure événementiel ...
                    clic sur l'icon (le bouton) du bout qui a 3 petits points

                    tu attéris directement dans le module VBA du formulaire !

                    C'est là que tu va placé le code :
                    Private Sub tbxDateDebut_AfterUpdate()
                    
                        Dim ChaineSQL As String, Critere1 As String, Critere2 As String
                    
                         If ((tbxDateDebut.Text <> "") And (tbxDateFin.Text <> "")) Then
                    
                            Critere1 = Me.tbxDateDebut.Text
                            Critere2 = Me.tbxDateFinal.Text
                            
                            ChaineSQL = "SELECT [Maintenance].[Refmaintenance], [Maintenance].[Numlicence_cle], [Maintenance].[Fin_garantie], [Maintenance].[Fin_extension]"
                            ChaineSQL = ChaineSQL & " " & "FROM Maintenance "
                            ChaineSQL = ChaineSQL & "WHERE ((([Maintenance].[Fin_garantie])>" & Critere1 & " "
                            ChaineSQL = ChaineSQL & "And ([Maintenance].[Fin_garantie])<" & Critere2 & "));"
                            
                            If (ChangeRequeteDef("nom_de_la_requete", ChaineSQL)) Then
                                DoCmd.OpenForm "second_formulaire", acNormal, "", "[Champs]", , acNormal
                            End If
                        
                         End If
                         
                    End Sub
                    '
                    


                    bon, ça c'est le truc en gros, mais je dois souvent valider la construction de la chaine SQL en mode
                    pas à pas d'exécution VBA.

                    Lupin
                    1. Tout ca, ca y est j'ai compris je te remercie je crois meme que j'ai compris la signification des codes mais le seul petit truc c'est toujours pour les textboxs: c'est une fonction speciale avec son icone ou c'est par exemple une zone de liste modifiable
                      Sinon pour le reste je te remercie et si il y a d autres problemes je te re-derangerais demain! .....ou avant si tu n'as pas repondu a cette question!
                  2. re :

                    effectivement, pour ma part j'utilise des zones de liste modifiable, qui sont accroché
                    sur des mini requètes de mes tables pour obtenir les données voulues.

                    Je sélectionne une valeur dans ma liste déroulante et la requête est modifé
                    selon ce nouveau critère par programmation et j'ouvre alors un second formulaire récapitulatif
                    de la recherche.

                    Sur ce second formulaire, lorsque je double-clic sur un enregistrement choisi,
                    ce second formulaire se ferme et mon formiulaire pricinpal pointe sur l'enregistrement
                    que j'ai choisi dans le second formulaire.

                    C'est très efficace pour la recherche :-)

                    Lupin
                    1. d'accord je dois y aller donc je relirais tout ca ce soir et si j'ai un pb je t embeterais encore demain
                  3. merci beaucoup :-)
                    1. Comme prevu je te re-derange pour plusieurs raisons:
                      la premiere, je n'est pas compris ce que tu as dit la:
                      "j'ouvre alors un second formulaire récapitulatif
                      de la recherche.

                      Sur ce second formulaire, lorsque je double-clic sur un enregistrement choisi,
                      ce second formulaire se ferme et mon formiulaire pricinpal pointe sur l'enregistrement
                      que j'ai choisi dans le second formulaire."
                      Ensuite j'ai tout suivi a nouveau la procedure et ma requete reste avec les 2 parametres
                      WHERE ((([Maintenance].[Fin_garantie])>#1/1/2007# And ([Maintenance].[Fin_garantie])<#1/1/2008#));
                      et je vois pas comment arranger ca en attendant tes reponses je continue a chercher ( j'avais prevenu que je n'etais pas un rapide!)
                  4. re :

                    Ton formulaire principal [ Tri_dates ] devrait afficher l'ensemble de tes tables en pointant sur une
                    requête globale qui rend tout le contenu de tes tables !

                    Quelques questions :

                    1.) as-tu créés 2 textbox sur ton formulaire Tri_dates ?

                    2.) peux-tu entrer dans la procédure évènementiel de l'après MAJ de ces textbox ?

                    3.) as-tu créés un 4ième requête ?

                    4.) si oui, quelle est le nom de cette nouvelle requête ?

                    5.) as-tu créés un formulaire qui s'accroche à cette nouvelle requête ?

                    6.) si oui, quelle est son nom ?

                    Lupin
                    1. 1 oui il y a 2 textboxs
                      2 la procedure est bien rentree et le code y est
                      3 oui il y a une 4eme requete
                      4 elle s appellle R_tridate
                      5 Qu est-ce que tu veux dire par accrocher? parce qu avec l assistant j'en ai fait un qui s appelle F_tridate
                      6 voila
                  5. En fait je m'excuse platement car comme un gros blaireau j'avais lie le dernier formulaire a une requete qui n'etait pas la bonne! autant pour moi je vais fignoler et je te remercie
                    1. euh ca marche toujours pas en fait parce que c'est toujours l intervalle 01/01/07 et 01/01/08
                      1. re :

                        as-tu inclus la fonction qui modifie la requête :

                        Public Function ChangeRequeteDef(ChaineRequete As String, ChaineSQL As String) As Boolean
                            
                            Dim Definition As Variant
                            
                            If ((ChaineRequete = "") Or (ChaineSQL = "")) Then
                                ChangeRequeteDef = False
                            Else
                                Set Definition = CurrentDb.QueryDefs(ChaineRequete)
                                Definition.SQL = ChaineSQL
                                Definition.Close
                                RefreshDatabaseWindow
                                ChangeRequeteDef = True
                            End If
                            
                        End Function
                        '
                        

                        Lupin
                        1. Non ca se met ou ca?
                      • 1
                      • 2
                      • 3