[Writer] Publipostage avec images
Modérateur : Vilains modOOs
Règles du forum
Aucune question dans cette section !
Celle-ci rassemble les meilleures macros et portions de code. Vous pouvez en revanche commenter ou argumenter le code exposé. Vous pouvez même remercier l'auteur (cela fait toujours plaisir) en indiquant par exemple dans quel cadre ou contexte vous en avez eu l'utilité.
Si vous avez à poster quelque chose, faites-le depuis la section Macros et API et demandez à un modérateur de l'y déplacer.
Aucune question dans cette section !
Celle-ci rassemble les meilleures macros et portions de code. Vous pouvez en revanche commenter ou argumenter le code exposé. Vous pouvez même remercier l'auteur (cela fait toujours plaisir) en indiquant par exemple dans quel cadre ou contexte vous en avez eu l'utilité.
Si vous avez à poster quelque chose, faites-le depuis la section Macros et API et demandez à un modérateur de l'y déplacer.
- c-stefan
- Membre fOOndateur
- Messages : 1146
- Inscription : 16 janv. 2006 15:07
- Localisation : Lisieux
- Contact :
[Writer] Publipostage et fusion de documents
Ce suprême de code rassemble les meilleurs exemples pour étendre les possibilités de publipostage.
-
- Grand Maître de l'OOffice
- Messages : 11276
- Inscription : 02 mai 2006 10:42
[Writer] Publipostage avec images
Problématique : on dispose d'une table avec un champ contenant des Url pointant vers des images ; on souhaite réaliser un publipostage utilisant ce champ pour afficher l'image dans un contrôle Image.
Plusieurs approches sont possibles, notamment la décompression puis modification des fichiers XML constituant un document OpenOffice.
La bibliothèque jointe est un exemple (limité...) d'une autre solution réalisable par macro.
L'objectif n'est pas de recréer un assistant de publipostage mais de proposer un minimum de fonctionnalités, avec un minimum de contraintes de mise en oeuvre : la lettre-type doit simplement comprendre un contrôle image (Picto) de même nom que le champ comprenant l'url et le formulaire sous-jacent doit être fondé sur la même table.
Il ne s'agit donc pas ici d'une extension (la forme extension n'a été choisie que pour faciliter l'installation) et donc, volontairement, pas de commande de menu ajoutée, ni d'icône, etc.
Outre l'atteinte de l'objectif (créer un document de publipostage incluant les images), l'intérêt est ici pour moi de regrouper dans cette procédure quelques techniques "classiques" de manipulation des documents OpenOffice :
Le document joint présente plus en détail l'installation, l'utilisation et les limitations.
Ces dernières pourraient bien entendu être levées... Encore une fois, l'objectif n'est pas de recréer un assistant "complet".
Par voie de conséquence il est inutile de poster pour demander l'évolution de ce code qui n'est qu'un exemple
La bibliothèque (télécharger)
Le document de présentation (télécharger)
Ci-dessous le code (mais il sera nécessaire de télécharger la bibliothèque pour disposer de la boîte de dialogue).
Plusieurs approches sont possibles, notamment la décompression puis modification des fichiers XML constituant un document OpenOffice.
La bibliothèque jointe est un exemple (limité...) d'une autre solution réalisable par macro.
L'objectif n'est pas de recréer un assistant de publipostage mais de proposer un minimum de fonctionnalités, avec un minimum de contraintes de mise en oeuvre : la lettre-type doit simplement comprendre un contrôle image (Picto) de même nom que le champ comprenant l'url et le formulaire sous-jacent doit être fondé sur la même table.
Il ne s'agit donc pas ici d'une extension (la forme extension n'a été choisie que pour faciliter l'installation) et donc, volontairement, pas de commande de menu ajoutée, ni d'icône, etc.
Outre l'atteinte de l'objectif (créer un document de publipostage incluant les images), l'intérêt est ici pour moi de regrouper dans cette procédure quelques techniques "classiques" de manipulation des documents OpenOffice :
- Création de document à partir d'un modèle
- Navigation et écriture dans un document via les curseurs
- Manipulation de formats
- Manipulation de contrôles de formulaire
- Manipulation de champs insérés dans le document
- Manipulation de jeu de données (connexion, jeu d'enregisrements)
Le document joint présente plus en détail l'installation, l'utilisation et les limitations.
Ces dernières pourraient bien entendu être levées... Encore une fois, l'objectif n'est pas de recréer un assistant "complet".
Par voie de conséquence il est inutile de poster pour demander l'évolution de ce code qui n'est qu'un exemple
La bibliothèque (télécharger)
Le document de présentation (télécharger)
Ci-dessous le code (mais il sera nécessaire de télécharger la bibliothèque pour disposer de la boîte de dialogue).
Code : Tout sélectionner
option explicit
global PysDlg as object, PysConnexion as object
Sub PysLancerPublipostage
dim PysLettreType as object, PysNewDoc as object, PysTexte as object, PysCurseur as object
dim PysForm as object, PysCtrlImg as object, PysTables as object
dim PysRowSet as object, PysEnum as object, PysChamp as object, PysRange as object
dim PysProp(0) as new com.sun.star.beans.PropertyValue
dim PysUrl as string
dim PysNbForms as integer
PysProp(0).name = "AsTemplate"
PysProp(0).value = true
PysLettreType = thiscomponent
PysUrl = PysLettreType.url
' Ne travaille que si le document a été enregistré (car on l'utilise par insertion > fichier)
if PysUrl <> "" and not(PysLettreType.isModified) then
' Création d'un nouveau document fondé sur la letre-type
PysNewDoc = stardesktop.loadComponentFromUrl(PysUrl, "_blank", 0, PysProp())
' Chargement de la bibliotheque Tools car utilisation des fonctions IndexinArray et ToggleWindow
GlobalScope.BasicLibraries.LoadLibrary("Tools")
PysPatienter
ToggleWindow false
' Ne travaille que si le document comprend un formulaire
if PysNewDoc.DrawPage.Forms.count <> 0 then
PysForm = PysNewDoc.DrawPage.Forms.getByIndex(0)
' Ne travaille que si le formulaire ne comprend qu'un seul contrôle (picto)
if PysForm.count = 1 then
' Accès à ce contrôle
PysCtrlImg = PysForm.getByIndex(0)
' On remonte du formulaire à la "connexion" utile pour :
' - créer le jeu d'enregistrements
' - accéder aux formats de données
PysConnexion = PysForm.ActiveConnection
if IsNull(PysConnexion) then
MsgBox("Connexion impossible", 16)
else
PysTables = PysConnexion.Tables
' Ne travaille que si la source ne comprend qu'une table
if PysTables.count = 1 then
' Création du jeu d'enregistrements correspondant
PysRowSet = createUnoService("com.sun.star.sdb.RowSet")
with PysRowSet
.activeConnection = PysConnexion
.CommandType = "com.sun.star.sdb.CommandType.Table"
.Command = PysConnexion.Tables.getByIndex(0).Name
.execute
end with
' Utilise la fonction (Tools) pour tester si la source de données comprend
' un champ de même nom que le contrôle Image
if IndexinArray(PysCtrlImg.name, PysRowSet.Columns.ElementNames) <> -1 then
' Toutes les conditions sont réunies, on peut "boucler" sur les enregistrements
with PysRowSet
.beforeFirst
PysNbForms = 0
while .next
' Pour le premier enregistrement, le document a déjà été créé, sinon
' on va à la fin du document, on insère un paragraphe avec saut de page
' puis on insère la lettre-type à la fin
if PysNbForms <> 0 then
PysTexte = PysNewDoc.text
PysCurseur = PysTexte.createTextCursor
PysCurseur.gotoEnd(False)
PysTexte.insertControlCharacter(PysCurseur, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, false)
PysCurseur.breakType = com.sun.star.style.BreakType.PAGE_BEFORE
PysCurseur.insertDocumentFromURL(PysUrl, array())
PysForm = PysNewDoc.DrawPage.Forms.getByIndex(PysNbForms)
PysCtrlImg = PysForm.getByIndex(0)
end if
' Assignation de l'url de l'image (contenue dans le champ de même nom dans la table)
PysCtrlImg.ImageUrl = convertToUrl(.columns.getByName(PysCtrlImg.name).String)
PysNbForms = PysNbForms + 1
'Boucle sur les champs du document (et non de la source...)
PysEnum = PysNewDoc.TextFields.createEnumeration
' Tant qu'il y en a...
do while PysEnum.hasMoreElements
PysChamp = PysEnum.nextElement
' S'il s'agit d'un champ lié à la base de données
if PysChamp.supportsService("com.sun.star.text.TextField.Database") then
' Vérifie qu'il y a bien un champ du même nom
if IndexinArray(PysChamp.TextFieldMaster.DataColumnName, PysRowSet.Columns.ElementNames) <> -1 then
' Récupération de la position du champ dans le document
PysRange=PysChamp.anchor.start
' Création d'un curseur d'écriture pour remplacer le champ par le texte contenu
' dans la base
PysCurseur = PysRange.text.createTextCursorByRange(PysRange)
' Nécessaire de formater les champs Date ou Numérique
' avant d'écrire le contenu du champ
select case .columns.getByName(PysChamp.TextFieldMaster.DataColumnName).TypeName
case "DATE","DATETIME","TIME"
PysCurseur.string =_
PysFormat(.columns.getByName(PysChamp.TextFieldMaster.DataColumnName).String,_
.columns.getByName(PysChamp.TextFieldMaster.DataColumnName).FormatKey)
case "DECIMAL","NUMERIC"
PysCurseur.string =_
PysFormat(val(.columns.getByName(PysChamp.TextFieldMaster.DataColumnName).String),_
.columns.getByName(PysChamp.TextFieldMaster.DataColumnName).FormatKey)
case else
PysCurseur.string =.columns.getByName(PysChamp.TextFieldMaster.DataColumnName).String
end select
' Supprime le champ
PysChamp.dispose
end if
end if
loop
' Met à jour la collection des champs du document
PysNewDoc.TextFields.refresh
wend
.dispose
end with
else
MsgBox("Aucun champ nommé " & PysCtrlImg.name & " ne figure dans la source de données", 16)
end if
else
MsgBox("Table non trouvée", 16)
end if
end if
else
MsgBox("Impossible de trouver le contrôle image dans le formulaire", 16)
end if
else
MsgBox("Aucun formulaire n'a été trouvé", 16)
end if
ToggleWindow true
PysFinPatienter
msgbox "Terminé...", 64, "Publipostage"
else
MsgBox("La lettre type doit avoir été enregistrée", 16)
end if
End Sub
sub PysPatienter
' Affiche un dialogue d'attente à l'utiliateur
dim PysBibli as Object, PysMonDialog as object, PysControle as object
DialogLibraries.LoadLibrary("PysPublipostage")
PysBibli=DialogLibraries.GetByName("PysPublipostage")
PysMonDialog=PysBibli.GetByName("PysDlgPatienter")
PysDlg=CreateUnoDialog(PysMonDialog)
PysDlg.setVisible(True)
PysDlg.model.PysTextMsg.Text="Veuillez patienter..."
' Nécessaire pour laisser le temps à la connexion à la source de données de s'établir
wait 20
end sub
sub PysFinPatienter
PysDlg.setVisible(False)
PysDlg.Dispose
end sub
function PysFormat(PysChamp, PysKey as long) as string
' A partir du numéro de format (PysKey) on recherche dans les formats, on obtient ainsi la chaîne représentant le format
' Par exemple : # ##0,00 [$€-40C];[RED]-# ##0,00 [$€-40C]
' Appel de la fonction Calc FORMAT (TEXT en GB) pour formater le contenu du champ avec ce format
' Nota : on ne peut utiliser la propriété NumberFormats de "thiscomponent" (la lettre-type) car les formats sont différents.
' On appelle donc logiquement le NumberFormatsSupplier de la "database" à laquelle on remonte via la Connexion.
dim PysService as object
PysService = CreateUnoService("com.sun.star.sheet.FunctionAccess")
PysFormat = PysService.callFunction("TEXT", array(PysChamp, PysConnexion.Parent.NumberFormatsSupplier.NumberFormats.getByKey(PysKey).FormatString))
end function
- Hubert Lambert
- SuppOOrter
- Messages : 1214
- Inscription : 06 avr. 2016 09:26
[Writer] Publipostage avec images (bis)
Bonjour,
Dans la suite logique de ce message, j’ai eu envie de généraliser la macro proposée pour la rendre utilisable quel que soit le type de document (étiquettes ou lettre), le type d’image, le nombre d’images par document, l’emplacement de l’image (cadre, tableau…), etc.
Comme je souhaiterais faire évoluer cette macro en fonction des besoins des utilisateurs, il me semble que la section Projets se prête mieux que la section Macros et API pour la publication du code. Mais libre aux modérateurs de déplacer le fil s’ils l’estiment utile.
Le "bis" du titre fait référence à la macro de Pierre-Yves Samyn citée dans le message précité, qui y propose une réécriture complète de la fusion de documents. Celle-ci propose une autre voie, qui "colle" au plus près du code existant (en l'occurrence le service MailMerge) et se focalise exclusivement sur l'intégration des images via une ébauche d'assistant.
Mode d’emploi
1. Dézipper les fichiers joints dans un même répertoire et les importer (Alt-F11 → Gérer → Bibliothèques → Importer et choisir le fichier "script.xlb").
2. Ouvrir un document modèle ou en créer un de manière classique; pour les images, insérer à l’endroit voulu un cadre qui ne contiendra que le champ correspondant à l’url.
3. Depuis le document modèle ouvert, exécuter la macro "publipostage_avec_images" (Alt-F11 → Mes Macros → PublipostageAvecImages → Module1 → Exécuter).
4. Choisir les enregistrements et les options, puis lancer.
Si aucun enregistrement n’est sélectionné, tous seront utilisés.
Le document modèle peut être créé à partir de l'assistant inclus dans la macro, par glisser-déposer des en-têtes de champs.
Les url des images peuvent être absolues ou relatives.
Bugs connus
En raison du bug décrit ici, la sélection d’enregistrements est défaillante sous OpenOffice : il ne sera possible que de fusionner l’ensemble des éléments (sans sélection donc) ou un seul à la fois.
Cordialement.
Dans la suite logique de ce message, j’ai eu envie de généraliser la macro proposée pour la rendre utilisable quel que soit le type de document (étiquettes ou lettre), le type d’image, le nombre d’images par document, l’emplacement de l’image (cadre, tableau…), etc.
Comme je souhaiterais faire évoluer cette macro en fonction des besoins des utilisateurs, il me semble que la section Projets se prête mieux que la section Macros et API pour la publication du code. Mais libre aux modérateurs de déplacer le fil s’ils l’estiment utile.
Le "bis" du titre fait référence à la macro de Pierre-Yves Samyn citée dans le message précité, qui y propose une réécriture complète de la fusion de documents. Celle-ci propose une autre voie, qui "colle" au plus près du code existant (en l'occurrence le service MailMerge) et se focalise exclusivement sur l'intégration des images via une ébauche d'assistant.
Mode d’emploi
1. Dézipper les fichiers joints dans un même répertoire et les importer (Alt-F11 → Gérer → Bibliothèques → Importer et choisir le fichier "script.xlb").
2. Ouvrir un document modèle ou en créer un de manière classique; pour les images, insérer à l’endroit voulu un cadre qui ne contiendra que le champ correspondant à l’url.
3. Depuis le document modèle ouvert, exécuter la macro "publipostage_avec_images" (Alt-F11 → Mes Macros → PublipostageAvecImages → Module1 → Exécuter).
4. Choisir les enregistrements et les options, puis lancer.
Si aucun enregistrement n’est sélectionné, tous seront utilisés.
Le document modèle peut être créé à partir de l'assistant inclus dans la macro, par glisser-déposer des en-têtes de champs.
Les url des images peuvent être absolues ou relatives.
Bugs connus
En raison du bug décrit ici, la sélection d’enregistrements est défaillante sous OpenOffice : il ne sera possible que de fusionner l’ensemble des éléments (sans sélection donc) ou un seul à la fois.
Cordialement.
- Pièces jointes
-
- PublipostageAvecImages.zip
- v0.2
- (4.23 Kio) Téléchargé 472 fois
AOOo 4.1.7 sur Win10
AOOo 4.1.x sur Linux Mint
LibreOffice 5.x/6.x sur Linux Mint
--
▼ | « Nos défauts devraient nous donner une qualité : l'indulgence pour les défauts des autres » (Rivarol)
AOOo 4.1.x sur Linux Mint
LibreOffice 5.x/6.x sur Linux Mint
--
▼ | « Nos défauts devraient nous donner une qualité : l'indulgence pour les défauts des autres » (Rivarol)
- Dude
- IdOOle de la suite
- Messages : 25143
- Inscription : 03 mars 2006 08:45
- Localisation : 127.0.0.1
- Contact :
[Writer] Publipostage simplissime pour débuter
Réalisation d'un publipostage visant à fusionner dans un ODT unique plusieurs documents ainsi qu'un export dans des PDF distincts.
Bibliography est la source de données utilisée afin de simplifier à l'extrême l'exemple.
Bibliography est la source de données utilisée afin de simplifier à l'extrême l'exemple.
Code : Tout sélectionner
Sub Main
oListener = createUnoListener("pub_", "com.sun.star.text.XMailMergeListener")
oUdp = ThisComponent.DocumentProperties.getUserDefinedProperties()
oPub = createUnoService("com.sun.star.text.MailMerge")
with oPub
.OutputType = com.sun.star.text.MailMergeType.FILE
.DataSourceName = oUdp.MRG_DataSource
.CommandType = oUdp.MRG_SourceType
.Command = oUdp.MRG_Source
.DocumentURL = ThisComponent.getURL()
.SaveAsSingleFile = True
.Filter = oUdp.MRG_SQLFilter
.addMailMergeEventListener(oListener)
.execute(Array())
.removeMailMergeEventListener(oListener)
end with
End Sub
Sub pub_notifyMailMergeEvent(oEvt)
Dim aFiltre(0) as new com.sun.star.beans.PropertyValue
aFiltre(0).Name = "FilterName"
aFiltre(0).Value = "writer_pdf_Export"
oPub = oEvt.Source
oDoc = oEvt.Model
oId = oDoc.TextFieldMasters.getByName("com.sun.star.text.fieldmaster.DataBase.Bibliography.biblio.Identifier")
oChamp = oId.DependentTextFields(0)
sID = oChamp.CurrentPresentation
oEvt.Model.storeToURL(oPub.DocumentURL &"_"& sID &".pdf", aFiltre)
End Sub
Sub pub_disposing(oEvt)
'RAS
End Sub