Office 15

SharePoint 2013 : OpenXML Word AltChunk sur CodePlex

Posted on

Hello,

Faisant suite à l’article sur l’utilisation de l ‘API Open XML 2.5 pour générer des documents WORD avec l’utilisation du ALTCHUNK via SharePoint 2013, je vous met à disposition le projet CodePlex.

Lien ici : http://openxmlaltchunk.codeplex.com/

Enjoy !

SharePoint 2013 : OpenXML au Service de SharePoint 3/5

Posted on

Troisième article de notre série consacré à l’utilisation d’OpenXML avec SharePoint 2013 ou 2010, celui-ci sera dédié

à l’utilisation des AltChunk dans nos générations de document WORD.

La problématique est la suivante, comment intégrer du contenu HTML provenant de SharePoint et l’injecter dans notre document.

 

AltChunk Késako ?

 

Dans l’univers OpenXML et normalisé ISO/IEC-29500 Standard Compliance, AltChunk  est défini comme une possibilité d’intégrer des Contenus Externe.

En l’occurrence tout type de format, puisque AltChunk va simplement dans le cadre de document externe établir un lien de relation propre

à l’unicité du Altchunk.  Si l’on schématise cela donne :

image

WordAltChunkProcessing

Dans notre démo nous allons créer un document Word Template en y ajoutant un Content Control en mode Bounding Box :

image

Côté SharePoint, une liste avec une colonne de type HTML où j’ai ajouté un tableau.

image

Dans un premier temps je déclare une classe HTMLBUILDER qui me permettra de mettre mon code SharePoint entre mes balises HTML, dans cette classe j’y déclare une méthode StringBuilder.

public StringBuilder BuilderHtml(string paramhtml)
        {
            StringBuilder xhtmlBuilder = new StringBuilder();
            xhtmlBuilder.Append("<html>");
            xhtmlBuilder.Append("<body>");
            xhtmlBuilder.Append(paramhtml);
            xhtmlBuilder.Append("</body>");
            xhtmlBuilder.Append("</html>");

            return xhtmlBuilder;
        }

 

Une fois ma classe mise en place, j’entame la création d’une méthode qui s’intitule AltChunkMethod

qui aura la capacité de lire mon document word, de récupérer le ContentControl avec

l’alias défini et ensuite de renseigner un nom (ID, de préférence unique) pour créer un altchunk.

    protected static void AltChunkMethod(WordprocessingDocument outDoc, string htmlbuilder, string alias,
string chunkid)
        {
            string altChunkId = chunkid;//se doit d'être unique
            AlternativeFormatImportPart chunk = outDoc.MainDocumentPart.AddAlternativeFormatImportPart
                (AlternativeFormatImportPartType.Xhtml, altChunkId);
            //Utilisation en mémoire d'html
            using (MemoryStream xhtmlStream = new MemoryStream(Encoding.UTF8.GetBytes(htmlbuilder)))
            {
                chunk.FeedData(xhtmlStream);//Injection html

                AltChunk altChunk = new AltChunk();
                altChunk.Id = altChunkId;

                //Parcours dans le document à la recherche d'alias
                var resprocess = from bm in outDoc.MainDocumentPart.Document.Body.Descendants<SdtAlias>()
                                 where bm.Val.Value == alias
                                 select bm;
                var process = resprocess.SingleOrDefault();
                var parent = process.Parent;

                parent.InsertAfterSelf(altChunk);//Insertion dans le ContentControl

            }
        }

Il ne me reste plus qu’a injecter mon contenu HTML. de la façon suivante :

foreach (SPListItem item in listitems)
 {
    /*HTML-RTE*/
    HtmlBuilder html_builder = new HtmlBuilder();
    StringBuilder xhtmlBuilder = html_builder.BuilderHtml(item["Description"].ToString());
    AltChunkMethod(outDoc, xhtmlBuilder.ToString(), "altchunk", "chunkid");
}

Résultat

image

Remarques

Si vous avez plusieurs ContentControl pouvant héberger de l’html, vous vous devrez de rendre l’id du Altchunk unique à chaque parcours, ainsi lors du parcours des items de la liste,vous ne vous retrouverez pas avec toutes vos données dans un seul ContentControl

Projet CodePlex

Vous pouvez trouvez les ressources sur codeplex : http://openxmlaltchunk.codeplex.com/

SharePoint 2013 : OpenXML PowerPoint Generation sur CodePlex

Posted on

Faisant suite à l’article sur l’utilisation de l ‘API Open XML 2.5 pour générer des documents PowerPoint via SharePoint 2013, je vous met à disposition le projet CodePlex, vous permettant de mieux apprendre la techno.

Lien ici : http://openxmlppt.codeplex.com/

Enjoy !

SharePoint 2010 : OpenXML au Service de SharePoint 1/5

Posted on

Commençons par notre première série d’article à travers l’utilisation de “Open XML” pour la génération de documents sous SharePoint.

Le but de cette série est de partager sur les différentes problématiques rencontrées lors de l’utilisation de l’API Open XML sous SharePoint.

Rappel sur le format Open XML

Plutôt que de vous faire une è-nième présentation d’Open XML je vous envoie vers quelques ressources qui vous seront forte utiles pour la compréhension des différentes codes abordés.

Je me baserai sur des exemples du SDK 2.0 plutôt que sur la version CTP 2.5.

Bien que certaines classes ont été dépréciées bon nombre des codes utilisés sont maintenable et ne présentent pas une grande difficulté a porter.

Open XML SDK 2.0 for Microsoft Office: http://www.microsoft.com/en-us/download/details.aspx?id=5124

Open XML MSDN : http://msdn.microsoft.com/en-us/library/bb448854(office.14).aspx

Open XML Developer : http://openxmldeveloper.org/

WordProcessing

Rentrons dans le vif du détail par un petit exemple ou j’ai besoin d’alimenter un tableau dont mes données sont stockées dans SharePoint.

Je créé un tableau de 4 colonnes puis dans mon onglet Développeur, je rajoute un Content Control de type “ Rich Text” au dessus de mon tableau de façon à l’entourer et je lui donne comme nom “tabA”

image_thumb3

Ce document fera office de Template une fois que cela est j’ai une liste SharePoint qui contient 3 items que je vais répéter en ajoutant de façon dynamique à mon tableau.

image_thumb5

Code Inside

using System;
using Microsoft.SharePoint;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using W = DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml.Wordprocessing;
using System.Linq;
using System.Collections.Generic;


namespace OpenXMLDemo
{
    public class Program
    {
        private const string url = "http://spvm/sites/demo";

        public static void Main(string[] args)
        {
            Console.WriteLine("/*Génération Document Word Sample*/n");
            GenerateDocument();
            Console.WriteLine("/*Fin*/n");
            Console.ReadKey();
        }


    private static void GenerateDocument()
    {
      Stream docstream = null;
      using (SPSite site = new SPSite(url))
       {
        SPWeb web = site.OpenWeb();
        SPFile spf = web.GetFile("Shared Documents/word-demo.docx");
         if (!spf.Exists)
           { Console.WriteLine("Le Document n'éxiste pasn");}
         else
          { docstream = spf.OpenBinaryStream(); }
         if (docstream != null)
           {Console.WriteLine("Début de la phase de WordProcessingn");
             using (WordprocessingDocument outDoc = WordprocessingDocument.Open(docstream, true))
            {
               MainDocumentPart mainPart = outDoc.MainDocumentPart;
               List<SdtElement> sdtListB = mainPart.Document.Descendants<SdtElement>().ToList();
               SdtElement sB = mainPart.Document.Body.Descendants<SdtElement>().
               Where(r => r.SdtProperties.GetFirstChild<W.Tag>().Val == "tabA").Single();
               W.Table theTable = sB.Descendants<W.Table>().Single();
               W.TableRow theRow = theTable.Elements<W.TableRow>().Last();


                SPList spList = web.Lists.TryGetList("demo");

                 if (spList != null)
                  {
                   SPQuery qry = new SPQuery();
                   qry.ViewFields = @"<FieldRef Name='_x0063_ol1' />" +
                   "<FieldRef Name='_x0063_ol2' /><FieldRef Name='_x0063_ol3' />" +
                    "<FieldRef Name='_x0063_ol4' />";

                    SPListItemCollection listItems = spList.GetItems(qry);
                    foreach (SPListItem item in listItems)
                    {
                        W.TableRow rowCopy = (W.TableRow)theRow.CloneNode(true);

                        rowCopy.Descendants<W.TableCell>().ElementAt(0).Append(new Paragraph
                           (new Run(new W.Text(item["_x0063_ol1"] as string))));
                        rowCopy.Descendants<W.TableCell>().ElementAt(1).Append(new Paragraph
                            (new Run(new W.Text(item["_x0063_ol2"] as string))));
                        rowCopy.Descendants<W.TableCell>().ElementAt(2).Append(new Paragraph
                           (new Run(new W.Text(item["_x0063_ol3"] as string))));
                        rowCopy.Descendants<W.TableCell>().ElementAt(3).Append(new Paragraph
                          (new Run(new W.Text(item["_x0063_ol4"] as string))));
                        theTable.AppendChild(rowCopy);

                    }



                }


               outDoc.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);

             }

           CREATE_OUTPUT_DOC(web, docstream, "word_output", ".docx");

                }
            }

    }


        private static void CREATE_OUTPUT_DOC(SPWeb web, Stream outputStream, string filename, string ext)
        {
            try
            {
                SPList outputLibrary = web.Lists.TryGetList("Shared Documents");


                if (outputLibrary != null)
                {

                    string outputFileUrl = string.Format("{0}/{1}",
                        outputLibrary.RootFolder.ServerRelativeUrl, filename + ext);

                    web.AllowUnsafeUpdates = true;
                    outputLibrary.RootFolder.Files.Add(outputFileUrl, outputStream);
                    web.Update();

                    if (outputStream != null)
                    {
                        outputStream.Dispose();
                    }
                    Console.WriteLine("Le Document a bien été générén");

                }

            }
            catch (Exception ex)
            {
                Console.WriteLine("Erreur de création de Documentn :" + ex.ToString());

            }
        }
    }
}

Lançons notre Application

Vous lancez le code Snippet fournit et normalement si tout ce passe bien vous devriez avoir un nouveau document office avec vos données à l’intérieur

image_thumb7

Résultat

image_thumb10

A bientôt pour le prochain article !

SharePoint 2013 : Mettez des Apps dans votre Ferme

Posted on

Les Apps de SharePoint 2013 vont nous permettre d’étendre les possibilités de la plateforme en nous permettant d’utiliser bon nombre de codes JavaScript, Html5 ou CSS.

Voici un petit exemple des possibilités que ce nouveau format nous offre.

Une App ?

Une App est avant-tout une application web qui est développée, intégrée et enregistrée dans SharePoint.

3 types d’applications existent :

  • AutoHosted
  • Provider-Hosted
  • SharePoint Hosted

 

SharePoint-hosted:

Fourni un environnement isolé du web parent, cette application possède son propre sous-domaine.Vous avez la possibilité d’utiliser les listes, des OOTB WebParts.

En revanche pas de code Server-Side possible, uniquement l’appel au CSOM de JavaScript.

Provider-hosted

Ici c’est votre propre infrastructure d’hébergement.Vous avez la possibilité d’offrir une exposition à vos Apps par l’utilisation de ODATA. Ajoutons que la création d’Event Receiver distants est possible.

Autohosted

Les Services Windows Azure & SQL Azure vous fournissent un support supplémentaire. Principalement vous utiliserez les API REST + OAuth ou le CSOM.

 

Application

Dans ce schéma vous pouvez trouver les principales possibilité qu’offre les APPS dans votre UI SharePoint

SharePoint app UX extensions

un petit lien pour aller plus loin : http://msdn.microsoft.com/en-us/library/fp179922(v=office.15).aspx#AccessingApp

 

Installation

Ma Plateforme de test est la suivante :

  • Windows Server 2012 RTM
  • SharePoint 2013 RTM
  • SQL Server 2012
  • Visual Studio 2012

Commande PowerShell

Set-SPAppDomain “sps.local”

$account = New-SPManagedAccount

Une authentification est demandée si vous voulez un nouveau compte de management sinon vous pouvez très bien renseigner un compte directement comme ci-dessous

$account = Get-SPManagedAccount “spsadministrateur”

$appPoolSubSvc = New-SPServiceApplicationPool -Name SettingsServiceAppPool -Account $account

$appPoolAppSvc = New-SPServiceApplicationPool -Name AppServiceAppPool -Account $account

$appSubSvc = New-SPSubscriptionSettingsServiceApplication –ApplicationPool $appPoolSubSvc –Name SettingsServiceApp –DatabaseName SettingsServiceDB

$proxySubSvc = New-SPSubscriptionSettingsServiceApplicationProxy –ServiceApplication $appSubSvc

$appAppSvc = New-SPAppManagementServiceApplication -ApplicationPool $appPoolAppSvc -Name AppServiceApp -DatabaseName AppServiceDB

$proxyAppSvc = New-SPAppManagementServiceApplicationProxy -ServiceApplication $appAppSvc Set-SPAppSiteSubscriptionName -Name “myapp” -Confirm:$false

Les services sont crées et disponible dans la centrale

image

image

Une fois cela effectué. L’on peut ouvrir Visual Studio 2012 commencer à créer un projet “ App pour SharePoint 2013”, et choisir “ SharePoint hosted”.

Vous pouvez aussi déployer votre application  en l’ajouter depuis l’interface.

Dans App in Testing > New App to Deploy puis

image

Et récupérer votre App dans le dossier “binDebugapp.publishSharePointApp3.app” de votre solution

Une fois deployée cliquez sur Trust It

image

Guide des Erreurs courantes

 

Si vous avez cette erreur : “there are no adresses available for this application

Cela peut correspondre au fait que vous ayez des doublons de services ou que l’App Domain n’est pas renseigné.

Si vous avez supprimés vos services  depuis la centrale d’administration et que en essayant vous voulez refaire une installation :

Alors lancer la commande Get-SPServiceApplicationPool | select Id, Name

image

Puis rendez-vous dans IIS Manager

image

et cliquez sur Afficher les Applications.

Une dépendance est présente, cliquez dessus et changer le pool vers .Net 4.0 Classic. Et il vous sera possible de retirer le AppServiceAppPool.

Puis Supprimer  SettingsServiceAppPool en premier par commande :

image

suivi de de la suppression dans la centrale d’administration du AppService

puis de la commande :

image

 

 

Pour aller plus loin le lien de la MSDN sur ce sujet : http://msdn.microsoft.com/en-us/library/fp179930(v=office.15).aspx

MVP SharePoint 2012

Posted on

Hello à tous !

C’est avec une immense joie que je vous annonce que j’ai été nommé MVP SharePoint Server.

Un grand Merci à Microsoft.

Voici mon profil sur la plateforme MVP : Nabil BABACI MVP SharePoint

 

SharePoint 2010-2013 / InfoPath : InfoPath XSN Modifier sur CodePlex

Posted on

Salut à tous,

J’ai publié un petit tool destiné à éditer rapidement les DATA CONNECTIONS dans les formulaires InfoPath de façon dynamique.

Il vous permettra de faire un UNPACK du XSN ( Format CAB), puis de modifier / remplacer les adresses de vos connections, notamment SharePoint, et de vous fournir un nouveau template XSN tout beau tour propre.

Et bien évidemment il fonctionne aussi pour Office 2013.

Lien ici : http://infopathxsn.codeplex.com/

Bonne utilisation

 

Office 2013 – Interview chez Microsoft France

Posted on

Hello à tous

Une petite vidéo sur Office 2013 en tant que MSP tournée chez Microsoft France :

Source : http://www.blogoffice.fr/education

TechDays 2012 – Ask The Expert

Posted on

C’est avec une grande joie que je serai présent aux TechDays 2012 en tant qu’ATE (Ask-The-Expert) dans le pôle Efficacité Collective et Individuelle .

De plus je serai aussi sur le stand Communautaire ExiaMS (http://www.exiams.fr/).

@bientôt