Oui, on peut imprimer un PDF (ou d'autres fichiers) directement depuis Excel en VBA. Pratique pour lancer des impressions de factures, fiches de paie, documents RH… à partir d'une liste dans Excel ou d'un répertoire. Sans devoir les ouvrir!
Ci-dessous, vous trouverez 4 méthodes modernes pour le faire: la méthode Shell "classique", l’API Windows ShellExecute (32/64 bits), la ligne de commande (Adobe/Foxit) pour cibler une imprimante, et un fallback PowerShell. Chaque méthode a son intérêt selon le poste et le contexte.
Sommaire
- Méthode 1 – Shell (rapide, imprime via l'appli par défaut)
- Méthode 2 – WinAPI ShellExecute (compatible 32/64 bits)
- Méthode 3 – Ligne de commande (Adobe Reader / Foxit) pour cibler une imprimante
- Méthode 4 – PowerShell (fallback simple)
- Exemples utiles pour une impression efficace
- FAQ rapide
- Pour aller plus loin en VBA
Méthode 1 – Shell (rapide, imprime via l'appli par défaut)
La version "simple" que beaucoup utilisent: on passe par l'Explorateur Windows (objet Shell) pour exécuter le verbe Print
du fichier. Important : cette impression utilise l'imprimante par défaut du système et le viewer PDF par défaut (Edge, Reader, Foxit…). Ci-dessous, une version robuste (test d'existence du fichier, gestion de chemin/dossier).
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 |
' par Excel-Malin.com ( https://excel-malin.com ) Public Function ImprimerFichier(ByVal FichierAImprimer As Variant) As Boolean On Error GoTo fin Dim s As String, d As String, n As String Dim sh As Object, fo As Object, it As Object s = CStr(FichierAImprimer) If Len(Dir$(s)) = 0 Then Exit Function ' fichier introuvable d = Left$(s, InStrRev(s, "\") - 1) n = Mid$(s, InStrRev(s, "\") + 1) Set sh = CreateObject("Shell.Application") Set fo = sh.Namespace(d) If fo Is Nothing Then Exit Function Set it = fo.ParseName(n) If it Is Nothing Then Exit Function it.InvokeVerb "Print" ImprimerFichier = True fin: End Function ' Exemple d'utilisation Sub Exemple_Imprimer_Shell() Call ImprimerFichier("C:\Docs\MaFacture.pdf") End Sub |
Attention : si rien ne se passe, c'est souvent lié au viewer par défaut (ou à des politiques IT). Dans ce cas, testez la méthode 2 ou 3.
Méthode 2 – WinAPI ShellExecute (compatible 32/64 bits)
Ici, on appelle directement l'API Windows ShellExecute
avec l'opération "print"
. C'est propre et compatible avec Microsoft 365 32/64 bits.
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 |
#If VBA7 Then Private Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _ ByVal hwnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, _ ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long _ ) As LongPtr #Else Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _ ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, _ ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long _ ) As Long #End If Public Function ImprimerFichier_ShellExecute(ByVal FichierAImprimer As Variant) As Boolean Dim s As String #If VBA7 Then Dim ret As LongPtr #Else Dim ret As Long #End If s = CStr(FichierAImprimer) If Len(Dir$(s)) = 0 Then Exit Function Const SW_HIDE As Long = 0 ret = ShellExecute(0, "print", s, vbNullString, vbNullString, SW_HIDE) ImprimerFichier_ShellExecute = (ret > 32) ' >32 = succès End Function ' Exemple d'utilisation Sub Exemple_Imprimer_ShellExecute() Call ImprimerFichier_ShellExecute("C:\Docs\MaFacture.pdf") End Sub |
Comme la méthode 1, cela passe par l'imprimante par défaut et le viewer par défaut.
Méthode 3 – Ligne de commande (Adobe Reader / Foxit) pour cibler une imprimante
Besoin de choisir une imprimante précise sans toucher à l'imprimante par défaut ? On peut lancer le viewer PDF avec des arguments en ligne de commande. Les paramètres varient selon les versions, mais les schémas ci-dessous fonctionnent souvent.
1 2 3 4 5 6 7 8 9 10 |
Public Function ImprimerPDF_Adobe(ByVal Pdf As Variant, _ ByVal NomImprimante As String, _ ByVal CheminAcrobat As String) As Boolean ' CheminAcrobat = chemin complet vers AcroRd32.exe ou AcroRd64.exe If Len(Dir$(CStr(Pdf))) = 0 Then Exit Function Dim cmd As String cmd = """" & CheminAcrobat & """ /t """ & CStr(Pdf) & """ """ & NomImprimante & """" Shell cmd, vbHide ImprimerPDF_Adobe = True End Function |
1 2 3 4 5 6 7 8 9 10 |
Public Function ImprimerPDF_Foxit(ByVal Pdf As Variant, _ ByVal NomImprimante As String, _ ByVal CheminFoxit As String) As Boolean ' CheminFoxit = chemin complet vers FoxitReader.exe / FoxitPDFReader.exe If Len(Dir$(CStr(Pdf))) = 0 Then Exit Function Dim cmd As String cmd = """" & CheminFoxit & """ -t """ & CStr(Pdf) & """ """ & NomImprimante & """" Shell cmd, vbHide ImprimerPDF_Foxit = True End Function |
À noter : les commutateurs peuvent changer selon la version du viewer. Testez localement et, si besoin, adaptez (certains Adobe demandent aussi le pilote/port).
Méthode 4 – PowerShell (fallback simple)
PowerShell sait aussi lancer l'action Print
du fichier. Nous pouvons donc l’appeler depuis VBA. Cela reste dépendant du viewer par défaut et de l'imprimante par défaut.
1 2 3 4 5 6 7 8 9 10 |
Public Function ImprimerFichier_PowerShell(ByVal FichierAImprimer As Variant) As Boolean Dim s As String, cmd As String s = CStr(FichierAImprimer) If Len(Dir$(s)) = 0 Then Exit Function cmd = "powershell -NoProfile -Command " & _ """Start-Process -FilePath '" & Replace(s, """", "\""") & "' -Verb Print""" CreateObject("WScript.Shell").Run cmd, 0, False ImprimerFichier_PowerShell = True End Function |
Exemples utiles pour une impression efficace
Imprimer tous les PDF d'un dossier
1 2 3 4 5 6 7 8 9 10 11 12 |
Sub ImprimerTousLesPDF(ByVal Dossier As String) Dim f As String If Right$(Dossier, 1) = "\" Then f = Dir$(Dossier & "*.pdf") Else f = Dir$(Dossier & "\*.pdf") End If Do While Len(f) > 0 Call ImprimerFichier(Dossier & IIf(Right$(Dossier, 1) = "\", "", "\") & f) f = Dir$ Loop End Sub |
(Option) Basculer temporairement l'imprimante par défaut
Si vous n'utilisez pas la méthode 3, vous pouvez basculer l'imprimante par défaut avant d'imprimer, puis la remettre. À éviter, de préférence, sur des postes gérés/partagés.
1 2 3 |
Public Sub DefinirImprimanteParDefaut(ByVal NomImprimante As String) CreateObject("WScript.Network").SetDefaultPrinter NomImprimante End Sub |
FAQ rapide
Pour aller plus loin en VBA
Quelques articles supplémentaires pour plus d'efficacité et d'efficience avec VBA:
- Liste de toutes les fonctions VBA – toutes les fonctions au même endroit
- Manipulation des fichiers en VBA
- Gestion des dates et du temps en VBA
- (Dé)compresser des fichiers et dossiers en VBA
- VBA : envoyer un email à partir d’Excel
20 commentaires sur “Imprimer un PDF en VBA depuis Excel (4 méthodes modernes)”
Bonjour
Est-ce que ce code fonctionne aussi sur la version Access 2016 ?
Je n'ai pas de message d'erreur mais l'impression ne se fait pas, ni ne va dans le spooler.
Merci pour votre site.
Bonjour Paul,
comme ça, je ne sais ni affirmer, ni infirmer cette info.
Quand j'ai un peu de temps, je vais le tester et je vous tiens au courant.
Cordialement, Martin
Merci, mais n'y perdez pas trop de temps :). Si je trouve une solution, je l'ajouterai ici.
Bonjour,
j'ai repris votre code en le modifiant légèrement, mais malheureusement, ce la ne fonctionne pas …
Nouveau code :
Sub ImpressionDeFichier()
'par Excel-Malin.com ( https://excel-malin.com )
Dim FichierAImprimer As String
Destination = ThisWorkbook.Path & "\Rapports_PDF\"
FichierAImprimer = Destination & "test.pdf" '<– chemin complet du fichier à imprimer
CreateObject("Shell.Application").Namespace(0).ParseName(FichierAImprimer).InvokeVerb ("Print")
End Sub
En effet, j'obtiens le message suivant : "Erreur d'execution '91' : Variable objet ou variable de bloc With non definie "
Y a t il une cas à cocher dans le VBE / outils / reference ?
Je suis sous office 365 / Windows 07 et mon imprimante par défaut est PDF Creator (car je veux créer un rapport avec plusieurs feuilles de mon fichier excel)
Merci d'avance pour votre aide !
Bonjour Eric,
2 remarques:
1) ce message d'erreur correspond au cas où le fichier mentionné n'existe pas. Vous pouvez le vérifier avec ce code:
"VBA: Vérifier si fichier existe"
2) Je viens de tester avec une imprimante virtuelle (CutePDFWriter) avec un fichier existant et le fichier "s'imprime" comme il faut. Donc je pense que le fait qu'il s'agisse d'une imprimante virtuelle ne pose pas de problème…
J'espère que cela vous aidera à résoudre votre problème.
Cordialement Martin
En late binding comme ici les variables passées à Shell doivent être impérativement de type Variant
d'où l'erreur à cause de la variable String utilisée.
Par contre en early binding – en activant la référence – aucun souci …
Merci pour le tuyau Marc!
Cordialement, Martin
Bonjour,
est-il possible de modifier cette commande que l'impression soit faite sans qu'il ouvre le fichier ?
merci
Bonjour !
Est-il possible de combiner ceci avec une impression d'une feuille excel pour créer un seul et même fichier ? J'ai un document avec plusieurs fiches produits auxquelles je dois rattacher des fiches techniques en pdf est-ce réalisable. Merci !
Bonjour,
Esct-ce qu'il y a une référence particulière à activer ? Parce que pour ma part, rien de se passe. Que j'en fasse une procédure ou une fonction, il ne se passe rien. Je suis sous une version 2010.
Merci.
Précision : Je viens de tester l'impression de fichier .png et .docx et cela fonctionne. Le problème est pour les fichiers .pdf
C'est très étrange. Faut-t-il un lecteur PDF particulier ? J'utilise Sumatra PDF portable. J'ai essayé de mettre Edge en lecteur par défaut, mais cela ne s'imprime toujours pas.
Bonjour Seb,
normalement, il ne faut pas activer de référence particulière.
Il est par contre possible que votre lecteur PDF ne soit pas compatible avec les fonctions Microsoft. (regardez ici: https://docs.microsoft.com/en-us/windows/win32/shell/folderitem-invokeverb)
Moi j'utilise Adobe Reader DC (qui est je pense pré-installé dans les dernières versions de Windows) et tout se passe sans problème.
Bien à toi, Martin
Bonjour, j'ai une erreur d’exécution 91 sur la ligne principale de la fonction. Mes chemins d'acces sont bons et le pdf est bien présent. J'ai bien acrobat reader dc sur mon ordi.
Bonjour,
je viens d'adapter les fonctions en remplaçant le type de variable de
String
àVariant
comme suggéré par Marc L dans un des commentaires.Cela devrait résoudre le problème. Vous pouvez alors réessayer.
Cordialement, Martin
Bonjour,
J'ai essayé d'adapter la fonction pour qu'avec une boucle, cela puisse imprimer tous les fichiers pdf dans un dossier. Mais j'avoue que mon do while ne marche pas du tout. Pourriez vous avoir la gentillesse de m'expliquer comment vous auriez fait votre boucle pour imprimer toutes les factures dans votre screen avec la fonction que vous avez créé.
Bonjour,
Merci pour vos informations.
Pour ma part, je me demande s'il est obligatoire d'avoir:
==> "La seule chose dont vous avez besoin est le chemin complet (dossier & nom du fichier) du fichier à imprimer."
Est-il possible de faire plusieurs macro de ce type:
Bouton 1 : Imprimer le PDF actif (à l'écran) en format A4 sur l'imprimante 1
Bouton 2 : Imprimer le PDF actif (à l'écran) en format A1 sur l'imprimante 2
Cette demande est dû à impression de nombreux PDF avec des formats différents.
Merci bien
Bonjour,
je voulais savoir s'il était possible de modifier ce code pour que l'impression se déroule sans que le fichier ne soit ouvert ?
merci
Bonjour, les imprimantes de mon réseau requiert un mot de passe, est t'il possible de le passer en paramètre dans le code ?
j'ai utilisé votre fonction d'impression de fichier Pdf, qui fonctionne bien
cependant le problème que je rencontre est de pouvoir utiliser différentes imprimantes en fonction du type de document à imprimer
j'ai utilisé SetDefaultPrinter qui m'a permis de sélecter l'imprimante pour la première impression mais le problème subsiste car acrobat reste ouvert et garde l'imprimante initiale, il faudrait "tuer" l'application pour la redémarrer mais je n'ai pas trouvé de méthode
merci si vous avez une solution
Bonjour,
tout d'abord merci, cela fonctionne tres bien.
Dans mon cas je souhaiterais imprimer que la premiere page. Est-ce que c'est possible avec le code que vous proposez ?
J'ai bien entendu cherche sur internet mais toutes les autres solutions sont trop lourde pour juste imprimer que la premiere page.
Merci