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
Sommaire→Requêtes- 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 FunctionPuis 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 FunctionEt 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 FunctionAinsi, 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 SubVersions : 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 FunctionAinsi, 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 DESCNous 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


