Marquer un document openxml en tant que final

Contenu du snippet

Word 2007 utilise le format de fichier OpenXML que l'on peut manipuler très facilement avec .net 3 via le namespace System.IO.Packaging. Via l'interface de Word 2007 on peut marquer le document en tant que finale (mark as final) ainsi le document n'est plus modifiable via Word 2007, il est en lecture seule.

Ce code permet de reproduire la fonction "Mark As Final" de Word. Pour cela il faut modifier la propriété "_MarkAsFinal" des "Custom Properties" d'un document OpenXML.

Source / Exemple :


using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Packaging;
using System.IO;
using System.Xml;
using System.Diagnostics;

namespace CS.Utilities 
{
    public static class OpenXMLHelper
    {

        public static void MarkAsFinal(String docxPath)
        {
            MarkAsFinal(docxPath, true);
        }

        public static void MarkAsFinal(String docxPath, Boolean markAsFinal)
        {

            const String K_customPropertiesContentType = "application/vnd.openxmlformats-officedocument.custom-properties+xml";
            const String K_customPropertiesRelationType = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties";

            // chargement du package
            Package package = Package.Open(docxPath);

            // on positionne une propriété du package mais cela ne suffit pas pour que le document soit marqué comme "Final"
            if (markAsFinal)
                package.PackageProperties.ContentStatus = "Final";
            else if (package.PackageProperties.ContentStatus == "Final")
                package.PackageProperties.ContentStatus = String.Empty;

            // On va éditer les Custom Properties du document

            // Récuperation de l'uri de la partie
            Uri uri = new Uri(@"/docProps/custom.xml", UriKind.Relative);

            // obtention ou création de la partie (les custom properties) 
            PackagePart part;
            if (package.PartExists(uri))
            {
                part = package.GetPart(uri);
            }
            else
            {
                part = package.CreatePart(uri, K_customPropertiesContentType);
                XmlDocument basicDoc = new XmlDocument();
                basicDoc.LoadXml(@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
                                <Properties xmlns=""http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"" xmlns:vt=""http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"">
                                </Properties>");
                StreamWriter sw = new StreamWriter(part.GetStream(FileMode.Create, FileAccess.ReadWrite));
                basicDoc.Save(sw);
                sw.Close();
                sw.Dispose();
            }

            // modification de la partie 
            XmlDocument doc = new XmlDocument();
            doc.Load(part.GetStream());

            XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
            nsmgr.AddNamespace("vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
            nsmgr.AddNamespace("def", "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties");

            // on modifie notre document XML pour qu'il ait ces tags 
            //<property fmtid=""{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"" pid=""2"" name=""_MarkAsFinal"">
            //    <vt:bool>true</vt:bool>
            //</property>

            XmlNode node = doc.SelectSingleNode(@"/def:Properties/def:property[@name=""_MarkAsFinal""]/vt:bool", nsmgr);
            if (node != null)
            {
                node.InnerText = markAsFinal ? "true" : "false";
            }
            else
            {
                node = doc.SelectSingleNode(@"/def:Properties/def:property[@name=""_MarkAsFinal""]", nsmgr);
                if (node != null)
                {
                    XmlNode valueNode = doc.CreateElement("vt:bool", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
                    valueNode.InnerText = markAsFinal ? "true" : "false";
                    node.AppendChild(valueNode);
                }
                else
                {
                    XmlNode markAsFinalNode = doc.CreateElement("property", "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties");

                    XmlAttribute fmtIDAttribute = doc.CreateAttribute("fmtid");
                    fmtIDAttribute.Value = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}";
                    markAsFinalNode.Attributes.Append(fmtIDAttribute);

                    // le pid minimum est 2, on regarde le maximum et on lui rajoute 1 
                    XmlNodeList pidNodes = doc.SelectNodes(@"/def:Properties/def:property/@pid", nsmgr);
                    int pid = 1;
                    foreach (XmlNode pidNode in pidNodes)
                    {
                        if (int.Parse(pidNode.Value) > pid)
                            pid = int.Parse(pidNode.Value);
                    }

                    pid += 1;

                    XmlAttribute pidAttribute = doc.CreateAttribute("pid");
                    pidAttribute.Value = pid.ToString();
                    markAsFinalNode.Attributes.Append(pidAttribute);

                    XmlAttribute nameAttribute = doc.CreateAttribute("name");
                    nameAttribute.Value = "_MarkAsFinal";
                    markAsFinalNode.Attributes.Append(nameAttribute);

                    XmlNode valueNode = doc.CreateElement("vt:bool", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
                    valueNode.InnerText = markAsFinal ? "true" : "false";
                    markAsFinalNode.AppendChild(valueNode);

                    doc.DocumentElement.AppendChild(markAsFinalNode);
                }

                package.CreateRelationship(uri, TargetMode.Internal, K_customPropertiesRelationType);
            }

            // enregistrement du document 
            doc.Save(part.GetStream());

            package.Flush();
            package.Close();
        }
   }
}

Conclusion :


Cet article explique comment modifier les custom properties d'un document OpenXML via le code et via l'interface Word 2007
http://msdn2.microsoft.com/en-us/library/bb308936.aspx

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.