Hi All,
i am trying to added Document ID at the footer of Word file programatically using the following code. Following code is working only when i am uploading the document first time and its adding the ID at the footer. But problem is when i am uploading same file into same document library, document Id is just going away. i have tried to use ItemUpdated method but it doesn't work. what i need to modify into code, so that same document ID will be remains at the footer of document no matter how many times uploaded document. any help will greatly appreciated.
using System;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;
using System.IO;
using System.IO.Packaging;
using DocumentFormat.OpenXml.Packaging;
using System.Xml;
using System.Collections.Generic;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
namespace AddHeaderFooterReceiver.ItemAddedEventReceiver
{
/// <summary>
/// List Item Events
/// </summary>
public class ItemAddedEventReceiver : SPItemEventReceiver
{
/// <summary>
/// An item was added.
/// </summary>
public string GetFooter()
{
string footerVal = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><w:ftr xmlns:ve=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"
xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" xmlns:v=\"urn:schemas-microsoft-com:vml\"
xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\"><w:p
w:rsidR=\"00C24C70\" w:rsidRDefault=\"00C24C70\"><w:pPr><w:pStyle w:val=\"Footer\" /></w:pPr><w:r><w:t>Hi</w:t></w:r></w:p><w:p w:rsidR=\"00C24C70\" w:rsidRDefault=\"00C24C70\"><w:pPr><w:pStyle
w:val=\"Footer\" /></w:pPr></w:p></w:ftr>";
return footerVal;
}
public void WDAddFooter(Stream footerContent, Stream fileContent)
{
// Given a document name, and a stream containing valid footer content,
// add the stream content as a footer in the document.
const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
const string wordmlNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
const string footerContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml";
const string footerRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer";
const string relationshipNamespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
PackagePart documentPart = null;
using (Package wdPackage = Package.Open(fileContent, FileMode.Open, FileAccess.ReadWrite))
{
// Get the main document part (document.xml).
foreach (System.IO.Packaging.PackageRelationship relationship in wdPackage.GetRelationshipsByType(documentRelationshipType))
{
Uri documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), relationship.TargetUri);
documentPart = wdPackage.GetPart(documentUri);
// There is only one officeDocument.
break;
}
Uri uriFooter = new Uri("/word/footer1.xml", UriKind.Relative);
if (wdPackage.PartExists(uriFooter))
{
// Although you can delete the relationship
// to the existing node, the next time you save
// the document after making changes, Word
// will delete the relationship.
wdPackage.DeletePart(uriFooter);
}
// Create the footer part.
PackagePart footerPart = wdPackage.CreatePart(uriFooter, footerContentType);
// Load the content from the input stream.
// This may seem redundant, but you must read it at some point.
// If you ever need to analyze the contents of the footer,
// at least it is already in an XmlDocument.
// This code uses the XmlDocument object only as
// a "pass-through" -- giving it a place to hold as
// it moves from the input stream to the output stream.
// The code could read each byte from the input stream, and
// write each byte to the output stream, but this seems
// simpler...
XmlDocument footerDoc = new XmlDocument();
footerContent.Position = 0;
footerDoc.Load(footerContent);
// Write the footer out to its part.
footerDoc.Save(footerPart.GetStream());
// Create the document's relationship to the new part.
PackageRelationship rel = documentPart.CreateRelationship(uriFooter, TargetMode.Internal, footerRelationshipType);
string relID = rel.Id;
// Manage namespaces to perform Xml XPath queries.
NameTable nt = new NameTable();
XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
nsManager.AddNamespace("w", wordmlNamespace);
// Get the document part from the package.
// Load the XML in the part into an XmlDocument instance.
XmlDocument xdoc = new XmlDocument(nt);
xdoc.Load(documentPart.GetStream());
// Find the node containing the document layout.
XmlNode targetNode = xdoc.SelectSingleNode("//w:sectPr", nsManager);
if (targetNode != null)
{
// Delete any existing references to footers.
//XmlNodeList footerNodes = targetNode.SelectNodes("./w:footerReference", nsManager);
//foreach (System.Xml.XmlNode footerNode in footerNodes)
//{
// targetNode.RemoveChild(footerNode);
//}
// Create the new footer reference node.
XmlElement node = xdoc.CreateElement("w:footerReference", wordmlNamespace);
XmlAttribute attr = node.Attributes.Append(xdoc.CreateAttribute("r:id", relationshipNamespace));
attr.Value = relID;
node.Attributes.Append(attr);
targetNode.InsertBefore(node, targetNode.FirstChild);
}
// Save the document XML back to its part.
xdoc.Save(documentPart.GetStream(FileMode.Create, FileAccess.Write));
}
}
public override void ItemAdded(SPItemEventProperties properties)
{
string extension = properties.ListItem.Url.Substring(properties.ListItem.Url.LastIndexOf(".") + 1);
if (extension == "docx")
{
//string headerContent = GetHeader().Replace("hello", properties.ListItem["Name"].ToString());
//string footerContent = GetFooter().Replace("Hi", properties.ListItem["Modified"].ToString());
//string footerContent = GetFooter().Replace("Hi", properties.ListItem["_dlc_DocId"].ToString() + " V : " +properties.ListItem["_UIVersionString"].ToString());
string footerContent = GetFooter().Replace("Hi", properties.ListItem["_dlc_DocId"].ToString());
//string footerContent1 = GetFooter().Replace("Hi", properties.ListItem["_UIVersionString"].ToString());
//Stream headerStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(headerContent));
//Stream footerStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(footerContent));
Stream footerStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(footerContent));
//Stream footerStream1 = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(footerContent1));
MemoryStream fileStream = new MemoryStream();
fileStream.Write(properties.ListItem.File.OpenBinary(), 0, (int)properties.ListItem.File.TotalLength);
//WDAddHeader(headerStream, fileStream);
//WDAddFooter(footerStream, fileStream);
WDAddFooter(footerStream, fileStream);
//WDAddFooter(footerStream1, fileStream);
properties.ListItem.File.SaveBinary(fileStream);
}
}
}