Les meilleures sources Access
Les meilleures sources AccessConsultez toutes les sources
Nombre d'auteurs : 44, nombre de sources : 147, création le 19 mars 2013
- Concaténer plusieurs enregistrements dans une seule colonne
- Classer des données par plage
- Classer les résultats d'une requête
- Dupliquer des enregistrements en cascade
- Générer un calendrier
- Effectuer des recherches phonétiques
- Réaliser des totaux en ligne et en colonne
- Réaliser un tableau de score
- Comment afficher les données à l'inverse d'une requête analyse croisée ?
Versions : 97 et supérieures
Important : Pour que ce code fonctionne, vous devez ajouter une référence Microsoft DAO à votre projet.
Voici un exemple de table :
Projet | NomParticipant |
---|---|
1 | Dupont |
1 | Durand |
1 | Paul |
2 | Dupont |
2 | Luc |
Dans une requête R01, vous souhaitez obtenir la liste des projets ainsi que la liste des participants sur une seule colonne et une seule ligne par projet.
Projet | LesParticipants |
---|---|
1 | Dupont Durand Paul |
2 | Dupont Luc |
Pour cela, il vous faut placer ce code dans un module :
Public
Function
RecupParticipant
(
Projet As
Long
) As
String
Dim
res As
DAO.Recordset
Dim
SQL As
String
'Selectionne les participant du projet
SQL =
"SELECT NomParticipant FROM Tbl_Projet WHERE Projet="
&
Projet
Set
res =
CurrentDb.OpenRecordset
(
SQL)
'Concatene les différents enregistrement
While
Not
res.EOF
RecupParticipant =
RecupParticipant &
res.Fields
(
0
).Value
&
" "
res.MoveNext
Wend
'Enleve le dernier espace
RecupParticipant =
Left
(
RecupParticipant, Len
(
RecupParticipant) -
1
)
'libere la mémoire
Set
res =
Nothing
End
Function
Puis créer la requête :
R01 :
SELECT
DISTINCT
Tbl_projet.Projet, Recupparticipant(
Projet)
AS
LesParticipants
FROM
Tbl_projet;
Dans une requête R02, vous souhaitez obtenir la liste des participants ainsi que la liste de leurs projets sur une seule colonne et une seule ligne par participant.
NomParticipant | LesProjets |
---|---|
Dupont | 1;2 |
Durand | 1 |
Luc | 2 |
Paul | 1 |
Pour arriver à un tel résultat, placer dans un module le code suivant :
Public
Function
RecupProjet
(
Nom As
String
) As
String
Dim
res As
DAO.Recordset
Dim
SQL As
String
'Selectionne les projet du partcipant
'chr(34) correspond a des guillemets pour encadrer le texte
SQL =
"SELECT Projet FROM Tbl_Projet WHERE NomParticipant="
&
_
Chr
(
34
) &
Nom &
Chr
(
34
)
Set
res =
CurrentDb.OpenRecordset
(
SQL)
'Concatene les différents enregistrement
While
Not
res.EOF
RecupProjet =
RecupProjet &
res.Fields
(
0
).Value
&
";"
res.MoveNext
Wend
'Enleve le dernier ;
RecupProjet =
Left
(
RecupProjet, Len
(
RecupProjet) -
1
)
'libere la mémoire
Set
res =
Nothing
End
Function
Et enfin, créer la requête SQL :
R02 :
SELECT
DISTINCT
Tbl_projet.NomParticipant, Recupprojet(
NomParticipant)
AS
LesProjets
FROM
Tbl_projet;
Version : Access 2000 et ultérieures
Cet exemple vous permet de classer des données en fonction d'une plage. Par exemple, le nombre 101 appartient à la tranche 100 à 199 si l'on considère des plages de 100 éléments.
Placez le code suivant dans un module :
Function
fIntervalle
(
ByVal
Valeur As
Double
, _
Optional
ByVal
EspaceIntervalle As
Double
=
25
) As
String
Dim
l1 As
Long
Dim
l2 As
Long
l1 =
(
Valeur \
EspaceIntervalle) *
EspaceIntervalle
If
Valeur >=
0
Then
l2 =
l1 +
EspaceIntervalle -
1
fIntervalle =
l1 &
" à "
&
l2
Else
l2 =
l1 -
EspaceIntervalle +
1
fIntervalle =
l2 &
" à "
&
l1
End
If
End
Function
Ainsi, Msgbox fIntervalle(101,100) affiche 100 à 199.
Un exemple fréquent d'utilisation est le classement des notes des élèves d'une classe. Prenons l'exemple de la table tblNote suivante :
Eleve | Note | Devoir |
---|---|---|
PAUL | 12 | Devoir n°1 |
REMI | 13 | Devoir n°1 |
MARC | 4 | Devoir n°1 |
YVES | 3 | Devoir n°1 |
MARTIN | 5 | Devoir n°1 |
SIMON | 8 | Devoir n°1 |
LUC | 9 | Devoir n°1 |
LUCIE | 3 | Devoir n°1 |
MARIE | 2 | Devoir n°1 |
BILL | 0 | Devoir n°1 |
GERALDINE | 2 | Devoir n°1 |
SOPHIE | 2 | Devoir n°1 |
FELICIEN | 17 | Devoir n°1 |
ANNE | 18 | Devoir n°1 |
PAUL | 12 | Devoir n°2 |
REMI | 1 | Devoir n°2 |
MARC | 3 | Devoir n°2 |
YVES | 3 | Devoir n°2 |
MARTIN | 18 | Devoir n°2 |
SIMON | 17 | Devoir n°2 |
LUC | 16 | Devoir n°2 |
LUCIE | 4 | Devoir n°2 |
MARIE | 5 | Devoir n°2 |
BILL | 3 | Devoir n°2 |
GERALDINE | 8 | Devoir n°2 |
SOPHIE | 10 | Devoir n°2 |
FELICIEN | 11 | Devoir n°2 |
ANNE | 19 | Devoir n°2 |
A l'aide d'une première requête (R01), nous pouvons calculer la répartition des notes.
SELECT
fIntervalle(
note,5
)
AS
Tranche, *
FROM
tblNote
ORDER
BY
Val(
fIntervalle(
note,5
))
;
Tranche | Eleve | Note | Devoir |
---|---|---|---|
0 à 4 | YVES | 3 | Devoir n°2 |
0 à 4 | LUCIE | 3 | Devoir n°1 |
0 à 4 | MARIE | 2 | Devoir n°1 |
0 à 4 | BILL | 0 | Devoir n°1 |
0 à 4 | GERALDINE | 2 | Devoir n°1 |
0 à 4 | SOPHIE | 2 | Devoir n°1 |
0 à 4 | MARC | 3 | Devoir n°2 |
0 à 4 | YVES | 3 | Devoir n°1 |
0 à 4 | MARC | 4 | Devoir n°1 |
0 à 4 | LUCIE | 4 | Devoir n°2 |
0 à 4 | BILL | 3 | Devoir n°2 |
0 à 4 | REMI | 1 | Devoir n°2 |
5 à 9 | LUC | 9 | Devoir n°1 |
5 à 9 | MARTIN | 5 | Devoir n°1 |
5 à 9 | SIMON | 8 | Devoir n°1 |
5 à 9 | MARIE | 5 | Devoir n°2 |
5 à 9 | GERALDINE | 8 | Devoir n°2 |
10 à 14 | REMI | 13 | Devoir n°1 |
10 à 14 | PAUL | 12 | Devoir n°2 |
10 à 14 | PAUL | 12 | Devoir n°1 |
10 à 14 | SOPHIE | 10 | Devoir n°2 |
10 à 14 | FELICIEN | 11 | Devoir n°2 |
15 à 19 | ANNE | 18 | Devoir n°1 |
15 à 19 | ANNE | 19 | Devoir n°2 |
15 à 19 | MARTIN | 18 | Devoir n°2 |
15 à 19 | SIMON | 17 | Devoir n°2 |
15 à 19 | LUC | 16 | Devoir n°2 |
15 à 19 | FELICIEN | 17 | Devoir n°1 |
Puis une seconde nous permet de faire l'analyse croisée des notes afin d'obtenir les tranches en colonne.
TRANSFORM Count
(
R01.Eleve)
AS
CompteDeEleve
SELECT
R01.Devoir
FROM
R01
GROUP
BY
R01.Devoir
PIVOT R01.Tranche;
Devoir | 0 à 4 | 5 à 9 | 10 à 14 | 15 à 19 |
---|---|---|---|---|
Devoir n°1 | 7 | 3 | 2 | 2 |
Devoir n°2 | 5 | 2 | 3 | 4 |
Cette section propose plusieurs requêtes pour classer des enregistrements.
Voici notre table exemple (elle est nommée Tbl_Note) :
Note | Nom |
---|---|
10 | Paul |
12 | Dupont |
6 | Henry |
20 | Luc |
16 | Marc |
12 | Etienne |
12 | Simon |
20 | Lucien |
1. Classement indexé à zéro des notes par ordre décroissant correspondant à :
Rang | Note | Nom |
---|---|---|
0 | 20 | Lucien |
0 | 20 | Luc |
2 | 16 | Marc |
3 | 12 | Simon |
3 | 12 | Etienne |
3 | 12 | Dupont |
6 | 10 | Paul |
7 | 6 | Henry |
SELECT
(
SELECT
Count
(
Note)
FROM
tbl_note T2
WHERE
T2.Note>
T1.Note)
AS
Rang,
T1.Note, *
FROM
tbl_note AS
T1
ORDER
BY
T1.Note DESC
;
Rang | Note | Nom |
---|---|---|
0 | 20 | Lucien |
0 | 20 | Luc |
1 | 16 | Marc |
2 | 12 | Simon |
2 | 12 | Etienne |
2 | 12 | Dupont |
3 | 10 | Paul |
4 | 6 | Henry |
SELECT
(
SELECT
Count
(
Note)
FROM
(
SELECT
Distinct
Note FROM
tbl_note)
T2
WHERE
T2.Note>
T1.Note)
AS
Rang,
T1.Note, *
FROM
tbl_note AS
T1
ORDER
BY
T1.Note DESC
;
2. Classement indexé à zéro des notes par ordre croissant correspondant à :
Rang | Note | Nom |
---|---|---|
0 | 6 | Henry |
1 | 10 | Paul |
2 | 12 | Simon |
2 | 12 | Etienne |
2 | 12 | Dupont |
5 | 16 | Marc |
6 | 20 | Lucien |
6 | 20 | Luc |
SELECT
(
SELECT
Count
(
Note)
FROM
tbl_Note T2
WHERE
T2.Note<
T1.Note)
AS
Rang, T1.Note, *
FROM
tbl_note AS
T1
ORDER
BY
T1.Note;
Rang | Note | Nom |
---|---|---|
0 | 6 | Henry |
1 | 10 | Paul |
2 | 12 | Simon |
2 | 12 | Etienne |
2 | 12 | Dupont |
3 | 16 | Marc |
4 | 20 | Lucien |
4 | 20 | Luc |
SELECT
(
SELECT
Count
(
Note)
FROM
(
SELECT
Distinct
Note FROM
tbl_note)
T2
WHERE
T2.Note<
T1.Note)
AS
Rang, T1.Note, *
FROM
tbl_note AS
T1
ORDER
BY
T1.Note;
3. Classement indexé à 1 :
Il suffit d'ajouter 1 à chaque ligne
Rang | Note | Nom |
---|---|---|
1 | 6 | Henry |
2 | 10 | Paul |
3 | 12 | Simon |
3 | 12 | Etienne |
3 | 12 | Dupont |
6 | 16 | Marc |
7 | 20 | Lucien |
7 | 20 | Luc |
SELECT
(
SELECT
Count
(
Note)
FROM
tbl_note T2
WHERE
T2.Note<
T1.Note)
+
1
AS
Rang, T1.Note, *
FROM
tbl_note AS
T1
ORDER
BY
T1.Note;
4. Classeement sur deux champs :
Cet exemple tri par note et par nom :
Rang | Note | Nom |
---|---|---|
1 | 6 | Henry |
2 | 10 | Paul |
3 | 12 | Dupont |
3 | 12 | Etienne |
3 | 12 | Simon |
6 | 16 | Marc |
7 | 20 | Luc |
7 | 20 | Lucien |
SELECT
(
SELECT
Count
(
Note)
FROM
tbl_note T2
WHERE
T2.Note<
T1.Note)
+
1
AS
Rang, T1.Note, *
FROM
tbl_note AS
T1
ORDER
BY
T1.Note,Nom ;
Versions : Access 2000 et supérieures
Cet exemple permet de dupliquer un enregistrement ainsi que ses données sous-jacentes.
Soit les tables suivantes :
- Protocole(IdProtocole,NomProtocole)
- LigneProtocole(IdLigne,LibelleLigne,IdProtocole#)
Les deux clés primaires (soulignées) sont de type Numérotation Automatique.
L'utilisation de DAO va nous permettre de dupliquer le protocole n°1, de récuperer l'identifiant du nouvel enregistrement puis ensuite de construire une requête qui recopiera les lignes du protocole.
Pour cela, vous devez ajouter la référence Microsoft DAO à votre projet.
Private
Sub
Dupliquer
(
)
Dim
rstProtocole As
DAO.Recordset
, rstProtocole2 As
DAO.Recordset
Dim
Db As
DAO.Database
, fld As
DAO.Field
Dim
sql As
String
Dim
id As
Long
Set
Db =
CurrentDb
'Ouvre le recordset où sera prélevé le protocole
Set
rstProtocole =
Db.OpenRecordset
(
"SELECT NomProtocole FROM Protocole WHERE IdProtocole=1"
)
'Verifie que le protocole 1 existe
If
rstProtocole.EOF
Then
Exit
Sub
'ouvre le recordset où sera ajouté le protocole
Set
rstProtocole2 =
Db.OpenRecordset
(
"protocole"
)
'Duplique le protocole
With
rstProtocole2
.AddNew
'duplique les champs
For
Each
fld In
rstProtocole.Fields
.Fields
(
fld.Name
) =
fld.Value
Next
id =
.Fields
(
"idprotocole"
)
.Update
'se positionne sur l'enregistrement ajouté
End
With
'Duplique les lignes
sql =
"insert into LigneProtocole (IdProtocole,Libelleligne) SELECT "
&
_
id &
", LibelleLigne FROM LigneProtocole WHERE idprotocole=1"
Db.Execute
sql
End
Sub
Versions : Toutes
Objectif : Etablir un calendrier des absences des employés d'une entreprise sans utiliser VBA
Soit la table des absences nommées tblAbsence :
NumEmploye | DebutAbsence | FinAbsence |
---|---|---|
1 | 10/12/2005 | 13/12/2005 |
2 | 25/12/2005 | 01/01/2006 |
3 | 26/12/2005 | 27/12/2005 |
1 | 04/05/2006 | 07/05/2006 |
On désire obtenir la liste des jours où chaque employé a été absent.
Pour cela 3 tables "outils" sont nécessaires.
- La table tbl_Jours regroupe les numéros des jours : de 0 à 31
- La table tbl_Mois regroupe les mois : de 0 à 12
- La table tbl_Annee regroupe les années utiles : de 2000 à 2010 pour notre exemple
Ainsi, l'ensemble des jours peut être obtenu par une requête nommée R01_Calendrier
SELECT
tbl_Jours.Numero &
"/"
&
tbl_Mois.Numero &
"/"
&
tbl_Annee.Numero AS
D
FROM
tbl_jours, tbl_mois, tbl_annee
WHERE
IsDate(
tbl_Jours.Numero &
"/"
&
tbl_Mois.Numero &
"/"
&
tbl_Annee.Numero)
ORDER
BY
tbl_annee.Numero, tbl_Mois.numero, tbl_Jours.numero;
Enfin, une autre requête nous permet d'obtenir le résultat souhaité
SELECT
NumEmploye, D
FROM
TblAbsence, R01_Calendrier
WHERE
D>=
DebutAbsence AND
D<=
FinAbsence
ORDER
BY
NumEmploye,D
NumEmploye | D |
---|---|
1 | 10/12/2005 |
1 | 11/12/2005 |
1 | 12/12/2005 |
1 | 13/12/2005 |
1 | 4/5/2006 |
1 | 5/5/2006 |
1 | 6/5/2006 |
1 | 7/5/2006 |
2 | 1/1/2006 |
2 | 25/12/2005 |
2 | 26/12/2005 |
2 | 27/12/2005 |
2 | 28/12/2005 |
2 | 29/12/2005 |
2 | 30/12/2005 |
2 | 31/12/2005 |
3 | 26/12/2005 |
3 | 27/12/2005 |
Un inconvénient majeur est que les produits cartésiens de la première requête ramènent un nombre important de données. Pour contourner cela, il serait possible de filtrer les années de la première requête de telle sorte à ne pas générer trop d'enregistrements inutiles.
Versions : 2000 et supérieures
Ce code permet de rechercher des occurences proches phonétiquement d'un critère. Pour cela, la méthode utilisée est celle de l'algorithme Soundex. Vous en trouverez les origines ici.
Je vous propose donc une traduction de cet algorithme en VBA :
Option
Compare Database
Option
Explicit
Public
Function
Prepare
(
Mot As
String
) As
String
'Cette fonction est inspirée de :
'http://sqlpro.developpez.com/cours/soundex/
'On enleve les espaces et convertit en majuscule
Dim
I As
Integer
Dim
Caractere
Mot =
Trim
$(
UCase
$(
Mot))
'On convertit les caractères accentués
For
I =
1
To
Len
(
Mot)
Caractere =
Mid
(
Mot, I, 1
)
Select
Case
Asc
(
Caractere)
Case
192
, 194
, 196
Prepare =
Prepare &
"A"
Case
199
Prepare =
Prepare &
"S"
Case
200
To
203
Prepare =
Prepare &
"E"
Case
204
, 206
, 207
Prepare =
Prepare &
"I"
Case
212
, 214
Prepare =
Prepare &
"O"
Case
217
, 219
, 220
Prepare =
Prepare &
"U"
Case
Else
If
Caractere <>
" "
&
Caractere <>
"-"
Then
_
Prepare =
Prepare &
Caractere
End
Select
Next
I
End
Function
Public
Function
Soundex
(
Mot As
String
) As
String
Dim
TLettre
(
) As
Variant
Dim
I As
Integer
Dim
Lettre As
String
Dim
Tmp As
String
'Tableau de correspondance
TLettre =
Array
(
""
, "1"
, "2"
, "3"
, ""
, "1"
, "2"
, ""
, ""
, "2"
, _
"2"
, "4"
, "5"
, "5"
, ""
, "1"
, "2"
, "6"
, "2"
, "3"
, _
""
, "1"
, ""
, "2"
, ""
, "2"
)
Mot =
Prepare
(
Mot)
'cas particulier de chaine vide
If
Len
(
Mot) =
0
Then
Soundex =
"0000"
Else
'cas particulier de chaine à 1 caractère
If
Len
(
Mot) =
1
Then
Soundex =
Mot &
"000"
Else
'Enleve le H (si présent) au début
If
Left
(
Mot, 1
) =
"H"
Then
Mot =
Mid
(
Mot, 2
)
Soundex =
Left
(
Mot, 1
)
For
I =
2
To
Len
(
Mot)
Lettre =
Mid
(
Mot, I, 1
)
'Transcode
If
Lettre >=
"A"
And
Lettre <=
"Z"
Then
Tmp =
TLettre
(
Asc
(
Lettre) -
Asc
(
"A"
))
'Evite les doublons
If
Tmp <>
Right
(
Soundex, 1
) Then
Soundex =
Soundex &
Tmp
End
If
Next
I
End
If
End
If
'on recupère les 4 premiers
If
Len
(
Soundex) >=
4
Then
Soundex =
Left
(
Soundex, 4
)
Else
'sinon on complete
For
I =
Len
(
Soundex) To
3
Soundex =
Soundex &
"0"
Next
I
End
If
End
Function
Ainsi, Soundex("Martin") et Soundex("Martan") renvoient la même valeur.
Vous trouverez un exemple d'utilisation complet dans des requêtes SQL en télechargeant le fichier Zip.
Version : 2000 et supérieures
Cet exemple traite plusieurs cas, tous basés sur la table suivante (Commande) :
Ref | Quantite | Mois |
---|---|---|
A1 | 5 | Juin |
A2 | 10 | Mai |
A2 | 3 | Juin |
A4 | 4 | Aout |
A4 | 4 | Juin |
A1 | 3 | Mai |
A1 | 3 | Mai |
Premier cas
On désire obtenir la somme des produits commandés par mois et par référence ainsi que la somme total des quantités par produit quelque soit le mois.
Le résultat attendu est donc :
Ref | Total | Aout | Juin | Mai |
---|---|---|---|---|
A1 | 11 | 0 | 5 | 6 |
A2 | 13 | 0 | 3 | 10 |
A4 | 8 | 4 | 4 | 0 |
Ce résultat est obtenu par :
TRANSFORM Nz(
Sum
(
Commande.quantite)
,"0"
)
AS
SommeDequantite
SELECT
Commande.Ref
, Nz(
Sum
(
Commande.quantite)
,"0"
)
AS
Total
FROM
Commande
GROUP
BY
Commande.Ref
PIVOT Commande.mois;
Deuxième cas
Si l'on souhaite obtenir au contraire la somme des quantités de tous les produits confondus commandés par mois, il est possible de retourner le tableau, c'est à dire faire figurer les produits en colonne et les mois en ligne.
Mois | Total de quantité | A1 | A2 | A4 |
---|---|---|---|---|
Aout | 4 | 0 | 0 | 4 |
Juin | 12 | 5 | 3 | 4 |
Mai | 6 | 6 | 10 | 0 |
Ce résultat est obtenu par :
TRANSFORM Nz(
Sum
(
Commande.quantite)
,"0"
)
AS
SommeDequantite
SELECT
Commande.mois, Nz(
Sum
(
Commande.quantite)
,"0"
)
AS
[Total de quantite]
FROM
Commande
GROUP
BY
Commande.mois
PIVOT Commande.Ref
;
Dernier cas
On souhaite obtenir les sommes en colonne et en ligne :
Ref | Total colonne | Aout | Juin | Mai |
---|---|---|---|---|
A1 | 8 | 0 | 5 | 3 |
A2 | 13 | 0 | 3 | 10 |
A4 | 8 | 4 | 4 | 0 |
TOTAL | 32 | 4 | 12 | 16 |
Dans ce cas, il nous faut passer par une requête temporaire nommée RTotal qui va calculer les sommes des colonnes :
SELECT
Commande.Ref
, Mois, Commande.quantite AS
Total,0
as
Ordre
FROM
Commande
UNION
(
SELECT
"TOTAL"
, Mois, sum
(
Quantite)
,1
as
Ordre FROM
Commande GROUP
BY
Mois,"TOTAL"
,1
)
;
Explications :
On utilise une requête Union pour rassembler les lignes de la table commande ainsi que les lignes Total. Le mot TOTAL sert à considerer le total comme une référence d'un produit. Le champ Ordre va nous servir à afficher la ligne TOTAL en bas de la liste. Cette requête affiche donc :
Ref | Mois | Total | Ordre |
---|---|---|---|
A1 | Juin | 5 | 0 |
A1 | Mai | 3 | 0 |
A2 | Juin | 3 | 0 |
A2 | Mai | 10 | 0 |
A4 | Aout | 4 | 0 |
A4 | Juin | 4 | 0 |
TOTAL | Aout | 4 | 1 |
TOTAL | Juin | 12 | 1 |
TOTAL | Mai | 16 | 1 |
Ensuite notre requête d'analyse croisée devient :
TRANSFORM Nz(
Sum
(
Rtotal.Total)
,"0"
)
AS
SommeDeTotal
SELECT
Rtotal.Ref
, Nz(
Sum
(
Rtotal.Total)
,"0"
)
AS
[Total colonne]
FROM
Rtotal
GROUP
BY
Rtotal.Ref
, ordre
ORDER
BY
Ordre
PIVOT Rtotal.Mois;
Il est important d'appliquer un tri sur le champ Ordre pour afficher la ligne TOTAL en bas.
Notons que :
ORDER
BY
Ordre DESC
Nous afficherait la ligne TOTAL en haut.
Version : Access 2000 et supérieures
Cet exemple d'analyse croisée permet de représenter un tableau à deux dimensions permettant d'afficher les résultats d'un championnat de tennis.
La table source est nommée tblResultat et possède les données suivantes :
joueur1 | joueur2 | setpourjoueur1 | setcontrejoueur1 |
---|---|---|---|
TOTO | LULU | 2 | 0 |
DEDE | JEAN | 2 | 1 |
LULU | DEDE | 2 | 0 |
JEAN | TOTO | 0 | 2 |
Avant d'appliquer une requête d'analyse croisée, nous avons besoin d'une première requête nommée RPrepa. Cette requête va notamment créer les couples JEAN - JEAN, etc ... afin de différencier les matchs qui ne peuvent pas être joués. De même la requête dédouble le jeu d'enregistrements en permuttant joueur1 et joueur2.
Le code SQL est le suivant :
SELECT
joueur1 as
J1,joueur2 AS
J2,[setpourjoueur1]
as
PP,[setcontrejoueur1]
as
PC
FROM
tblResultat
UNION
SELECT
joueur2 as
J1,joueur1 AS
J2,[setcontrejoueur1]
as
PP,[setpourjoueur1]
as
PC
FROM
tblResultat
UNION
SELECT
DISTINCT
joueur1 as
J1,joueur1 as
J2,"A"
as
PP,"A"
AS
PC FROM
tblResultat;
Ce qui renvoie :
J1 | J2 | PP | PC |
---|---|---|---|
DEDE | DEDE | A | A |
DEDE | JEAN | 2 | 1 |
DEDE | LULU | 0 | 2 |
JEAN | DEDE | 1 | 2 |
JEAN | JEAN | A | A |
JEAN | TOTO | 0 | 2 |
LULU | DEDE | 2 | 0 |
LULU | LULU | A | A |
LULU | TOTO | 0 | 2 |
TOTO | JEAN | 2 | 0 |
TOTO | LULU | 2 | 0 |
TOTO | TOTO | A | A |
Les matchs non jouables (JEAN-JEAN) possèdent donc un A à la place du résultat.
Enfin, la requête d'analyse croisée rassemble les données :
TRANSFORM IIf(
IsNull
(
First
(
PP))
,"A jouer"
,
IIF(
First
(
PP)=
"A"
,"Non Jouable"
,First
(
PP)
&
"-"
&
First
(
PC)))
AS
Resultat
SELECT
J1
FROM
RPrepa
GROUP
BY
J1
PIVOT J2;
Le résultat est alors :
J1 | DEDE | JEAN | LULU | TOTO |
---|---|---|---|---|
DEDE | Non Jouable | 2-1 | 0-2 | A jouer |
JEAN | 1-2 | Non Jouable | A jouer | 0-2 |
LULU | 2-0 | A jouer | Non Jouable | 0-2 |
TOTO | A jouer | 2-0 | 2-0 | Non Jouable |
Cette procédure crée une table cible à partir de la table source (ou requête source de type analyse croisée. Dans ce cas, remplacer TableDefs par QueryDefs). Elle fait le travail inverse d'une requête analyse croisée : les premières colonnes spécifiées par nbfix restent inchangées, la colonne (ipivot) suivante reprendra les intitulés des colonnes supérieures à nbfix la colonne suivante (dpivot) contient les valeurs transposées.
Il faut que tous les champs (sauf ceux spécifiés par nbfix) soient de même type !!!
Sub
anadecroise
(
Source As
String
, cible As
String
, nbfix As
Integer
)
Dim
base As
DAO.Database
Dim
champ As
DAO.Field
Dim
depart As
DAO.Recordset
Dim
departdef As
DAO.Fields
Dim
boucle As
Integer
Dim
typechamp As
Integer
Dim
incohérent As
Boolean
Dim
sql As
String
Dim
sqlb As
String
If
Source =
cible Then
Exit
Sub
Set
base =
CurrentDb
(
)
'ici la procédure s'arrête si la table source n'existe pas
Set
depart =
base.OpenRecordset
(
Source)
Set
departdef =
base.TableDefs
(
Source).Fields
'vérification du nombre de champ à transposer
If
nbfix +
2
>
departdef.Count
Then
MsgBox
"il doit y avoir au moins deux champs à transposer"
, vbCritical
, "ERREUR"
Exit
Sub
End
If
'vérification du type des champs de source
typechamp =
departdef
(
nbfix).Type
incohérent =
False
For
boucle =
nbfix +
1
To
departdef.Count
-
1
Set
champ =
departdef
(
boucle)
If
champ.Type
<>
typechamp Then
incohérent =
True
Next
boucle
If
incohérent Then
MsgBox
"tous les champs transposés doivent avoir le même type"
, vbCritical
, "ERREUR"
Exit
Sub
End
If
'création de la table cible et ajout de la première colonne à transposer
sql =
"SELECT "
For
boucle =
0
To
nbfix -
1
sql =
sql &
departdef
(
boucle).name
&
","
Next
boucle
sql =
sql &
"'"
&
departdef
(
nbfix).name
&
"' as ipivot"
sql =
sql &
", "
&
departdef
(
nbfix).name
&
_
" as dpivot into "
&
cible &
" from "
&
Source &
";"
Debug.Print
sql
DoCmd.RunSQL
(
sql)
sql =
"INSERT INTO "
&
cible &
"("
For
boucle =
0
To
nbfix -
1
sql =
sql &
departdef
(
boucle).name
&
","
Next
boucle
sql =
sql &
"ipivot,dpivot ) select "
For
boucle =
0
To
nbfix -
1
sql =
sql &
departdef
(
boucle).name
&
","
Next
boucle
DoCmd.SetWarnings
False
'ajout des données suivantes
For
boucle =
nbfix +
1
To
departdef.Count
-
1
sqlb =
sql &
"'"
&
departdef
(
boucle).name
&
"' as ipivot,"
_
&
departdef
(
boucle).name
&
" as dpivot from "
&
Source &
";"
DoCmd.RunSQL
(
sqlb)
Next
boucle
DoCmd.SetWarnings
True
End
Sub