SharePoint 2010: Read content
controls values from Microsoft Word via OpenXml and save as Metadata (properties) of a Document
Set on Event Reciever (C#.Net)
Context: The
customer wants to use the Microsoft Word to fill up his data on a daily basis. They
want a functionality in SharePoint that when a document is uploaded into the document
set of a document library then all the data from a word document should be synchronized
into the document set.
Solution: The
solution I proposed is to use content controls in the word document and later I
will use event receiver to read the information from a word document and update
that information into the (metadata) properties of the document set.
I used ‘ItemAdded’
event receiver for reading the word document via Open Xml sdk 2.0. The following
is the code for reading the word document and updating the information of a
word document into the document set properties;
////// An item was added. /// public override void ItemAdded(SPItemEventProperties properties) { if (properties.ListTitle == "ListName") { if (IsFolder(properties.ListItem) == false) { DocumentSet documentSet = GetDocumentSet(properties); SPFile spfile = properties.ListItem.File; if (spfile.Name.Contains(".doc")) { if (!spfile.Name.Contains("MetaDataReport")) { byte[] byteArray = spfile.OpenBinary(); using (MemoryStream mem = new MemoryStream()) { mem.Write(byteArray, 0, (int)byteArray.Length); using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true)) { XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"; XDocument xdoc = wordDoc.MainDocumentPart.Annotation(); #region "Read word document and find & get content controls" using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream())) using (XmlReader xr = XmlReader.Create(sr)) xdoc = XDocument.Load(xr); wordDoc.MainDocumentPart.AddAnnotation(xdoc); XElement bodyElement = xdoc .Element(w + "document") .Element(w + "body"); IEnumerable contentControlsTags = bodyElement.Descendants(w + "sdt"); #endregion //Check whether the user is uploading in Document Set or on a Library SPListItem spListItem = null; if (documentSet != null) spListItem = documentSet.Item; else spListItem = properties.ListItem; foreach (XElement contentControlsTag in contentControlsTags) { string strSpFldName = contentControlsTag.Element(w + "sdtPr").Element(w + "tag").Attribute(w + "val").Value.ToString(); string strValue = contentControlsTag.Element(w + "sdtContent").Element(w + "r").Element(w + "t").Value.ToString(); if (spListItem.Fields.ContainsField(strSpFldName)) spListItem[strSpFldName] = strValue; } spListItem.Update(); } } } } } } } /// /// Get document set Object /// private DocumentSet GetDocumentSet(SPItemEventProperties properties) { SPFile spfile = properties.ListItem.File; DocumentSet documentSet = DocumentSet.GetDocumentSet(spfile.ParentFolder); if (documentSet.ParentFolder.Name == properties.List.Title) { if (documentSet != null) return documentSet; } return null; } ////// Check if the item is a folder /// public bool IsFolder(SPListItem item) { return item.Folder != null; } public static class LocalExtensions { public static XDocument GetXDocument(this OpenXmlPart part) { XDocument xdoc = part.Annotation(); if (xdoc != null) return xdoc; using (StreamReader sr = new StreamReader(part.GetStream())) using (XmlReader xr = XmlReader.Create(sr)) xdoc = XDocument.Load(xr); part.AddAnnotation(xdoc); return xdoc; } public static void PutXDocument(this OpenXmlPart part) { XDocument xdoc = part.GetXDocument(); if (xdoc != null) { // Serialize the XDocument object back to the package. using (XmlWriter xw = XmlWriter.Create(part.GetStream (FileMode.Create, FileAccess.Write))) { xdoc.Save(xw); } } } public static string StringConcatenate( this IEnumerable source) { return source.Aggregate( new StringBuilder(), (s, i) => s.Append(i), s => s.ToString()); } } public class Utility { public static string GetStringBySplit(string stringWords, int returnPostion, string[] splitChar) { string[] split = stringWords.Split(splitChar, StringSplitOptions.RemoveEmptyEntries); if (split.Length > 1) return split[returnPostion]; return stringWords; } }
Note: It is not the actual solution but the foundation from
where I started building the solution.
Cheers…. J
No comments:
Post a Comment