Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Comparer deux tables champ par champ

6 réponses
Avatar
JMarc
Bonjour,

J'utilise Access ponctuellement, et là, je seche un peu...

Dans le but de vérifier des données migrées entre deux systèmes, je dois
comparer deux tables de 60 champs chacune.
J'aimerai identifier chaque enregistrement dont un des champs ne
correspond pas dans l'autre table, puis afficher les données de chaque
champs en erreur.

Pour le moment, j'ai fait une requête pour chaque champ, et je trouve
les erreurs, mais lorsqu'il y a plusieurs erreurs dans un même
enregistrement, cela devient un peu fastidieux.

Je ne suis que très peu familier avec VB, donc si vous avez une idée sur
une méthode simple... je suis preneur.

Merci beaucoup par avance pour vos idées !!!

JMarc

6 réponses

Avatar
Eric
Bonjour,

Sans être certain de te donner la réponse que tu attends:

Une procédure en VBA qui crée la requête retournant les enregistrements
non identiques dans les 2 tables et ce quelque soit le nombre de champs
ayant un contenu différent. Par contre le nb de champs par
enregistrements sera de 2*60 c'est à dire qu'elle affiche le contenu de
l'enregistrement de la 1ere table associée à celui de la 2eme table,
mais par souci de lisibilité, ils sont regroupés 2 par 2.
Au final, il faudra pour chaque ligne renvoyée procéder à l'analyse.

Les tables ont la même structure avec les champs dans le même ordre et
le 1er champ de chaque table est le champ servant de jointure.

Procédure à copier dans un module de portée globale
(Charger la référence Microsoft DAO 3.x Object Library)

Sub yy()
On Error GoTo ErrTraitement
Dim t1 As DAO.TableDef, t2 As DAO.TableDef
Dim bd As DAO.Database, rq As DAO.QueryDef
Dim strSQL As String, strWhere As String
Dim i As Integer
Set bd = CurrentDb
Set t1 = bd.TableDefs("Test1")
Set t2 = bd.TableDefs("Test2")
' Génération du SQL
strSQL = "Select"
'Par souci de lisibilité les champs de même rang sont cote à cote
For i = 0 To t1.Fields.Count - 1
strSQL = strSQL & " a." & t1.Fields(i).Name & ", b." &
t2.Fields(i).Name & ","
Next i
strSQL = Left(strSQL, Len(strSQL) - 1)
strSQL = strSQL & " from test1 a inner join Test2 b on a." &
t1.Fields(0).Name & "= b." & t2.Fields(0).Name & " Where "
For i = 0 To t1.Fields.Count - 1
strWhere = strWhere & "a." & t1.Fields(i).Name & "<> b." &
t2.Fields(i).Name & " or "
Next i
strWhere = Left(strWhere, Len(strWhere) - 3)
strSQL = strSQL & strWhere
' Fin du SQL
Set rq = bd.CreateQueryDef("tmp", strSQL) ' création de la requête
DoCmd.OpenQuery "tmp" ' ouverture de la requête
' Récupération des variables-objet
Set rq = Nothing
Set t1 = Nothing
Set t2 = Nothing
Set bd = Nothing
Exit Sub
ErrTraitement:
If Err.Number = 3012 Then ' la requête existe déjà
bd.QueryDefs.Delete "tmp" 'Suppresssion de la requête
Resume 0
Else ' autre erreur
MsgBox Err.Number & " " & Err.Description
End If
End Sub

Autre solution qui affiche dans une msgbox les n° des enregistrements
pour lesquels les champs sont différents avec le nom du champ et les
valeurs. Mais ce n'es concevable que pour un faible nombre de données.
(Fourni juste pour l'exemple)

Sub zz()
Dim strSQL As String, rs As DAO.Recordset
Dim i As Integer, msg As String
' text1 et test2 sont des tables relatives aux données des cliens
' numclient est la clé primaire de chaque table
strSQL = " Select * from test1 a inner join test2 b on
a.numclient=b.numclient;"
Set rs = CurrentDb.OpenRecordset(strSQL)
Do While Not rs.EOF
For i = 0 To (rs.Fields.Count) / 2 - 1
If rs(i) <> rs(i + (rs.Fields.Count) / 2) Then
msg = msg & "Enreg n° " & rs(0) & " : " &
Mid(rs(i).Name, 3) & ":" & rs(i) _
& " ---> " & rs(i + (rs.Fields.Count) / 2) & vbCrLf
End If
Next i
rs.MoveNext
Loop
MsgBox msg
rs.Close
Set rs = Nothing
End Sub


Bonjour,

J'utilise Access ponctuellement, et là, je seche un peu...

Dans le but de vérifier des données migrées entre deux systèmes, je dois
comparer deux tables de 60 champs chacune.
J'aimerai identifier chaque enregistrement dont un des champs ne
correspond pas dans l'autre table, puis afficher les données de chaque
champs en erreur.

Pour le moment, j'ai fait une requête pour chaque champ, et je trouve
les erreurs, mais lorsqu'il y a plusieurs erreurs dans un même
enregistrement, cela devient un peu fastidieux.

Je ne suis que très peu familier avec VB, donc si vous avez une idée sur
une méthode simple... je suis preneur.

Merci beaucoup par avance pour vos idées !!!

JMarc


--
A+
Eric
http://www.mpfa.info/
Archives : http://groups.google.fr/group/microsoft.public.fr.access?hl=fr

Avatar
JMarc
Bonsoir Eric,

Merci pour toutes ces explications, je vais tester cela demain si je
comprends tout...

Je te tiens au courant du résultat !

JMarc


Bonjour,

Sans être certain de te donner la réponse que tu attends:

Une procédure en VBA qui crée la requête retournant les enregistrements
non identiques dans les 2 tables et ce quelque soit le nombre de champs
ayant un contenu différent. Par contre le nb de champs par
enregistrements sera de 2*60 c'est à dire qu'elle affiche le contenu de
l'enregistrement de la 1ere table associée à celui de la 2eme table,
mais par souci de lisibilité, ils sont regroupés 2 par 2.
Au final, il faudra pour chaque ligne renvoyée procéder à l'analyse.

Les tables ont la même structure avec les champs dans le même ordre et
le 1er champ de chaque table est le champ servant de jointure.

Procédure à copier dans un module de portée globale
(Charger la référence Microsoft DAO 3.x Object Library)

Sub yy()
On Error GoTo ErrTraitement
Dim t1 As DAO.TableDef, t2 As DAO.TableDef
Dim bd As DAO.Database, rq As DAO.QueryDef
Dim strSQL As String, strWhere As String
Dim i As Integer
Set bd = CurrentDb
Set t1 = bd.TableDefs("Test1")
Set t2 = bd.TableDefs("Test2")
' Génération du SQL
strSQL = "Select"
'Par souci de lisibilité les champs de même rang sont cote à cote
For i = 0 To t1.Fields.Count - 1
strSQL = strSQL & " a." & t1.Fields(i).Name & ", b." &
t2.Fields(i).Name & ","
Next i
strSQL = Left(strSQL, Len(strSQL) - 1)
strSQL = strSQL & " from test1 a inner join Test2 b on a." &
t1.Fields(0).Name & "= b." & t2.Fields(0).Name & " Where "
For i = 0 To t1.Fields.Count - 1
strWhere = strWhere & "a." & t1.Fields(i).Name & "<> b." &
t2.Fields(i).Name & " or "
Next i
strWhere = Left(strWhere, Len(strWhere) - 3)
strSQL = strSQL & strWhere
' Fin du SQL
Set rq = bd.CreateQueryDef("tmp", strSQL) ' création de la requête
DoCmd.OpenQuery "tmp" ' ouverture de la requête
' Récupération des variables-objet
Set rq = Nothing
Set t1 = Nothing
Set t2 = Nothing
Set bd = Nothing
Exit Sub
ErrTraitement:
If Err.Number = 3012 Then ' la requête existe déjà
bd.QueryDefs.Delete "tmp" 'Suppresssion de la requête
Resume 0
Else ' autre erreur
MsgBox Err.Number & " " & Err.Description
End If
End Sub

Autre solution qui affiche dans une msgbox les n° des enregistrements
pour lesquels les champs sont différents avec le nom du champ et les
valeurs. Mais ce n'es concevable que pour un faible nombre de données.
(Fourni juste pour l'exemple)

Sub zz()
Dim strSQL As String, rs As DAO.Recordset
Dim i As Integer, msg As String
' text1 et test2 sont des tables relatives aux données des cliens
' numclient est la clé primaire de chaque table
strSQL = " Select * from test1 a inner join test2 b on
a.numclient=b.numclient;"
Set rs = CurrentDb.OpenRecordset(strSQL)
Do While Not rs.EOF
For i = 0 To (rs.Fields.Count) / 2 - 1
If rs(i) <> rs(i + (rs.Fields.Count) / 2) Then
msg = msg & "Enreg n° " & rs(0) & " : " &
Mid(rs(i).Name, 3) & ":" & rs(i) _
& " ---> " & rs(i + (rs.Fields.Count) / 2) & vbCrLf
End If
Next i
rs.MoveNext
Loop
MsgBox msg
rs.Close
Set rs = Nothing
End Sub


Bonjour,

J'utilise Access ponctuellement, et là, je seche un peu...

Dans le but de vérifier des données migrées entre deux systèmes, je
dois comparer deux tables de 60 champs chacune.
J'aimerai identifier chaque enregistrement dont un des champs ne
correspond pas dans l'autre table, puis afficher les données de chaque
champs en erreur.

Pour le moment, j'ai fait une requête pour chaque champ, et je trouve
les erreurs, mais lorsqu'il y a plusieurs erreurs dans un même
enregistrement, cela devient un peu fastidieux.

Je ne suis que très peu familier avec VB, donc si vous avez une idée
sur une méthode simple... je suis preneur.

Merci beaucoup par avance pour vos idées !!!

JMarc





Avatar
JMarc
Bonsoir Eric,

J'ai testé tes modules, et effectivement, ça s'approche de ce que je
cherche.

Si j'abuse, excuse-moi et dis le moi.
En fait, je souhaiterai voir seulement les champs en erreur dans
l'enregistrement, car si il y en a 1 en erreur sur 60, c'est trop dur à
analyser. Y a-t-il un moyen simple d'améliorer ton code ?

Sinon, la seconde possibilité me parait peut-être plus simple, mais je
pense que je suis confronté à une limite d'access concernant le nombre
maxi de caractères dans une boite de message car avec la première
méthode, je sais que j'ai 480 lignes en erreur, mais la seconde qui est
plus précise, ne me donne que les 25-30 premières.

Idéalement, peut-on retourner les infos vers une table plutôt que vers
une boite de message ?

Merci encore, et surtout si j'abuse de ton temps, dis le moi !

JMarc

Bonjour,

Sans être certain de te donner la réponse que tu attends:

Une procédure en VBA qui crée la requête retournant les enregistrements
non identiques dans les 2 tables et ce quelque soit le nombre de champs
ayant un contenu différent. Par contre le nb de champs par
enregistrements sera de 2*60 c'est à dire qu'elle affiche le contenu de
l'enregistrement de la 1ere table associée à celui de la 2eme table,
mais par souci de lisibilité, ils sont regroupés 2 par 2.
Au final, il faudra pour chaque ligne renvoyée procéder à l'analyse.

Les tables ont la même structure avec les champs dans le même ordre et
le 1er champ de chaque table est le champ servant de jointure.

Procédure à copier dans un module de portée globale
(Charger la référence Microsoft DAO 3.x Object Library)

Sub yy()
On Error GoTo ErrTraitement
Dim t1 As DAO.TableDef, t2 As DAO.TableDef
Dim bd As DAO.Database, rq As DAO.QueryDef
Dim strSQL As String, strWhere As String
Dim i As Integer
Set bd = CurrentDb
Set t1 = bd.TableDefs("Test1")
Set t2 = bd.TableDefs("Test2")
' Génération du SQL
strSQL = "Select"
'Par souci de lisibilité les champs de même rang sont cote à cote
For i = 0 To t1.Fields.Count - 1
strSQL = strSQL & " a." & t1.Fields(i).Name & ", b." &
t2.Fields(i).Name & ","
Next i
strSQL = Left(strSQL, Len(strSQL) - 1)
strSQL = strSQL & " from test1 a inner join Test2 b on a." &
t1.Fields(0).Name & "= b." & t2.Fields(0).Name & " Where "
For i = 0 To t1.Fields.Count - 1
strWhere = strWhere & "a." & t1.Fields(i).Name & "<> b." &
t2.Fields(i).Name & " or "
Next i
strWhere = Left(strWhere, Len(strWhere) - 3)
strSQL = strSQL & strWhere
' Fin du SQL
Set rq = bd.CreateQueryDef("tmp", strSQL) ' création de la requête
DoCmd.OpenQuery "tmp" ' ouverture de la requête
' Récupération des variables-objet
Set rq = Nothing
Set t1 = Nothing
Set t2 = Nothing
Set bd = Nothing
Exit Sub
ErrTraitement:
If Err.Number = 3012 Then ' la requête existe déjà
bd.QueryDefs.Delete "tmp" 'Suppresssion de la requête
Resume 0
Else ' autre erreur
MsgBox Err.Number & " " & Err.Description
End If
End Sub

Autre solution qui affiche dans une msgbox les n° des enregistrements
pour lesquels les champs sont différents avec le nom du champ et les
valeurs. Mais ce n'es concevable que pour un faible nombre de données.
(Fourni juste pour l'exemple)

Sub zz()
Dim strSQL As String, rs As DAO.Recordset
Dim i As Integer, msg As String
' text1 et test2 sont des tables relatives aux données des cliens
' numclient est la clé primaire de chaque table
strSQL = " Select * from test1 a inner join test2 b on
a.numclient=b.numclient;"
Set rs = CurrentDb.OpenRecordset(strSQL)
Do While Not rs.EOF
For i = 0 To (rs.Fields.Count) / 2 - 1
If rs(i) <> rs(i + (rs.Fields.Count) / 2) Then
msg = msg & "Enreg n° " & rs(0) & " : " &
Mid(rs(i).Name, 3) & ":" & rs(i) _
& " ---> " & rs(i + (rs.Fields.Count) / 2) & vbCrLf
End If
Next i
rs.MoveNext
Loop
MsgBox msg
rs.Close
Set rs = Nothing
End Sub


Bonjour,

J'utilise Access ponctuellement, et là, je seche un peu...

Dans le but de vérifier des données migrées entre deux systèmes, je
dois comparer deux tables de 60 champs chacune.
J'aimerai identifier chaque enregistrement dont un des champs ne
correspond pas dans l'autre table, puis afficher les données de chaque
champs en erreur.

Pour le moment, j'ai fait une requête pour chaque champ, et je trouve
les erreurs, mais lorsqu'il y a plusieurs erreurs dans un même
enregistrement, cela devient un peu fastidieux.

Je ne suis que très peu familier avec VB, donc si vous avez une idée
sur une méthode simple... je suis preneur.

Merci beaucoup par avance pour vos idées !!!

JMarc





Avatar
Eric
Bonjour,

Oui il est possible de stocker dans une table, mais les champs doivent
donc être définis comme Texte car leur contenu doit pouvoir stocker
aussi bien du texte que du numérique.

Essaies avec cette procédure mais tu auras dans la table une ligne par
erreur. Ainsi, si 3 erreurs dans un enregistrement alors 3 lignes dans
la table. (Remplaces la procédure avec la msgbox)

Sub zz()
On Error GoTo ErrTraitement
Dim strSQL As String, rs As DAO.Recordset
Dim i As Integer
' test1 et test2 sont des tables relatives aux données des clients
' numclient est la clé primaire de chaque table
' Hypothèse : Test1 est la bonne table
' Une table tblErreurs est créée dont les champs à l'exception du
1er sont
' de type Text
strSQL = strSQL & "Create Table tblErreurs("
strSQL = strSQL & "NumEnreg Long,"
strSQL = strSQL & "NomChamp Text,"
strSQL = strSQL & "ValeurTable1 Text,"
strSQL = strSQL & "ValeurTable2 Text)"
CurrentDb.Execute strSQL ' création de la table tblErreurs
strSQL = " Select * from test1 a inner join test2 b on
a.numclient=b.numclient;"
Set rs = CurrentDb.OpenRecordset(strSQL)
Do While Not rs.EOF
For i = 0 To (rs.Fields.Count) / 2 - 1
If rs(i) <> Nz(rs(i + (rs.Fields.Count) / 2)) Then
' SQL d'ajout dans la table
strSQL = "Insert into tblErreurs Values(" _
& rs(0) & ",'" & Mid(rs(i).Name, 3) _
& "'," & Chr(34) & rs(i) & Chr(34) _
& "," & Chr(34) & rs(i + (rs.Fields.Count) / 2) _
& Chr(34) & ")"
CurrentDb.Execute strSQL ' insertion
End If
Next i
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Exit Sub
ErrTraitement:
If Err.Number = 3010 Then ' Table existe déjà
CurrentDb.TableDefs.Delete "tblErreurs" ' suppression
Resume 0
Else ' autre erreur
MsgBox Err.Number & " " & Err.Description
End If
End Sub

Bonsoir Eric,

J'ai testé tes modules, et effectivement, ça s'approche de ce que je
cherche.

Si j'abuse, excuse-moi et dis le moi.
En fait, je souhaiterai voir seulement les champs en erreur dans
l'enregistrement, car si il y en a 1 en erreur sur 60, c'est trop dur à
analyser. Y a-t-il un moyen simple d'améliorer ton code ?

Sinon, la seconde possibilité me parait peut-être plus simple, mais je
pense que je suis confronté à une limite d'access concernant le nombre
maxi de caractères dans une boite de message car avec la première
méthode, je sais que j'ai 480 lignes en erreur, mais la seconde qui est
plus précise, ne me donne que les 25-30 premières.

Idéalement, peut-on retourner les infos vers une table plutôt que vers
une boite de message ?

Merci encore, et surtout si j'abuse de ton temps, dis le moi !

JMarc



--
A+
Eric
http://www.mpfa.info/
Archives : http://groups.google.fr/group/microsoft.public.fr.access?hl=fr

Avatar
Eric
re,

Le champ NumEnreg de la table tblErreurs contient la valeur du champ de
jointure entre les 2 tables. J'ai supposé ce champ Numérique Entier Long
(dans mon exemple, il s'agit d'un numéro de client).

Si dans ton cas, le champ de jointure est de type Text,
le sql de creation de la table tblErreurs doit être :
strSQL = strSQL & "Create Table tblErreurs("
strSQL = strSQL & "NumEnreg Text,"
strSQL = strSQL & ... ' rest inchangé

et le sql d'insertion:
strSQL = "Insert into tblErreurs Values(" _
& "'" & rs(0) & "','" & Mid(rs(i).Name, 3) _
& "'," & Chr(34) & rs(i) & Chr(34) _
...


--
A+
Eric
http://www.mpfa.info/
Archives : http://groups.google.fr/group/microsoft.public.fr.access?hl=fr
Avatar
JMarc
Merci Eric, je vais tester tout cela lundi.
Ce n'est pas génant s'il y a plusieurs ligne par erreur, je ferai une
requête croisée ou un tableau croisé sous XL et ce sera parfait !

Mais si je peux encore poser une question, à quoi sert "la référence
Microsoft DAO 3.x Object Library" ? Pourquoi faut-il l'activer et
pourquoi n'est-elle pas activé par défaut ?

Merci encore !

JMarc

re,

Le champ NumEnreg de la table tblErreurs contient la valeur du champ de
jointure entre les 2 tables. J'ai supposé ce champ Numérique Entier Long
(dans mon exemple, il s'agit d'un numéro de client).

Si dans ton cas, le champ de jointure est de type Text,
le sql de creation de la table tblErreurs doit être :
strSQL = strSQL & "Create Table tblErreurs("
strSQL = strSQL & "NumEnreg Text,"
strSQL = strSQL & ... ' rest inchangé

et le sql d'insertion:
strSQL = "Insert into tblErreurs Values(" _
& "'" & rs(0) & "','" & Mid(rs(i).Name, 3) _
& "'," & Chr(34) & rs(i) & Chr(34) _
...