Précédent   Forum des professionnels en informatique > Logiciels > Microsoft Office > Excel > Macros et VBA Excel
Macros et VBA Excel Vos questions relatives aux macros Excel, à l'utilisation de VBA et à l'automatisation de vos classeurs Excel.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 12/09/2011, 16h45   #1
Invité régulier
 
Inscription : mai 2011
Messages : 29
Détails du profil
Informations forums :
Inscription : mai 2011
Messages : 29
Points : 5
Points : 5
Par défaut Copier données feuille Excel vers table Access sans doublons

Bonjour à tous,

J'ai une application Excel relié à une base Access pour stocker les données. J'ai crée une fonction qui permet de coller les données d'une feuille de l'application vers la base. Le problème survient lorsque je met à jour les valeurs de la feuille et que je rapelle ma fonction, il y a un message qui apparaît m'indiquant la présence d'un doublon. Je voudrais savoir comment faire pour que la fonction mette à jour l'enregistrement si celui ci existe déjà (Clé primaire de la table : ID_Action). Ci dessous, le code de la fonction qui me permet de copier les données:
Code :
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
Sub ExportExcel()
Dim Plage As Range
Dim Array1 As Variant
Dim x As Variant
Dim Db1 As Database
Dim Rs1 As Object
 
 
' Opening database
Set Db1 = DBEngine.OpenDatabase(DBEXPORT)
'Open SaveMatrix table
Set Rs1 = Db1.OpenRecordset("Save_Matrix", dbOpenDynaset)
 
Set Plage = Worksheets("SaveMatrix").Range("A1").CurrentRegion.Offset(1, 0)
     Set Plage = Plage.Resize(Plage.Rows.Count - 1, Plage.Columns.Count)
 
Array1 = Plage.Value
 
     For x = 1 To UBound(Array1, 1)
          With Rs1
               .AddNew
            .Fields("ID_Action") = Array1(x, 1)
            .Fields("Compilance_Conse") = Array1(x, 2)
            .Fields("Compilance_Freq") = Array1(x, 3)
            .Fields("Safety_Conse") = Array1(x, 4)
            .Fields("Safety_Freq") = Array1(x, 5)
            .Fields("Environment_Conse") = Array1(x, 6)
            .Fields("Environment_Freq") = Array1(x, 7)
            .Fields("Integrity_Conse") = Array1(x, 8)
            .Fields("Integrity_Freq") = Array1(x, 9)
            .Fields("SCE_Conse") = Array1(x, 10)
            .Fields("SCE_Freq") = Array1(x, 11)
            .Fields("Financial_Conse") = Array1(x, 12)
            .Fields("Financial_Freq") = Array1(x, 13)
            .Fields("Media_Conse") = Array1(x, 14)
            .Fields("Media_Freq") = Array1(x, 15)
            .Fields("LevelCompil_Conse") = Array1(x, 16)
            .Fields("LevelFreq_Conse") = Array1(x, 17)
            .Fields("LevelSafety_Conse") = Array1(x, 18)
            .Fields("LevelSafety_Freq") = Array1(x, 19)
            .Fields("LevelEnvi_Conse") = Array1(x, 20)
            .Fields("LevelEnvi_Freq") = Array1(x, 21)
            .Fields("LevelIntegrity_Conse") = Array1(x, 22)
            .Fields("LevelIntegrity_Freq") = Array1(x, 23)
            .Fields("LevelSCE_Conse") = Array1(x, 24)
            .Fields("LevelSCE_Freq") = Array1(x, 25)
            .Fields("LevelFinancial_Conse") = Array1(x, 26)
            .Fields("LevelFinancial_Freq") = Array1(x, 27)
            .Fields("LevelMedia_Conse") = Array1(x, 28)
            .Fields("LevelMedia_Freq") = Array1(x, 29)
            .Fields("Result_Compil") = Array1(x, 30)
            .Fields("Result_Safe") = Array1(x, 31)
            .Fields("Result_Envi") = Array1(x, 32)
            .Fields("Result_integrity") = Array1(x, 33)
            .Fields("Result_SCE") = Array1(x, 34)
            .Fields("Result_Financial") = Array1(x, 35)
            .Fields("Result_Media") = Array1(x, 36)
            .Fields("Final_Result") = Array1(x, 37)
            .Fields("Manual_Result") = Array1(x, 38)
            .Update
          End With
     Next
 
     ' Close database
     Db1.Close
 
    'Delete records feom the sheet
     Plage.ClearContents
End Sub
Merci de votre aide
dragoes64 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2011, 17h18   #2
Membre actif
 
Inscription : novembre 2008
Messages : 188
Détails du profil
Informations forums :
Inscription : novembre 2008
Messages : 188
Points : 194
Points : 194
Si ta feuille Excel contient toutes les données (celles qui sont déjà dans la base, plus les nouvelles), une méthode bourrin mais simple consisterait à vider ta table et à tout ré-exporter dedans (si le temps d'exécution est acceptable, bien entendu).

Sinon tu peux toujours tester si ton record existe déjà. Mais dans ce cas-là je te conseillerai d'utiliser un 'table-type" recordset car je pense que ce sera plus rapide qu'un 'dynaset-type'.
En plus la recherche est plus simple car avec un 'table-type" on définit explicitement une clé primaire et on peut donc faire une recherche dessus avec comme conséquence implicite qu'il y aura au plus un résultat. En revanche avec un 'dynaset-type', il peut y avoir plusieurs occurrences et il y a donc plusieurs méthodes (FindNext, FindPrevious, FindFirst et FindLast).

Du coup tu déclares ton recordset comme ça:

Code :
1
2
3
'Open SaveMatrix table
Set Rs1 = Db1.OpenRecordset("Save_Matrix", dbOpenTable)
Rs1.Index = "PrimaryKey"
Et pour savoir si ton recordset existe déjà:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
Rs1.Seek("=", Array(x, 1))
If Rs1.NoMatch Then    'Si un enregistrement correspond, il devient l'enregistrement courant
 
     [...]    'Ajoute ton nouveau record
 
Else
 
    Rs1.Edit
    [...]    'Modifie les fields nécessaires
    Rs1.Update
 
End if
A adapter à tes conditions particulières, bien sûr.
Sclarckone est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/09/2011, 08h57   #3
Invité régulier
 
Inscription : mai 2011
Messages : 29
Détails du profil
Informations forums :
Inscription : mai 2011
Messages : 29
Points : 5
Points : 5
Bonjour,

Juste quelques petites questions :

"Primary Key" : je laisse comme sa ou je mets l'intitulé de ma clé

Rs1.Seek("=", Array(x, 1)) : le "=" je le laisse ossi ou il faut mettre quelque chose en particulier (il me met erreur de compilation)

A part les changements données, mon code je pe le garder come tel ou il y a des choses à supprimé ?

Merci
dragoes64 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/09/2011, 11h11   #4
Membre actif
 
Inscription : novembre 2008
Messages : 188
Détails du profil
Informations forums :
Inscription : novembre 2008
Messages : 188
Points : 194
Points : 194
Citation:
Envoyé par dragoes64 Voir le message
"Primary Key" : je laisse comme sa ou je mets l'intitulé de ma clé
Normalement si tu as un seul champ définit comme clé primaire, il ne devrait pas y avoir d'ambigüité donc tu peux laisser comme ça. Jette un œil à la collection Indexes de ta table si ça ne fonctionne pas.

Citation:
Envoyé par dragoes64 Voir le message
Rs1.Seek("=", Array(x, 1)) : le "=" je le laisse ossi ou il faut mettre quelque chose en particulier (il me met erreur de compilation
Il faut laisser le "=" tel quel et pour le deuxième argument (key1), je pense que l'aide VBA est assez explicite:

Citation:
Envoyé par VBA Help
Le type de données de champ de l'argument key1 doit être identique à celui du champ correspondant dans l'index en cours. Par exemple, si l'index en cours fait référence à un champ numérique (par exemple, N° employé), key1 doit contenir des données numériques. De même, si l'index en cours fait référence à un champ texte (par exemple, Nom), key1 doit être une chaîne.
Tiens-moi au courant si ça ne fonctionne pas, auquel cas je testerai de mon côté. Normalement tu dois pouvoir garder le reste de ton code car la seule chose ayant vraiment changé, c'est le type de recordset (dynaset en table, et les 2 sont assez proches).
Sclarckone est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/09/2011, 13h41   #5
Invité régulier
 
Inscription : mai 2011
Messages : 29
Détails du profil
Informations forums :
Inscription : mai 2011
Messages : 29
Points : 5
Points : 5
J'ai un problème avec cette ligne :

Rs1.Seek("=" , Array1(x, 1)
Le message dit "Erreur de compilation Attendu séparateur de liste ou ) "

J'ai beau cherché je vois pas ou rajouter cet élément ( j'ai pensé à un = après Seek mais il me dit encore qu'il manque une parenthèse)

Merci
dragoes64 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/09/2011, 13h48   #6
Membre actif
 
Inscription : novembre 2008
Messages : 188
Détails du profil
Informations forums :
Inscription : novembre 2008
Messages : 188
Points : 194
Points : 194
Citation:
Envoyé par dragoes64 Voir le message
Le message dit "Erreur de compilation Attendu séparateur de liste ou ) "
Peut-être que tu as oublié une parenthèse:

Code :
Rs1.Seek("=" , Array1(x, 1))
Sinon c'est parce qu'en VBA, pour les appels de procédures, il ne faut normalement pas lister les arguments entre parenthèses (c'est réservé aux fonctions). Personnellement je n'aime pas donc j'utilise toujours les parenthèses .

2 solutions:

Ou tu enlèves les parenthèses:

Code :
Rs1.Seek "=" , Array1(x, 1)
ou tu utilises 'Call' devant (il parait que ce n'est pas recommandé mais je ne sais pas pourquoi et je n'ai jamais eu de problème avec):

Code :
Call Rs1.Seek("=" , Array1(x, 1))
Sclarckone est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/09/2011, 09h11   #7
Invité régulier
 
Inscription : mai 2011
Messages : 29
Détails du profil
Informations forums :
Inscription : mai 2011
Messages : 29
Points : 5
Points : 5
En enlevant les parenthèses sa marche parfaitement.

Merci à toi Sclarckone tu m'as été d'une grande aide. Ce sujet est à présent résolu !!!
dragoes64 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 00h01.


 
 
 
 
Partenaires

Hébergement Web