Wednesday, June 4, 2014

SharePoint: Read Word document from document libray, make changes and save as a new Word document in a Document set using C#.Net.

Context: I had to read a word template document consisting of content controls from a document library. The next step, I had to do is to read properties of the document set and place data into the content controls. I then have to create a new document based on the word template and changes and later save into the document.


Solution: I used OpenXml to read the word document from the document libarary. Later I made the changes by replacing the values in the XElement objects. Once I have the changes made in the memory, I created a new word document using Microsoft.SharePoint Api(Server object model) and save it into the respective document set. The following is the code that I wrote to achieve this task.



private void ReadTemplateDoc(SPFile spFile, string folderPath)
        {
            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();

                    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");

                    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();
                        //Save the metadata into Templates
                        if (hashtableMetaData[strSpFldName] != null)
                        {
                            string[] separator = { ";#" };
                            string valueMetaData = Utility.GetStringBySplit(hashtableMetaData[strSpFldName].ToString(), 1, separator);
                            contentControlsTag.Element(w + "sdtContent").Element(w + "r").Element(w + "t").SetValue(valueMetaData);
                        }
                    }

                    wordDoc.MainDocumentPart.PutXDocument();

                    string filePath = string.Empty;
                    string fileName = string.Empty;

                    using (SPWeb currentWeb = SPContext.Current.Web)
                    {
                        currentWeb.AllowUnsafeUpdates = true;
                        SPList spList = currentWeb.Lists[listId];
                        string documentSetName = spList.GetItemById(itemId).Name;
                        fileName = documentSetName + " - MetaDataReport.docx";
                        filePath = itemUrl + "/" + fileName;
                        spFile.ParentFolder.Files.Add(filePath, mem, true);
                        currentWeb.AllowUnsafeUpdates = false;
                        //Page.ClientScript.RegisterOnSubmitStatement(typeof(Page), "closePage", "window.onunload = CloseWindow();");
                    }

                    Page.Response.Clear();
                    string htmlMessage = "alert('Metadata report generated named as : " + fileName + "');";
                    this.Page.Response.Write("");
                    Page.Response.End();

                  
                }
            }
        }


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;
        }
    }

No comments:

Post a Comment