[Résolu] [C#] Publipostage et pages blanches

Discussions et questions sur tout ce qui concerne la programmation tous langages et tous modules confondus.

Modérateur : Vilains modOOs

Règles du forum
:alerte: Balisage obligatoire dans cette section !
Aidez-nous à vous aider au mieux en balisant correctement votre question : reportez-vous sur les règles de cette section avant de poster !
quiphenix
Fraîchement OOthentifié
Messages : 3
Inscription : 14 août 2015 11:42

[Résolu] [C#] Publipostage et pages blanches

Message par quiphenix »

Bonjour à tous,

Je suis actuellement en train de développer un petit bout de code en C# permettant d'utiliser Open Office 4.1.1 pour faire du publipostage via le SDK sous Windows 8.1.

Au niveau de la structure, j'ai une simple source de données au format CSV, utilisée dans un document ODT via la définition d'un ODB. Cette partie fonctionne bien selon mes besoins ... à part le fait que Open Office m'intercale des pages blanches invisibles entre chaque impression d'un élément de ma source de données.
Par exemple, si mon CSV contient 3 lignes et que mon document modèle ne fait qu'une seule page, je vais obtenir (dans un ODT ou à l'impression directe): Page de donnée 1 / Page blanche / Page de donnée 2 / Page blanche / Page de donnée 3. Soit un document de 5 pages alors qu'il ne devrait en faire que 3.
Plus curieux, si j'utilise la fonction de génération d'un document ODT et que j'ouvre le fichier résultat avec Writer, je ne vois pas les pages vides, seule l'indication "Page 1 sur 5" dans la barre d'information d'Open Office m'indique l'existence des pages indésirables (cf capture en pièce jointe).

Voici le code de mon publipostage pour obtenir mon fichier résultat :

Code : Tout sélectionner

static void FusionODTFile(string filePath, string destFolder, bool saveAsSingleFile = false)
{
            XComponentContext oStrap = uno.util.Bootstrap.bootstrap();

            XMultiServiceFactory oServMan = (XMultiServiceFactory)oStrap.getServiceManager();

            XJob publipostageJob = (XJob)oServMan.createInstance("com.sun.star.text.MailMerge");
            string odtFile = string.Format("file:///{0}", filePath.Replace("\\", "/"));
            string resultFolder = string.Format("file:///{0}", destFolder.Replace("\\", "/"));

            NamedValue[] namedValue = new NamedValue[8];
            namedValue[0] = new NamedValue();
            namedValue[0].Name = "DocumentURL";
            namedValue[0].Value = new uno.Any(odtFile);

            // Nom de la source de données
            namedValue[1] = new NamedValue();
            namedValue[1].Name = "DataSourceName";
            namedValue[1].Value = new uno.Any(_dataSourceName);

            // Données de la table
            namedValue[2] = new NamedValue();
            namedValue[2].Name = "CommandType";
            namedValue[2].Value = new uno.Any(unoidl.com.sun.star.sdb.CommandType.TABLE);

            // Nom de la table utilisée
            namedValue[3] = new NamedValue();
            namedValue[3].Name = "Command";
            namedValue[3].Value = new uno.Any(_tableName);

            // Type de sortie
            namedValue[4] = new NamedValue();
            namedValue[4].Name = "OutputType";
            namedValue[4].Value = new uno.Any(unoidl.com.sun.star.text.MailMergeType.FILE);

            // Dossier contenant les fichiers
            namedValue[5] = new NamedValue();
            namedValue[5].Name = "OutputURL";
            namedValue[5].Value = new uno.Any(resultFolder);

            // Préfixe des fichiers de sortie
            namedValue[6] = new NamedValue();
            namedValue[6].Name = "FileNamePrefix";
            namedValue[6].Value = new uno.Any(_outputFilePrefix);

            // Création d'un seul fichier de sortie
            namedValue[7] = new NamedValue();
            namedValue[7].Name = "SaveAsSingleFile";
            namedValue[7].Value = new uno.Any(saveAsSingleFile);

            publipostageJob.execute(namedValue);
}
En avançant dans mon problème, j'ai remarqué l'existence dans Open Office d'une option d'impression permettant de ne pas imprimer les pages blanches. Après avoir un peu galéré pour retrouver l'option dans l'API, j'ai fini par la trouver. Seul problème : l'option n'est pas prise en compte immédiatement ! Il faut que le programme se termine une première fois pour qu'à la deuxième exécution, le programme n'imprime pas les pages blanches.
De plus, cette option semble persistante ce qui est gênant (modifier les options de l'utilisateur dans son dos n'est jamais terrible).

Voici le code que j'utilise pour modifier l'option d'impression puis ouvrir le document pour l'imprimer :

Code : Tout sélectionner

static void OpenAndPrintODTFile(string filePath, string printerName, bool hidden)
{
            XComponentContext oStrap = uno.util.Bootstrap.bootstrap();

            XMultiServiceFactory oServMan = (XMultiServiceFactory)oStrap.getServiceManager();

            // Permet de ne pas imprimer les pages vides automatiquement placées entre chaque enregistrement
            XPrintSettingsSupplier printSettingSupplier = (XPrintSettingsSupplier)oServMan.createInstance("com.sun.star.text.GlobalSettings");
            XPropertySet printSettings = printSettingSupplier.getPrintSettings();
            uno.Any printEmptyPage = printSettings.getPropertyValue("PrintEmptyPages");
            if (((bool)printEmptyPage.Value) == true)
            {
                printSettings.setPropertyValue("PrintEmptyPages", new uno.Any(false));
            }

            XComponentContext oStraper = uno.util.Bootstrap.bootstrap();

            XMultiServiceFactory oServManager = (XMultiServiceFactory)oStraper.getServiceManager();

            XComponentLoader oDesk = (XComponentLoader)oServManager.createInstance("com.sun.star.frame.Desktop");

            string url = string.Format("file:///{0}", filePath.Replace("\\", "/")); 
            // Ouverture d'un doc vide 
            // url = @"private:factory/scalc";

            PropertyValue[] propVals;
            if (hidden)
            {
                // Permet de masquer la fenetre
                propVals = new PropertyValue[1];
                propVals[0] = new PropertyValue();
                propVals[0].Name = "Hidden";
                propVals[0].Value = new uno.Any(true);
            }
            else
            {
                propVals = new PropertyValue[0];
            }

            XComponent oDoc = oDesk.loadComponentFromURL(url, "_blank", 0, propVals);

            XTextDocument doc = (XTextDocument)oDoc;

            XPrintable printableDocument = (XPrintable)oDoc;

            PropertyValue[] printerProperties = new PropertyValue[1];

            // Nom de l'imprimante utilisée
            printerProperties[0] = new PropertyValue();
            printerProperties[0].Name = "Name";
            printerProperties[0].Value = new uno.Any(printerName);

            printableDocument.setPrinter(printerProperties);

            PropertyValue[] printJobProperties = new PropertyValue[3];

            // Nombre de copies du doc
            printJobProperties[0] = new PropertyValue();
            printJobProperties[0].Name = "CopyCount";
            printJobProperties[0].Value = new uno.Any(1);

            // Impression synchrone
            printJobProperties[1] = new PropertyValue();
            printJobProperties[1].Name = "Wait";
            printJobProperties[1].Value = new uno.Any(true);

            printJobProperties[2] = new PropertyValue();
            printJobProperties[2].Name = "Collate";
            printJobProperties[2].Value = new uno.Any(true);

            // Impression
            printableDocument.print(printJobProperties);

            oDoc.dispose();

            oDoc = null;
}
Voilà où j'en suis : j'ai donc un programme qui ne fonctionne potentiellement pas la première fois et qui peut changer les paramétrages de l'utilisateur... ce qui ne me satisfait pas.

Je cherche donc de l'aide pour savoir s'il est possible de supprimer ces mystérieuses pages blanches :
- soit à la source, lors du publipostage (utilisation du service mailMerge avec une option non-documentée ?).
- soit par programmation en supprimant les pages indésirables du document.
- soit à l'impression en trouvant le moyen de forcer l'application du paramétrage, me permettant ainsi de faire le changement d'option uniquement le temps de l'impression.

C'est également la première fois que j'utilise l'API Open Office, je suis donc ouvert à toute suggestion concernant mon code si vous avez des conseils, astuces, etc. ;)

Merci à vous pour votre aide, n'hésitez pas si vous avez des questions complémentaires.
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par quiphenix le 19 août 2015 15:03, modifié 1 fois.
OpenOffice 4.1.1 sous Windows 8.1
Avatar de l’utilisateur
Dude
IdOOle de la suite
IdOOle de la suite
Messages : 25181
Inscription : 03 mars 2006 07:45
Localisation : 127.0.0.1

Re: [C#] Publipostage et pages blanches

Message par Dude »

Salut,

Le plus simple est de ne pas passer par l'API.
Fabrique toi-même tes ODT avec ton langage C#.
Bref, gagner du temps en perdant ses vieux réflexes de pilotage d'application.

:idea:
quiphenix
Fraîchement OOthentifié
Messages : 3
Inscription : 14 août 2015 11:42

Re: [C#] Publipostage et pages blanches

Message par quiphenix »

Dude a écrit :Salut,

Le plus simple est de ne pas passer par l'API.
Fabrique toi-même tes ODT avec ton langage C#.
Bref, gagner du temps en perdant ses vieux réflexes de pilotage d'application.

:idea:
Bonjour,

Merci pour la suggestion, malheureusement ce n'est pas possible dans le cas qui me concerne.
En effet, le logiciel sur lequel je travaille utilise déjà le publipostage Word pour permettre aux utilisateurs de personnaliser et d'imprimer des documents et nous souhaiterions simplement ouvrir la fonctionnalité aux gens qui utilisent Open Office. De plus, les utilisateurs doivent pouvoir personnaliser eux-même les documents et pour ça, seule l'utilisation du publipostage et l'édition d'un document modèle par OOWriter est envisageable pour ne pas avoir à tout redévelopper.

Pour revenir sur le problème : sur la suggestion d'un collègue, j'ai envisagé un soucis dans ma source de données qui ferait apparaitre des pages vides (par exemple, un problème sur les caractères de fin de ligne qui pourraient faire croire à l'existence de lignes vides dans ma source) mais même en changeant ma source CSV par un classeur OOCalc ou même une base OOBase, le problème persiste. Pour vous, qui êtes plus habitués à l’environnement Open Office, le publipostage a toujours fonctionné comme ça ?

Edit: je viens de retrouver la déclaration de bug correspondante sur le bug tracker d'Open Office. Apparemment, ce soucis est présent depuis 2006 et ne sera pas corrigé :/
OpenOffice 4.1.1 sous Windows 8.1
Avatar de l’utilisateur
Dude
IdOOle de la suite
IdOOle de la suite
Messages : 25181
Inscription : 03 mars 2006 07:45
Localisation : 127.0.0.1

Re: [C#] Publipostage et pages blanches

Message par Dude »

quiphenix a écrit :De plus, les utilisateurs doivent pouvoir personnaliser eux-même les documents et pour ça, seule l'utilisation du publipostage et l'édition d'un document modèle par OOWriter est envisageable pour ne pas avoir à tout redévelopper.
Je ne vois pas en quoi ma proposition ne serait pas viable.
Il suffit de remplacer dans le content.xml de l'ODT, les balises indiquant les champs de la source de données.
Celles-ci sont sous la forme :

Code : Tout sélectionner

<text:database-display 
 text:table-name="Nom_de_la table" 
 text:table-type="table" 
 text:column-name="Nom_de_colonne" 
 text:database-name="Nom_déclaré_pour_la_source"><Nom_du_champ></text:database-display>
quiphenix a écrit :Apparemment, ce soucis est présent depuis 2006 et ne sera pas corrigé
Je pencherai plutôt pour le rapport 58919.
quiphenix
Fraîchement OOthentifié
Messages : 3
Inscription : 14 août 2015 11:42

Re: [C#] Publipostage et pages blanches

Message par quiphenix »

Dude a écrit :
quiphenix a écrit :De plus, les utilisateurs doivent pouvoir personnaliser eux-même les documents et pour ça, seule l'utilisation du publipostage et l'édition d'un document modèle par OOWriter est envisageable pour ne pas avoir à tout redévelopper.
Je ne vois pas en quoi ma proposition ne serait pas viable.
Il suffit de remplacer dans le content.xml de l'ODT, les balises indiquant les champs de la source de données.
Celles-ci sont sous la forme :

Code : Tout sélectionner

<text:database-display 
 text:table-name="Nom_de_la table" 
 text:table-type="table" 
 text:column-name="Nom_de_colonne" 
 text:database-name="Nom_déclaré_pour_la_source"><Nom_du_champ></text:database-display>
quiphenix a écrit :Apparemment, ce soucis est présent depuis 2006 et ne sera pas corrigé
Je pencherai plutôt pour le rapport 58919.
Bonjour,

Effectivement, je n'étais pas sur le bug racine, merci pour le lien. :wink:

Théoriquement, il serait effectivement possible d'utiliser la création de document, mais ça revient à ré-implémenter le publipostage à la main en faisant attention à toutes les variations possibles (planches d'étiquette, etc.) et franchement, ça me parait encore plus hasardeux que le pilotage (malgré ses défauts !).

Concernant mon problème d'option utilisateur, en examinant l'intérieur du fichier ODT généré, j'ai repéré l'option en question dans le fichier "settings.xml". En la modifiant directement dans le fichier ODT sans passer par le SDK, l'option est modifiée instantanément et utilisée directement pour l'impression, sans persistance, ce qui m'évite de toucher aux options de l'utilisateur. Mon problème est donc résolu, même si ça utilise pas mal de bidouille...

Donc pour résumer et si ça peut aider quelqu'un un jour :
  • Étape 1 : génération d'un fichier résultat ODT via MailMerge (cf code du premier post)
  • Étape 2 : ouverture de l'ODT en Zip pour modifier l'option "PrintEmptyPages" à "false" dans le fichier "settings.xml"
  • Étape 3 : ouverture de l'ODT par OOWriter pour imprimer le document (cf code du premier post, sans la partie de modification de l'option via le SDK)
Ce n'est pas idéal, mais ça fonctionne. Je marque le sujet en résolu, mais je reste ouvert à toute proposition !
Merci encore pour le coup de main et l'inspiration ;)
OpenOffice 4.1.1 sous Windows 8.1
Avatar de l’utilisateur
Petricikian
Fraîchement OOthentifié
Messages : 1
Inscription : 11 avr. 2022 13:24

Re: [Résolu] [C#] Publipostage et pages blanches

Message par Petricikian »

Bonjour, j'ai une question sur la façon de fusionner plusieurs e-mails ?
OpenOffice 2.4 ?????? Windows 10
Avatar de l’utilisateur
Bidouille
RespOOnsable forum
RespOOnsable forum
Messages : 12230
Inscription : 08 nov. 2005 16:23
Localisation : Caen, France

Re: [Résolu] [C#] Publipostage et pages blanches

Message par Bidouille »

Question résolue en 2015.
Merci de ne pas déterrer de fils aussi vieux.