Le scénario

Je dispose d'une table tbl Clients dont voici la structure :

Quelques données dans la table :

Le client n°2 est associé à plusieurs pièces jointes, stockées dans le champ Documents (2 étant la valeur de la clef primaire [Numéro Client] qui identifie le client).

Premier test

  • D'une part, la liste des clients peut être obtenue par un Recordset.
  • D'autre part, il y a une relation de "1 à plusieurs" entre le client et ses pièces jointes ("1 client peut avoir plusieurs pièces jointes), Access gère donc la liste des pièces jointes comme une autre table. Concrètement, si [tbl Clients].Documents est le champ de type Pièce jointe, dans la table tbl Clients, la valeur de ce champ - [tbl Clients].Documents.Value - est un nouveau Recordset qui fournit la liste des pièces jointes.
Voici un petit test pour le vérifier :
Sub TestPJ()
  Dim rst1 As DAO.Recordset
  Dim rst2 As DAO.Recordset
  Dim strSQL As String
 
  ' Se positionner sur l'enregistrement souhaité
  strSQL = "SELECT * FROM [tbl Clients] WHERE [Numéro Client] = 2;"
  Set rst1 = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot)
 
  ' Obtenir le "sous-recordset" des pièces jointes
  Set rst2 = rst1("Documents").Value
   
  ' Lister les pièces jointes
  While Not rst2.EOF
    Debug.Print rst2("Filename")
    rst2.MoveNext
  Wend
 
  ' On ferme les 2 Recordsets
  rst2.Close
  Set rst2 = Nothing
  rst1.Close
  Set rst1 = Nothing
End Sub
  • rst1 est un Recordset qui nous permet de nous positionner sur le client numéro 2 (voir la chaîne SQL qui sert à ouvrir le Recordset).
  • Une fois positionné sur le bon client, on ouvre un 2ème Recordset, obtenu par la valeur (Value) du champ Documents.
  • Il ne reste plus qu'à parcourir le 2ème Recordset en boucle, pour obtenir le nom (Filename) de chaque pièce jointe.
Pour tester ce bout de code, ouvrez la fenêtre de debug (CTRL + G), et tapez-y :
TestPJ et appuyez sur la touche [Entrée].
Vous pouvez aussi placer votre curseur dans le bloc de code VBA, et cliquer sur l'icône Exécuter Sub/UserForm.

Vous obtiendrez par exemple :

Un encore meilleur code :-)

On peut maintenant généraliser le code précédent, pour pouvoir lister les pièces jointes de n'importe quelle table et de n'importe quel champ. Ce qui donne :

' ---
' LISTE DES PIECES JOINTES ACCESS 2007
' ---
'
Public Sub PJListe( _
  ByVal strTable As String, _
  ByVal strChamp As String, _
  ByVal strWhere As String)
 
  Dim rst1 As DAO.Recordset
  Dim rst2 As DAO.Recordset
  Dim strSQL As String
 
  ' Chaîne SQL pour l'extraction de l'enregistrement
  strSQL = "SELECT [" & strChamp & "]" _
    & " FROM [" & strTable & "]" _
    & " WHERE " & strWhere
   
  ' Ouverture de l'enregistrement
  Set rst1 = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot)
 
  ' Ouverture du "sous-recordset"
  If rst1.RecordCount > 0 Then
    Set rst2 = rst1(strChamp).Value
   
    ' Liste des pièces jointes
    While Not rst2.EOF
      Debug.Print rst2("Filename")
      rst2.MoveNext
    Wend
   
    ' On ferme le Recordset des pièces jointes
    rst2.Close
    Set rst2 = Nothing
  End If
 
  ' On ferme le Recordset principal
  rst1.Close
  Set rst1 = Nothing
End Sub

Tester le code

La procédure VBA doit recevoir 3 paramètres :

  • Le nom de la table concernée.
  • le nom du champ qui contient les pièces jointes (un champ de type Pièce jointe, donc).
  • une clause SQL WHERE valide, qui va permettre d'extraire un enregistrement précis (et unique). Sans doute un filtre sur la clef primaire de la table...
Par exemple :