Publipostage : type défini par l'utilisateur non défini
Bonjour à tous,
j'ai un petit souci avec une macro pour du publipostage d'annexe de bon de commande.
le code provient du site et fonctionne très bien sur un de mes fichiers.
J'ai réalisé un nouveau fichier (car nouveau contrat donc nouveaux prestataire) en tout point identique au précédent, à la seule exception prés que j'ai utilisé la fonctionnalité des tableaux structurés pour ma base de publiposte (onglet "BASE" de la source de données).
Lorsque je lance la macro j'ai un message "type défini par l'utilisateur non défini" à la ligne
Dim WordDoc As Word.Document
Dim appWord As Word.Application
J'ai été vérifié dans word et Microsoft Word 16.0 Object Library ainsi Microsoft Office 16.0 Object Library sont bien cochés (idem dans Excel).
A la lecture du message de @BrunoM45 (Type d'utilisateur non défini (excel-pratique.com) je me suis dit que je devrais corriger et remplacer
Dim WordDoc As Word.Document
Dim appWord As Word.Application
par
Dim DocWord As Object
Dim WordApp As Object
mais en faisant ça, la macro coince au moment de l'édition pdf (pour autant elle réalise la fusion) et sort un message d'erreur "appel de procédure incorrect" à l'exécution de cette ligne :
.ExportAsFixedFormat OutputFileName:=(nom_fichier), _
ExportFormat:=wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:= _
wdExportOptimizeForPrint, Range:=wdExportAllDocument, From:=1, To:=1, _
Item:=wdExportDocumentContent, IncludeDocProps:=False, KeepIRM:=False, _
CreateBookmarks:=wdExportCreateHeadingBookmarks, DocStructureTags:=True, _
BitmapMissingFonts:=False, UseISO19005_1:=False
Avez vous une idée du pourquoi cela fonctionne avec un fichier et pas l'autre ? (désolé dans le code ci-dessous, il s'agit de chemin réseau)
Sub publipostage()
Dim WB1 As Workbook, WB2 As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet
Dim MaPlage As Range
Set WB1 = ActiveWorkbook
Set ws1 = WB1.Sheets("BASE")
Set WB2 = Workbooks.Open("\\Filer3\placido_cde_pub$\05_Fournitures\09_Outillage_materiaux\Outillage_matiere_oeuvre_2023\BASE_NE_PAS_TOUCHER.xlsx")
Set ws2 = WB2.Sheets("BASE")
With WB1.Worksheets("BASE")
Set MaPlage = .Range("A1:AJ60")
End With
MaPlage.Copy
WB2.Worksheets("BASE").Range("A2").PasteSpecial Paste:=xlValues
Application.CutCopyMode = False
WB2.Save
WB2.Close False 'ferme
'--------------------------------------------------------------------------------
'Nécessite d'activer la référence "Microsoft Word xx.x Object Library"
'--------------------------------------------------------------------------------
Dim WordDoc As Word.Document
Dim appWord As Word.Application
Dim NomBase, fic_doc, cheminW, cheminZ, fichier_source, DocName As String
Dim nom_fichier, Nomsourcebase, message_boite As String
Dim fin, i As Integer
ChDir ActiveWorkbook.Path
fic_doc = ("\\Filer3\placido_cde_pub$\05_Fournitures\09_Outillage_materiaux\Outillage_matiere_oeuvre_2023\modele commande1.dotm")
Application.ScreenUpdating = False
'recupération du chemin ou se trouve le doc W pour enregistrement des PDF au meme endroit
fichier_source = ActiveWorkbook.Name
cheminW = Dir(fic_doc)
cheminW = Replace(fic_doc, cheminW, "")
cheminZ = ("\\Filer3\placido_cde_pub$\05_Fournitures\09_Outillage_materiaux\Outillage_matiere_oeuvre_2023\")
NomBase = cheminW & "BASE_NE_PAS_TOUCHER.xlsx"
Application.DisplayAlerts = False
Set appWord = New Word.Application
appWord.Visible = True
'Ouverture du document principal Word
Set DocWord = appWord.Documents.Open(fic_doc)
With DocWord.MailMerge
'Ouvre la base de données le fichier excel doit avoir sa feuille nommée 'feuil1'
.OpenDataSource Name:=NomBase, Connection:="Driver={Microsoft Excel Driver (*.xlsx)};" & "DBQ=" & NomBase & "; ReadOnly=True;", SQLStatement:="SELECT * FROM [BASE$]"
fin = .DataSource.RecordCount
End With
Last_Row1 = ws1.Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To Last_Row1
'fonctionnalité de publipostage pour le document spécifié
With DocWord.MailMerge
'Spécifie la fusion vers un nouveau doc
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
'Prend en compte uniquement l'enregistrement i
With .DataSource
.FirstRecord = i
.LastRecord = i
End With
'Exécute l'opération de publipostage
.Execute Pause:=False
'recupère le nom et prenom de la personne 'colonnes 1 et 2 du fichier source excel
.DataSource.ActiveRecord = i
DocName = .DataSource.DataFields(35).Value
End With
nom_fichier = cheminZ & DocName & ".pdf"
With appWord.ActiveDocument
'export pdf
.ExportAsFixedFormat OutputFileName:=(nom_fichier), _
ExportFormat:=wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:= _
wdExportOptimizeForPrint, Range:=wdExportAllDocument, From:=1, To:=1, _
Item:=wdExportDocumentContent, IncludeDocProps:=False, KeepIRM:=False, _
CreateBookmarks:=wdExportCreateHeadingBookmarks, DocStructureTags:=True, _
BitmapMissingFonts:=False, UseISO19005_1:=False
'fermeture du fichier W sans enregistrement
.Close False
End With
Next i
Application.ScreenUpdating = True
'Fermeture du document Word
DocWord.Close False
appWord.Quit
End Sub
merci pour votre aide.
Bonjour Dav86
Vous n'avez malheureusement pas bien lu le fil
Il est indiqué ici https://forum.excel-pratique.com/s/goto/1052195 ce qu'il faut faire
a savoir ajouter la référence de l'application concernée
A+
Bonjour BrunoM45 et merci pour la réponse.
J'ai lu les éléments entre early binding et late binding. je comprends la logique mais j'avoue que la syntaxe m'échappe.
ceci étant, la macro fonctionne (j'avais tout bonnement fait une erreur dans l'adresse du document de fusion
Du coup, j'ai quand même un souci. L'opération de publipostage se fait correctement, idem pour le nommage du fichier mais j'ai une erreur à l'instruction
et cela génère le message d'erreur suivant :
cela me semble normal car j'ai 3 enregistrements et 3 fichiers pdf. Je suppose que la macro tombe sur une ligne vide mais là où je ne comprends pas c'est que l'instruction
Last_Row1 = ws1.Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To Last_Row1
a bien pour objectif de trouver la dernière ligne remplie. Je pensais mettre une instruction du type "on error resume next" mais quand je fais ça, seul le premier fichier est publié correctement, les deux autres ont des champs vides.
Je remets la totalité du code pour être exhaustif.
Sub publi_david()
Dim WB1 As Workbook, WB2 As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet
Dim MaPlage As Range
Set WB1 = ActiveWorkbook
Set ws1 = WB1.Sheets("BASE")
Set WB2 = Workbooks.Open("\\Filer3\placido_cde_pub$\05_Fournitures\09_Outillage_materiaux\Outillage_matiere_oeuvre_2023\BASE_NE_PAS_TOUCHER.xlsx")
Set ws2 = WB2.Sheets("PUBLIPOSTAGE")
With WB1.Worksheets("BASE")
Set MaPlage = .Range("A2:AH60")
End With
MaPlage.Copy
WB2.Worksheets("PUBLIPOSTAGE").Range("A2").PasteSpecial Paste:=xlValues
Application.CutCopyMode = False
WB2.Save
WB2.Close False 'ferme
'--------------------------------------------------------------------------------
'Nécessite d'activer la référence "Microsoft Word xx.x Object Library"
'--------------------------------------------------------------------------------
Dim docWord As Word.Document
Dim appWord As Word.Application
Dim NomBase, fic_doc, cheminW, cheminZ, fichier_source, DocName As String
Dim nom_fichier, Nomsourcebase, message_boite As String
Dim fin, i As Integer
ChDir ActiveWorkbook.Path
fic_doc = ("\\Filer3\placido_cde_pub$\05_Fournitures\09_Outillage_materiaux\Outillage_matiere_oeuvre_2023\modele commande1.dotm")
Application.ScreenUpdating = False
'recupération du chemin ou se trouve le doc W pour enregistrement des PDF au meme endroit
fichier_source = ActiveWorkbook.Name
cheminW = Dir(fic_doc)
cheminW = Replace(fic_doc, cheminW, "")
cheminZ = ("\\Filer3\placido_cde_pub$\05_Fournitures\09_Outillage_materiaux\Outillage_matiere_oeuvre_2023\A IMPRIMER\")
NomBase = cheminW & "BASE_NE_PAS_TOUCHER.xlsx"
Application.DisplayAlerts = False
Set appWord = New Word.Application
appWord.Visible = True
'Ouverture du document principal Word
Set docWord = appWord.Documents.Open(fic_doc)
With docWord.MailMerge
'Ouvre la base de données le fichier excel doit avoir sa feuille nommée 'feuil1'
.OpenDataSource Name:=NomBase, Connection:="Driver={Microsoft Excel Driver (*.xlsx)};" & "DBQ=" & NomBase & "; ReadOnly=True;", SQLStatement:="SELECT * FROM [PUBLIPOSTAGE$]"
fin = .DataSource.RecordCount
End With
Last_Row1 = ws1.Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To Last_Row1
'fonctionnalité de publipostage pour le document spécifié
With docWord.MailMerge
'Spécifie la fusion vers un nouveau doc
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
'Prend en compte uniquement l'enregistrement i
With .DataSource
.FirstRecord = i
.LastRecord = i
End With
'Exécute l'opération de publipostage
.Execute Pause:=False
.DataSource.ActiveRecord = i
DocName = .DataSource.DataFields(18).Value
End With
nom_fichier = cheminZ & DocName & ".pdf"
With appWord.ActiveDocument
'export pdf
.ExportAsFixedFormat OutputFileName:=(nom_fichier), _
ExportFormat:=wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:= _
wdExportOptimizeForPrint, Range:=wdExportAllDocument, From:=1, To:=1, _
Item:=wdExportDocumentContent, IncludeDocProps:=False, KeepIRM:=False, _
CreateBookmarks:=wdExportCreateHeadingBookmarks, DocStructureTags:=True, _
BitmapMissingFonts:=False, UseISO19005_1:=False
'fermeture du fichier W sans enregistrement
.Close False
End With
Next i
Application.ScreenUpdating = True
'Fermeture du document Word
docWord.Close False
appWord.Quit
End Sub
merci pour vos éclairages :)
Bonjour,
Dans le code on compte le nombre d'enregistrement disponible ici
fin = .DataSource.RecordCount
Donc, pour moi la boucle devrait être
For i = 1 To fin
A tester
A+
merci beaucoup BrunoM45
très bonne soirée