Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1532 connectés 

  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  [VBA] fonction paramétré renvoyant le résultat d'une requête ACCESS

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[VBA] fonction paramétré renvoyant le résultat d'une requête ACCESS

n°2176908
le petit b​leu
Posté le 21-02-2013 à 17:13:49  profilanswer
 

Bonjour,
 
J'ai une base de donnée sous ACCESS contenant des informations que je souhaiterai pouvoir exploiter dans des pages excel.
 
Pour illustrer mon propos, je vous propose un exemple simplifiant beaucoup les choses.
Soit une table:
 
Société1 DatedeCréation
Société2 DatedeCréation
Société3 DatedeCréation
Société4 DatedeCréation
Société5 DatedeCréation
Société6 DatedeCréation
 
Ainsi,  pour obtenir la date de création d'une société, j'ai créé une requête sur ACCESS qui me demande en argument le nom d'une société (et qui fonctionne très bien).
J'aurai donc souhaité créer une fonction VBA prenant en argument le nom de la société et me renvoyant dans ma cellule la date de création de la société.
 
C'est surement très simple, mais cela fait maintenant plusieurs heures que je cherche sans trouver de réponse.
 
Merci pour votre aide.

mood
Publicité
Posté le 21-02-2013 à 17:13:49  profilanswer
 

n°2177010
hush hush
je savais que ça te plairait
Posté le 22-02-2013 à 09:58:27  profilanswer
 

Tiens, c'est marrant, je bosse sur du VBA/Access en ce moment :o
 
Pour commencer, il faut que tu ajoute les références qui vont bien dans ton vba:
Microsoft DAO 3.6 Object Library
Peut etre que tu aura besoin aussi de ClFileSearch, un petit coup de google t'en diras plus :o
 
Ensuite, dans le code de ta fonction, il faut que tu paramètre certaines choses:
ta base de donnée: dim db as dao.Database
ton recordset (set de données bdd): dim rstNomSociete as dao.Recordset
ta requête d'extraction: dim sRequete as string
 
'Stocker le chemin de ta base de donnée dans une variable cheminBdd
 
'Ouvrir ta bdd:
set db = DBEngine.Opendatabase(cheminBdd)
 
'Construire ta requête Access (ie: en language SQL, quasiment le même que celui généré par l'assistant requête d'access)
sRequete = "SELECT nomtable.DateCreation FROM nomtable WHERE nomtable.NomSociété =" & ... (iiiha, bienvenue dans la gestion des string, google est ton ami)
 
'Parametrer l'objet requête
Set rstNomSociete = db.OpenRecordset(sRequete)
 
'Récupérer le resultat
Do Until rstNomSociete.EOF
    nomfonction = rstNomSociete![NomChampsquivabien]
    rstNomSociete.MoveNext
Loop
 
'On dit au revoir:
rstNomSociete.Close
db.close
 
Valà, t'as de quoi faire,
En fonction de ton niveau en programmation, ça te prendra entre 3 et 300 minutes à tester :o

n°2177014
le petit b​leu
Posté le 22-02-2013 à 10:18:44  profilanswer
 

C'est pas si simple que ça en fait.
Bon, je m'y mets. Je me plonge dedans.
 
Merci pour la réponse. Rendez vous dans 300 minutes.

n°2177015
hush hush
je savais que ça te plairait
Posté le 22-02-2013 à 10:22:46  profilanswer
 

Oui je m'en doute :)
Mais commence par tester 1 seul acces à la base pour 1 requête :)
C'est le plus dur,
Ensuite, ça va tout seul.
SI je peux me permettre: je pense que chercher des sociétés par le nom est risqué (aurtographe...)
Essaye de fonctionner par id plutôt (clés uniques)
 
Enfin, pour la constuction de ta requête, j'imagine que t'as pas mal de tables, rencarde toi sur les inner join. Et pour finir, ton meilleur ami dans ces cas là (après google) c'est l'assitant création de requêtes ;)

n°2177028
le petit b​leu
Posté le 22-02-2013 à 11:32:14  profilanswer
 

Bon bon bon,
Je me suis lancé. Et pas de problème pour le code. Je me documente donc c'est super, j'apprends plein de truc.  
 
Entre la concaténation de chaine de caractère, la fonction .EOF (très utile ce truc d'ailleurs),  la connexion à la base de données etc.
 
En revanche, je ne suis pas sur d'avoir saisi l'essentiel.
C'est à dire la petite boucle
 
Do Until rstNomSociete.EOF  
    nomfonction = rstNomSociete![NomChampsquivabien]  
    rstNomSociete.MoveNext  
Loop  
 
 
nomfonction ? C'est quoi ? c'est nomSociete dont tu voulais parler ?
et NomChampsquivabien, c'est bien le champ contenant les dates.  
 
Appelons le ChampsDatedeCreation. C'est ça ou je suis à coté de la plaque ?
 
Enfin bon, j'avance doucement mais surement.  
 
Pour les noms de sociétés, leur clé est en fait leur nom court et il n'y en a que quelques unes. Donc ce n'est pas génant.
Merci pour les inner join, je vais en effet l'utiliser maintenant que tu m'as glissé l'idée.
 
 
Bref, merci beaucoup pour m'avoir mis sur la voie. Je ne m'en sortais pas sinon.

n°2177030
hush hush
je savais que ça te plairait
Posté le 22-02-2013 à 11:44:50  profilanswer
 

Pas de problème, j'ai moi même passé mon niveau de zero à opérationnel sur la partie gestion de base de donnée, une fois les clés de base en main (sans jeu de mot), c'est assez facile, je continue d'être confronté à des petits bugs, mais ça se passe bien :o

le petit bleu a écrit :

Bon bon bon,
En revanche, je ne suis pas sur d'avoir saisi l'essentiel.
C'est à dire la petite boucle 1
 
Do Until rstNomSociete.EOF  
    nomfonction = rstNomSociete![NomChampsquivabien]  
    rstNomSociete.MoveNext  
Loop  
 
 
nomfonction ? C'est quoi ? c'est nomSociete dont tu voulais parler ? 2
et NomChampsquivabien, c'est bien le champ contenant les dates.  
 
Appelons le ChampsDatedeCreation. C'est ça ou je suis à coté de la plaque ? 3


1- En fait, quand tu fait une requête sus acces, tu as un certain nombre de resultats répondant à tes critères.
Imagine que tu cherche non pas une société mais les sociétés ayant + de 5 ans d'existance, tu auras donc N résultats.
CHAQUE resultat est un recordset (littéralement, set de données, soit une ligne de ta table sociétés)
La boucle permet de les lire tous, car ils arrivent 1 par 1
Dans ton cas, tu cherche 1 société par sa clé (nom de société), à priori tu aura 0 ou 1 résultat, la boucle ne semble pas avoir de sens mais elle permet d'éviter un bug en cas de rst vide (enfin, je pense, tu peux tester sans et nous dire ce que ça donne)
2-Dans ton premier post, tu parle de créer une fonction vba :)
c'est donc le nom de ta fonction.
EN vba, tu la déclare:
function recupDateCrea(nomsociete as string) as date
   'code qui cherche la date sur access
   'quand il  la trouve, on entre le résultat dans la fonction
   recupDateCrea = xxxx 'avec xxxx la date de création récupérée par ton code
 
end function
 
Ainsi, dans une cellule tu pourra mettre: =recupDateCrea(nomSocieteCourt) (ou pointer sur une cellule avec le nom recherché)
Et tu aura ton résultat dans la cellule :)
 
3-C'est le nom du champs dans la base, exactement comme il est entré, c'est bien ChampsDatedeCreation
 
:jap:

n°2177034
le petit b​leu
Posté le 22-02-2013 à 11:47:45  profilanswer
 

C'est bon ça marche !!
 
Comme quoi je suis bete, j'ai posé ma question trop vite. Un énorme merci !
 
bref, c'est super. Je vais pouvoir me lancer sur des trucs plus compliqués maintenant que je sais que c'est possible.
 
<3
 
Encore merci.
 

n°2177037
hush hush
je savais que ça te plairait
Posté le 22-02-2013 à 11:51:27  profilanswer
 

Pas de problème, juste tiens nous au courant de comment ça marche.
Résoudre un problème, c'est bien, laisser une trace pour les suivants, c'est bien mieux :o

n°2177045
le petit b​leu
Posté le 22-02-2013 à 12:05:12  profilanswer
 

Alors pour le coup, c'est mot pour mot ce que tu as écris. Donc il suffit vraiment de recopier et d'adapter.
J'ai fait une procédure pour tester. Donc la boucle est ainsi :  
 
Do Until rstNomEntreprise.EOF
    DateCreation = rstNomEntreprise![DateCreation]
    rstNomEntreprise.MoveNext
Loop
 
 
Juste pour la concaténation de caractère :
sRequete = "SELECT ENTREPRISE.NomCourt, ENTREPRISE.DateCreation FROM ENTREPRISES WHERE (((ENTREPRISE.NomCourt)="
sRequete = sRequete & Chr$(34) & nomFond & Chr$(34) & " ))"
 
' Chr$(34) : correspond aux guillemets nécessaire pour la requête.
 
Sinon tout le reste, c'est un one shot. Tout est correct.

n°2177052
hush hush
je savais que ça te plairait
Posté le 22-02-2013 à 12:18:51  profilanswer
 

:) Merci,
Si ça marche comme ça, c'est très bien, maintenant, il faut compléter et finir par faire TOUT ce que tu souhaite faire,
Je parlais plutôt de ça en fait, n'hésite pas à nous donner des nouvelles de l'avancement de ton projet, enfin, si t'as le temps/envie.
 
Pour ton code, j'ai deux petites remarque:
-C'est un choix délibéré de faire ça en deux lignes? :

Code :
  1. sRequete = "SELECT ENTREPRISE.NomCourt, ENTREPRISE.DateCreation FROM ENTREPRISES WHERE (((ENTREPRISE.NomCourt)="
  2. sRequete = sRequete & Chr$(34) & nomFond & Chr$(34) & " ))"


Tu peux le faire en une seule fois:
sRequete = "SELECT ENTREPRISE.NomCourt, ENTREPRISE.DateCreation FROM ENTREPRISES WHERE (((ENTREPRISE.NomCourt)=" & Chr$(34) & nomFond & Chr$(34) & " ))"
Si c'est trop long et que tu souhaite casser la ligne en plusieurs lignes pour mieux la lire:
sRequete = "SELECT ENTREPRISE.NomCourt, ENTREPRISE.DateCreation FROM _
 ENTREPRISES WHERE (((ENTREPRISE.NomCourt)=" & Chr$(34) & nomFond & Chr$(34) & " ))"
C'est de la cosmétique, perso, je préfère tout mettre sur une seule ligne :o
 
Le Chr$(34) est judicieux, perso, je prefère la méthode compliquée :o. En gros, pour mettre " dans une chaine de caractères, il suffit de le doubler:
sRequete = "SELECT ENTREPRISE.NomCourt, ENTREPRISE.DateCreation FROM ENTREPRISES WHERE (((ENTREPRISE.NomCourt)=""" & nomFond & """ ))"
ça a l'avantage d'être compact, pas bcp plus lisibles, mais plus compact!
Bonne chance pour la suite!

mood
Publicité
Posté le 22-02-2013 à 12:18:51  profilanswer
 

n°2177112
le petit b​leu
Posté le 22-02-2013 à 16:40:29  profilanswer
 


Citation :

Tu peux le faire en une seule fois:  
sRequete = "SELECT ENTREPRISE.NomCourt, ENTREPRISE.DateCreation FROM ENTREPRISES WHERE (((ENTREPRISE.NomCourt)=" & Chr$(34) & nomFond & Chr$(34) & " ))"  
Si c'est trop long et que tu souhaite casser la ligne en plusieurs lignes pour mieux la lire:  
sRequete = "SELECT ENTREPRISE.NomCourt, ENTREPRISE.DateCreation FROM _  
 ENTREPRISES WHERE (((ENTREPRISE.NomCourt)=" & Chr$(34) & nomFond & Chr$(34) & " ))"  
C'est de la cosmétique, perso, je préfère tout mettre sur une seule ligne :o


C'est vrai. J'ai modifié pour la cosmétique.
 
 
Bon, j'ai un peu l'impression d'abuser et d'être vraiment nul, mais comment est ce que je peux faire maintenant pour renvoyer les résultats d'une requête ou il y a plusieurs éléments en réponse ?  
 
Typiquement, afficher toutes les entreprises qui ont été créé en 2002 ?
 
Comme ça, ça permettra de boucler le sujet en ayant vu le cas unique et le cas multiple.
 
Il y a juste la boucle à modifier et le type de variable de retour de la fonction j'imagine ?

n°2177119
hush hush
je savais que ça te plairait
Posté le 22-02-2013 à 17:08:48  profilanswer
 

La boucle à priori est bonne.
Ce que tu dois faire maintenant, c'est programmer la récupération de ces résultats multiples et les afficher.
 
Do Until rstNomSociete.EOF  
    nomfonction = rstNomSociete![NomChampsquivabien]  
    rstNomSociete.MoveNext  
Loop  
 
Le code va boucler (ie repasser dans la boucle) tant qu'il y a d'autres résultats.
Si tu prend ce code inchangée, tu vas les écraser et ne gardera que la dernière.
 
Il y a plusieurs façons de faire mais voici la plus simple:
 
Au lieu de faire une fonction, faire plutôt une procédure sub,
Disons que tu as n résultats, que tu souhaite écrire les uns à la suite des autres dans un tableau démarrant en cellule A1 de ta feuille,
Tu peux alors faire:
i = 1
Do Until rstNomSociete.EOF  
    worksheets("NomFeuille" ).cells(i,1).value = rstNomSociete![NomChampsquivabien1]
    worksheets("NomFeuille" ).cells(i,2).value = rstNomSociete![NomChampsquivabien2]
    worksheets("NomFeuille" ).cells(i,3).value = rstNomSociete![NomChampsquivabien3]
    rstNomSociete.MoveNext  
    i=i+1
Loop  
 
A toi de nettoyer proprement tes plages de données avant l'execution de ta macro et d'être sûr de n'avoir rien en dessous du tableau résultat suscéptible de se faire écraser par un trop grand nombre de résultats
Ce code va executer n fois la boucle (car il trouve n société crées en 2002) et écrire donc n lignes à partir de la ligne 1 sur 3 colonnes (ici A, B et C)
Tu pourra créer un bouton sur ta feuille pour appeler la macro et utiliser les cellules de cette feuille pour entrer ton ou tes critères de recherche.
 
 
Pour le cas unique, la fonction se prête bien à l'exercice, sauf que pour le moment, elle ne renvoi qu'un résultat (la date de création). Il se peut que tu ai envie d'en récupérer plus, même s'il n'y a qu'une seule réponse.
Exemple: tu recherche les données de l'entreprise sncf, il n'y en a qu'une (de sociétés sncf) mais tu veux récupérer 3 ou 4 informations. Il va falloir adapter ta fonction.
Aussi, cette fonction sera exécutée à chaque calcul de la feuille. SI tu es en calcul automatique, c'est un peu la merde: connections sql dans tous les sens, pas optimal en termes de perfs...
Bref, je te conseil de rester plutôt sur les sub, qui se contrôlent mieux!
 
Et n'oublie pas de fermer les rst et les db dans ton code (cf premier exemple avec les instructions .close)

n°2177129
le petit b​leu
Posté le 22-02-2013 à 17:50:12  profilanswer
 

Mais pourquoi un truc du genre ne pourrait pas fonctionner ?
J'essaye de créer un tableau dynamique et à chaque boucle je donne la valeur trouvée à la cellule du tableau. Mais bon, ça ne semble pas vouloir fonctionner.
 

Code :
  1. Dim i As Integer
  2. i = 1
  3. Dim EntrepriseDansFond() As String
  4. ReDim EntrepriseDansFond(1)
  5. Do Until rstNomFond.EOF
  6.     EntrepriseDansFond(i) = rstNomFond![Nom]
  7.     rstNomFond.MoveNext
  8.     i = i + 1
  9.     ReDim EntrepriseDansFond(i)
  10. Loop

n°2177131
Marc L
Posté le 22-02-2013 à 17:53:23  profilanswer
 

Code :
  1.     ReDim Preserve EntrepriseDansFond(i)


           Voir l'aide de ReDim …
 

n°2177134
le petit b​leu
Posté le 22-02-2013 à 18:09:50  profilanswer
 

Ah bah oui forcément  ...
A jouer à l'apprenti sorcier, on peut pas avoir tout bon au premier coup.
 
Ok, donc là ça fonctionne. C'est super. Merci beaucoup.
 
Bon weekend ! Je reviendrai dessus lundi.

n°2177159
hush hush
je savais que ça te plairait
Posté le 22-02-2013 à 20:34:10  profilanswer
 

le petit bleu a écrit :

Ah bah oui forcément  ...
A jouer à l'apprenti sorcier, on


apprends un tas de trucs :)
Bon week end à vous deux
Edit: F1 est d'une grande aide, surtout en 2003, ça marche en 2010 mais moins bien je trouve...

Message cité 1 fois
Message édité par hush hush le 22-02-2013 à 20:35:21
n°2177240
Marc L
Posté le 24-02-2013 à 11:26:03  profilanswer
 

hush hush a écrit :

[…] ça marche en 2010 mais moins bien je trouve...

            Idem en 2007 …
 

n°2177359
le petit b​leu
Posté le 25-02-2013 à 13:09:36  profilanswer
 

Bon, Back to business.
 
Bonjour, bon lundi à tous.
 
Tout ça, ça marche bien. Maintenant, je cherche à éliminer les doublons de mon tableau obtenu.
 
Je suis entrain de faire un truc assez grossier ou je créé un nouveau tableau que j'alimente depuis le tableau contenant les doublons si la valeur n'est pas déjà dans ce tableau.
 
Donc à chaque fois ça doit parcourir tout le tableau pour vérifier à chaque fois que la valeur n'est pas déjà présente.
Il n'y a rien qui serait plus "fonctionnel" ?
 
En vous remerciant d'avance.


Message édité par le petit bleu le 25-02-2013 à 13:10:16
n°2177367
Marc L
Posté le 25-02-2013 à 13:32:02  profilanswer
 

 
           Voir l'aide de la méthode  Find  et l'exemple dans le sujet Macro pour supprimer une ligne
 

n°2177403
hush hush
je savais que ça te plairait
Posté le 25-02-2013 à 15:40:17  profilanswer
 

Comment ça se fait que tu ai des doublons dans ta base? Je pensais que tu avais une seule entrée pour chaque société...
Je creuserais plutôt du coté d'acces pour la "gestion" de données!
Regarde un peu ça: http://www.w3schools.com/sql/sql_distinct.asp
 
Access est vraiment orienté gestion de données, c'est son boulot, il vaut mieux le lui faire faire plutôt que le mimer sur excel,
Excel, c'est bien pour les calculs et une interface utilisateur sympathique.

n°2177409
le petit b​leu
Posté le 25-02-2013 à 16:08:57  profilanswer
 

Hé hé !
 

Citation :

Regarde un peu ça: http://www.w3schools.com/sql/sql_distinct.asp


C'est moi qui ne sais pas chercher sur google ou quoi ?
J'ai cherché à le faire avec le mot clé "distinct" mais je n'avais pas trouvé d'exemple clair.
Bref, ça marche super avec ton exemple. Je ne sais pas pourquoi ça n'a pas marché plus tôt ...
 
Cela m'a aussi permis de le faire en VBA également. Mais bon, c'était forcément un peu plus lent.
 

Citation :

Comment ça se fait que tu ai des doublons dans ta base?


En fait c'est le résultat d'une requête qui me renvoi des doublons dans la liste des sociétés. Et je cherchais en effet à supprimer tout ces doublons mais je n'y étais pas arrivé.
En gros, exactement le même cas que dans le lien que tu m'as envoyé.
 
Merci encore !

n°2177415
hush hush
je savais que ça te plairait
Posté le 25-02-2013 à 16:16:35  profilanswer
 

Derien! :)
Pour tes recherches google, je te conseille d'ajouter VBA SQL voir Access en mots clés de tes recherches!
Il y a un nombre incalculables de sites répondants à ces questions courantes :)
Et souvent, tu as une réponse complète et "propre"

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  [VBA] fonction paramétré renvoyant le résultat d'une requête ACCESS

 

Sujets relatifs
Récupérer résultat semaine en fonction d'une dateBatch ping affichage résultat
[Access] Problème formulaire requêteRésultat de checkbox dans une cellule. Excel 2007
Requete SqL[VBA] Pied de page en lien avec une cellule [Résolu]
[VBA] activer feuille avec variable dans le nomVBA 2003 TCD : faire des regroupement de valeurs de champ automatique
Plus de sujets relatifs à : [VBA] fonction paramétré renvoyant le résultat d'une requête ACCESS


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR