Thursday, July 17, 2014

Open XML SDK - Generate documents from office word template in sharepoint server 2013

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using DataBinding = DocumentFormat.OpenXml.Wordprocessing.DataBinding;
using Ds = DocumentFormat.OpenXml.CustomXmlDataProperties;
using System.Xml;
using System.Text.RegularExpressions;
using OpenXmlPowerTools;
using System.IO;
using System.Data;
using System.Text;
using System.Collections.Generic;
using System.Xml.Linq;

using Microsoft.JScript.Vsa;

using Microsoft.JScript.Vsa;

#region Read Template
        protected System.Collections.Generic.List<SPListItem> ListItems;
        private void ReadTemplate()
        {
            string ListId = SourceListID.Substring(1, SourceListID.Length - 2).ToLower();
            Guid sourceID = new Guid(ListId);
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite spSite = new SPSite(SPContext.Current.Web.Url + "/sites/training"))
                {
                    using (SPWeb spWeb = spSite.OpenWeb())
                    {
                        spWeb.AllowUnsafeUpdates = true;
                        SPDocumentLibrary sourceDocLib = (SPDocumentLibrary)spWeb.Lists[sourceID];
                        // Get template file
                        SPFile template = sourceDocLib.GetItemById(Convert.ToInt32(SelectedItemId)).File;
                        string fileName = Path.GetFileNameWithoutExtension(template.Name) + "-" + Convert.ToString(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")).Replace(":", "").Replace("-", "").Replace(" ", "-") + Path.GetExtension(template.Name);
                        // Copy file to destination document library
                        template.CopyTo(destDocumentLibName + "/" + fileName, false);
                        // Get copied file from destination document library
                        SPDocumentLibrary spList = (SPDocumentLibrary)spWeb.Lists.TryGetList(destDocumentLibName);
                        if (spList != null)
                        {
                            SPQuery qry = new SPQuery();
                            qry.Query =
                            string.Format(@"<Where>
                              <Eq>
                                 <FieldRef Name='FileLeafRef' />
                                 <Value Type='File'>{0}</Value>
                              </Eq>
                           </Where>
                           <OrderBy>
                              <FieldRef Name='FileLeafRef' />
                           </OrderBy>", fileName);
                            qry.ViewFields = @"<FieldRef Name='FileLeafRef' />";
                            qry.RowLimit = 1;
                            SPListItemCollection listItems = spList.GetItems(qry);
                            SPListItem item = listItems[0];
                            SPFile destFile = item.File;

                            GenerateDocumentFromTemplate(spWeb, destFile);
                        }
                        spWeb.AllowUnsafeUpdates = false;
                    }
                }
            });
        }
        #endregion


       #region Generate document from template
        private void GenerateDocumentFromTemplate(SPWeb web, SPFile file)
        {
            string docPlainText = string.Empty;
            Dictionary<string, string> Lists = new Dictionary<string, string>();

            using (MemoryStream memoryStream = new MemoryStream())
            {
                byte[] byteArray = file.OpenBinary();
                memoryStream.Write(byteArray, 0, byteArray.Length);

                using (WordprocessingDocument myDoc = WordprocessingDocument.Open(memoryStream, true, new OpenSettings()))
                {                   
                    // Read all list(s) name(s) from document                   
                    #region Iterate template document and get find lists used in template
                    string s = myDoc.MainDocumentPart.Document.Body.InnerText;
                    Regex r = new Regex(@"{{(.+?)}}");
                    MatchCollection mc = r.Matches(s);

                    string tempString = string.Empty;
                    foreach (Match m in mc)
                    {
                        if (m.Value.Contains("{{") && m.Value.Contains("}}") && m.Value.Contains(":"))
                        {
                            tempString = m.Value.Replace("{{", "").Replace("}}", "").Split(':')[0];

                            if (Lists.ContainsValue(tempString) == false)
                            {
                                Lists.Add(tempString, tempString);
                            }
                        }
                        else
                        {
                            lblMsg.Text += "Template is not in proper format!! Should be in {{Listname:columnName}}- GenerateDocumentFromTemplate()";
                        }
                    }
                    #endregion

                }
            }
            using (MemoryStream memoryStream = new MemoryStream())
            {
                byte[] byteArray = file.OpenBinary();
                memoryStream.Write(byteArray, 0, byteArray.Length);
                using (WordprocessingDocument myDoc = WordprocessingDocument.Open(memoryStream, true, new OpenSettings()))
                {
                    // acept revision
                    RevisionAccepter.AcceptRevisions(myDoc);

                    #region Process list one by one
                    SPListItemCollection items = null;
                    SPList list = null;

                    foreach (KeyValuePair<string, string> listname in Lists)
                    {
                        if (string.IsNullOrEmpty(listname.Value) == false)
                        {
                            list = GetSPList(listname.Value);
                            if (list != null)
                            {
                                items = GetListItems(list);
                                if (items.Count > 0)
                                {
                                    foreach (SPListItem item in items)
                                    {
                                        foreach (SPField field in list.Fields)
                                        {
                                            if (field.Hidden == false)
                                            {

                                                TextReplacer.SearchAndReplace(myDoc, "{{" + list.Title + ":" + field.InternalName + "}}", Convert.ToString(item[field.InternalName]), false);
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    lblMsg.Text += "</br>  list " + listname.Value + " Items count is not valid!! -- GenerateDocumentFromTemplate()";
                                }
                            }
                            else
                            {
                                lblMsg.Text += "</br> list " + listname.Value + " is null !! -- GenerateDocumentFromTemplate()";
                            }
                        }
                    }
                    // Process math formula
                    XDocument xDoc = myDoc.MainDocumentPart.GetXDocument();
                    Dictionary<string, string> formulaLists = GetAllFormulasInDocument(xDoc);
                    foreach (KeyValuePair<string, string> item in formulaLists)
                    {
                        string calcResult = CalculateFormula(item.Value.Replace("Formula", "").Replace("(", "").Replace(")", ""));
                        TextReplacer.SearchAndReplace(myDoc, item.Key, calcResult, false);
                    }
                    #endregion
                }
                #region overright generated document in destination document library
                string linkFileName = string.Empty;
                linkFileName = file.Item["FileRef"].ToString();
                file.ParentFolder.Files.Add(linkFileName, memoryStream, true);
                string str = "<a href='/sites/Training/GenDocs/Forms/AllItems.aspx' target='_blank' >Go to documents</a>";
                lblMsg.Text = "Document generated successfully. &nbsp;&nbsp;&nbsp;&nbsp;" + str;
                #endregion
            }
        }
        #endregion


public string CalculateFormula(string evaluationString)
        {
            Object result = null;
            try
            {
                VsaEngine en = VsaEngine.CreateEngine();
                result = Microsoft.JScript.Eval.JScriptEvaluate(evaluationString, en);               
            }
            catch
            {
                //lblMsg.Text += "<br/> CalculateFormula() -" +ex.Message;
            }
            return result.ToString();

        }

No comments:

Post a Comment