begin process at 2012 02 16 11:26:56
  Trouver un code source :
 
dans
 
Accueil > 

Tutoriels

 > 

VBA

 > MISE À JOUR D 'UN BD ACCESS VIA UNE MACRO VBA ENREGISTRÉ DANS UN FICHIER EXCELL

MISE À JOUR D 'UN BD ACCESS VIA UNE MACRO VBA ENREGISTRÉ DANS UN FICHIER EXCELL


 Information sur le tutoriel

Déposé par emarck le 29/08/2007 20:03:31
Dans la catégorie VBA
Vu : 35 960 fois
 

Ecrire un message privé à l'auteur
Commentaire sur cette source (40)
Ajouter un commentaire et/ou une note

Note :
Aucune note

 Description

Ce tuto est le résultat de recherche sur ce site et sur d'autre site internet afin de trouver une méthode simple et efficace pour mettre à jour les champs d' une table access via excel. J'utilise donc la méthode ADO afin de connecter excel à la bd et transférer le contenu de certaine cellule dans une table access­.


Tutorial

Merci a tous les collaborateurs anonyme qui laisse des sources sur internet. Grace à ceux-ci nous pouvons greffer des bouts de code pris à gauche et à droite pour finir par aboutir à un code qui satifaisant nos besoins et nos attentes !

Bon code  !

emarck

'Dans un fichier excel créer une nouvelle macro et la modifier comme suit.

'Ne pas oublier d'aller dans le menu "Outils->Références" de la macro afin de sélectionner la référence suivante:

'Microsoft ActiveX Data Objects Recordset x.x Library  (dans mon cas j'ai pris la version 2.8 avec excel 2003)

' Pour débuter déclarer une variable public pour la connection comme ceci :

Public cnx As ADODB.Connection

' Ensuite créer la routine suivante  le nom  excel_to_access se retrouvera dans la liste des vos macros dans excel.

Vous pouvez ensuite associer un bouton  à cette macro afin de rendre l'opération plus transparente.

Si vous voulez que l'opération se fasse à l'ouverture de votre fichier excel, changer le nom excel_to_access pour  auto_open

ou auto_close si vous désirez que le tout s'active lors de la fermeture de votre fichier. 

Sub excel_to_access()
    
    Dim chemin As String // chemin est un nom que vous devez associer à une cellule dans excel
    Application.Goto Reference:="chemin"// permet de se positionner sur la cellule se nommant chemin
    
    chemin = ActiveCell // active la cellule en question
   
    ' Nous testons si le fichier est accessible
    If Len(Dir(chemin)) > 0 Then
        ' Déclaration de la variable de connexion
        Set cnx = New ADODB.Connection
       
        ' Connexion à la base
        ConnectDB cnx, chemin
    Else
        MsgBox "La base n'a pas pu être trouvée" & vbCrLf & _
                chemin & vbCrLf & _
                "n'est pas un chemin valide.", vbCritical + vbOKOnly
    End If
   
End Sub

'Routine de connection après avoir validé l'existance de la bd

Sub ConnectDB(ByRef cnx As ADODB.Connection, ByVal chemin As String)
    

    'Définition du recordset   

    Dim rec As New ADODB.Recordset
    'Définition du pilote de connexion
    cnx.Provider = "Microsoft.Jet.Oledb.4.0"
    'Définition de la chaîne de connexion
    cnx.ConnectionString = chemin
    'Ouverture de la base de données
    cnx.Open

    //ouverture de la table  T-Taux cotisation employeur

rec.Open "SELECT * FROM [T-Taux cotisation employeur]", cnx, adOpenKeyset, adLockOptimistic 

//Associtation des informations contenu dans les cellules excel avec les champs de la table access 
   
rec.Fields("Année") = Excel.Cells(2, 1).Value
rec.Fields("Ass maladie taux") = Excel.Cells(4, 2).Value
rec.Fields("Ass emploi taux base") = Excel.Cells(5, 2).Value
rec.Fields("Ass emploi taux collectif") = Excel.Cells(5, 3).Value
rec.Fields("Ass emploi taux non collectif") = Excel.Cells(5, 4).Value
rec.Fields("Ass emploi salaire max") = Excel.Cells(12, 2).Value
rec.Fields("RRQ taux") = Excel.Cells(6, 2).Value
rec.Fields("RRQ plancher") = Excel.Cells(6, 3).Value
rec.Fields("RRQ plafond") = Excel.Cells(13, 2).Value
rec.Fields("CSST taux") = Excel.Cells(10, 5).Value
rec.Fields("CSST salaire max") = Excel.Cells(14, 2).Value
rec.Fields("Fonds pension") = Excel.Cells(7, 2).Value
rec.Fields("Ass collectives") = Excel.Cells(21, 5).Value

//Mise à jour de la table access avec les nouvelles informations

rec.Update

Fermeture du recordset
rec.Close
Set rec = Nothing // déconnecter le recordset
End Sub 

Le nom  sub excel_to_access se retrouvera dans la liste des vos macros dans excel.

Vous pouvez ensuite associer un bouton  à cette macro afin de rendre l'opération plus transparente.

Si vous voulez que l'opération se fasse à l'ouverture de votre fichier excel, changer le sub nom excel_to_access pour sub auto_open

ou sub auto_close si vous désirez que le tout s'active lors de la fermeture de votre fichier.

Bon code !

emarck
 

Commentaires

Commentaire de emarck le 30/08/2007 15:08:31

Bonjour,
         les commentaires sont bienvenue !

emarck

Commentaire de Adn56 le 26/10/2007 10:58:37

salut, j'essaye de comprendre ;) d'ou mes questions :
-Il faut que la bdd soit créé avant, avec ces tables ?
-La celulle "chemin" contient quoi ? c:\mondossier\mabase.mdb ?
-rec.Fields("Année") = Excel.Cells(2, 1).Value , c'est la valeur de la celulle qui se place dans le champs Année, mais sur quelle ligne ?
-Comment faire une recherche dans cette base du coup ?
-supprimer une ligne de la base
-modifier un champs, avec rec.Update ?
arf j'ai encore plein d'autre questions pour enrichir ce tuto ;)
++

Commentaire de Adn56 le 26/10/2007 11:16:36

bon ca commence mal, j'ai bien inscrit la réf 2.8 comme toi, mais il me jette dés cette ligne : Public cnx As ADODB.Connection (type défini par l'utilisateur non défini) :( ??

Commentaire de delcroil le 30/10/2007 14:59:25

bonjour,

je suis en train d'essayer de comprendre ton code. Excel.Cells(4,2).value? peux-tu préciser ce que ca veut dire (quelle est la plage de cellule visée).

ADN56: Je pense que tu dois creer les tables toi meme. La cellule chemin doit bien contenir le chemin c:\mondossier\mabase.mdb.
Je suis en train de faire des tests mais rien ne s'incrit dans ma base.

Commentaire de emarck le 30/10/2007 20:58:36

Bonjour,
La ligne Public cnx As ADODB.Connection doit être dans la section déclaration (Générale)

La cellule que j'ai nommé chemin contiendra le chemin d'accès comme cette exemple.

c:\ma_mbd\mabd.mbd

Il est sur que votre bd doit déjà existé. Le code ne permet pas de créer une bd de zéro, mais d'ouvrir une bd pour ensuite modifier les enregistrement.

Les tables et champs doivent existé. Pour l'exemple je suis dans une table qui ne contien qu'un enregistrement.

Le recordset se connecte à la bd via la requete sql sur ma table et se place par défaut sur l'enregistrement #1 qui est unique.

Par exemple :
rec.Fields("Année") = Excel.Cells(2, 1).Value

Dit prend le contenu de la cellule #2 de la colonne #1
ou si vous préférer de la cellule A2 de la feuil1 et copier le contenu de cette cellule dans le recordset "rec" à la position correspondant au champs "Année" de la table.

Qui par défaut est dans le premier enregistrement de ma bd , car elle ne contien qu'une ligne.

Si votre classeur excel contien des feuils nommé, donné le nom de la feuille dans votre ligne de code
Si la feuil se nomme commande le code serait comme ceci:

rec.Fields("Année") = commande.Cells(2, 1).Value
Vous pouvez voir le nom de vos feuil dans la fenêtre
Projet-VBAProject
Je n'ai pas eu le temps de retoucher mon tuto , cependant, à voir vos question ça m'orriente dans quel direction allé. Sous peu je vais modifier le tuto avec plus d'option.

Mais la logique est normalement la même que si vous feriez un appli vb avec un recodset.

Vous pourriez par exemple prendre la partie de code ou je remplis le recordset et la mettre dans une fonction qui serait appelé seulement lorsque vous cliqueriez sur un bouton.

Ainsi vous pourriez vous créer un bouton suivant précédent pour passer au prochain enregistrement ou au précédent avec le recordset. et un bouton mise à jour qui prendrais les infos de vos champs excell et les transfèrerais dans votre table access.

Je vais tenter de refaire un exemple de code plus complet. au courant de la semaine.

emarck



  

Commentaire de emarck le 30/10/2007 21:32:10

Pour le problème de connection avec ADODB.Connection

Ajouter la reférence
Microsoft ActiveX Data Object 2.8 Library

ça devrait réglé le problème

emarck

Commentaire de fadily le 08/11/2007 17:04:42

juste une chose pour la recherche on utilisant une liste deroulante (combobox)
comment on peut le faire?

Commentaire de emarck le 20/11/2007 22:43:43

Bonjour voici un petit exemple de création d'une liste déroulante dans un tableur Excel.
_____________________________________________________________
'Création d'une liste déroulante dans un tableur Excel
'J'ai utilisé Excel 2003
'le chiffre 1 est la distance entre la bord gauche de la feuille
'et le contrôle  de liste déroulante.
'Le chiffre 2 est la distance entre le haut de la colone et le contrôle
'Le chiffre 59 est la longueur du contrôle
'Le chiffre 11 est la largeur du contrôle
'Si vous ouvrez un nouveau chiffrier excel sans modifier la taille
'des cellules le contrôle suivant entrera dans la cellule
'#1 de la colonne #1. à vous d'ajuster les grandeurs par la suite

Feuil1.DropDowns.Add(1, 2, 59, 11).Select
    
'ajout de donner dans la liste déroulante
    Feuil1.DropDowns.AddItem "test"
    Feuil1.DropDowns.AddItem "test2"
    'Nous positionons la liste déroulante sur le second items.
    'Nous pouvons constaté que l'item test est #1 et test2 #2
    
    'Contrairement à certain langage de programmation
    'ou test aurait été l'item #0 et test2 l'item #1
    Feuil1.DropDowns.ListIndex = 2
_________________________________________________________________

Cette exemple permet de créer une liste déroulante de zero et d'insérer des donner à l'intérieur et d'ensuite sélectionner la seconde donnée pour l'afficher. Logiquement je remplacerais les donner test et test2 par vos donner à ajouter dans la bd
et je ferais pointer le recordset sur le champs à mettre à jours. Ensuite
il ne reste qu'à dire au recordset ou aller chercher l'information à ajouter.

Si ont ce base que la commande suivante prend l'info d'une cellule et l'ajoute dans le champs voulu, un mix du code ci-dessus pourrait faire le travail.

ex: rec.Fields("Année") = Excel.Cells(2, 1).Value
deviendrait
rec.Fields("Année") = Feuil1.DropDowns.ListIndex(2).Value

Ceci reste à testé

emarck

Commentaire de theb3ast le 28/11/2007 17:29:44

bonsoir tlm ;

je suis tres novice en developpement VBA et sur acces et en regardant ton code je me posais une question , y'a t'il moyen via VBA(a partir du fichier excel ) d'agir sur une critere ds une requete de selection Acces .

bon j'essaye d'etre plus clair : jai une requete de selection ds une base access , j'aurais besoin d'agir sur le critere "DATE" (qui est un champs ds ma requete) afin de le limiter a une date bien precise,(et donc pouvoir extraire que les champs avec la date que j'ai choisis)et cela a partir d'excel ...

j'espere que tu pourra m'aider

merci d'avance,

Commentaire de mohaned le 29/11/2007 11:02:19

merci beaucoup emarck;c'est se que je cherche depuis lentemps c'est trés magique

Commentaire de emarck le 30/11/2007 00:27:54

Merci c'est gentil. Je n'avais jamais pensé à faire ce genre de code jusqu'à ce que il me soit demandé au travail de lier excel et access. Tant mieux si ça peu aider des gens :o)

Commentaire de emarck le 24/01/2008 17:34:07

Bonjour theb3ast,  

         il peutêtre possible de modifier la requêtes dans excel. Théoriquement si ta requêtes actuel fonctionne en acces elle devrait fonctionner dans un vba excel. Seul chose à vérifier:

rec.Open "SELECT * FROM rec.Open "SELECT * FROM [T-Taux cotisation employeur]", cnx, adOpenKeyset, adLockOptimistic

Moidifie ta requête pour quel ressemble à celle-ci  c'est à dire encadre tes table avec des [ et ] puis pense au " " En théorie si tu mets ta requête modifier dans le rec.Open excel ira ouvrir la table généré par ta requête. Donc si ta requête contien des exceptions tel Where table1.date = "2008-01-23"... tu devrais pouvoir avoir accès juste au date spécifié.

tu peux prendre exemple sur le code de liste déroulante en inversant les rec.Feilds afin qu' il soit alimenté par ta table et non l'inverse.

ex: rec.Fields("Année") = Excel.Cells(2, 1).Value
deviendrait
rec.Fields("Année") = Feuil1.DropDowns.ListIndex(2).Value

Espérant de donner quelques piste.

emarck

Commentaire de bintou123 le 11/03/2008 12:10:28

Bonjour,

Ce n'est pas un commentaire mais plutot une question.
Tout d'abord bravo pour ton travil. Je voudrais dans le même sens créer une appli qui va m'aider à exporter les données d'une base de données Access vers une autre base de données de même structure.
Merci.

Commentaire de emarck le 12/03/2008 18:15:53

Bonjour BINTOU123,
                   tout dépent de qu'elle type de bd tu parles. Est-ce-que tu veux transférer des données de Access à une seconde bd Access, ou de Access à Excel ou autres ?

Si c'est de access à access il offre une fonction
d'importation de table entre bd directement dans access.  

emarck

Commentaire de user03 le 24/04/2008 16:05:35

Bonjour,
je travaille mnt sur une application d'ajout,modif,recherche sur ACCESS , est ce que vous pouvez m'aider a trouver une application déja faite, ou uu tuto...

Merci bcp

Commentaire de emarck le 29/04/2008 22:57:06

Bonjour,
         le code vba ci-dessus est fortement inspiré des codes vb6 et vb2003 permettant la liaison entre une bd access et une application vb.

En fait, les routine sont identique soit

1.créer une connection avec la bd avec une requête sql

2.créer un créer un recordset.

Ensuite le reste c'est presque identique au code vba ci-dessus, le recordset est le contenant dans lequel vous envoyer vos données afin de les intégrés dans la bd. Il est aussi le contenant utilisé par la bd pour vous transmettres de l' information.

Il existe sur le site des exemples très complets à ce sujet.

Est-ce-que ça réponds a votre question ?

Je pense par contre a ajouter un tuto sur les bd et à remodeler celui-ci lorsque j'aurai plus de temps.

emarck
  

Commentaire de coincoinmsn le 21/05/2008 17:39:58

Bonjour Emark,
Ton code 'est res utile et il fonctionne plutot pas mal!
Cependant, lors de l'execution de la macro, quand on arrive au premier:
rec.Fields("Cust_ID") = Excel.Cells(3, 3).Value
Bim, la ca plante, "running time error 3021, Either BOF or EOF is true...", et la c'est la panique!

Le "cust ID" est le non dun de mes champ ds ma BDD access ds l'entiter customers, ayant defini au prealable:

Set rec = New ADODB.Recordset
rec.Open "SELECT * FROM [Customers]", cnx, adOpenKeyset, adLockOptimistic

Vois tu d'ou cela peut il provenir, un indice, une solution? normalement la macro devrait mettre la valeur de la cellule C3 dans la colonne Cust ID de la BDD entite Customers?

Merci pour ton aide deja efficace!
(je debute ac access et suis moye pas terrible en VBA, mais on apprend!)

Commentaire de emarck le 22/05/2008 02:56:42

Bonjour COINCOINMSN,

Est-ce-que le code d'erreur est le suivant ??

Run time Error 3021: Either BOF or EOF is True, or the current record has been deleted.

Il arrive parfois que lors de la compilation vb

que le recordset ne soit pas dans une bonne position. Par exemple que le pointeur se place à la fin du recordset.

Ceci cause une erreur, car le pointeur tombe dans le vide.

En effet, il ne retourne pas automatiquement du dernier au premier enregistrement.  Ce que tu peux essayer, c'est de faire un test afin de savoir si ton pointeur est bien positionné. Si il ne l'est pas tu le force à ce placer correctement.

Tu peux donc faire une vérification de ce type:

if rec.eof=true then

rec.bof

end if

Ensuite tu peux faire le reste de ton code.



Tu peux aussi directement forcer le pointeur.
BOF = Begin Of File = Début de fichier
EOF = End Of File  =Fin de fichier



rec.BOF

le reste de ton code

n'oublie pas de faire

rec.update pour mettre à jour ta bd dans access

Autre possibilité ta cellule excel est vide et lors  de la compilation le moteur vba met de la scrappe dans le recordset au lieu du contenu de ta cellule.

Essaie de faire un exécution pas à pas afin de faire ce que contien tes différentes variables. Quelques fois c'est surprenant ce qu'ont y découvre.

Je n'ai pas testé les exemples de code que je t'ai donné, mais il y a toujours possibilité de vérifier ton code si tu en mais un extrait en ligne ou si tu me l'envoi.







Commentaire de aurore21 le 11/06/2008 15:40:26

Bonjour,

felicitation pr ce code cela m'est bien utile ! cependant je rencontre un pb : ma table access est en realité un tableau a double entree.(valeur de 6 indices de marché en fonction de la date) comment puis-je faire pr lui dire d'aller sur la bonne ligne suivant mes deux variables qui sont dont le nom de l'indice et la date pour modifier la valeur ?
le code suivant ne prend en effet qu'une seule variable :
rec.Fields("Année") = Excel.Cells(2, 1).Value

merci pour votre aide !

Commentaire de emarck le 11/06/2008 19:54:31

Bonjour AURORE21,
                 est-ce-que vous pouvez me donnée plus de détail sur ce que vous entendez par double entree ?

Est-ce-que c'est une clé sur 2 champs ?

Si vous pouviez me donner plus d'info...

Merci

emarck      

Commentaire de emarck le 19/06/2008 19:51:43

Bonjour AURORE21,

                 je n'ai pas fais de test supplémentaire, mais peutêtre que ta solution réside dans la moficiation de la requète sql du recordset. Ou dans l'ajout d' un second recordset et d'une seconde requête sql.

emarck

Commentaire de Rezins le 22/08/2008 19:14:21

Bonjour,

Merci pour ce code, qui me sera très utile si quelqu'un a la gentillesse de m'expliquer comment faire pour que l'enregistrement ne se fasse pas systématique sur la première ligne de ma table. J'aimerais qu'il se fasse sur la ligne suivante qui elle est vide.

Si qq'un peut m'aider, il est le très bienvenu !
Merci

Commentaire de emarck le 22/08/2008 19:59:07

Bonjour REZINS,
                le code actuellement sur le site fait une mise à jour de la bd. Ceci dit rien ne t'empèche de le modifier pour qu'il ajoute des enregistrement.

Actuellement rec.update permet la mise à jour de la bd
remplace le par:

rec.addnew // pour ajouter un nouvel enregistrement

Si tu as plus d'un enregistrement et que tu veux te promener d'un à l'autre utilise les commandes suivantes:

rec.movenext //aller au suivant
rec.moveprevious // aller au précédent
rec.movefirst //aller directement au premier
rec.movelast // aller directement au dernier

Si tu veux tu peux utilisé des commandes dans les if ou les for ou les while...

// tant que x est différent dernier enregistrement...
if x <> rec.EOF then

end if  


//tant que x est différent de la fin du fichier.
rec.bof// se place au début du fichier
while x <> rec.EOF then
...
wend

J'espère t'avoir éclairé...

Bon code !
emarck  




Commentaire de Rezins le 24/08/2008 19:13:33

Bonjour et merci Emarck !

En plaçant juste après la ligne rec.open, un rec.movelast suivi d'un rec.addnew j'ai réussi à alimenter ma base de données "à la volée" à partir d'une feuille excel. C'est peut être pas le moyen le plus direct mais ca fonctionne.  

Bien utile pour moi !

Commentaire de emarck le 25/08/2008 02:04:37

Pas de quoi REZINS !

Tant mieux, si ça résoud ton problème.

Bon code

emarck

Commentaire de woyo le 06/10/2008 15:36:10

j'ai un problème avec le chemin
je l'associe comment a ma bd stp?

Commentaire de woyo le 06/10/2008 17:26:04

jai resolu le pb d'association du chemin.
j'ai ce mess d'erreur a présent
Run time Error 3021: Either BOF or EOF is True, or the current record has been deleted.

je fais comment?
merci d'avance

Commentaire de emarck le 06/10/2008 21:04:01

Bonjour WOYO,
              le même problème revient quelques fois tu dois faire un test pour savoir ou est situé ton pointeur. Quelques fois il arrive que le pointeur dépasse le dernier enregistrement. Dans ce cas il tombe dans le vide ou devient de valeur null.
Donc soit l'enregistrement est vide, car le code que j'ai mis en ligne présume que tu as au moins un enregistrement dans la table. Si c'est pas le cas commence par ajouter un enregistrement.

Si tu as un enregistrement dans la table ou plus d'un le pointeur ne doit pas être initialisé correctement.

fait un code de type

if rec.eof=true then

rec.bof

end if

Ensuite tu peux faire le reste de ton code.



Tu peux aussi directement forcer le pointeur.
BOF = Begin Of File = Début de fichier
EOF = End Of File  =Fin de fichier



rec.BOF

le reste de ton code

n'oublie pas de faire

rec.update pour mettre à jour ta bd dans access

Bon code !

emarck

Commentaire de Jenmina le 23/10/2008 16:49:03

Bonjour,

Je crée une macro sous Excel pour recuperer des informations sur une base de données.
J'aimerais juste savoir comment je peux faire appeler à un champ de la base de données Access.

Dans l'exemple si dessous je fais appel à un champs d'une table mais Excel ne le detecte pas comme un objet Access.
'If offr_tdoc.tdoc_code = "CH" Then
      '    ActiveSheet.Cells(i, j + 10).Value = RST1![otdo_date]
  'End If
Donc que dois-je rajouter ?

Cordialement,
Jenmina.

Commentaire de emarck le 27/10/2008 16:57:35

Bonjour JENMINA,
                  
                en regardant ton code je comprend que tu désir prendre une date contenu dans une table access et l'envoyer dans une cellule au coordonné (i,j+10) ...

Je ne sais pas si tu arrives à avoir une donnée dans ton ficher excel ou pas. Ceci dit si tu n'as pas modifier le type de ta cellule (i,j+10) access te transmettera une date, mais elle sera afficher comme un nombre.

Idéalement modifie le format de ta cellule dans excel pour qu'elle affiche les dates.

Ensuite une code comme ci-dessous fait le travail

ActiveSheet.Cells(i,j + 10).Value = rec.Fields("date")

Ce qui fait que la date contenu dans le champs "date" de ta table sera placé dans ta cellule (i, j +10) de ta feuille active.

Ton code devrait donnée l'équivalent, cependant la partie RST1![otdo_date] me semble suspecte.Les crochet sont utilisé par la requête sql, peut être remplacer les [] par des ()

Bon code !

emarck
ActiveSheet.Cells(i, j + 10).Value = RST1![otdo_date]

Commentaire de Timi493 le 29/10/2008 16:33:08

Bonjour Emarck,
J'ai utilisé ton code pour ajouter des informations de fichiers excel dans une base de donnée access.
Cette BDD possède plusieurs tables et tout ce passe bien pour 'charger' les données dans les différents champs des tables.
C'est super.
J'ai néanmoins un souci, dans la table commandes la valeur du champs "réfCommande" peu déjà êtres présent et donc ça plante la macro.
Je voudrai faire vérifier la présence de la valeur du champs de la cellule excel (2, 4) dans la table et si il est présent il ferme la table, si non il copie la valeur.
J'ai fais plusieurs tentative mais ça ne marche pas, il faut dire que je ne suis pas un grand spécialiste de VB.
J'accepterai bien un coup de main.
Merci.

Voici une partie du code actuel

Sub ConnectDB(ByRef cnx As ADODB.Connection, ByVal chemin As String)
    
    Dim rec As New ADODB.Recordset
    cnx.Provider = "Microsoft.Jet.Oledb.4.0"
    cnx.ConnectionString = chemin
    cnx.Open

      '//ouverture de la table
rec.Open "SELECT * FROM [commandes]", cnx, adOpenKeyset, adLockOptimistic
rec.MoveLast 'placement sur le dernier enregistrement
rec.AddNew 'ajoute un enregistrement

'//vérification de l'existance de la RéfCommande

'----???--------------------------------------

'//Associtation des informations excel dans la table access

rec.Fields("RéfCommande") = Excel.Cells(2, 4).Value

'//Mise à jour de la table
rec.Update
rec.Close
End Sub


Timi493

Commentaire de emarck le 30/10/2008 16:39:37

Bonjour Timi493,


                un façon simple de faire ta validation serait de faire un if contenant ta condition.

'si le champs RéfCommande est différent de vide...
'écrire les actions à faire dans le cas ou
'la condition 'est vrai... Exemple un msgBox

If rec.Fields("RéfCommande").Value <> "" then

MsgBox "test"

End If


Si tu veux valider le contenu de cellule suivante
Excel.Cells(2,4).Value tu devras faire une étape supplémentaire. Il semble que suite à mes test le format entre la valeur de la cellule et la valeur du champs accèss ne soit pas compatible directement.

Une commande if comme celle-ci dessous considère toujours le résultat de la validation comme faux. le MsgBox n'est jamais activé.

If rec.Fields("RéfCommande").Value = Excel.Cell(2,4).Value then

MsgBox "test"

End If

Pour corriger le problème, tu dois mettre la valeur de la cellule (2,4) dans une variable

Ex:

Dim var_cell as string

var_cell = Excel.Cells(2,4).Value

If rec.Fields("RéfCommande").Value = var_cell then

MsgBox "test"

End If

ainsi la fonction if compare le contenu du champs access avec du texte et exécute le Msgbox... Dans ton cas tu pourrais mettre comme instruction dans le if de faire le mise à jour et fermer access... Dans le cas ou la variable n'égale pas le champs access il continu le code, fais la modification dans la bd, la mise à jour et ferme la bd.

Espérant t'avoir donnée quelques pistes de solution.

Bon code !

emarck

Commentaire de Timi493 le 30/10/2008 17:52:16

Merci de ta réponse Emarck
Pour compléter mon précédent mail voici quelques détails:
En fait j'avais mis en code ceci

if rec.Fields("RéfCommande") = Excel.Cells(2, 4).Value then
rec.Close
Else
rec.Fields("RéfCommande") = Excel.Cells(2, 4).Value
rec.Update
rec.Close

Mais j'ai la boite de dialogue d'erreur avec le texte ci dessous qui apparait

Erreur d'exécution '--------':
Modification non effectuées: risque de doublons dans champs index,
clé principale ou relation interdisant les doublons. Modifiez les données
des champs contenant les doublons, enlevez ou redéfinissez l'index
pour permettre les doublons et recommencez.

En réalité j'ai 2 tables, une [Commandes] et une [Produits]

Je charge donc dans ma table commande le numéro de commande a la suite des autres et dans la table produit un produit avec sa désignation.

Par la suite je charge d'autres produits de la même commande.
Il n'y a pas de problème pour la table produit car les repère sont toujours différent, mais en revanche pour le numéro de commande je dois absolument voir si il existe dans la liste réfcommande et fermer la table si il est présent ou le créer si il ni est pas.
Voilà, je vais regarder d'un peu plus prêt et si je trouve je donne la réponse.
En tous cas le code général est super et ça faisait longtemps que je cherchais.
Merci encore.

Timi493

Commentaire de emarck le 30/10/2008 18:40:33

Bonjour Timi493,
                ton if est bon, mais je me trompe ou il fait par défaut toujours l'exécution de ton else sans jamais passé sur le rec.close... ? Essaie de placé le contenu de ta cellule dans une variable et de faire la comparaison avec la variable. Il devrait exécuté le rec.close correctement. ceci dit le message que tu as semble être du au fait que access détect un conflit avec tes relations de table.

C'est sur que si tu champs réfCommande est une clé primaire access ne voudras pas te laissé faire. Sauf peutêtre si tu le force à accepter les doublons... Le problème semble plus venir de ta structure de bd.

Il y aurait possibilité d'automatisé la génération de tes numéro de commande avec access lors de la création d'une nouvelle ligne d'enregistrement.

Quel est la raison pour rentrer 2 fois le même numéro ? est-ce-que pour retourner dans ta commande afin de faire des modifications ? Si c'est dans ce but, rien t'empèche de faire une fonction recherche et modification indépendante de ta fonction d'ajout...

Bon code

emarck



Commentaire de Timi493 le 31/10/2008 10:39:15

Bonjour Emarck,
Tu as raison j'avais remarqué aussi qu'il allait directement au Else.
En fait je vais expliqué en détail et simplement mon besoin et la cause.
J'ai une BDD Access dans laquelle je saisie des clients et ce que l'on fabrique pour eux.
Cette base je la remplie par l'intermédiaire de formulaires. C'est long, et ça me prend le 'choux'.
Ensuite j'ai une matrice Excel qui me sert de lancement en fabrication des éléments du client.
Un exemple :
Une commande tombe n° 2008 125
Le client Mr Dupont
Commande : 1 table, 4 chaises et 1 bureau.
Je vais avoir dans ma BDD le N° de commande unique dans la table "Commandes" et par l'intermédiaire d'un sous formulaire je vais saisir dans la table "Produit" 1 table puis 4 chaises et 1 bureau (3 lignes d'enregistrement)
Je vais avoir 3 dossiers de fabrication sur tableur Excel, 1 pour le bureau, 1 pour les 4 chaises et 1 pour la table.
Dans chaque dossier le N° de commande "2008 125" qui sera identique pour les trois dossiers et, la désignation "bureau",  la quantité "1", le repère "B", c'est infos change à chaque dossier bien sur. J'ai fait un bouton avec ta macro qui me copie le numéro de commande dans la table "commandes" et dans la table "Produits" les autres infos. L'incrémentation ce passe bien dans la table "Produits" même si il y a des doublons mais ce n'est jamais le cas. Pour la table "Commandes" lors du premier transfert tout vas bien puisque le numéro de commande n'existe pas donc il l'incrémente parfaitement mais c'est ensuite lors du chargement des données des autres fichiers Excel qu'il bloque d'où la nécessité d'ignorer le numéro de commande si il est présent.
Je confirme que c'est une clé primaire ce numéro de commande, il ne peu pas y avoir de boulons. Je ne peu en aucun cas toucher à cette base de donnée car elle gère plein d'autres choses, aussi car je ne connais pas assez Access pour modifier quoi que ce soit et en plus le "concepteur" de cette base n'est plus joignable.
Bon je vais stopper mon baratin, je vais tester la variable et je poste les résultats dès que possible.
On va bien finir par y arriver.
En tout cas c'est super enrichissant de partager des infos.
Merci.

Timi493

Commentaire de Timi493 le 31/10/2008 15:25:05

bonjour,
J'étais persuadé d'avoir trouvé,
J'avais laissé le rec.addnew avant la vérification de la refcommande le fait de le placer apres le then faisait marcher parfaitement la macro avec la variable ou avec le if then else.
J'ai fait 2 fichiers excel différent pour faire des tests.
Tout a marché impeccable pendent 1 heure avec plein de test et subitement, sans rien changer une des macro m'a remis les mêmes messages d'erreur
Et puis maintenant c'est l'autre qui plante sur le rec.update.
Le pire c'est que je n'ai pas fait de modif ni dans la macro ni dans la BDD.
Je pense que je vais faire un break pour y voir plus clair.
Autre info qui peut êtres sera utile à certains, l'activation dans vba du microsoft activeX data objects library doit se faire sur chaque fichier, ce n'est pas lié au PC mais au fichier lui-même.
J'avais eu un blocage aussi sur ce point.
Je continue perplexe .

Timi493

Commentaire de Timi493 le 31/10/2008 18:01:49

Re Bonjour,
voici le code, il fonctionne mais pas toujours.
Parfois on peu changer les données plusieurs fois sans problème et parfois non.
Si l'on réouvre un fichier existant c'est pareil.
Même chose avec une variable.

Sub ConnectDB(ByRef cnx As ADODB.Connection, ByVal chemin As String)
    
    Dim rec As New ADODB.Recordset
    cnx.Provider = "Microsoft.Jet.Oledb.4.0"
    cnx.ConnectionString = chemin
    'Ouverture de la base de données
    cnx.Open
    '//ouverture de la table Commandes
rec.Open "SELECT * FROM [commandes]", cnx, adOpenKeyset, adLockOptimistic
rec.MoveLast 'placement sur le dernier enregistrement
'//vérification de l'existance de la RéfCommande
If rec.Fields("RéfCommande") = Feuil1.Cells(2, 5).Value Then
rec.Close
Else
'//Associatation des informations contenu dans les cellules excel avec les champs de la table access
rec.AddNew 'ajoute un enregistrement
rec.Fields("RéfCommande") = Feuil1.Cells(2, 5).Value
rec.Fields("RéfClient") = 1
rec.Fields("Nom") = Feuil1.Cells(1, 5).Value
rec.Update
rec.Close
End If

j'avais laissé un ' devant Set rec, comme ci dessous, je l'ai enlevé mais rien ni fait.

rec.Close
'Set rec = Nothing // déconnecter le recordset
End Sub

Je sèche !

Timi493

Commentaire de emarck le 10/11/2008 16:16:20

Bonjour Timi493,
                 hier soir j'ai regardé le code et les fichiers que tu m'as envoyés. 2 petits points me semble suspect.

Le permier est dans le code lui-même. Il s'agit du commencement du code par aller placer ton recordset au dernier enregistrement...

J'ai supposé que tu le placais ainsi, afin de te préparer à l'ajout dans le cas ou le # de RéfCommande ne serait pas présent. Ce qui fait que tu laisses access déterminer si le # est présent ou pas...

Théoriquement c'est logique et ça devrait fonctionner. Cependant, access est quelques fois imprévisible... Il peut aussi bien réagire comme tu le souhaites, comme il peut tomber en panne mystérieusement.

Le fait de te placé au dernier enregistrement fait en sorte que access peut aussi bien placé ton recordset à la fin de la table et ainsi faire un dépassement. Ce qui donne un plantage de la macro. Ou agir correctement.

Une seconde observation est le fait que tu entres le # de RéfCommande avec un espace ou sans. Dans excel ça ne fait pas d'importance. Cependant dans accèss le fait que ton champs RéfCommande soit un numérique, il n'accepte pas la mise en forme des nombres (masque de saisie).

Lorsque tu valides si ton #RéfCommande de excel est dans la table ou pas. Le rec.close est toujours sauté, car 123 45 est différent de 12345...

Donc si tu utilises le signe = le if passe au else et si tu utilises le signe <> le if exécute le rec.close

Idéalement standardisé le format du numéro pour 12345 au lieu de 123 45 lors de l'entré au clavier. Access risque de moins faire de problème de cette façon. Et tu sembles avoir mis un masque sur ta cellule afin que le # soit dans excel afficher comme étant 123 45. Tu ne cause pas de problème dans le cas d'une impression le format sera 123 45. Lors du transfère dans access le format sera 12345. Seul hic par défaut access refuse les masques de saisie sur les champs numérique.

Je crois que si tu changes le type de champs pour un texte tout en gardant la clé primaire sur le champs. Tu pourrais lors de création de rapport dans access faire afficher le champs correctement et utilisé le format 123 45 lors de l'entré de donné dans excel.

L'essentielle est que vous soyez constant dans le format. Si le premier item est entrer 123 45 et le second 12345 et le troisième 123 45. Vous risquez de tomber en erreur.

Ceci dit j'ai modifier votre code ci-dessus afin que ce soit la macro et non access qui se charge de la validation du champs  et détermine si vous pouvez ajouter ou non l'enregistrement.

Voici le code :

Sub ConnectDB(ByRef cnx As ADODB.Connection, ByVal chemin As String)
    
    Dim rec As New ADODB.Recordset
    cnx.Provider = "Microsoft.Jet.Oledb.4.0"
    cnx.ConnectionString = chemin
    'Ouverture de la base de données
    cnx.Open
    '//ouverture de la table Commandes
rec.Open "SELECT * FROM [commandes]", cnx, adOpenKeyset, adLockOptimistic
rec.MoveLast 'placement sur le dernier enregistrement
'la partie ci-dessus est identique je ne l'ai pas touché
'les modifications se font après le rec.MoveLast

'Code ajouter par  emarck
'9 novembre 2008
'Permet de garder en mémoire la valeur du dernier  enregistrement ce qui permetera de savoir que nous sommes à la fin de la table

dernier_enreg = rec.Fields("RéfCommande").Value

'On se place au début de la table afin de faire la recherche
rec.MoveFirst

'//vérification de l'existance de la RéfCommande
Dim var_eof As Boolean 'variable pour simuler un EOF
Dim var_cell As String 'votre variable
var_cell = Feuil1.Cells(2, 5).Value
var_eof = False 'une variable boolean simule le EOF
                'pour les besoin du while

'On boucle tout les enregistrements de la table
'afin de savoir si le # de chantier existe déjà.

While var_eof <> True ' tant que la variable est pas vrai
'on valide la valeur de la table avec la valeur recherché
'si elle est différente ont passe à la suivante

If rec.Fields("RéfCommande").Value <> var_cell And rec.Fields("RéfCommande").Value <> dernier_enreg Then
rec.MoveNext
Else
'sinon ont test si la valeur est vraiment identique avec
'celle recherché Si c'est le cas ont ferme le recordset
'et nous simulons un code EOF=true

If rec.Fields("RéfCommande").Value = var_cell Then
rec.Close
var_eof = True
'le msgbox est seulement la pour savoir si le if est exécuté..
MsgBox "Le chantier" + " " + var_cell + " " + "existe déjà !"

Else

     'Si la valeur trouver n'est pas celle rechercher
     'On vérifie si le code EOF est toujours faux
     'et si nous sommes rendu au dernier enregistrement
     'si c'est le cas ont ajoute l'enregistrement dans   la table

If var_eof = False And rec.Fields("RéfCommande").Value = dernier_enreg Then
'Si c'est le cas on ajoute l'enregistrement
rec.AddNew 'ajoute un enregistrement
rec.Fields("RéfCommande") = Feuil1.Cells(2, 5).Value
rec.Fields("RéfClient") = 1
rec.Fields("Nom") = Feuil1.Cells(1, 5).Value
rec.Fields("N°Commande") = Feuil1.Cells(2, 5).Value
rec.Update
rec.Close
var_eof = True 'on simule le EOF=true

'on ferme les différents if de la boucle...
End If
End If
End If
Wend 'ont ferme la boucle while


Voilà j'espère que ça te donnera des indices j'ai tester le code et il semble bien fonctionner. Cependant j'ai pas fais de test pendant des heures.

Bon code !

emarck















Commentaire de Timi493 le 12/11/2008 08:43:04

Bonjour Emarck,
Je viens d'incorporer ton code dans ma matrice excel et ça fonctionne. Je n'ai fait qu'un test mais je suis persuadé que c'est bon car ce test n'avait jamais fonctionné.
Je suis super heureux.
Merci encore pour ce code.
Tu as fait du super travail, je ne m'en serais jamais sorti tout seul.

Timi493

Commentaire de emarck le 13/11/2008 00:29:51

Bonjour Timi493,
                                 génial si ça fonctionne, ici je n'ai fais que quelques test avec le email que tu m'avais envoyé et la procédure pour remplir la matrice...

Bon code !

emarck

 Ajouter un commentaire




Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,016 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales