Création d'un code VBA pour extraire plusieurs fichiers PDF Excel
Bonjour,
Je souhaiterai extraire et enregistrer un fichier PDF pour chaque client (colonne B), le nom du fichier serait celui du numéro du client (toujours en colonne B).
Je suis parti sur le code ci-dessous mais il sort en erreur et je ne comprends pas pourquoi.
Sub ExporterPDF_ParClient_Corrigé_Final()
' Déclaration des variables
Dim wsData As Worksheet
Dim rngData As Range
Dim colClient As Range
Dim cell As Range
Dim clientUnique As Object
Dim clientName As Variant
Dim pdfPath As String
Dim fileName As String
Dim lastRow As Long
' --- PARAMÈTRES À CONFIGURER ---
Const SHEET_NAME As String = "Feuil1"
' LIGNE DES EN-TÊTES : VÉRIFIEZ CE NUMÉRO DANS VOTRE FEUILLE EXCEL !
Const HEADER_ROW As Long = 4 ' Ex: Si les en-têtes sont en ligne 4, mettez 4.
' Colonne contenant le nom du client (Colonne C = 3)
Const CLIENT_COLUMN As Long = 3
' Chemin où les fichiers PDF seront enregistrés (le dossier doit exister)
pdfPath = "C:\Users\VotreNomUtilisateur\Desktop\PDF_Clients\" ' <--- À CHANGER
' --------------------------------
Set clientUnique = CreateObject("Scripting.Dictionary")
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error GoTo ErrorHandler
Set wsData = ThisWorkbook.Sheets(SHEET_NAME)
' --- PRÉPARATION : Nettoyage et Détermination de la Plage ---
' Retirer tous les filtres existants
If wsData.AutoFilterMode Then
wsData.AutoFilter.ShowAllData
End If
' Déterminer la dernière ligne de données (colonne A ou B, peu importe, juste pour la fin de la plage)
lastRow = wsData.Cells(wsData.Rows.Count, "A").End(xlUp).Row
If lastRow < HEADER_ROW Then
MsgBox "Aucune donnée trouvée après la ligne d'en-tête (" & HEADER_ROW & ").", vbExclamation
GoTo CleanUp
End If
' Plage rngData pour le filtre, DOIT inclure la ligne d'en-tête
Set rngData = wsData.Range(wsData.Cells(HEADER_ROW, "A"), wsData.Cells(lastRow, wsData.UsedRange.Columns.Count))
' Plage colClient pour la collecte, SANS la ligne d'en-tête
Set colClient = wsData.Range(wsData.Cells(HEADER_ROW + 1, CLIENT_COLUMN), wsData.Cells(lastRow, CLIENT_COLUMN))
' 1. COLLECTER LES NOMS DE CLIENTS UNIQUES
For Each cell In colClient
If Trim(cell.Value) <> "" Then
' Utiliser UCase pour garantir l'unicité des noms de clients (ignore la casse)
clientUnique(UCase(Trim(cell.Value))) = Trim(cell.Value)
End If
Next cell
' Créer le dossier s'il n'existe pas
If Dir(pdfPath, vbDirectory) = "" Then
MkDir pdfPath
End If
' 2. BOUCLER SUR CHAQUE CLIENT, FILTRER ET EXPORTER
' Appliquer le filtre initial sur la plage de données
rngData.AutoFilter
For Each clientName In clientUnique.Keys
' Filtrer la colonne (Field:=3 car colonne C est la 3ème colonne de la plage A:...)
' Le critère est la valeur stockée dans le dictionnaire (pas la clé en majuscules)
rngData.AutoFilter Field:=CLIENT_COLUMN, Criteria1:=clientUnique(clientName)
' --- Préparation du nom de fichier ---
' Retirer les caractères illégaux pour un nom de fichier
fileName = clientUnique(clientName)
fileName = Replace(fileName, "/", "_")
fileName = Replace(fileName, "\", "_")
fileName = Replace(fileName, ":", "_")
fileName = Replace(fileName, "*", "_")
fileName = Replace(fileName, "?", "_")
fileName = Replace(fileName, Chr(34), "_")
fileName = Replace(fileName, "<", "_")
fileName = Replace(fileName, ">", "_")
fileName = Replace(fileName, "|", "_")
' S'assurer que le nom n'est pas trop long
If Len(fileName) > 150 Then
fileName = Left(fileName, 150)
End If
filePath = pdfPath & fileName & ".pdf"
' --- Exportation PDF ---
' Exporter SEULEMENT la zone de la feuille qui contient des données
' y compris les en-têtes et les données filtrées
wsData.UsedRange.ExportAsFixedFormat Type:=xlTypePDF, _
Filename:=filePath, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
Next clientName
CleanUp:
' 4. NETTOYAGE ET FIN
' Retirer le filtre final
If wsData.AutoFilterMode Then
wsData.AutoFilter.ShowAllData
End If
' Rétablir les paramètres par défaut
Application.ScreenUpdating = True
Application.DisplayAlerts = True
If Not Err.Number Then
MsgBox "L'extraction PDF par client est terminée !" & vbCrLf & "Les fichiers se trouvent dans : " & pdfPath, vbInformation, "Terminé"
End If
Exit Sub
ErrorHandler:
' Gestionnaire d'erreurs
MsgBox "Une erreur est survenue (" & Err.Number & ": " & Err.Description & ") au moment de traiter le client : " & clientUnique(clientName) & vbCrLf & _
"Veuillez vérifier les valeurs de HEADER_ROW et CLIENT_COLUMN.", vbCritical, "Erreur VBA"
Resume CleanUp ' Continue le nettoyage avant de sortir de la sub
End SubLe fichier étant trop lourd pour être partagé je le mets sur Sheets Test - Google Sheets
Merci d'avance
bonjour Breizhoneig,
ne pouvez-vous pas partagé le fichier avec uniquement la feuille "feuil1" et une vingtaine de lignes (anonymisées)?
Vos données, c'est un tableau structuré ?
Bonjour,
Il s'agit d'un TCD, entre temps j'ai fait d'autres tests, pour en arriver à ce code
Option Explicit
Sub Imprimer_PDF_Decoupage_Final()
' Déclaration des variables
Dim ws As Worksheet
Dim dLig As Long
Dim startLig As Long
Dim endLig As Long
Dim currentLig As Long
Dim sPath As String ' Chemin de sauvegarde choisi
Dim sCli As String
Dim sPrevCli As String
Dim fldrPicker As FileDialog ' Objet pour sélectionner le dossier
' --- PARAMÈTRES CRUCIAUX ---
' Colonne où se trouve le nom du client (Colonne A = 1)
Const CLIENT_COL As String = "B"
' Ligne à partir de laquelle commence le premier bloc de données client
' VÉRIFIEZ CE NUMÉRO DANS VOTRE FEUILLE "Feuil1"
Const FIRST_DATA_ROW As Long = 11 ' <--- À VÉRIFIER
' La dernière colonne que vous souhaitez imprimer (A à AG)
Const LAST_PRINT_COL As String = "AG"
' ----------------------------
Set ws = ThisWorkbook.Sheets("Feuil1")
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error GoTo ErrorHandler
' 1. SÉLECTION DU DOSSIER PAR L'UTILISATEUR
Set fldrPicker = Application.FileDialog(msoFileDialogFolderPicker)
With fldrPicker
.Title = "Sélectionnez le dossier où enregistrer les fichiers PDF"
.AllowMultiSelect = False
If .Show = True Then
sPath = .SelectedItems(1) & Application.PathSeparator
Else
MsgBox "Opération annulée par l'utilisateur. Aucun fichier PDF ne sera créé.", vbExclamation
GoTo CleanUp ' Sortir si l'utilisateur annule
End If
End With
' 2. LOGIQUE DE DÉCOUPAGE ET D'EXPORTATION
With ws
' Détermination de la dernière ligne
dLig = .Range(CLIENT_COL & .Rows.Count).End(xlUp).Row
' Initialisation
sPrevCli = "DEPART_INIT"
startLig = FIRST_DATA_ROW
' Boucle principale : parcourt toutes les lignes de données
For currentLig = FIRST_DATA_ROW To dLig + 1
' Condition : Si la ligne actuelle marque le début d'un nouveau bloc OU est la fin du tableau
If (Trim(.Range(CLIENT_COL & currentLig).Value) <> "" And .Range(CLIENT_COL & currentLig).Value <> sPrevCli) Or currentLig = dLig + 1 Then
' Traitement du BLOC PRÉCÉDENT
If startLig < currentLig Then
endLig = currentLig - 1
' Récupérer le nom du client du bloc précédent
sCli = .Range(CLIENT_COL & endLig).End(xlUp).Value
If Trim(sCli) <> "" And sCli <> "Etablissement" Then
' --- A) DÉFINIR LA ZONE D'IMPRESSION ---
.PageSetup.PrintArea = "$" & CLIENT_COL & "$" & startLig & ":$" & LAST_PRINT_COL & "$" & endLig
' --- B) EXPORTATION PDF ---
' Nettoyer le nom du client pour le nom du fichier
Dim cleanCli As String
cleanCli = Replace(sCli, "/", "_")
cleanCli = Replace(cleanCli, "\", "_")
cleanCli = Replace(cleanCli, ":", "_")
cleanCli = Replace(cleanCli, "*", "_")
cleanCli = Replace(cleanCli, "?", "_")
cleanCli = Replace(cleanCli, Chr(34), "_")
cleanCli = Replace(cleanCli, "<", "_")
cleanCli = Replace(cleanCli, ">", "_")
cleanCli = Replace(cleanCli, "|", "_")
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, _
Filename:=sPath & cleanCli & ".pdf", _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
End If
End If
' Préparer pour le bloc suivant
startLig = currentLig
sPrevCli = Trim(.Range(CLIENT_COL & currentLig).Value)
End If
Next currentLig
' Nettoyage final de la zone d'impression Excel
.PageSetup.PrintArea = ""
End With
CleanUp:
' Rétablir les paramètres
Application.ScreenUpdating = True
Application.DisplayAlerts = True
If Not Err.Number And sPath <> "" Then
MsgBox "L'extraction PDF par client est terminée !" & vbCrLf & "Les fichiers ont été enregistrés dans : " & sPath, vbInformation
End If
Exit Sub
ErrorHandler:
' Gestionnaire d'erreurs
MsgBox "Une erreur est survenue (" & Err.Number & ": " & Err.Description & ") à la ligne " & currentLig & "." & vbCrLf & _
"Veuillez vérifier la valeur de FIRST_DATA_ROW.", vbCritical, "Erreur VBA Découpage"
Resume CleanUp
End SubCependant, il ne me sort que les sous totaux :/
re,
c''est un TCD, alors copiez ce TCD (ou les 20 premières lignes) et collez-le "special valeurs" dans un nouveau fichier.
C'est quou exactement l'erreur de cette macro ?
Un TCD est même plus facile à gérer ...
Le soucis de ce code c'est que le premier client à être extrait est bon, mais le deuxième se cumule avec le premier et ainsi de suite
re,
j'ai créé mes propres données + TCD dans la feuille "Blad1" et puis la macro "Imprimer_PDF_Decoupage_Final" crée des pdfs, ce n'est pas encore dans des sous-dossiers.
Sub Imprimer_PDF_Decoupage_Final()
Dim TCD, i, j, sName
Application.ScreenUpdating = False
Set TCD = Sheets("blad1").PivotTables(1) 'votre TCD
With TCD
.PivotCache.MissingItemsLimit = xlMissingItemsNone 'supprimer les items qui ne sont plus là
.ClearAllFilters 'clear existing filters
With .PivotFields("Client") 'pour la colonne "Client"
For i = 1 To .PivotItems.Count 'boucler tous les clients
sName = ThisWorkbook.Path & "\" & .PivotItems(i).Name & ".pdf" 'nom du pdf
Application.StatusBar = sName: DoEvents 'montrer ce nom dans le "statusbar"
.PivotItems(i).Visible = True 'certainement commencer avec montrer cet item
For j = 1 To .PivotItems.Count 'puis boucler tous les items
.PivotItems(j).Visible = (i = j) 'cacher tous sauf le "i"
Next
TCD.TableRange1.ExportAsFixedFormat Type:=xlTypePDF, Filename:=sName 'créer le pdf
Next
End With
.ClearAllFilters 'clear existing filters
End With
Application.StatusBar = False
End SubBonjour,
Je m'insère dans ce fil suivi par BsAlv.
Sans code VBA et à tester sur vos fichiers --> https://forum.excel-pratique.com/astuces/convertir-un-tableau-d-un-fichier-pdf-vers-un-fichier-excel...
Crdlt
@Dan, c'était Excel vers PDF et pas PDF vers Excel,
@BsAlv :
Juste !
J'aurais dû lire les codes avant...
merci