L'objectif est de pouvoir inséré dans le document généré d'autre requête et table que dans un publipostage classique par Open Office.
On a donc un modèle de publipostage avec des champs de mailing inséré dedans grâce a Open office.
Tout d'abord un singleton pour créer le context et quelques objet et interface dont nous auront besoin. Noter la methode reload qui permet de palier a un bug d'openoffice : On capte l'exception "Connection reset" et on reload le singleton..
Code : Tout sélectionner
package Office;
import com.sun.star.beans.XPropertySet;
import com.sun.star.bridge.XBridge;
import com.sun.star.bridge.XBridgeFactory;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.comp.helper.BootstrapException;
import com.sun.star.connection.XConnection;
import com.sun.star.connection.XConnector;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.lib.unoloader.UnoLoader;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.uno.XCurrentContext;
import java.io.IOException;
import ooo.connector.BootstrapSocketConnector;
/**
*
* @author Yolpo
*/
public class SingletonOOo {
private XCurrentContext xCurCont = null;
private XComponentContext xContext = null;
private static SingletonOOo oOo = null;
private XMultiComponentFactory serviceManager = null;
private Object desktop = null;
private XComponentLoader loader = null;
private static XBridge bridge;
private Object mxMSF;
public static final String DEFAULT_CONNECTION_STRING = "socket,host=localhost,port=8100";
private SingletonOOo() throws BootstrapException, Exception{
try {
openConnectionOpenOffice();
} catch (Exception e) {
throw new java.lang.Exception(e);
}
}
//permet de réaffecter mes variable quand la connection a reset : Probleme connu d'openoffice en java.
public static synchronized void reload() throws BootstrapException, Exception{
oOo = new SingletonOOo();
}
public static synchronized SingletonOOo GetInstance() throws BootstrapException, Exception{
if(oOo == null || bridge == null){
oOo = new SingletonOOo();
}
return oOo;
}
public XMultiComponentFactory getServiceManager() throws BootstrapException, Exception {
return serviceManager;
}
public XComponentContext getXContext() throws BootstrapException, Exception {
return xContext;
}
public XComponentLoader getLoader() throws BootstrapException, Exception {
return loader;
}
public void openConnectionOpenOffice()
{
System.out.println("Ici");
try
{
//un timer en cas de reload : pour que le process ait le temps d'etre kill avant le reload..
Thread.sleep(2000);
xContext = BootstrapSocketConnector.bootstrap("C:\\Program Files\\OpenOffice.org 3\\program\\soffice.exe");
if (xContext == null)
System.out.println("mxComponentContext is null");
// Création de l'objet de type Connector permettant de créer une
// connection entre java et OOo
Object x = xContext.getServiceManager().createInstanceWithContext("com.sun.star.connection.Connector", xContext);
XConnector xConnector = (XConnector) UnoRuntime.queryInterface(XConnector.class, x);
// Création de la connection entre java et OOo
XConnection connection = xConnector.connect(DEFAULT_CONNECTION_STRING);
if (connection == null)System.out.println("Connection est null");
// Création du bridge, étape très importante pour pouvoir
// fermer OOo sans avoir à faire un system.exit();
// Le bridge est créé suivant la connection connection et le
// protocol de discussion urp
x = xContext.getServiceManager().createInstanceWithContext("com.sun.star.bridge.BridgeFactory", xContext);
XBridgeFactory xBridgeFactory = (XBridgeFactory) UnoRuntime.queryInterface(XBridgeFactory.class, x);
if (xBridgeFactory == null)System.out.println("Bdridge est null");
bridge = xBridgeFactory.createBridge("", "urp", connection, null);
// Création de la XMultiComponentFactory qui permettra d'avoir
// acces aux services tels que le mailmerge
XComponent xComponent = (XComponent) UnoRuntime.queryInterface(XComponent.class, bridge);
if (bridge == null)System.out.println("Bridge null");
x = bridge.getInstance("StarOffice.ServiceManager");
serviceManager = (XMultiComponentFactory) UnoRuntime.queryInterface(XMultiComponentFactory.class, x);
XPropertySet xProperySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, serviceManager);
Object oDefaultContext = xProperySet.getPropertyValue("DefaultContext");
xContext = (XComponentContext) UnoRuntime.queryInterface(XComponentContext.class, oDefaultContext);
serviceManager = xContext.getServiceManager();
desktop = serviceManager.createInstanceWithContext(
"com.sun.star.frame.Desktop", xContext );
loader = ( XComponentLoader )UnoRuntime.queryInterface( XComponentLoader.class, desktop );
if (mxMSF == null)
{
mxMSF = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, serviceManager);
}
}
catch (Exception exception)
{
System.err.println(exception);
}
}
public void closeConnectionOpenOffice()
{
XComponent xcomponent = (XComponent) UnoRuntime.queryInterface(XComponent.class, bridge);
xcomponent.dispose();
}
}
Après on crée une classe mère qui comprendras des méthodes qui pourront servir a chaque scénario (voir plus bas) de publipostage.
Code : Tout sélectionner
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package p0;
import Office.SingletonOOo;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import com.sun.star.beans.PropertyValue;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.frame.XStorable;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
/**
*
* @author Yolpo
*/
public class PublipostJava {
private XComponentContext context = null;
private XComponent document = null;
private XMultiComponentFactory serviceManager = null;
XComponentLoader loader = null;
public PublipostJava() { }
/**
* Créer un document
* <p>
* @return
* Le document construit
* @param templateFile
* Le template du document
* @param isUserEditable
* True = permet au user d'éditer le doc
* False = interdit au user d'éditer le doc
*/
public XComponent createDoc(String templateFile,boolean isUserEditable) throws java.lang.Exception {
// Get Context et service manager de SingletonOOo
if (context == null) {
context = SingletonOOo.GetInstance().getXContext();
serviceManager = SingletonOOo.GetInstance().getServiceManager();
loader = SingletonOOo.GetInstance().getLoader();
}
// get XComponentLoader. pour load le doc.
// Propriété générale du document (voir com.sun.star.document.MediaDescriptor).
ArrayList<PropertyValue> props = new ArrayList<PropertyValue>();
PropertyValue p = null;
if (templateFile != null) {
// Autorise l'utilisation d'un Template.
p = new PropertyValue();
p.Name = "AsTemplate";
p.Value = new Boolean (true);
props.add(p);
}
// Rend le document invisible.
p = new PropertyValue();
p.Name = "Hidden";
p.Value = new Boolean(true);
props.add(p);
PropertyValue[] properties = new PropertyValue[props.size()];
props.toArray(properties);
// Création du document
// (voir com.sun.star.frame.XComponentLoader pour détails).
if (templateFile != null) {
// Créer une copie du template. pour travailler dessus.
if (loader == null){
context = SingletonOOo.GetInstance().getXContext();
serviceManager = SingletonOOo.GetInstance().getServiceManager();
loader = SingletonOOo.GetInstance().getLoader();
}
}
String templateFileURL = filePathToURL(templateFile);
document = loader.loadComponentFromURL(
templateFileURL, // URL du temlpate
"_blank", // Nom de la fenetre (_blank en cré une nouvelle).
0, // On ne cherche pas de flag.
properties); // Propriétées.
return document;
}
/**
* Sauver un doc donné a l'url donnée au format pdf.
* <p>
* @param document
* Le document a sauvegarder (XComponent)
* @param saveFile
* Url complete du fichier (String)
* @param format
* Le format final (MS word, pdf , odt etc) (Enum OOo voir Filtername dans API)
* @param overwrite
* Doit-on écraser le fichier si il existe deja.(boolean)
*/
protected synchronized void storeDocComponent(XComponent xDoc, String storeUrl) throws java.lang.Exception {
XStorable xStorable = (XStorable)UnoRuntime.queryInterface(XStorable.class, xDoc);
storeUrl = filePathToURL(storeUrl);
PropertyValue[] storeProps = new PropertyValue[2];
storeProps[0] = new PropertyValue();
storeProps[0].Name = "FilterName";
storeProps[0].Value = "writer_pdf_Export";
storeProps[1] = new PropertyValue();
storeProps[1].Name = "Overwrite";
storeProps[1].Value = new Boolean(true);
xStorable.storeToURL(storeUrl, storeProps);
//xDoc.dispose();
XComponent xComp = (XComponent) UnoRuntime.queryInterface(XComponent.class, xStorable);
xComp.dispose();
}
/** Converti si besoin l'url. */
private String filePathToURL(String file) {
File f = new File(file);
StringBuffer sb = new StringBuffer("file:///");
try {
sb.append(f.getCanonicalPath().replace('\\', '/'));
} catch (IOException e) {
}
return sb.toString();
}
/**
* @param args
*/
}
Code : Tout sélectionner
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package p0.scenario;
import com.sun.star.beans.PropertyVetoException;
import com.sun.star.beans.UnknownPropertyException;
import com.sun.star.beans.XPropertySet;
import com.sun.star.container.NoSuchElementException;
import com.sun.star.container.XEnumeration;
import com.sun.star.container.XEnumerationAccess;
import com.sun.star.container.XIndexAccess;
import com.sun.star.container.XNameAccess;
import com.sun.star.lang.IllegalArgumentException;
import com.sun.star.lang.IndexOutOfBoundsException;
import com.sun.star.lang.WrappedTargetException;
import com.sun.star.lang.XComponent;
import com.sun.star.table.XTableRows;
import com.sun.star.text.XText;
import com.sun.star.text.XTextField;
import com.sun.star.text.XTextFieldsSupplier;
import com.sun.star.text.XTextTable;
import com.sun.star.text.XTextTablesSupplier;
import com.sun.star.uno.UnoRuntime;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import p0.PublipostJava;
/**
*
* @author Jalin
*/
public class ScenarioBleu extends PublipostJava{
Map mesvaleurs = new HashMap();
String[][] maTable;
XComponent document = null;
String prefix;
String[] mesIndex = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"};
public ScenarioBleu(String templateDoc,Boolean bool, String prefix, Map mesVal, String[][] matab) throws Exception{
super();
this.mesvaleurs = mesVal;
maTable = matab;
this.prefix = prefix;
document = createDoc(templateDoc,bool);
populChamp();
popultable();
//Enregistrement du doc avec url complete.(voir méthode storeDocComponent)
storeDocComponent(document, "C:/partage/"+prefix+".pdf");
}
/**
* Remplir les champs de mailing
* <p>
* @void
* Method qui modifie la variable de classe document donc pas de return
* @param XComponent document
* le document
* @param mesvaleurs
* Clé : champ a cherché dans le doc
* valeur : String pour affecter sa valeur au champ.
*/
private void populChamp() throws UnknownPropertyException,PropertyVetoException, NoSuchElementException, WrappedTargetException, IllegalArgumentException{
//Acces au Champs de mailing
XTextFieldsSupplier fieldSupplier = (XTextFieldsSupplier)UnoRuntime.queryInterface(XTextFieldsSupplier.class, document);
XEnumerationAccess xEnumField = fieldSupplier.getTextFields();
//Création d'un itérateur pour boucler dessus
Iterator iter = mesvaleurs.entrySet().iterator();
//Remplacement des champs par les données qui conviennent.
while (iter.hasNext())
{
Map.Entry ent = (Entry) iter.next();
String cle = (String) ent.getKey();
String valeur = (String) ent.getValue();
//Enum des textfield du document pour boucler dessus.
XEnumeration xEnum = xEnumField.createEnumeration();
while (xEnum.hasMoreElements()){
//Récupération du textfield
XTextField text = (XTextField) UnoRuntime.queryInterface(XTextField.class, xEnum.nextElement());
XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, text);
// Test et affectation du contenu si match.
if (xPropertySet.getPropertyValue("Content").equals(cle))
xPropertySet.setPropertyValue("Content", valeur);
}
}
}
/**
* Remplir le tableau.
* <p>
* @void
* Method qui modifie la variable de classe document donc pas de return
* @param XComponent document
* le document
* @param maTable
* Tableau a 2 dimensions qui contient les données a inséré dans le tableau
*/
private void popultable() throws IndexOutOfBoundsException, WrappedTargetException {
XText xCellText = null;
String contenu = "";
//Acces au table existante du document
XTextTablesSupplier xTablesSupplier = (XTextTablesSupplier) UnoRuntime.queryInterface(XTextTablesSupplier.class, document );
XNameAccess xNamedTables = xTablesSupplier.getTextTables();
//Index des Tables existantes
XIndexAccess xIndexedTables = (XIndexAccess) UnoRuntime.queryInterface(XIndexAccess.class, xNamedTables);
//Pour chaque table ( Dans mon cas a priori une seule)
for (int i = 0; i < xIndexedTables.getCount(); i++) {
//Récupération de l'interface Table
Object table = xIndexedTables.getByIndex(i);
XTextTable xTextTable = (XTextTable) UnoRuntime.queryInterface(XTextTable.class, table);
//Récupération de sa collection de lignes
XTableRows rows = xTextTable.getRows();
//On enleve toutes les linges sauf celles des en-têtes
rows.removeByIndex(1,(rows.getCount()-2));
//On insere autant de ligne dont on a besoin.
rows.insertByIndex(rows.getCount(), maTable[0].length-1);
//Remplissage de gauche vers droite et de haut vers le bas en commencant par la 2eme ligne(La premiere contenant les titres).
for (int j = 0; j<maTable[0].length; j++){
for (int k = 0;k<maTable.length;k++){
contenu = maTable[k][j];
//Récupération d'une cellule.
xCellText = (XText) UnoRuntime.queryInterface (XText.class, xTextTable.getCellByName (mesIndex[k]+(j+2)) );
//Remplissage de la cellule
xCellText.setString(contenu);
}
}
}
}
}
ca donne un truc du genre :
Code : Tout sélectionner
try {
new ScenarioBleu(templateDoc, false,name,map,monTab);
}
catch (Exception e){
System.out.println("Connection reset... : ");
KillSOffice.killOpenOffice();
SingletonOOo.reload();
System.out.println("Singleton Reload");
new ScenarioBleu(templateDoc, false,name,map,monTab);
}
finally{
System.out.println("Tout va bien, pfiouuuu");
}