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

Access Discussion :

Code VBA à implanter sous Access 2010 [AC-2010]


Sujet :

Access

  1. #1
    Membre à l'essai
    Homme Profil pro
    Ingénieur Mécanique
    Inscrit en
    Juillet 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur Mécanique
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2015
    Messages : 12
    Points : 11
    Points
    11
    Par défaut Code VBA à implanter sous Access 2010
    Bonjour à tous,

    Je crée en ce moment même une base de données, et j'ai besoin d'une requête récursive un peu lourde qui doit passer par un code VBA sous ACCESS 2010.

    J'ai trouvé ce merveilleux code, dans une conversation de ce forum

    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
    Public Sub compter(idpiece As String, idPieceACompter As String, ByRef QtteTotal As Integer, Optional nb As Integer = 1)
      '
      Dim qdf As DAO.QueryDef
      Dim rcs As DAO.Recordset
      '
       QtteTotal = QtteTotal + _
            nb * Nz(DLookup("[Quantite]", "COMPOSITION", "[ComposantId]='" & idpiece & "' AND [ComposeId]='" & idPieceACompter & "'"), 0)
     
      ' ici j'utilise une requête enregistrée et paramétrée, nommée "RSelect" dont voici le SQL:
      ' PARAMETERS [Référence pièce ?] Text ( 12 );
      ' SELECT COMPOSITION.ComposeId, COMPOSITION.Quantite
      ' FROM COMPOSITION
      ' WHERE COMPOSITION.ComposantId = [Référence pièce ?] ;
      '
      Set qdf = CurrentDb.QueryDefs("RSelect")
          qdf.Parameters("[Référence pièce ?]") = idpiece
     
      Set rcs = qdf.OpenRecordset
     
      If Not rcs.EOF Then
        rcs.MoveFirst
            Do While Not rcs.EOF
                If rcs.Fields(0) <> idPieceACompter Then
                  Call compter(rcs.Fields(0), idPieceACompter, QtteTotal, rcs.Fields(1)) ' <==appel récursif
                End If
            rcs.MoveNext
            Loop
      End If
     
      Set qdf = Nothing
      Set rcs = Nothing
     
    End Sub
    qui est apellée par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Public Sub appel()
    Dim qt As Integer
    '
    qt = 0
        Call compter("aile", "rivet", qt)         ' réponse: 183
        ' Call compter("aileron", "rivet", qt)    ' réponse: 13
        ' Call compter("train", "rivet", qt)      ' réponse: 20
        ' Call compter("aile", "charniere", qt)   ' réponse: 5
     
    MsgBox (qt)
    '
    End Sub
    Donc mon problème est de savoir très précisément comment implanter cette macro VBA sous Acess 2010, car ça m'a l'air un peu figé. Des captures d'écrans seraient les bienvenues

    Merci à tous d'avance !!!

  2. #2
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 096
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 096
    Points : 31 518
    Points
    31 518
    Billets dans le blog
    16
    Par défaut Ailes, rivets, récursivité, Access vba, macros et tout ça...
    Bonsoir develalex,


    J’ai retrouvé du code VBA que j’avais développé il y a environ un an pour m’entraîner. Ce code pourrait être rendu moins verbeux, mais j’ai déjà supprimé plein d’instructions servant à des choses qui ne nous concernent pas ici.

    Pour récupérer ce code (ou tout autre !) :

    Dans la barre de menus, cliquer sur l’onglet « Database Tools » (désolé pour les termes, je n’ai que la version 2013 et angloricaine d’ACCESS... ) :







    Cliquer sur l’icône « Visual Basic » : on entre dans l’univers VBA (bien sombre ) :






    Pour arriver à amorcer la pompe, on clique sur l’icône qui va bien (« Insert Module ») :





    Fiat lux ! On a droit maintenant de créer des instructions :






    Coller le code VBA (que je fournis un peu plus loin).





    Avant d’exécuter le code, créer les tables COMPOSANT (équivalente de la table COMPOSITION de mon message précédent) et PILE (table temporaire, dans laquelle on empile les comptages) :

    COMPOSANT
    {EnsembleId varchar, EnsembleParent varchar, Quantite integer}
    KEY {EnsembleId, EnsembleParent} ;

    PILE
    {PileId autonumber, Niveau integer, EnsembleId varchar, EnsembleParent varchar, Quantite integer}
    KEY {Niveau EnsembleId, EnsembleParent} ;

    Les fonctions et procédures présentes dans le code VBA :

    Une fonction (AilesRivetsRecursonsAmorce()) permet d’amorcer la pompe ; elle passe la main à une procédure récursive (AilesRivetsRecursonsJoyeusement) qui compte les composants (exemple, les rivets) du composé (exemple, l’aile).


    Code VBA :

    
    Option Compare Database
    Option Explicit
    
    '-------------------------------------------------------------------------
    '   Amorce du comptage
    '-------------------------------------------------------------------------
    
    Function AilesRivetsRecursonsAmorce()
    
    Dim MaBase As DAO.Database
    Dim Amorce As Integer, LeComposé As String, LeComposant As String, TotalOut As Integer
    
    Set MaBase = CurrentDb
    
    Amorce = 1
    LeComposé = "aile"
    LeComposant = "rivet"
    
    ' Initialisation de la pile utilisée pour les récursions
    MaBase.Execute "DELETE FROM PILE ;"
    
    'C'est parti pour compter les rivets !
    Call AilesRivetsRecursonsJoyeusement(Amorce, LeComposé, LeComposant, TotalOut)
     
     AilesRivetsRecursonsAmorce = TotalOut
     
    ' Au résultat
     MsgBox " Composé : " & LeComposé & Chr(13) & Chr(13) _
            & "Nombre total d'éléments du type " & LeComposant & " : " & TotalOut
    
    
    MaBase.Execute "DELETE FROM PILE ;"
    
    Set MaBase = Nothing
     
    End Function
    
    '-------------------------------------------------------------------------
    '   Routine récursive
    '-------------------------------------------------------------------------
    
    Sub AilesRivetsRecursonsJoyeusement(ByRef Amorce As Integer, ByVal LeComposé As String, ByVal Composant As String, ByRef TotalOut As Integer)
    
    Dim MaBase As DAO.Database, Sqlresult As DAO.Recordset
    Dim Kount As Integer, Requete As String, theNiveau As Integer
    
    Set MaBase = CurrentDb
    
    Requete = "SELECT COUNT(*) AS Kount FROM PILE ;"
    Set Sqlresult = MaBase.OpenRecordset(Requete, dbOpenDynaset)
    Kount = Sqlresult.Fields("Kount")
    
    If Kount = 0 Then
        theNiveau = 1
    Else
        Requete = "SELECT DISTINCT MAX(Niveau) AS MaxNiveau FROM PILE ;"
        Set Sqlresult = MaBase.OpenRecordset(Requete, dbOpenDynaset)
        theNiveau = Sqlresult.Fields("MaxNiveau").Value + 1
    End If
    
    If Amorce = 1 Then
        
        Requete = "INSERT INTO PILE (EnsembleId, EnsembleParent, Quantite, Niveau) VALUES ('" & LeComposé & "', 0, 0, 1) ;"
        MaBase.Execute Requete
            
        Requete = "INSERT INTO PILE (EnsembleId, Ensembleparent, Quantite, Niveau)" _
                       & " SELECT EnsembleId, Ensembleparent, Quantite, " & 2 _
                       & " FROM   COMPOSANT" _
                       & " WHERE  Ensembleparent = '" & LeComposé & "' ;"
            
        MaBase.Execute Requete
            
        '' Allez petit ! on récurse !
        Call AilesRivetsRecursonsJoyeusement(0, LeComposé, Composant, TotalOut)
    Else
        Requete = "SELECT COUNT(*) AS Kount " _
                    & "FROM (SELECT x.EnsembleId " _
                          & "FROM   COMPOSANT AS x INNER JOIN PILE AS y ON x.Ensembleparent = y.EnsembleId " _
                          & "WHERE  Niveau = " & theNiveau - 1 & ") as truc ; "
                     
        Set Sqlresult = MaBase.OpenRecordset(Requete, dbOpenDynaset)
        Kount = Sqlresult.Fields("Kount")
    
        If Kount > 0 Then
    
             
            Requete = "INSERT INTO PILE (EnsembleId, Quantite, Niveau, Ensembleparent) " _
                        & " SELECT x.EnsembleId, SUM(x.Quantite * y.Quantite), " & theNiveau & ", x.Ensembleparent " _
                        & " FROM   COMPOSANT AS x INNER JOIN PILE AS y ON x.Ensembleparent = y.EnsembleId " _
                        & " WHERE  Niveau = " & theNiveau - 1 _
                        & " GROUP BY x.EnsembleId, x.Ensembleparent, " & theNiveau & " ;"
    
    
    MaBase.Execute Requete Call AilesRivetsRecursonsJoyeusement(0, LeComposé, Composant, TotalOut)
    
            Requete = "SELECT SUM(Quantite) AS TotalOut FROM PILE WHERE EnsembleId = '" & Composant & "' ;"
       
    
    Set Sqlresult = MaBase.OpenRecordset(Requete, dbOpenDynaset) If Not IsNull(Sqlresult.Fields("totalOut")) Then TotalOut = Sqlresult.Fields("totalOut") Else TotalOut = 0 End If Sqlresult.Close End If End If End Sub
    Pour contrôler les boucles infinies, il serait bon de tester la profondeur atteinte !


    Pour tester et exécuter le code VBA directement :






    Pour exécuter les instructions pas à pas, utiliser la touche de fonction F8 :







    Pour exécuter à partir d’une macro, on commence par créer celle-ci (logique ^^) :

    Barre de menu : onglet « CREATE », icône « Macro » :






    Cézigue nous demande d’ajouter une action (je rappelle que j’utilise ACCESS 2013, mais en principe ça marche aussi pour ACCESS 2010) :





    Dans sa liste déroulante on choisit « RunCode » (ExécuterCode) :






    On fournit le nom de la fonction qui prendra la main :






    On ferme la fenêtre et on donne un nom à la macro :





    Elle est là !






    On l’exécute en double cliquant sur son nom :

    =>









    J’espère qu’il n’y aura pas de problème avec ACCESS 2010...

  3. #3
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    Nom d'une pipe, c'est la grande forme !

  4. #4
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 096
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 096
    Points : 31 518
    Points
    31 518
    Billets dans le blog
    16
    Par défaut Ad augusta per angusta
    Salut Claude,


    Heu... Accouchement un peu pénible d’un code quand même verbeux, dans le contexte bridant des macros ACCESS (et la chaleur n’aide pas...)

    La requête proposée par Chamberlin il y a 20 ans dans Database Programming & Design (mai 1996) est quand même plus légère er rafraîchissante :





    Ou la mouture qu’il a proposée en 1994 avec ses collègues d’IBM dans Extending relational database technology for new applications (IBM Systems Journal , Vol 33, No 2, 1994) :





    Mais les choses étant ce qu’elles sont...

  5. #5
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 594
    Points : 281 907
    Points
    281 907
    Par défaut
    d’un code quand même verbeux
    ... ce qui le rend compréhensible !

  6. #6
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 096
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 096
    Points : 31 518
    Points
    31 518
    Billets dans le blog
    16
    Par défaut
    Une précision :

    Fonction AilesRivetsRecursonsAmorce :

    Plutôt que de les avoir en dur dans le code, on peut préférer choisir les valeurs du composant et du composé à l’aide de la fonction InputBox :

      
    Function AilesRivetsRecursonsAmorce()
    
    Dim MaBase As DAO.Database
    Dim Amorce As Integer, LeComposé As String, LeComposant As String, TotalOut As Integer
    
    Set MaBase = CurrentDb
    
    Amorce = 1
    
    LeComposé = InputBox("Composé : ")
    LeComposant = InputBox("Composant : ")
    
    ' Initialisation de la pile utilisée pour les récursions
    MaBase.Execute "DELETE FROM PILE ;"
    
    'C'est parti pour compter les rivets !
    Call AilesRivetsRecursonsJoyeusement(Amorce, LeComposé, LeComposant, TotalOut)
     
     AilesRivetsRecursonsAmorce = TotalOut
     
    ' Au résultat
     MsgBox " Composé : " & LeComposé & Chr(13) & Chr(13) _
            & "Nombre total d'éléments du type " & LeComposant & " : " & TotalOut
    
    
    MaBase.Execute "DELETE FROM PILE ;"
    
    Set MaBase = Nothing
     
    End Function
    
    

  7. #7
    Membre à l'essai
    Homme Profil pro
    Ingénieur Mécanique
    Inscrit en
    Juillet 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur Mécanique
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2015
    Messages : 12
    Points : 11
    Points
    11
    Par défaut
    Bonjour tout le monde,

    En ce frais lundi matin (puisque je suis à Cambridge, et pas dans votre canicule toute française) je vais m'atteler à tout ça.

    Que cela marche ou non je tiens à vous remercier du temps que vous m'avez consacré. Je reviens vous dire si cela fonctionne dans deux petites heures. (Ambitieux le jeune homme)

    A tchao bonsoir.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Ingénieur Mécanique
    Inscrit en
    Juillet 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur Mécanique
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2015
    Messages : 12
    Points : 11
    Points
    11
    Par défaut
    Alors alors fsmrel,

    Tout marche super j'ai même pu adapter ça à mes tables déjà créée (bon c'était pas sorcier en même temps, le plus dur c'est toi qui l'as fait).

    J'ai une autre interrogation, qui était d'ailleurs ce que je cherchais à faire depuis le début:
    Au lieu de renvoyer le nombre de fois ou tel composant est utilisé, avec une modification astucieuse, est ce que ton programme ne pourrait pas être capable de me dire tout les composants (avec leur quantité) d'un composé. J'arrive à le faire sur 1 niveau avec une requête SQL classique que voilà :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT PARTS_1.description, COMPOSITION.Quantity
    FROM (PARTS INNER JOIN COMPOSITION ON PARTS.IDparts = COMPOSITION.ComposedOf) INNER JOIN PARTS AS PARTS_1 ON COMPOSITION.Compose = PARTS_1.[PartNnumber]
    WHERE (((PARTS.PartNnumber)=[What is the part number?]));
    Du coup j'aimerai appeler cette requête et ce de manière récursive dans ton joli programme.

    Sache que ton aide m'a déjà beaucoup aidé. Et toutes les interfaces montrées sous Access 2013 sont les mêmes sous Access 2010, donc encore merci

    Au plaisir de lire ta réponse qui clora sans aucun doute ce topic.

  9. #9
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 096
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 096
    Points : 31 518
    Points
    31 518
    Billets dans le blog
    16
    Par défaut
    Bonjour develalex,


    Citation Envoyé par develalex Voir le message
    est ce que ton programme ne pourrait pas être capable de me dire tout les composants (avec leur quantité) d'un composé ?
    Sans problème !

    Je fais d’abord une petite sieste, parce qu’il fait chaud, ensuite je selle mon cheval et j’arrive au galop !

  10. #10
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 096
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 096
    Points : 31 518
    Points
    31 518
    Billets dans le blog
    16
    Par défaut
    Examinons l’instruction suivante dans la procédure AilesRivetsRecursonsJoyeusement (je viens de la bleuir dans le message #2 :

    
    Requete = "INSERT INTO PILE (EnsembleId, Quantite, Niveau, Ensembleparent) " _
                & " SELECT x.EnsembleId, SUM(x.Quantite * y.Quantite), " & theNiveau & ", x.Ensembleparent " _
                & " FROM   COMPOSANT AS x INNER JOIN PILE AS y ON x.Ensembleparent = y.EnsembleId " _
                & " WHERE  Niveau = " & theNiveau - 1 _
                & " GROUP BY x.EnsembleId, x.Ensembleparent, " & theNiveau & " ;"
    
    
    Elle a pour objet d’enrichir la table PILE à chaque itération. En fin de parcours son contenu est le suivant (faites un SELECT * FROM PILE) :

    
    PileId    Niveau    EnsembleId    Ensembleparent    Quantite
         1         1    aile          0                        0
         2         2    aileron       aile                     1
         3         2    longeron      aile                     5
         4         2    rivet         aile                   100
         5         2    train         aile                     1
         6         3    charnière     aileron                  2
         7         3    charnière     train                    3
         8         3    rivet         aileron                  5
         9         3    rivet         longeron                50
        10         3    rivet         train                    8
        11         4    rivet         charnière               20
    
    
    Autrement dit, une fois la macro exécutée, vous pouvez soumettre la requête suivante pour connaître le nombre de rivets pour une aile :

    
    SELECT SUM(Quantite)
    FROM   PILE
    WHERE  EnsembleId = "rivet";
    
    
    Et pour connaître pour une aile le détail par composant :

    
    SELECT EnsembleId, SUM(Quantite)
    FROM   PILE
    GROUP BY EnsembleId ;
    
    
    J’ai simplifié et nettoyé la partie VBA :

    
    '-------------------------------------------------------------------------
    '   Amorce du comptage
    '-------------------------------------------------------------------------
    
    Function AilesRivetsRecursonsAmorce()
    
    Dim MaBase As DAO.Database
    Dim Amorce As Integer, LeComposé As String, LeComposant As String, TotalOut As Integer
    
    Set MaBase = CurrentDb
    
    Amorce = 1
    
    LeComposé = InputBox("Composé : ")
    LeComposant = InputBox("Composant : ")
    
    ' Initialisation de la pile utilisée pour les récursions
    MaBase.Execute "DELETE FROM PILE ;"
    
    'C'est parti pour compter les rivets !
    Call AilesRivetsRecursonsJoyeusement(Amorce, LeComposé, LeComposant)
    
    Set MaBase = Nothing
    
    End Function
    
    

    
    '-------------------------------------------------------------------------
    '   Routine récursive
    '-------------------------------------------------------------------------
    
    Sub AilesRivetsRecursonsJoyeusement(ByRef Amorce As Integer, ByVal Composé As String, ByVal Composant As String)
    
    Dim MaBase As DAO.Database, Sqlresult As DAO.Recordset
    Dim Kount As Integer, requete As String, theNiveau As Integer
    
    Set MaBase = CurrentDb
    
    requete = "SELECT COUNT(*) AS Kount FROM PILE ;"
    Set Sqlresult = MaBase.OpenRecordset(requete, dbOpenDynaset)
    Kount = Sqlresult.Fields("Kount")
    
    If Kount = 0 Then
        theNiveau = 1
    Else
        requete = "SELECT DISTINCT MAX(Niveau) AS MaxNiveau FROM PILE ;"
        Set Sqlresult = MaBase.OpenRecordset(requete, dbOpenDynaset)
        theNiveau = Sqlresult.Fields("MaxNiveau").Value + 1
    End If
    
    If Amorce = 1 Then
        
        requete = "INSERT INTO PILE (EnsembleId, EnsembleParent, Quantite, Niveau) VALUES ('" & Composé & "', 0, 0, 1) ;"
        MaBase.Execute requete
            
        requete = "INSERT INTO PILE (EnsembleId, Ensembleparent, Quantite, Niveau)" _
                       & " SELECT EnsembleId, Ensembleparent, Quantite, " & 2 _
                       & " FROM   COMPOSANT" _
                       & " WHERE  Ensembleparent = '" & Composé & "' ;"
            
        MaBase.Execute requete
            
        '' Allez petit ! on récurse !
        Call AilesRivetsRecursonsJoyeusement(0, Composé, Composant)
    Else
        requete = "SELECT COUNT(*) AS Kount " _
                    & "FROM (SELECT x.EnsembleId " _
                          & "FROM   COMPOSANT AS x INNER JOIN PILE AS y ON x.Ensembleparent = y.EnsembleId " _
                          & "WHERE  Niveau = " & theNiveau - 1 & ") as truc ; "
                     
        Set Sqlresult = MaBase.OpenRecordset(requete, dbOpenDynaset)
        Kount = Sqlresult.Fields("Kount")
        
        '' Tant que Kount > 0 c'est qu'on n'a pas fini d'empiler
        If Kount > 0 Then
               
            requete = "INSERT INTO PILE (EnsembleId, Quantite, Niveau, Ensembleparent) " _
                        & " SELECT x.EnsembleId, SUM(x.Quantite * y.Quantite), " & theNiveau & ", x.Ensembleparent " _
                        & " FROM   COMPOSANT AS x INNER JOIN PILE AS y ON x.Ensembleparent = y.EnsembleId " _
                        & " WHERE  Niveau = " & theNiveau - 1 _
                        & " GROUP BY x.EnsembleId, x.Ensembleparent, " & theNiveau & " ;"
               
            MaBase.Execute requete
    
            Call AilesRivetsRecursonsJoyeusement(0, Composé, Composant)
                
            Sqlresult.Close
                
        End If
    End If
    
    End Sub
    
    

    Rappel de l’exemple de structure de la macro :




    J’espère ne pas m’être emmêlé dans les copier/coller, tenez-moi au courant !

  11. #11
    Membre à l'essai
    Homme Profil pro
    Ingénieur Mécanique
    Inscrit en
    Juillet 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur Mécanique
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2015
    Messages : 12
    Points : 11
    Points
    11
    Par défaut
    Alors, j'ai copié collé ce que tu m'as donné dans un nouveau module que j'ai liée à une macro VBA , j'ai supprimée l'autre pour être sur qu'il n'y ait pas de conflit au niveau de la fonction apellée.

    Mais, lorsque je lance le programme, les deux boîtes s'affichent bien pour me demander le composé et composant, puis j'ai l'impression que le programme tourne deux secondes, il se termine mais ne me renvoie rien. Et en effet dans le programme on ne lui demande pas de retourner quoi que ce soit à la fin. Donc ou suis je censé lire tout les détails de composition ?

    Merciiiiii d'avance

  12. #12
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 096
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 096
    Points : 31 518
    Points
    31 518
    Billets dans le blog
    16
    Par défaut
    Comme je l’ai écrit dans mon message précédent, une fois la macro exécutée, vous pouvez soumettre la requête suivante pour connaître le nombre de rivets pour une aile :

    
    SELECT SUM(Quantite)
    FROM   PILE
    WHERE  EnsembleId = "rivet";
    
    
    Et pour connaître pour une aile le détail par composant :

    
    SELECT EnsembleId, SUM(Quantite)
    FROM   PILE
    GROUP BY EnsembleId ;
    
    
    Ce qui revient à dire que la partie VBA est désormais chargée de remplir la table PILE, alors qu’au départ elle affichait en plus une ligne (et une seule) pour montrer qu’une aile nécessite 183 rivets : avec une MsgBox, ça marche très bien. Le problème est que si l’on veut afficher le détail par composant, une MsgBox risque de ne pas suffire, d’où ma proposition de travailler en deux temps :

    1) Exécuter la macro pour remplir la table PILE ;

    2) Effectuer vous-même les SELECT permettant de consulter la table PILE à volonté et d’en extraire ce qu’on veut.

    Chaque SELECT fait l’objet d’un Query facile à construire (exemple : Rivets_par_aile). Avez-vous des difficultés à ce sujet ?




  13. #13
    Membre à l'essai
    Homme Profil pro
    Ingénieur Mécanique
    Inscrit en
    Juillet 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur Mécanique
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2015
    Messages : 12
    Points : 11
    Points
    11
    Par défaut
    Salut fsmrel,

    Alors voilà le code VBA que j'ai :

    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    Option Compare Database
    
    
    '-------------------------------------------------------------------------
    '   Amorce du comptage
    '-------------------------------------------------------------------------
    
    Function AilesRivetsRecursonsAmorce()
    
    Dim MaBase As DAO.Database
    Dim Amorce As Integer, LeComposé As String, LeComposant As String, TotalOut As Integer
    
    Set MaBase = CurrentDb
    
    Amorce = 1
    
    LeComposé = InputBox("Composé : ")
    LeComposant = InputBox("Composant : ")
    
    ' Initialisation de la pile utilisée pour les récursions
    MaBase.Execute "DELETE FROM PILE ;"
    
    'C'est parti pour compter les rivets !
    Call AilesRivetsRecursonsJoyeusement(Amorce, LeComposé, LeComposant)
    
    Set MaBase = Nothing
    
    End Function
    
    
    
    '-------------------------------------------------------------------------
    '   Routine récursive
    '-------------------------------------------------------------------------
    
    Sub AilesRivetsRecursonsJoyeusement(ByRef Amorce As Integer, ByVal Composé As String, ByVal Composant As String)
    
    Dim MaBase As DAO.Database, Sqlresult As DAO.Recordset
    Dim Kount As Integer, requete As String, theNiveau As Integer
    
    Set MaBase = CurrentDb
    
    requete = "SELECT COUNT(*) AS Kount FROM PILE ;"
    Set Sqlresult = MaBase.OpenRecordset(requete, dbOpenDynaset)
    Kount = Sqlresult.Fields("Kount")
    
    If Kount = 0 Then
        theNiveau = 1
    Else
        requete = "SELECT DISTINCT MAX(Niveau) AS MaxNiveau FROM PILE ;"
        Set Sqlresult = MaBase.OpenRecordset(requete, dbOpenDynaset)
        theNiveau = Sqlresult.Fields("MaxNiveau").Value + 1
    End If
    
    If Amorce = 1 Then
        
        requete = "INSERT INTO PILE (EnsembleId, EnsembleParent, Quantite, Niveau) VALUES ('" & Composé & "', 0, 0, 1) ;"
        MaBase.Execute requete
            
        requete = "INSERT INTO PILE (EnsembleId, Ensembleparent, Quantite, Niveau)" _
                       & " SELECT EnsembleId, Ensembleparent, Quantite, " & 2 _
                       & " FROM   COMPOSANT" _
                       & " WHERE  Ensembleparent = '" & Composé & "' ;"
            
        MaBase.Execute requete
            
        '' Allez petit ! on récurse !
        Call AilesRivetsRecursonsJoyeusement(0, Composé, Composant)
    Else
        requete = "SELECT COUNT(*) AS Kount " _
                    & "FROM (SELECT x.EnsembleId " _
                          & "FROM   COMPOSANT AS x INNER JOIN PILE AS y ON x.Ensembleparent = y.EnsembleId " _
                          & "WHERE  Niveau = " & theNiveau - 1 & ") as truc ; "
                     
        Set Sqlresult = MaBase.OpenRecordset(requete, dbOpenDynaset)
        Kount = Sqlresult.Fields("Kount")
        
        '' Tant que Kount > 0 c'est qu'on n'a pas fini d'empiler
        If Kount > 0 Then
               
            requete = "INSERT INTO PILE (EnsembleId, Quantite, Niveau, Ensembleparent) " _
                        & " SELECT x.EnsembleId, SUM(x.Quantite * y.Quantite), " & theNiveau & ", x.Ensembleparent " _
                        & " FROM   COMPOSANT AS x INNER JOIN PILE AS y ON x.Ensembleparent = y.EnsembleId " _
                        & " WHERE  Niveau = " & theNiveau - 1 _
                        & " GROUP BY x.EnsembleId, x.Ensembleparent, " & theNiveau & " ;"
               
            MaBase.Execute requete
    
            Call AilesRivetsRecursonsJoyeusement(0, Composé, Composant)
                
            Sqlresult.Close
                
        End If
    End If
    
    End Sub
    (J'ai mis en gras l'instruction qui peut être pose problème, si l'on supprime la table comment la retrouve t'il ?)

    Le probleme est qu'une fois cette Macro effectuée la table PILE ne contient pas ce qu'il faudrait:
    Voilà ma table COMPOSANT :
    Nom : TableCOMPOSANT.jpg
Affichages : 600
Taille : 39,2 Ko

    Et voilà seulement de quoi est composé la table PILE (alors que je teste un grand niveau de profondeur normalement (quelquechose comme le 5 eme niveau) :

    Nom : Resultat après macro.jpg
Affichages : 669
Taille : 29,0 Ko

    Pour ce qui est des requêtes ensuite il n'y a pas de souci normalement je saurais faire.

    Merci d'avance,

    Ps : Le temps de réponse est dû au fait que je ne travaille là dessus qu'au boulot donc entre 9h et 18h

    Ps2 : Note aussi que ton précédent programme fonctionnait très bien, donc je ne pense pas que le problème vienne des tables

  14. #14
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 096
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 096
    Points : 31 518
    Points
    31 518
    Billets dans le blog
    16
    Par défaut
    Bonjour develalex,


    Citation Envoyé par develalex
    J'ai mis en gras l'instruction qui peut être pose problème, si l'on supprime la table comment la retrouve t'il ?)
    Dans la fonction AilesRivetsRecursonsAmorce , on ne supprime pas la table PILE (ce qui nécessiterait l’exécution d’une instruction DROP TABLE), mais on la vide par DELETE des lignes qu’elle contient quand on exécute la fonction AilesRivetsRecursonsAmorce. En effet, il s’agit d’une table temporaire, dont le seul but est d’émuler la vue qui est définie dans l’exemple proposé par Chamberlin. Ainsi, dans le code que j’ai proposé, la table PILE persiste tant qu’on ne réexécute pas la fonction AilesRivetsRecursonsAmorce, ce qui laisse entre temps le loisir de soumettre les requêtes qu’on veut.

    Ainsi, quand je propose :

    Composé = "00136R01"
    Composant = "00151R01"

    Au résultat, la table PILE a pour contenu (ne pas tenir compte de l’attribut PileId qui évolue au fil des exécutions et ne joue aucun rôle fonctionnel) :

    
    PileId	Niveau	EnsembleId	Ensembleparent	Quantite
    33	1	00136R01	0	        0
    36	2	00137R01	00136R01	1
    34	2	00138R01	00136R01	1
    35	2	00139R01	00136R01	1
    37	3	00140R01	00138R01	1
    38	3	00141R01	00138R01	1
    39	3	00142R01	00139R01	1
    40	4	00143R01	00142R01	3
    41	4	00144R01	00142R01	1
    42	4	00145R01	00140R01	1
    43	4	00146R01	00141R01	1
    44	5	00147R01	00146R01	4
    45	5	00148R01	00146R01	1
    46	5	00149R01	00146R01	1
    47	6	00150R01	00149R01	1
    48	6	00151R01	00149R01	2
    
    
    A partir de là, on exploite cette table comme on veut, elle ne sera vidée de son contenu qu’à la prochaine exécution de la fonction AilesRivetsRecursonsAmorce.

    Par exemple, par Query Design (cf. mon message précédent), vous pouvez créer la requête suivante (qui répond à la question « est ce que ton programme ne pourrait pas être capable de me dire tout les composants (avec leur quantité) d'un composé ? ») :

    
    SELECT PILE.EnsembleId AS Composant, Sum(PILE.Quantite) AS QteParComposant
    FROM PILE
    GROUP BY PILE.EnsembleId ;
    
    
    Si on donne le nom « group_by_composant » à cette requête, on peut l’exécuter directement, à volonté, mais on peut aussi le faire (ce qui est plus lourd) via une macro « CompterLesRivetsParComposant » qui vide puis remplit la table PILE et exécute la requête (query) :


  15. #15
    Membre à l'essai
    Homme Profil pro
    Ingénieur Mécanique
    Inscrit en
    Juillet 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur Mécanique
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2015
    Messages : 12
    Points : 11
    Points
    11
    Par défaut
    Ok autant pour moi je suis un gros boulet, je tapais "00136N02" dans composé (qui est la vraie référence) et non pas "00136R01" comme j'ai mis dans mes tables exemples, forcément cela ne fonctionnait pas...



    Un énorme MERCI pour ton aide, et le temps que tu as pris pour m'expliquer toutes ces subtilités.

    J'éspère ne pas avoir à revenir ici, non que le coin ne soit pas agréable bien au contraire, mais parce que je pense que je vais pouvoir me débrouiller avec mes connaissances et les tutoriels pour la suite.



    EDIT: D'ailleurs ce programme est très fort parcequ'il permet une véritable arborescence si l'on ne remplit pas la case composant, il va juste descendre le plus bas possible et ne va rien trouver. Très intéressant.

  16. #16
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 096
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 096
    Points : 31 518
    Points
    31 518
    Billets dans le blog
    16
    Par défaut
    Citation Envoyé par develalex Voir le message
    Ok autant pour moi je suis un gros boulet, je tapais "00136N02" dans composé (qui est la vraie référence) et non pas "00136R01" comme j'ai mis dans mes tables exemples, forcément cela ne fonctionnait pas...
    Je m'en doutais, mais bon...

    Bonne route, and vote for me!

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

Discussions similaires

  1. Code barre gratuit sous access 97
    Par massol joel dans le forum Contribuez
    Réponses: 7
    Dernier message: 05/07/2017, 16h18
  2. Génération pdf sous access 2010 vba
    Par facilordi dans le forum VB 6 et antérieur
    Réponses: 0
    Dernier message: 24/03/2015, 11h54
  3. [AC-2010] Récupérer une Séquence Oracle en VBA sous Access 2010
    Par stef75 dans le forum VBA Access
    Réponses: 3
    Dernier message: 13/02/2013, 10h56
  4. [Formulaire] code VBA et runtime Access
    Par Frenchguy dans le forum Runtime
    Réponses: 11
    Dernier message: 23/11/2006, 17h09
  5. code VBA versus assistant Access
    Par zephyr59 dans le forum Access
    Réponses: 6
    Dernier message: 10/04/2006, 15h04

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