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

VBA Access Discussion :

Manipulation tables mysql à partir d'Access


Sujet :

VBA Access

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 134
    Points : 52
    Points
    52
    Par défaut Manipulation tables mysql à partir d'Access
    Bonjour, je gère actuellement une base de données de patients et de professionnels de santé sous access. Je m'occupe aussi du site internet de l'assoc., qui permet aux visiteurs d'afficher le listing des pros et des patients. Tous les mois je mets à jour la bdd mysql à partir des données Access, grâce à une requête access qui génère un code sql, que je n'ai plus qu'à exécuter via phpmyadmin.
    Maintenant j'aimerais automatiser un peu tout ça, et qu'access et mysql communiquent. Notamment je souhaite mettre à jour la table des adhérents (patients et professionnels) automatiquement.

    j'ai réussit à me connecter à ma base de données mysql, et à manipuler des enregistrements. C'est fun. Voilà le code utilisé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Dim cnx  As ADODB.Connection
    Dim rs As ADODB.Recordset
     
    Set cnx = New ADODB.Connection
    Set rs = New ADODB.Recordset
     
    cnx.ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};SERVER=...;DATABASE=bdd;UID=...;PWD=...;OPTION=3"
    cnx.Open
     
    cnx.Execute "INSERT INTO `bdd`.`patients` (`num_dossier_patient` ,`civilite_patient` ,`prenom_patient` ,`nom_patient` ,`telephone_patient` ,`date_admission_patient` ,`date_bilan_patient` ,`date_prochain_bilan_patient` ,`date_derniere_consulation` ,`date_prochaine_consulation`) VALUES ('04230108', 'Mr', 'mickey', 'mouse', '0166666666', '0000-00-00', '0000-00-00', '0000-00-00', '0000-00-00', '0000-00-00');"
    cnx.Close
    Voilà, c'est bien ça m'ajoute un enregistrement dans la table des patients.
    Bon, mais maintenant je souhaite exporter les données stockées sous access vers la bdd mysql. Par exemple, sous access j'ai une table "T_Patients", et sous mysql une table "patients". Je souhaite donc d'abord effacer (ou supprimer?) "patients" puis y insérer les données de "T_Patients". En plus les deux tables sont différentes (noms de champs différents), donc il va falloir passer par une requête (je ne peux pas remplacer "patients" par "T_Patients tel que).
    Comment procéder? je sais que c'est une question à laquelle je pourrais répondre avec un peu de documentation, et justement, si vous aviez une bonne adresse où on peut se documenter, ça m'intéresse évidemment.
    Merci bien!
    Pierre

  2. #2
    Rédacteur/Modérateur

    Avatar de Jean-Philippe André
    Homme Profil pro
    Architecte Power Platform, ex-Développeur VBA/C#/VB.Net
    Inscrit en
    Juillet 2007
    Messages
    14 639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Canada

    Informations professionnelles :
    Activité : Architecte Power Platform, ex-Développeur VBA/C#/VB.Net
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2007
    Messages : 14 639
    Points : 34 361
    Points
    34 361
    Par défaut
    bonjour,
    pour supprimer le contenu d'une table : http://www.developpez.net/forums/sho...d.php?t=482935

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 134
    Points : 52
    Points
    52
    Par défaut
    merci, je pense faire un CurrentDb.Execute "DELETE * FROM patients", il ne me reste plus qu'à repeupler cette table distante avec la table locale sous access, et ça je sais pas faire

  4. #4
    Expert éminent
    Avatar de LedZeppII
    Homme Profil pro
    Maintenance données produits
    Inscrit en
    Décembre 2005
    Messages
    4 485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Maintenance données produits
    Secteur : Distribution

    Informations forums :
    Inscription : Décembre 2005
    Messages : 4 485
    Points : 7 759
    Points
    7 759
    Par défaut
    Bonsoir,

    Je ne sais pas si tu tiens absolument à le faire en VBA + ADO.
    Dans ce cas voici un lien sur les recordset ADO : Comprendre les Recordset ADO
    Etapes:
    1. Vider table MySQL avec cnx.Execute suivit de l'instruction SQL MySQL adéquate (TRUNCATE TABLE nom_de_table).
    2. Ouvrir deux recordsets. Un pour la table Access, un pour la table MySQL.
      Pour le recordset sur la table Access on peut utiliser la connexion existante CurrentProject.Connection.
    3. Parcourir tout le recordset sur la table Access (tous les enregistrements) et copier champ à champ dans le recordset sur la table MySQL.


    Autre solution (la plus simple).
    Créer une source de données ODBC (DSN) avec le gestionnaire de Sources de données ODBC, pour la base de données MySQL.
    Dans Access créer une table liée ODBC dont la cible sera la table MySQL, via le DSN précédemment créé.
    A partir de la table liée on peut créer une requête de suppression pour la vider et une requête ajout pour la remplir avec les données de la table Access.

    A+

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 134
    Points : 52
    Points
    52
    Par défaut
    merci LedZep pour le tuto ADO, c'est une mine. Mais il va me falloir des heures de lecture pour la réponse à ma question, à savoir comment faire référence à des champs d'une autre base de données dans une requête sql. Pour sur que si j'arrive au bout de l'apprentissage des recordset ADO avec toute ma tête (je ne suis pas informaticien), cette dernière aura pris quelques centimètres de circonférence.
    Les étapes que tu cites me paraissent bien logiques, et je pensais procéder comme ça (à part l'ajout d'une étape de sauvegarde de la table distante, au cas où!)
    pour la liaison des tables + création de DSN, c'est en effet le plus simple, mais je trouve la méthode en VBA plus élégante
    Pierre

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 134
    Points : 52
    Points
    52
    Par défaut
    Bieng, avec ce code ça marche pas mal, je suis content :

    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
    Dim cnx  As ADODB.Connection
    Dim rs_dist As ADODB.Recordset
    Dim db As DAO.Database
    Dim rs_loc As DAO.Recordset
    Dim cpt As Long
     
    Set cnx = New ADODB.Connection
     
    cnx.ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};" & _
                             "SERVER=...;" & _
                             " DATABASE=...;" & _
                             "UID=...;PWD=...; OPTION=3"
    cnx.Open
     
    Set rs_dist = New ADODB.Recordset
    rs_dist.CursorType = adOpenKeyset
    rs_dist.LockType = adLockOptimistic
    rs_dist.Source = "SELECT * FROM patients"
    rs_dist.ActiveConnection = cnx
    rs_dist.Open
     
     
    DoCmd.SetWarnings False
    cnx.Execute "TRUNCATE TABLE patients"
     
    Set db = CurrentDb
    Set rs_loc = db.OpenRecordset("Select * from T_Patient WHERE [NumeroDossierPatient] is not null")
    rs_dist.MoveFirst
    rs_loc.MoveFirst
       While Not rs_loc.EOF
           rs_dist.AddNew
           rs_dist(0) = rs_loc(15)
           rs_dist(3) = rs_loc(5)
           rs_dist.Update
           rs_loc.MoveNext
           cpt = cpt + 1
        Wend
     
    MsgBox "le nombre de patients est maintenant de " & cpt
     
     
    DoCmd.SetWarnings True
    Set rs_loc = Nothing
    Set rs_dist = Nothing
    cnx.Close
    je me suis limité à deux champs pour l'instant, mais ça ne sera pas dur d'en rajouter d'autres.
    Comme l'opération de mise à jour prend au moins 30 secondes (pour 1000 enr. env.), y a t il un moyen d'afficher un message d'attente, ou même une barre de progression
    merci!

  7. #7
    Expert éminent
    Avatar de LedZeppII
    Homme Profil pro
    Maintenance données produits
    Inscrit en
    Décembre 2005
    Messages
    4 485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Maintenance données produits
    Secteur : Distribution

    Informations forums :
    Inscription : Décembre 2005
    Messages : 4 485
    Points : 7 759
    Points
    7 759
    Par défaut
    Rebonsoir,

    Voici un exemple qui recopie la table Client (Access) dans la table clientrb (MySQL)
    Les noms des champs sont identiques mais ils peuvent être différents.
    En revanche le type des champs doit être compatible.
    Par exemple je ne peux pas affecter du texte dans un champ numérique.
    Je ne peux pas affecter un champ de 40 caractères dans un champ de 30 caractères.
    Code vb : 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
    Sub CopyClient()
    Dim oCnMySQL As ADODB.Connection, oCnAcc As ADODB.Connection
    Dim rsDest As ADODB.Recordset, rsSce As ADODB.Recordset
     
    ' Connexion Access (Base en cours)
    ' Réutilise la connexion existante - Pas besoin de créer un nouvel objet
    Set oCnAcc = CurrentProject.Connection
     
    ' Connexion à base MySQL
    ' Crée objet Connection
    Set oCnMySQL = New ADODB.Connection
    ' Définit chaîne de connexion
    oCnMySQL.ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};" & _
                                "SERVER=LZ2;" & _
                                "DATABASE=test;" & _
                                "OPTION=3;" & _
                                "UID=anonymous;PWD="
    ' Ouvre la connexion
    oCnMySQL.Open
     
    ' Vider table MySQL
    oCnMySQL.Execute "TRUNCATE clientrb"
     
    ' Ouvrir recordset sur table Access - Client
    Set rsSce = New ADODB.Recordset
    rsSce.Open "SELECT * FROM Client", oCnAcc, adOpenKeyset, adLockOptimistic, adCmdText
     
    ' Ouvrir recordset sur table MySQL - clientrb
    Set rsDest = New ADODB.Recordset
    rsDest.Open "SELECT * FROM clientrb", oCnMySQL, adOpenStatic, adLockOptimistic, adCmdText
     
    ' Boucle sur les enregistrements sources
    Do While Not rsSce.EOF
       ' Créer nouvel enregistrement dans recordset destination
       rsDest.AddNew
       ' Copie champ à champ
       rsDest!NumCLi = rsSce!NumCLi
       rsDest!ADRNO = rsSce!ADRNO
       rsDest!DateCreate = rsSce!DateCreate
       rsDest!DateMaj = rsSce!DateMaj
       rsDest!RsCli = rsSce!RsCli
       rsDest!RsRue = rsSce!RsRue
       rsDest!RsRue2 = rsSce!RsRue2
       rsDest!RsLoc = rsSce!RsLoc
       rsDest!RsCP = rsSce!RsCP
       rsDest!RsVille = rsSce!RsVille
       rsDest!RsTel = rsSce!RsTel
       rsDest!RsFaxl = rsSce!RsFax
       rsDest!RsEmail = rsSce!RsEmail
       rsDest!RsSiret = rsSce!RsSiret
       rsDest!Statut = rsSce!Statut
       rsDest!PotVolAchats = rsSce!PotVolAchats
       rsDest!DateEntretien = rsSce!DateEntretien
       rsDest!Numclass = rsSce!Numclass
       rsDest!NumRank = rsSce!NumRank
       ' ajoute nouvel enregistrement
       ' Facultatif car le prochain rsDest.AddNew fera un .Update de manière implicite
       ' mais c'est plus lisible
       rsDest.Update
       ' Enregistrement Source suivant
       rsSce.MoveNext
    Loop
     
     
    FIN:
     
    If Not rsDest Is Nothing Then
       ' rsDest.BOF et rsDest.EOF sont vrais quand il n'y a aucun enregistrement en cours
       ' Si c'est le cas on ne peut pas tester .EditMode
       If Not (rsDest.BOF And rsDest.EOF) Then
          ' Au cas où enregistrement a créé par AddNew mais n'a pas été ajouté,
          ' on met à jour avec .Update
          If rsDest.EditMode <> adEditNone Then rsDest.Update
       End If
       If rsDest.State <> adStateClosed Then rsDest.Close
       Set rsDest = Nothing
    End If
     
    If Not rsSce Is Nothing Then
       If rsSce.State <> adStateClosed Then rsSce.Close
       Set rsSce = Nothing
    End If
     
    oCnMySQL.Close
    Set oCnMySQL = Nothing
    Set oCnAcc = Nothing
     
    End Sub
    Tu vois pourquoi je préfère une table liée et deux requêtes ?

    A+

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 134
    Points : 52
    Points
    52
    Par défaut
    merci Ledzep, c'est très clair. Si j'ai ce genre de limitation de type de champ, j'en viendrais aux tables liées je pense.

    Enfin, pour l'indicateur de progression, j'ai simplement créé une zone de texte ("cpt_pat_dst") dans mon formulaire, puis dans la boucle je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    While Not rs_loc.EOF
           rs_dist.AddNew
           rs_dist(0) = rs_loc(15)
           rs_dist(3) = rs_loc(5)
           rs_dist.Update
           rs_loc.MoveNext
           cpt = cpt + 1
           Me.cpt_pat_dst.SetFocus
           Me.cpt_pat_dst = cpt
           Me.cpt_pat_dst.Requery
    Wend
    voilà, c'est plutôt spartiate mais ça donne une bonne indication de l'avancement de la tâche.
    bonne nuit

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 134
    Points : 52
    Points
    52
    Par défaut
    juste trois remarques :

    1/
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ' Connexion Access (Base en cours)
    ' Réutilise la connexion existante - Pas besoin de créer un nouvel objet
    Set oCnAcc = CurrentProject.Connection
    ça a l'air plus propre comme ça en effet !

    2/ entre ces deux méthodes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    rsDest.Open "SELECT * FROM clientrb", oCnMySQL, adOpenStatic, adLockOptimistic, adCmdText
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Set rs_dist = New ADODB.Recordset
    rs_dist.CursorType = adOpenKeyset
    rs_dist.LockType = adLockOptimistic
    rs_dist.Source = "SELECT * FROM patients"
    rs_dist.ActiveConnection = cnx
    rs_dist.Open
    on ne déclare pas les mêmes paramètres, pourtant ça marche dans les 2 cas. J'ai lu les définitions de adCmdText et adOpenStatic, et ça me semble plutôt abscons, alors que adLockOptimistic est vital si on veut modifier les enregistrements je crois. Donc quels paramètres tu conseils dans ce cas?

    3/ je ne comprend pas ta procédure événementielle de la fin, ça sert à quoi?
    Pierre

  10. #10
    Expert éminent
    Avatar de LedZeppII
    Homme Profil pro
    Maintenance données produits
    Inscrit en
    Décembre 2005
    Messages
    4 485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Maintenance données produits
    Secteur : Distribution

    Informations forums :
    Inscription : Décembre 2005
    Messages : 4 485
    Points : 7 759
    Points
    7 759
    Par défaut
    Bonjour,

    A propos de ta deuxième remarque.
    La bibliothèque ADO est destinée à une programmation faisant abstraction de la source de données.
    Elle expose des méthodes et des propriétés pouvant répondre au plus grand nombre de cas possibles.
    Mais en fonction du fournisseur de données elles ne sont pas toutes supportées. Voir ici.
    En particulier, en ce qui concerne le type de curseur et le type de vérouillage, le fournisseur de données va essayer de répondre à ce qui est demandé du mieux possible.
    Je sais pour l'avoir expérimenté qu'avec le driver ODBC MySQL le curseur type Keyset n'est pas disponible et que l'on obtiendra un curseur type Static.
    adCmdText sert seulement à indiquer au fournisseur de données la nature de la propriété Source. En l'occurence une instruction SQL.
    Si j'avais mis adCmdTable par exemple, j'aurais mis en source "clientrb" et le fournisseur de données aurait créé l'instruction SQL lui-même.

    Pour la troisième remarque je suppose que tu fais allution à ce qui est après l'étiquette FIN.
    J'ai essayé de prendre en considération un maximum de cas de possibles pour fermer proprement les objets.
    Dans le cas normal, il suffit de fermer les objets avec la méthode Close puis de leur assigner la valeur Nothing.
    Mais par exemple, la méthode Close d'un Recordset peut générer une erreur à l'exécution si le recordset est vide, si un nouvel enregistrement n'a pas été sauvé, ou si le recordset est déjà fermé.
    D'où les nombreux If ...

    Pour mieux comprendre lis à tête reposée l'article "Comprendre les Recordsets ADO".
    Je "sais" utiliser ADO, mais je ne peux pas prétendre comprendre ou savoir exactement comment ça fonctionne.

    A+

Discussions similaires

  1. Réponses: 3
    Dernier message: 18/08/2009, 18h22
  2. Update table SQL à partir de ACCESS
    Par lesguignols dans le forum VBA Access
    Réponses: 8
    Dernier message: 04/03/2009, 14h30
  3. [MySQL] Crée table mysql à partir de .csv
    Par jonki dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 18/06/2008, 21h18
  4. Réponses: 11
    Dernier message: 01/05/2007, 23h43
  5. Réponses: 11
    Dernier message: 25/07/2006, 21h46

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