Comment insérer du contenu dans un document Word 2013 depuis une App Office ?

L'arrivée des Apps pour Office nous permet d'envisager de nouveaux scénarios d'intégration d'applications directement dans la suite Office (Excel, Word, PowerPoint ou Project).

On va voir dans cet article comment on peut intéragir avec un document Word pour y insérer des données depuis une application Office.

Création d'une application Office

Pour créer une nouvelle App Office avec Visual Studio 2013, il suffit de créer un nouveau projet de type App for Office 2013.

Template Visual Studio App for Office

Le setup permet de définir quel type d'app on souhaite créer (dans notre cas, on va garder Task pane app in pour créer une application qui apparaîtra dans un panneau latéral).

Setup Template Visual Studio App for Office

La solution créée va contenir 2 projets, un projet Web correspondant à l'application que l'on va créer et un projet Office qui sera chargé d'intégrer l'application Web dans Office. Le fichier office.js du projet Web (situé dans le répertoire Scripts/Office/1.0/ ou accessible via le CDN https://appsforoffice.microsoft.com/lib/1.0/hosted/office.js) contient toutes les API Javascript exposées par Office. C'est avec cette API que nous allons travailler.

Structure projet Visual Studio App For Office

Accès au document en Javascript

Avant de pouvoir utiliser les API Office, il va falloir attendre que le contexte du document ait eu le temps de s'initialiser. Pour cela, il faut utiliser la syntaxe suivante :

Office.initialize = function () {
    // Le contexte est maintenant initialisé
}

Pour accéder au document courant, l'API Javascript fournit un objet Document :

Office.context.document

Insertion de contenu

L'insertion de contenu va se faire via la méthode setSelectedDataAsync de l'objet document. Cette méthode permet d'insérer du contenu uniquement à la position du curseur (si une sélection est en cours, le contenu sera remplacé).

Le premier paramètre à passer à la méthode est le contenu à insérer. Le deuxième paramètre correspond aux options de l'insertion et va nous permettre de stipuler le type de données (via la propriété coercionType) que l'on va insérer (ex: texte, html, xml au format Office Open XML, etc.). Le troisième et dernier paramètre est un callback qui sera exécuté quand l'insertion aura été réalisée ou aura échouée.

Pour ajouter du texte, l'appel ressemblera à :

Office.context.document.setSelectedDataAsync("Mon message inséré",
    { coercionType : "text" }, 
    function(asyncResult) {
        // Callback
    });

Pour ajouter du code html, l'appel ressemblera à :

Office.context.document.setSelectedDataAsync("Mon message inséré",
    { coercionType : "html" }, 
    function(asyncResult) {
        // Callback
    });

Pour ajouter un template Office Open XML, l'appel ressemblera à :

Office.context.document.setSelectedDataAsync(templateOoxml,
    { coercionType : "ooxml" }, 
    function(asyncResult) {
        // Callback
    });

Utilisation des bindings

Evidemment, l'insertion de contenu uniquement au niveau de la position du curseur est très limitant. Pour contourner cela, on va avoir la possibilité d'insérer du contenu dans des Rich Text Content Control en passant par la fonctionnalité de binding.

Création des Rich Text Content Control dans le document Word

La création de Rich Text Content Control se fait via l'onglet Developer de Word. Pour l'activer, il faut aller dans le menu File > Options > Customize Ribbon et cocher Developer.

Activation onglet Developper

A partir de l'onglet Developer, on aura un bouton Rich Text Content Control qui va en insérer un dans le document Word. Une fois inséré, le bouton Properties va nous permettre de définir un titre au contrôle, que nous utiliserons plus tard pour créer le binding.

Toolbox Word Rich Text Content Control Properties Word Rich Text Content Control

Création du binding sur les Rich Text Content Control

Pour pouvoir intéragir avec le Rich Text Content Control depuis l'app Office, il va falloir passer par la fonctionnalité de binding de l'API Office. La première étape va consister à créer un binding sur le contrôle en utilisant la méthode addFromNamedItemAsync de la propriété bindings de l'objet document.

Les paramètres à passer vont être le titre du contrôle (défini lors de sa création), le type de binding (pour l'insertion de texte, ce sera "text"), des options pour notamment définir l'id du binding (qui nous sera utile pour y insérer du contenu) et une fonction de callback qui sera appelée quand le binding aura été effectué, avec succès ou non. La syntaxe sera la suivante pour créer un binding, dont l'id sera "MonBinding", sur un contrôle, dont le titre serait "MonContentControl" :

Office.context.document.bindings.addFromNamedItemAsync(
    "MonContentControl", 
    "text", 
    { id: "MonBinding" }, 
    function (asyncResult) {
    });

Maintenant que le binding est en place, on va pouvoir utiliser la méthode select de l'API pour le sélectionner puis la méthode setDataAsync pour y appliquer un contenu. La méthode select prend un sélecteur, de la forme bindings#{IdDuBinding} pour sélectionner un binding via son id, ce qui donnerait dans notre exemple :

Office.select("bindings#MonBinding")

La méthode setDataAsync prend en paramètre le contenu à insérer, des options permettant notamment de renseigner le type de données à insérer ainsi qu'un callback (de manière identique à la méthode setSelectedDataAsync vu précédemment).

Pour appliquer un contenu au binding, il faut utiliser la syntaxe suivante :
Office.select("bindings#MonBinding")
      .setDataAsync("Mon texte bindé", { coercionType: "text" });

Insertion des Rich Text Content Control depuis l'app Office

On a vu comment créer un Rich Text Content Control directement depuis Word puis comment y appliquer un contenu depuis l'App Office, en utilisant un binding. Si le document Word ne contient pas les Rich Text Content Control attendus (par exemple si l'utilisateur n'utilise pas un template Word contenant ces contrôles), la création du binding échouera et l'insertion ne pourra pas se faire.

Pour éviter cela, on peut insérer les Rich Text Content Control en utilisant la méthode setSelectedDataAsync vue précédemment (donc malheureusement uniquement au niveau du curseur). Le seul moyen d'insérer ces contrôles est de passer par le format ooxml en utilisant la syntaxe suivante :

Office.context.document.bindings.addFromNamedItemAsync(
    "MonContentControl",
    "text",
    { id: "MonBinding" },
    function (asyncResult) {
        if(asyncResult.status == "failed" 
           && asyncResult.error.message == "The named item does not exist.") {
	       Office.context.document.setSelectedDataAsync(templateOoxml
                   , { coercionType: 'ooxml' });
        }		
    }
);

Dans le callback de la création du binding, si la création n'a pas pu se faire et que l'erreur indique que le Rich Text Content Control "MonContentControl" n'existe pas, on insert le template ooxml (contenant ce contrôle).

On peut maintenant réappliquer les bindings et l'insertion pourra se faire avec succès :

Office.context.document.bindings.addFromNamedItemAsync(
    "MonContentControl",
    "text",
    { id: "MonBinding" },
    function (asyncResult) {
        if(asyncResult.status == "failed" 
           && asyncResult.error.message == "The named item does not exist.") {
	       Office.context.document.setSelectedDataAsync(templateOoxml
                , { coercionType: 'ooxml' }
                , function () {
                    Office.context.document.bindings.addFromNamedItemAsync(
						"MonContentControl",
						"text",
						{ id: "MonBinding" });
				});
        }
    }
);

Création du template ooxml

Il nous reste maintenant à créer le template ooxml contenant le ou les Rich Text Content Controls. Pour cela, on va créer un nouveau document Word et y ajouter tout le contenu souhaité (contenu, Rich Text Content Controls, mise en page, etc.). Une fois sauvegardé, il faut dézipper le document .docx.

Word dézippé

Les deux fichiers qui nous intéressent sont les fichiers document.xml et styles.xml situés dans le dossier word du document dézippé.

Word dézippé

Pour créer le template, il faut insérer le contenu de ces fichiers (sans l'entête xml) dans la structure suivante et enregistrer le fichier au format xml :

<pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">
  <pkg:part pkg:name="/_rels/.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="512">
    <pkg:xmlData>
      <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
      </Relationships>
    </pkg:xmlData>
  </pkg:part>
  <pkg:part pkg:name="/word/_rels/document.xml.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="256">
    <pkg:xmlData>
      <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
      </Relationships>
    </pkg:xmlData>
  </pkg:part>
  <pkg:part pkg:name="/word/document.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml">
    <pkg:xmlData>
<!-- Insérez le xml du fichier document.xml ici :
     Ex:
      <w.document [...]>
      </w:document>
-->     
    </pkg:xmlData>
  </pkg:part>
  <pkg:part pkg:name="/word/styles.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml">
    <pkg:xmlData>
<!-- Insérez le xml du fichier styles.xml ici :
     Ex:
      <w:styles [...]>
      </w:styles>
-->
    </pkg:xmlData>
  </pkg:part>
</pkg:package>

Le template ooxml est maintenant prêt à être inséré.

Bonne insertion !

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus