예제 #1
0
        static void Main(string[] args)
        {
            var n      = DateTime.Now;
            var tempDi = new DirectoryInfo(string.Format("ExampleOutput-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", n.Year - 2000, n.Month, n.Day, n.Hour, n.Minute, n.Second));

            tempDi.Create();

            WmlDocument originalWml = new WmlDocument("../../Original.docx");
            List <WmlRevisedDocumentInfo> revisedDocumentInfoList = new List <WmlRevisedDocumentInfo>()
            {
                new WmlRevisedDocumentInfo()
                {
                    RevisedDocument = new WmlDocument("../../RevisedByBob.docx"),
                    Revisor         = "Bob",
                    Color           = Color.LightBlue,
                },
                new WmlRevisedDocumentInfo()
                {
                    RevisedDocument = new WmlDocument("../../RevisedByMary.docx"),
                    Revisor         = "Mary",
                    Color           = Color.LightYellow,
                },
            };
            WmlComparerSettings settings        = new WmlComparerSettings();
            WmlDocument         consolidatedWml = WmlComparer.Consolidate(
                originalWml,
                revisedDocumentInfoList,
                settings);

            consolidatedWml.SaveAs(Path.Combine(tempDi.FullName, "Consolidated.docx"));
        }
예제 #2
0
        static void Main(string[] args)
        {
            var n      = DateTime.Now;
            var tempDi = new DirectoryInfo(string.Format("ExampleOutput-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", n.Year - 2000, n.Month, n.Day, n.Hour, n.Minute, n.Second));

            tempDi.Create();

            FileInfo templateDoc = new FileInfo("../../TemplateDocument.docx");
            FileInfo dataFile    = new FileInfo(Path.Combine(tempDi.FullName, "Data.xml"));

            // The following method generates a large data file with random data.
            // In a real world scenario, this is where you would query your data source and produce XML that will drive your document generation process.
            XElement data = GenerateDataFromDataSource(dataFile);

            WmlDocument wmlDoc = new WmlDocument(templateDoc.FullName);
            int         count  = 1;

            foreach (var customer in data.Elements("Customer"))
            {
                FileInfo assembledDoc = new FileInfo(Path.Combine(tempDi.FullName, string.Format("Letter-{0:0000}.docx", count++)));
                Console.WriteLine(assembledDoc.Name);
                bool        templateError;
                WmlDocument wmlAssembledDoc = DocumentAssembler.AssembleDocument(wmlDoc, customer, out templateError);
                if (templateError)
                {
                    Console.WriteLine("Errors in template.");
                    Console.WriteLine("See {0} to determine the errors in the template.", assembledDoc.Name);
                }
                wmlAssembledDoc.SaveAs(assembledDoc.FullName);
            }
        }
예제 #3
0
        static void Main(string[] args)
        {
            var n      = DateTime.Now;
            var tempDi = new DirectoryInfo(string.Format("ExampleOutput-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", n.Year - 2000, n.Month, n.Day, n.Hour, n.Minute, n.Second));

            tempDi.Create();

            WmlComparerSettings settings = new WmlComparerSettings();
            WmlDocument         result   = WmlComparer.Compare(
                new WmlDocument("../../Source1.docx"),
                new WmlDocument("../../Source2.docx"),
                settings);

            result.SaveAs(Path.Combine(tempDi.FullName, "Compared.docx"));

            var revisions = WmlComparer.GetRevisions(result, settings);

            foreach (var rev in revisions)
            {
                Console.WriteLine("Author: " + rev.Author);
                Console.WriteLine("Revision type: " + rev.RevisionType);
                Console.WriteLine("Revision text: " + rev.Text);
                Console.WriteLine();
            }
        }
예제 #4
0
        static void Main(string[] args)
        {
            var n      = DateTime.Now;
            var tempDi = new DirectoryInfo(string.Format("ExampleOutput-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", n.Year - 2000, n.Month, n.Day, n.Hour, n.Minute, n.Second));

            tempDi.Create();

            FileInfo templateDoc = new FileInfo("../../TemplateDocument.docx");
            FileInfo dataFile    = new FileInfo("../../Data.xml");

            WmlDocument wmlDoc = new WmlDocument(templateDoc.FullName);
            XElement    data   = XElement.Load(dataFile.FullName);
            bool        templateError;
            WmlDocument wmlAssembledDoc = DocumentAssembler.AssembleDocument(wmlDoc, data, out templateError);

            if (templateError)
            {
                Console.WriteLine("Errors in template.");
                Console.WriteLine("See AssembledDoc.docx to determine the errors in the template.");
            }

            FileInfo assembledDoc = new FileInfo(Path.Combine(tempDi.FullName, "AssembledDoc.docx"));

            wmlAssembledDoc.SaveAs(assembledDoc.FullName);
        }
        private static WmlDocument HashBlockLevelContent(
            WmlDocument source,
            WmlDocument sourceAfterProc,
            WmlComparerSettings settings)
        {
            using (var msSource = new MemoryStream())
                using (var msAfterProc = new MemoryStream())
                {
                    msSource.Write(source.DocumentByteArray, 0, source.DocumentByteArray.Length);
                    msAfterProc.Write(sourceAfterProc.DocumentByteArray, 0, sourceAfterProc.DocumentByteArray.Length);

                    using (WordprocessingDocument wDocSource = WordprocessingDocument.Open(msSource, true))
                        using (WordprocessingDocument wDocAfterProc = WordprocessingDocument.Open(msAfterProc, true))
                        {
                            // create Unid dictionary for source
                            XDocument sourceMainXDoc = wDocSource.MainDocumentPart.GetXDocument();
                            XElement  sourceMainRoot = sourceMainXDoc.Root ?? throw new ArgumentException();
                            Dictionary <string, XElement> sourceUnidDict = sourceMainRoot
                                                                           .Descendants()
                                                                           .Where(d => d.Name == W.p || d.Name == W.tbl || d.Name == W.tr)
                                                                           .ToDictionary(d => (string)d.Attribute(PtOpenXml.Unid));

                            XDocument afterProcMainXDoc = wDocAfterProc.MainDocumentPart.GetXDocument();
                            XElement  afterProcMainRoot = afterProcMainXDoc.Root ?? throw new ArgumentException();
                            IEnumerable <XElement> blockLevelElements = afterProcMainRoot
                                                                        .Descendants()
                                                                        .Where(d => d.Name == W.p || d.Name == W.tbl || d.Name == W.tr);

                            foreach (XElement blockLevelContent in blockLevelElements)
                            {
                                var cloneBlockLevelContentForHashing = (XElement)CloneBlockLevelContentForHashing(
                                    wDocAfterProc.MainDocumentPart,
                                    blockLevelContent,
                                    true,
                                    settings);

                                string shaString = cloneBlockLevelContentForHashing
                                                   .ToString(SaveOptions.DisableFormatting)
                                                   .Replace(" xmlns=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"", "");

                                string sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(shaString);
                                var    thisUnid = (string)blockLevelContent.Attribute(PtOpenXml.Unid);
                                if (thisUnid != null)
                                {
                                    if (sourceUnidDict.ContainsKey(thisUnid))
                                    {
                                        XElement correlatedBlockLevelContent = sourceUnidDict[thisUnid];
                                        correlatedBlockLevelContent.Add(new XAttribute(PtOpenXml.CorrelatedSHA1Hash, sha1Hash));
                                    }
                                }
                            }

                            wDocSource.MainDocumentPart.PutXDocument();
                        }

                    var sourceWithCorrelatedSHA1Hash = new WmlDocument(source.FileName, msSource.ToArray());
                    return(sourceWithCorrelatedSHA1Hash);
                }
        }
예제 #6
0
 private static void SaveDocumentIfDesired(WmlDocument source, string name, WmlComparerSettings settings)
 {
     if (SaveIntermediateFilesForDebugging && settings.DebugTempFileDi != null)
     {
         var fileInfo = new FileInfo(Path.Combine(settings.DebugTempFileDi.FullName, name));
         source.SaveAs(fileInfo.FullName);
     }
 }
예제 #7
0
 public PtWordprocessingCommentsPart(WmlDocument wmlDocument, Uri uri, XName name, params object[] values)
     : base(name, values)
 {
     ParentWmlDocument = wmlDocument;
     this.Add(
         new XAttribute(PtOpenXml.Uri, uri),
         new XAttribute(XNamespace.Xmlns + "pt", PtOpenXml.pt)
         );
 }
예제 #8
0
 public static WmlDocument SimplifyMarkup(WmlDocument doc, SimplifyMarkupSettings settings)
 {
     using (var streamDoc = new OpenXmlMemoryStreamDocument(doc))
     {
         using (WordprocessingDocument document = streamDoc.GetWordprocessingDocument())
             SimplifyMarkup(document, settings);
         return(streamDoc.GetModifiedWmlDocument());
     }
 }
예제 #9
0
        public static IEnumerable <ValidationErrorInfo> GetOpenXmlValidationErrors(string fileName,
                                                                                   string officeVersion)
        {
#if !NET35
            FileFormatVersions fileFormatVersion = FileFormatVersions.Office2013;
#else
            FileFormatVersions fileFormatVersion = FileFormatVersions.Office2010;
#endif
            try
            {
                fileFormatVersion = (FileFormatVersions)Enum.Parse(fileFormatVersion.GetType(), officeVersion);
            }
            catch (Exception)
            {
#if !NET35
                fileFormatVersion = FileFormatVersions.Office2013;
#else
                fileFormatVersion = FileFormatVersions.Office2010;
#endif
            }

            FileInfo fi = new FileInfo(fileName);
            if (Util.IsWordprocessingML(fi.Extension))
            {
                WmlDocument wml = new WmlDocument(fileName);
                using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(wml))
                    using (WordprocessingDocument wDoc = streamDoc.GetWordprocessingDocument())
                    {
                        OpenXmlValidator validator = new OpenXmlValidator(fileFormatVersion);
                        var errors = validator.Validate(wDoc);
                        return(errors.ToList());
                    }
            }
            else if (Util.IsSpreadsheetML(fi.Extension))
            {
                SmlDocument Sml = new SmlDocument(fileName);
                using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(Sml))
                    using (SpreadsheetDocument wDoc = streamDoc.GetSpreadsheetDocument())
                    {
                        OpenXmlValidator validator = new OpenXmlValidator(fileFormatVersion);
                        var errors = validator.Validate(wDoc);
                        return(errors.ToList());
                    }
            }
            else if (Util.IsPresentationML(fi.Extension))
            {
                PmlDocument Pml = new PmlDocument(fileName);
                using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(Pml))
                    using (PresentationDocument wDoc = streamDoc.GetPresentationDocument())
                    {
                        OpenXmlValidator validator = new OpenXmlValidator(fileFormatVersion);
                        var errors = validator.Validate(wDoc);
                        return(errors.ToList());
                    }
            }
            return(Enumerable.Empty <ValidationErrorInfo>());
        }
예제 #10
0
 public static WmlDocument AcceptRevisions(WmlDocument document)
 {
     using var streamDoc = new OpenXmlMemoryStreamDocument(document);
     using (var doc = streamDoc.GetWordprocessingDocument())
     {
         AcceptRevisions(doc);
     }
     return(streamDoc.GetModifiedWmlDocument());
 }
예제 #11
0
 public static WmlDocument ConvertHtmlToWml(
     string defaultCss,
     string authorCss,
     string userCss,
     XElement xhtml,
     HtmlToWmlConverterSettings settings,
     WmlDocument emptyDocument,
     string annotatedHtmlDumpFileName)
 {
     return(HtmlToWmlConverterCore.ConvertHtmlToWml(defaultCss, authorCss, userCss, xhtml, settings, emptyDocument, annotatedHtmlDumpFileName));
 }
예제 #12
0
        private static void SaveCleanedDocuments(WmlDocument source1, WmlDocument producedDocument, WmlComparerSettings settings)
        {
            if (SaveIntermediateFilesForDebugging && settings.DebugTempFileDi != null)
            {
                WmlDocument cleanedSource = CleanPowerToolsAndRsid(source1);
                SaveDocumentIfDesired(cleanedSource, "Cleaned-Source.docx", settings);

                WmlDocument cleanedProduced = CleanPowerToolsAndRsid(producedDocument);
                SaveDocumentIfDesired(cleanedProduced, "Cleaned-Produced.docx", settings);
            }
        }
예제 #13
0
 public static WmlDocument AddToc(WmlDocument document, string xPath, string switches, string title, int?rightTabPos)
 {
     using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(document))
     {
         using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument())
         {
             AddToc(doc, xPath, switches, title, rightTabPos);
         }
         return(streamDoc.GetModifiedWmlDocument());
     }
 }
예제 #14
0
 public static WmlDocument SearchAndReplace(WmlDocument doc, string search, string replace, bool matchCase)
 {
     using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(doc))
     {
         using (WordprocessingDocument document = streamDoc.GetWordprocessingDocument())
         {
             SearchAndReplace(document, search, replace, matchCase);
         }
         return(streamDoc.GetModifiedWmlDocument());
     }
 }
예제 #15
0
        public static DocxMetrics GetDocxMetrics(string fileName)
        {
            WmlDocument           wmlDoc   = new WmlDocument(fileName);
            MetricsGetterSettings settings = new MetricsGetterSettings();

            settings.IncludeTextInContentControls = false;
            settings.IncludeXlsxTableCellData     = false;
            var         metricsXml = MetricsGetter.GetDocxMetrics(wmlDoc, settings);
            DocxMetrics metrics    = new DocxMetrics();

            metrics.FileName = wmlDoc.FileName;

            metrics.StyleHierarchy      = GetXmlDocumentForMetrics(metricsXml, H.StyleHierarchy);
            metrics.ContentControls     = GetXmlDocumentForMetrics(metricsXml, H.Parts);
            metrics.TextBox             = GetIntForMetrics(metricsXml, H.TextBox);
            metrics.ContentControlCount = GetIntForMetrics(metricsXml, H.ContentControl);
            metrics.ComplexField        = GetIntForMetrics(metricsXml, H.ComplexField);
            metrics.SimpleField         = GetIntForMetrics(metricsXml, H.SimpleField);
            metrics.AltChunk            = GetIntForMetrics(metricsXml, H.AltChunk);
            metrics.Table                  = GetIntForMetrics(metricsXml, H.Table);
            metrics.Hyperlink              = GetIntForMetrics(metricsXml, H.Hyperlink);
            metrics.LegacyFrame            = GetIntForMetrics(metricsXml, H.LegacyFrame);
            metrics.ActiveX                = GetIntForMetrics(metricsXml, H.ActiveX);
            metrics.SubDocument            = GetIntForMetrics(metricsXml, H.SubDocument);
            metrics.ReferenceToNullImage   = GetIntForMetrics(metricsXml, H.ReferenceToNullImage);
            metrics.ElementCount           = GetIntForMetrics(metricsXml, H.ElementCount);
            metrics.AverageParagraphLength = GetIntForMetrics(metricsXml, H.AverageParagraphLength);
            metrics.RunCount               = GetIntForMetrics(metricsXml, H.RunCount);
            metrics.ZeroLengthText         = GetIntForMetrics(metricsXml, H.ZeroLengthText);
            metrics.MultiFontRun           = GetIntForMetrics(metricsXml, H.MultiFontRun);
            metrics.AsciiCharCount         = GetIntForMetrics(metricsXml, H.AsciiCharCount);
            metrics.CSCharCount            = GetIntForMetrics(metricsXml, H.CSCharCount);
            metrics.EastAsiaCharCount      = GetIntForMetrics(metricsXml, H.EastAsiaCharCount);
            metrics.HAnsiCharCount         = GetIntForMetrics(metricsXml, H.HAnsiCharCount);
            metrics.AsciiRunCount          = GetIntForMetrics(metricsXml, H.AsciiRunCount);
            metrics.CSRunCount             = GetIntForMetrics(metricsXml, H.CSRunCount);
            metrics.EastAsiaRunCount       = GetIntForMetrics(metricsXml, H.EastAsiaRunCount);
            metrics.HAnsiRunCount          = GetIntForMetrics(metricsXml, H.HAnsiRunCount);
            metrics.RevisionTracking       = GetBoolForMetrics(metricsXml, H.RevisionTracking);
            metrics.EmbeddedXlsx           = GetBoolForMetrics(metricsXml, H.EmbeddedXlsx);
            metrics.InvalidSaveThroughXslt = GetBoolForMetrics(metricsXml, H.InvalidSaveThroughXslt);
            metrics.TrackRevisionsEnabled  = GetBoolForMetrics(metricsXml, H.TrackRevisionsEnabled);
            metrics.DocumentProtection     = GetBoolForMetrics(metricsXml, H.DocumentProtection);
            metrics.Valid                  = GetBoolForMetrics(metricsXml, H.Valid);
            metrics.Languages              = GetStringForMetrics(metricsXml, H.Languages);
            metrics.NumberingFormatList    = GetStringForMetrics(metricsXml, H.NumberingFormatList);

            return(metrics);
        }
예제 #16
0
        static void Main(string[] args)
        {
            if (args.Length != 3)
            {
                PrintUsage();
                Environment.Exit(0);
            }

            FileInfo templateDoc = new FileInfo(args[0]);

            if (!templateDoc.Exists)
            {
                Console.WriteLine("Error, {0} does not exist.", args[0]);
                PrintUsage();
                Environment.Exit(0);
            }
            FileInfo dataFile = new FileInfo(args[1]);

            if (!dataFile.Exists)
            {
                Console.WriteLine("Error, {0} does not exist.", args[1]);
                PrintUsage();
                Environment.Exit(0);
            }
            FileInfo assembledDoc = new FileInfo(args[2]);

            if (assembledDoc.Exists)
            {
                Console.WriteLine("Error, {0} exists.", args[2]);
                PrintUsage();
                Environment.Exit(0);
            }

            WmlDocument wmlDoc = new WmlDocument(templateDoc.FullName);
            XElement    data   = XElement.Load(dataFile.FullName);
            bool        templateError;
            WmlDocument wmlAssembledDoc = DocumentAssembler.AssembleDocument(wmlDoc, data, out templateError);

            if (templateError)
            {
                Console.WriteLine("Errors in template.");
                Console.WriteLine("See {0} to determine the errors in the template.", assembledDoc.Name);
            }

            wmlAssembledDoc.SaveAs(assembledDoc.FullName);
        }
예제 #17
0
        public static HtmlToWmlConverterSettings GetDefaultSettings(WmlDocument wmlDocument)
        {
            HtmlToWmlConverterSettings settings = new HtmlToWmlConverterSettings();

            using (MemoryStream ms = new MemoryStream())
            {
                ms.Write(wmlDocument.DocumentByteArray, 0, wmlDocument.DocumentByteArray.Length);
                using (WordprocessingDocument wDoc = WordprocessingDocument.Open(ms, false))
                {
                    string majorLatinFont, minorLatinFont;
                    double defaultFontSize;
                    GetDefaultFontInfo(wDoc, out majorLatinFont, out minorLatinFont, out defaultFontSize);
                    settings.MajorLatinFont  = majorLatinFont;
                    settings.MinorLatinFont  = minorLatinFont;
                    settings.DefaultFontSize = defaultFontSize;

                    settings.MinorLatinFont            = "Times New Roman";
                    settings.DefaultFontSize           = 12d;
                    settings.DefaultBlockContentMargin = "auto";
                    settings.DefaultSpacingElement     = new XElement(W.spacing,
                                                                      new XAttribute(W.before, 100),
                                                                      new XAttribute(W.beforeAutospacing, 1),
                                                                      new XAttribute(W.after, 100),
                                                                      new XAttribute(W.afterAutospacing, 1),
                                                                      new XAttribute(W.line, 240),
                                                                      new XAttribute(W.lineRule, "auto"));
                    settings.DefaultSpacingElementForParagraphsInTables = new XElement(W.spacing,
                                                                                       new XAttribute(W.before, 100),
                                                                                       new XAttribute(W.beforeAutospacing, 1),
                                                                                       new XAttribute(W.after, 100),
                                                                                       new XAttribute(W.afterAutospacing, 1),
                                                                                       new XAttribute(W.line, 240),
                                                                                       new XAttribute(W.lineRule, "auto"));

                    XDocument mXDoc          = wDoc.MainDocumentPart.GetXDocument();
                    XElement  existingSectPr = mXDoc.Root.Descendants(W.sectPr).FirstOrDefault();
                    settings.SectPr = new XElement(W.sectPr,
                                                   existingSectPr.Elements(W.pgSz),
                                                   existingSectPr.Elements(W.pgMar));
                }
            }
            return(settings);
        }
예제 #18
0
        private static WmlDocument CleanPowerToolsAndRsid(WmlDocument producedDocument)
        {
            using (var ms = new MemoryStream())
            {
                ms.Write(producedDocument.DocumentByteArray, 0, producedDocument.DocumentByteArray.Length);
                using (WordprocessingDocument wDoc = WordprocessingDocument.Open(ms, true))
                {
                    foreach (OpenXmlPart cp in wDoc.ContentParts())
                    {
                        XDocument xd      = cp.GetXDocument();
                        object    newRoot = CleanPartTransform(xd.Root);
                        xd.Root?.ReplaceWith(newRoot);
                        cp.PutXDocument();
                    }
                }

                var cleaned = new WmlDocument("cleaned.docx", ms.ToArray());
                return(cleaned);
            }
        }
예제 #19
0
        private static void ConvertToDocx(string file, string destinationDir)
        {
            var sourceHtmlFi  = new FileInfo(file);
            var sourceImageDi = new DirectoryInfo(destinationDir);

            var destDocxFi = new FileInfo(Path.Combine(destinationDir, sourceHtmlFi.Name.Replace(".html", "-ConvertedByHtmlToWml.docx")));

            XElement html = HtmlToWmlReadAsXElement.ReadAsXElement(sourceHtmlFi);

            string usedAuthorCss = HtmlToWmlConverter.CleanUpCss((string)html.Descendants().FirstOrDefault(d => d.Name.LocalName.ToLower() == "style"));

            HtmlToWmlConverterSettings settings = HtmlToWmlConverter.GetDefaultSettings();

            // image references in HTML files contain the path to the subdir that contains the images, so base URI is the name of the directory
            // that contains the HTML files
            settings.BaseUriForImages = sourceHtmlFi.DirectoryName;

            WmlDocument doc = HtmlToWmlConverter.ConvertHtmlToWml(defaultCss, usedAuthorCss, userCss, html, settings);

            doc.SaveAs(destDocxFi.FullName);
        }
예제 #20
0
        public static WmlDocument AssembleDocument(WmlDocument templateDoc, XElement data, out bool templateError)
        {
            byte[] byteArray = templateDoc.DocumentByteArray;
            using (MemoryStream mem = new MemoryStream())
            {
                mem.Write(byteArray, 0, (int)byteArray.Length);
                using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))
                {
                    if (RevisionAccepter.HasTrackedRevisions(wordDoc))
                    {
                        throw new OpenXmlPowerToolsException("Invalid DocumentAssembler template - contains tracked revisions");
                    }

                    var te = new TemplateError();
                    foreach (var part in wordDoc.ContentParts())
                    {
                        ProcessTemplatePart(data, te, part);
                    }
                    templateError = te.HasError;
                }
                WmlDocument assembledDocument = new WmlDocument("TempFileName.docx", mem.ToArray());
                return(assembledDocument);
            }
        }
예제 #21
0
 public WmlDocument(WmlDocument other, params XElement[] replacementParts)
     : base(other)
 {
     using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(this))
     {
         using (Package package = streamDoc.GetPackage())
         {
             foreach (var replacementPart in replacementParts)
             {
                 XAttribute uriAttribute = replacementPart.Attribute(PtOpenXml.Uri);
                 if (uriAttribute == null)
                 {
                     throw new OpenXmlPowerToolsException("Replacement part does not contain a Uri as an attribute");
                 }
                 String uri  = uriAttribute.Value;
                 var    part = package.GetParts().FirstOrDefault(p => p.Uri.ToString() == uri);
                 using (Stream partStream = part.GetStream(FileMode.Create, FileAccess.Write))
                     using (XmlWriter partXmlWriter = XmlWriter.Create(partStream))
                         replacementPart.Save(partXmlWriter);
             }
         }
         this.DocumentByteArray = streamDoc.GetModifiedDocument().DocumentByteArray;
     }
 }
예제 #22
0
 public static bool HasTrackedRevisions(WmlDocument document)
 {
     return(RevisionProcessor.HasTrackedRevisions(document));
 }
예제 #23
0
 public static WmlDocument Compare(WmlDocument source1, WmlDocument source2, WmlComparerSettings settings)
 {
     return(CompareInternal(source1, source2, settings, true));
 }
예제 #24
0
        private static WmlDocument CompareInternal(
            WmlDocument source1,
            WmlDocument source2,
            WmlComparerSettings settings,
            bool preProcessMarkupInOriginal)
        {
            if (preProcessMarkupInOriginal)
            {
                source1 = PreProcessMarkup(source1, settings.StartingIdForFootnotesEndnotes + 1000);
            }

            source2 = PreProcessMarkup(source2, settings.StartingIdForFootnotesEndnotes + 2000);

            SaveDocumentIfDesired(source1, "Source1-Step1-PreProcess.docx", settings);
            SaveDocumentIfDesired(source2, "Source2-Step1-PreProcess.docx", settings);

            // at this point, both source1 and source2 have unid on every element.  These are the values that will
            // enable reassembly of the XML tree.  But we need other values.

            // In source1:
            // - accept tracked revisions
            // - determine hash code for every block-level element
            // - save as attribute on every element

            // - accept tracked revisions and reject tracked revisions leave the unids alone, where possible.
            // - after accepting and calculating the hash, then can use the unids to find the right block-level
            //   element in the unmodified source1, and install the hash

            // In source2:
            // - reject tracked revisions
            // - determine hash code for every block-level element
            // - save as an attribute on every element

            // - after rejecting and calculating the hash, then can use the unids to find the right block-level element
            //   in the unmodified source2, and install the hash

            // - sometimes after accepting or rejecting tracked revisions, several paragraphs will get coalesced into a
            //   single paragraph due to paragraph marks being inserted / deleted.
            // - in this case, some paragraphs will not get a hash injected onto them.
            // - if a paragraph doesn't have a hash, then it will never correspond to another paragraph, and such
            //   issues will need to be resolved in the normal execution of the LCS algorithm.
            // - note that when we do propagate the unid through for the first paragraph.

            // Establish correlation between the two.
            // Find the longest common sequence of block-level elements where hash codes are the same.
            // this sometimes will be every block level element in the document.  Or sometimes will be just a fair
            // number of them.

            // at the start of doing the LCS algorithm, we will match up content, and put them in corresponding unknown
            // correlated comparison units.  Those paragraphs will only ever be matched to their corresponding paragraph.
            // then the algorithm can proceed as usual.

            // need to call ChangeFootnoteEndnoteReferencesToUniqueRange before creating the wmlResult document, so that
            // the same GUID ids are used for footnote and endnote references in both the 'after' document, and in the
            // result document.

            WmlDocument source1AfterAccepting = RevisionProcessor.AcceptRevisions(source1);
            WmlDocument source2AfterRejecting = RevisionProcessor.RejectRevisions(source2);

            SaveDocumentIfDesired(source1AfterAccepting, "Source1-Step2-AfterAccepting.docx", settings);
            SaveDocumentIfDesired(source2AfterRejecting, "Source2-Step2-AfterRejecting.docx", settings);

            // this creates the correlated hash codes that enable us to match up ranges of paragraphs based on
            // accepting in source1, rejecting in source2
            source1 = HashBlockLevelContent(source1, source1AfterAccepting, settings);
            source2 = HashBlockLevelContent(source2, source2AfterRejecting, settings);

            SaveDocumentIfDesired(source1, "Source1-Step3-AfterHashing.docx", settings);
            SaveDocumentIfDesired(source2, "Source2-Step3-AfterHashing.docx", settings);

            // Accept revisions in before, and after
            source1 = RevisionProcessor.AcceptRevisions(source1);
            source2 = RevisionProcessor.AcceptRevisions(source2);

            SaveDocumentIfDesired(source1, "Source1-Step4-AfterAccepting.docx", settings);
            SaveDocumentIfDesired(source2, "Source2-Step4-AfterAccepting.docx", settings);

            // after accepting revisions, some unids may have been removed by revision accepter, along with the
            // correlatedSHA1Hash codes, this is as it should be.
            // but need to go back in and add guids to paragraphs that have had them removed.

            using (var ms = new MemoryStream())
            {
                ms.Write(source2.DocumentByteArray, 0, source2.DocumentByteArray.Length);
                using (WordprocessingDocument wDoc = WordprocessingDocument.Open(ms, true))
                {
                    AddUnidsToMarkupInContentParts(wDoc);
                }
            }

            var wmlResult = new WmlDocument(source1);

            using (var ms1 = new MemoryStream())
                using (var ms2 = new MemoryStream())
                {
                    ms1.Write(source1.DocumentByteArray, 0, source1.DocumentByteArray.Length);
                    ms2.Write(source2.DocumentByteArray, 0, source2.DocumentByteArray.Length);
                    WmlDocument producedDocument;

                    using (WordprocessingDocument wDoc1 = WordprocessingDocument.Open(ms1, true))
                        using (WordprocessingDocument wDoc2 = WordprocessingDocument.Open(ms2, true))
                        {
                            producedDocument = ProduceDocumentWithTrackedRevisions(settings, wmlResult, wDoc1, wDoc2);
                        }

                    SaveDocumentsAfterProducingDocument(ms1, ms2, settings);
                    SaveCleanedDocuments(source1, producedDocument, settings);

                    return(producedDocument);
                }
        }
예제 #25
0
        public static WmlDocument AssembleDocument(WmlDocument templateDoc, XmlDocument data, out bool templateError)
        {
            XDocument xDoc = data.GetXDocument();

            return(AssembleDocument(templateDoc, xDoc.Root, out templateError));
        }
        // the following gets a flattened list of ComparisonUnitAtoms, with status indicated in each ComparisonUnitAtom: Deleted, Inserted, or Equal

        // for any deleted or inserted rows, we go into the w:trPr properties, and add the appropriate w:ins or w:del element, and therefore
        // when generating the document, the appropriate row will be marked as deleted or inserted.

        public static List <WmlComparerRevision> GetRevisions(WmlDocument source, WmlComparerSettings settings)
        {
            using (var ms = new MemoryStream())
            {
                ms.Write(source.DocumentByteArray, 0, source.DocumentByteArray.Length);
                using (WordprocessingDocument wDoc = WordprocessingDocument.Open(ms, true))
                {
                    TestForInvalidContent(wDoc);
                    RemoveExistingPowerToolsMarkup(wDoc);

                    XElement             contentParent = wDoc.MainDocumentPart.GetXDocument().Root?.Element(W.body);
                    ComparisonUnitAtom[] atomList      =
                        CreateComparisonUnitAtomList(wDoc.MainDocumentPart, contentParent, settings).ToArray();

                    if (False)
                    {
                        var sb = new StringBuilder();
                        foreach (ComparisonUnitAtom item in atomList)
                        {
                            sb.Append(item + Environment.NewLine);
                        }
                        string sbs = sb.ToString();
                        TestUtil.NotePad(sbs);
                    }

                    List <IGrouping <string, ComparisonUnitAtom> > grouped = atomList
                                                                             .GroupAdjacent(a =>
                    {
                        string key = a.CorrelationStatus.ToString();
                        if (a.CorrelationStatus != CorrelationStatus.Equal)
                        {
                            var rt = new XElement(a.RevTrackElement.Name,
                                                  new XAttribute(XNamespace.Xmlns + "w",
                                                                 "http://schemas.openxmlformats.org/wordprocessingml/2006/main"),
                                                  a.RevTrackElement.Attributes().Where(a2 => a2.Name != W.id && a2.Name != PtOpenXml.Unid));
                            key += rt.ToString(SaveOptions.DisableFormatting);
                        }

                        return(key);
                    })
                                                                             .ToList();

                    List <IGrouping <string, ComparisonUnitAtom> > revisions = grouped
                                                                               .Where(k => k.Key != "Equal")
                                                                               .ToList();

                    if (False)
                    {
                        var sb = new StringBuilder();
                        foreach (IGrouping <string, ComparisonUnitAtom> item in revisions)
                        {
                            sb.Append(item.Key + Environment.NewLine);
                        }

                        string sbs = sb.ToString();
                        TestUtil.NotePad(sbs);
                    }

                    List <WmlComparerRevision> mainDocPartRevisionList = revisions
                                                                         .Select(rg =>
                    {
                        var rev = new WmlComparerRevision();
                        if (rg.Key.StartsWith("Inserted"))
                        {
                            rev.RevisionType = WmlComparerRevisionType.Inserted;
                        }
                        else if (rg.Key.StartsWith("Deleted"))
                        {
                            rev.RevisionType = WmlComparerRevisionType.Deleted;
                        }

                        XElement revTrackElement = rg.First().RevTrackElement;
                        rev.RevisionXElement     = revTrackElement;
                        rev.Author          = (string)revTrackElement.Attribute(W.author);
                        rev.ContentXElement = rg.First().ContentElement;
                        rev.Date            = (string)revTrackElement.Attribute(W.date);
                        rev.PartUri         = wDoc.MainDocumentPart.Uri;
                        rev.PartContentType = wDoc.MainDocumentPart.ContentType;

                        if (!RevElementsWithNoText.Contains(rev.ContentXElement.Name))
                        {
                            rev.Text = rg
                                       .Select(rgc => rgc.ContentElement.Name == W.pPr ? NewLine : rgc.ContentElement.Value)
                                       .StringConcatenate();
                        }

                        return(rev);
                    })
                                                                         .ToList();

                    IEnumerable <WmlComparerRevision> footnotesRevisionList =
                        GetFootnoteEndnoteRevisionList(wDoc.MainDocumentPart.FootnotesPart, W.footnote, settings);
                    IEnumerable <WmlComparerRevision> endnotesRevisionList =
                        GetFootnoteEndnoteRevisionList(wDoc.MainDocumentPart.EndnotesPart, W.endnote, settings);

                    List <WmlComparerRevision> finalRevisionList = mainDocPartRevisionList
                                                                   .Concat(footnotesRevisionList)
                                                                   .Concat(endnotesRevisionList)
                                                                   .ToList();

                    return(finalRevisionList);
                }
            }
        }
예제 #27
0
        private static WmlDocument PreProcessMarkup(WmlDocument source, int startingIdForFootnotesEndnotes)
        {
            // open and close to get rid of MC content
            using (var ms = new MemoryStream())
            {
                ms.Write(source.DocumentByteArray, 0, source.DocumentByteArray.Length);
                var os = new OpenSettings
                {
                    MarkupCompatibilityProcessSettings = new MarkupCompatibilityProcessSettings(
                        MarkupCompatibilityProcessMode.ProcessAllParts,
                        FileFormatVersions.Office2007)
                };

                using (WordprocessingDocument wDoc = WordprocessingDocument.Open(ms, true, os))
                {
                    OpenXmlPartRootElement unused = wDoc.MainDocumentPart.RootElement;
                    if (wDoc.MainDocumentPart.FootnotesPart != null)
                    {
                        // contrary to what you might think, looking at the API, it is necessary to access the root element of each part to cause
                        // the SDK to process MC markup.
                        OpenXmlPartRootElement unused1 = wDoc.MainDocumentPart.FootnotesPart.RootElement;
                    }

                    if (wDoc.MainDocumentPart.EndnotesPart != null)
                    {
                        OpenXmlPartRootElement unused1 = wDoc.MainDocumentPart.EndnotesPart.RootElement;
                    }
                }

                source = new WmlDocument(source.FileName, ms.ToArray());
            }

            // open and close to get rid of MC content
            using (var ms = new MemoryStream())
            {
                ms.Write(source.DocumentByteArray, 0, source.DocumentByteArray.Length);
                var os = new OpenSettings
                {
                    MarkupCompatibilityProcessSettings = new MarkupCompatibilityProcessSettings(
                        MarkupCompatibilityProcessMode.ProcessAllParts,
                        FileFormatVersions.Office2007)
                };

                using (WordprocessingDocument wDoc = WordprocessingDocument.Open(ms, true, os))
                {
                    TestForInvalidContent(wDoc);
                    RemoveExistingPowerToolsMarkup(wDoc);

                    // Removing content controls, field codes, and bookmarks is a no-no for many use cases.
                    // We need content controls, e.g., on the title page. Field codes are required for
                    // automatic cross-references, which require bookmarks.
                    // TODO: Revisit
                    var msSettings = new SimplifyMarkupSettings
                    {
                        RemoveBookmarks = true,

                        AcceptRevisions = false,
                        RemoveComments  = true,

                        RemoveContentControls = true,
                        RemoveFieldCodes      = true,

                        RemoveGoBackBookmark        = true,
                        RemoveLastRenderedPageBreak = true,
                        RemovePermissions           = true,
                        RemoveProof       = true,
                        RemoveSmartTags   = true,
                        RemoveSoftHyphens = true,
                        RemoveHyperlinks  = true
                    };
                    MarkupSimplifier.SimplifyMarkup(wDoc, msSettings);
                    ChangeFootnoteEndnoteReferencesToUniqueRange(wDoc, startingIdForFootnotesEndnotes);
                    AddUnidsToMarkupInContentParts(wDoc);
                    AddFootnotesEndnotesParts(wDoc);
                    FillInEmptyFootnotesEndnotes(wDoc);
                }

                return(new WmlDocument(source.FileName, ms.ToArray()));
            }
        }
예제 #28
0
        public static WmlDocument AppendParagraphToDocument(
            WmlDocument wmlDoc,
            string strParagraph,
            bool isBold,
            bool isItalic,
            bool isUnderline,
            string foreColor,
            string backColor,
            string styleName)
        {
            using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(wmlDoc))
            {
                using (WordprocessingDocument wDoc = streamDoc.GetWordprocessingDocument())
                {
                    StyleDefinitionsPart part = wDoc.MainDocumentPart.StyleDefinitionsPart;

                    Body body = wDoc.MainDocumentPart.Document.Body;

                    SectionProperties sectionProperties = body.Elements <SectionProperties>().FirstOrDefault();

                    Paragraph     paragraph     = new Paragraph();
                    Run           run           = paragraph.AppendChild(new Run());
                    RunProperties runProperties = new RunProperties();

                    if (isBold)
                    {
                        runProperties.AppendChild(new Bold());
                    }

                    if (isItalic)
                    {
                        runProperties.AppendChild(new Italic());
                    }


                    if (!string.IsNullOrEmpty(foreColor))
                    {
                        int colorValue = ColorParser.FromName(foreColor).ToArgb();
                        if (colorValue == 0)
                        {
                            throw new OpenXmlPowerToolsException(String.Format("Add-DocxText: The specified color {0} is unsupported, Please specify the valid color. Ex, Red, Green", foreColor));
                        }

                        string ColorHex = string.Format("{0:x6}", colorValue);
                        runProperties.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Color()
                        {
                            Val = ColorHex.Substring(2)
                        });
                    }

                    if (isUnderline)
                    {
                        runProperties.AppendChild(new Underline()
                        {
                            Val = UnderlineValues.Single
                        });
                    }

                    if (!string.IsNullOrEmpty(backColor))
                    {
                        int colorShade = ColorParser.FromName(backColor).ToArgb();
                        if (colorShade == 0)
                        {
                            throw new OpenXmlPowerToolsException(String.Format("Add-DocxText: The specified color {0} is unsupported, Please specify the valid color. Ex, Red, Green", foreColor));
                        }

                        string ColorShadeHex = string.Format("{0:x6}", colorShade);
                        runProperties.AppendChild(new Shading()
                        {
                            Fill = ColorShadeHex.Substring(2), Val = ShadingPatternValues.Clear
                        });
                    }

                    if (!string.IsNullOrEmpty(styleName))
                    {
                        Style style = part.Styles.Elements <Style>().Where(s => s.StyleId == styleName).FirstOrDefault();
                        //if the specified style is not present in word document add it
                        if (style == null)
                        {
                            using (MemoryStream memoryStream = new MemoryStream())
                            {
                                #region Default.dotx Template has been used to get all the paragraph styles
                                string base64 =
                                    @"UEsDBBQABgAIAAAAIQDTMB8uXgEAACAFAAATAAAAW0NvbnRlbnRfVHlwZXNdLnhtbLSUy27CMBBF
95X6D5G3VWLooqoqAos+li1S6QcYewJW/ZI9vP6+EwKoqiCRCmwiJTP33jNWxoPR2ppsCTFp70rW
L3osAye90m5Wsq/JW/7IsoTCKWG8g5JtILHR8PZmMNkESBmpXSrZHDE8cZ7kHKxIhQ/gqFL5aAXS
a5zxIOS3mAG/7/UeuPQOwWGOtQcbDl6gEguD2euaPjckEUxi2XPTWGeVTIRgtBRIdb506k9Kvkso
SLntSXMd0h01MH40oa6cDtjpPuhoolaQjUXEd2Gpi698VFx5ubCkLNptjnD6qtISDvraLUQvISU6
c2sKBBtoAiis0G7Pf5Ij4cZAujxF49sdD4gkuAbAzrkTYQXTz6tR/DLvBKkodyKmBi6PcbDuhEDa
QGie/bM5tjZtkdQ5jj4k2uj4j7H3K1urcxo4QETd/tcdEsn67Pmgvg0UqCPZfHu/DX8AAAD//wMA
UEsDBBQABgAIAAAAIQAekRq37wAAAE4CAAALAAAAX3JlbHMvLnJlbHOsksFqwzAMQO+D/YPRvVHa
wRijTi9j0NsY2QcIW0lME9vYatf+/TzY2AJd6WFHy9LTk9B6c5xGdeCUXfAallUNir0J1vlew1v7
vHgAlYW8pTF41nDiDJvm9mb9yiNJKcqDi1kVis8aBpH4iJjNwBPlKkT25acLaSIpz9RjJLOjnnFV
1/eYfjOgmTHV1mpIW3sHqj1FvoYdus4ZfgpmP7GXMy2Qj8Lesl3EVOqTuDKNain1LBpsMC8lnJFi
rAoa8LzR6nqjv6fFiYUsCaEJiS/7fGZcElr+54rmGT827yFZtF/hbxucXUHzAQAA//8DAFBLAwQU
AAYACADRagZB/Fz9fNYBAAALAwAAEAAAAGRvY1Byb3BzL2FwcC54bWztvQdgHEmWJSYvbcp7f0r1
StfgdKEIgGATJNiQQBDswYjN5pLsHWlHIymrKoHKZVZlXWYWQMztnbz33nvvvffee++997o7nU4n
99//P1xmZAFs9s5K2smeIYCqyB8/fnwfPyL+x7/3H3z8e7xblOllXjdFtfzso93xzkdpvpxWs2J5
8dlH6/Z8++CjtGmz5Swrq2X+2UfXefPR73H0OFs9ellXq7xui7xJCcayeXTZfvbRvG1Xj+7ebabz
fJE1Y2qxpC/Pq3qRtfRnfXG3Oj8vpvnTarpe5Mv27t7Ozqd3Z9UU0JqffHO9IvgKL1t9XXj5uzZf
zvLZ9sri+BHj/CZfrMqszY8e3w3+wh9Vm5VvikV+tCNf2r95sNlF3hzt8jfyOz79blXPGm0vv+PT
k3lWZ9OWaKpfeR/g++PVqiymWUsUP/qimNZVU5236Zc8jhRg+CW/Fd6iEb7Op+u6aK8VrP8JWjwv
lrnpUn4XzOvsos5Wc/OV9wG+fz3NyvyE6HR0npVNzk3cZwr3bfPV6k31FLRyrcLPw5F/t2jnr1fZ
1CIU/Yr7py/yGY3F799+hhbfJqaoS3RGQJYX+cxr2f9OKfyTwtJHu/fHO/QYkpqPhRKWO47+H1BL
AwQUAAYACADRagZBUsP9QroBAABvAgAAEQAAAGRvY1Byb3BzL2NvcmUueG1s7b0HYBxJliUmL23K
e39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6
O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iHv8e7xZlepnXTVEtP/tod7zzUZovp9WsWF58
9tFXb55tH3yUNm22nGVltcw/++g6bz76PY6Sx9PVo2lV5y/rapXXbZE3KQFaNo+mq88+mrft6tHd
u810ni+yZkwtlvTleVUvspb+rC/urrLp2+wiv7u3s/Pp3UXeZrOsze4C4PbKQvxIQc6mFuRqXZcM
YDa9m5f5Il+2zd3d8e5d17bN60UTfYG/8VouivZ6lUebmi9t63dNYRteXV2Nr+5xU8J/9+7v/cXz
1zzU7WIJUk3zj44ez6aPpnWetVV9dJIVbVks0+NmXubX26+qslxky8d3vSYgZ5k17RdE+PMinz25
vsuf1fllgZk52n181//zsY5TAOSzlPB7JKMx33z33snTN88+Otrb2d3b3nmwvXf/ze6DR3v3H+3s
/BT6Dt53ABeKwW0g3nuzt/tovwPRADhijEMeOfp/AFBLAwQUAAYACAAAACEA1mSzUfQAAAAxAwAA
HAAAAHdvcmQvX3JlbHMvZG9jdW1lbnQueG1sLnJlbHOskstqwzAQRfeF/oOYfS07fVBC5GxKIdvW
/QBFHj+oLAnN9OG/r0hJ69BguvByrphzz4A228/BineM1HunoMhyEOiMr3vXKnipHq/uQRBrV2vr
HSoYkWBbXl5sntBqTkvU9YFEojhS0DGHtZRkOhw0ZT6gSy+Nj4PmNMZWBm1edYtyled3Mk4ZUJ4w
xa5WEHf1NYhqDPgftm+a3uCDN28DOj5TIT9w/4zM6ThKWB1bZAWTMEtEkOdFVkuK0B+LYzKnUCyq
wKPFqcBhnqu/XbKe0y7+th/G77CYc7hZ0qHxjiu9txOPn+goIU8+evkFAAD//wMAUEsDBBQABgAI
ANFqBkF65TN3MwIAAJAFAAARAAAAd29yZC9kb2N1bWVudC54bWztvQdgHEmWJSYvbcp7f0r1Stfg
dKEIgGATJNiQQBDswYjN5pLsHWlHIymrKoHKZVZlXWYWQMztnbz33nvvvffee++997o7nU4n99//
P1xmZAFs9s5K2smeIYCqyB8/fnwfPyL+x7/3H3z8e7xblOllXjdFtfzso93xzkdpvpxWs2J58dlH
6/Z8++CjtGmz5Swrq2X+2UfXefPR73H0+OrRrJquF/myTQnAsnl0tZp+9tG8bVeP7t5tpvN8kTXj
RTGtq6Y6b8fTanG3Oj8vpvndq6qe3d3b2d3h31Z1Nc2bhno7yZaXWfORglv0oVWrfElfnlf1Imvp
z/ri7iKr365X2wR9lbXFpCiL9ppg73xqwFQ0hnr5SEFsW4TwyiNBSH+YN+rb9CuvPFUKcI9367wk
HKplMy9WbhhfFxp9OTdALjcN4nJRmnZXq939D5uDp3V2RT8cwNugP5OXFqVgvhni7s4tZgQg7Bu3
QSHs02CyyIql6/hrkcYj7u799wOw1wWwung/AN3J+byu1isHrfgwaGfLtxYW5Po9YOkk+0Nr3gtA
D5nX82xFEriYPjq7WFZ1NikJI5qylKiegq0/gsaZVLNr/Fyld/Gjyafty5o/uHj9g/QKrLK7t7dP
Guzq0Zx+v3+A3+9Kiy+ymj5uK2Lp3X1pUxcX89b9Oanatlq4v8v83Pt2nmeznJTDgz3+87yqWu/P
i3XLf5r+plXZ0MfNKpvm2og+v+uQvmuGc9dp0qP/B1BLAwQUAAYACADRagZB3iZxVZoCAAAzBwAA
EgAAAHdvcmQvZm9udFRhYmxlLnhtbO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3m
kuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrI
Hz9+fB8/Iv7Hv/cffPx7vFuU6WVeN0W1/Oyj3fHOR2m+nFazYnnx2Ufr9nz74KO0abPlLCurZf7Z
R9d589HvcfT46tF5tWyblN5eNo8W088+mrft6tHdu810ni+yZlyt8iV9eV7Vi6ylP+uLu4usfrte
bU+rxSpri0lRFu313b2dnU8/UjD1baBU5+fFNH9aTdeLfNny+3frvCSI1bKZF6vGQLu6DbSrqp6t
6mqaNw2NeFEKvEVWLC2Y3f0eoEUxraumOm/HNBjFiEHR67s7/NuidADuvx+APQtgMX10drGs6mxS
EukJk5SAfWSon149WmYL+uIkK4tJXfAXq2xZNfkufXeZlZ99tLO382znPv2L//Z37uHfj9K7aDmd
Z3WTt7bljn5+ni2K8tp83FwVTaPfrIp2OjdfXGZ1Abz0u6a4oG/WzWTns49Od+jZe/bsI/lk97OP
9umD4xP7yR6642dXP7lnP9nBJ1OGIy0ePtNPdv021OldIUOPHK+Lxev1kqmRle0L+szg/J//DX/s
f/b3/6lmND1K7e58SrDv0U/9L06pg0+jlMrWbfWehNLR3HOE2js4eGaI4BNq99MbCAUK774noY4J
sXKAa54QLfaVb/Z+aFyzd+xzzQl98uBg35DHcc3Dm7nm2ftyjQpR+ry4mLeDonTPkOOHJErHwHvv
tCNKezsPnvSIYnhmmCg77y1Kb4pF3qQv8qv0VbXIlgNk2SNeuUdaZp81zb33JEvNkN+PLD9sXtFf
mqP/B1BLAwQUAAQACADRagZBhoJdSR0EAAB5CQAAEQAAAHdvcmQvc2V0dGluZ3MueG1s7b0HYBxJ
liUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z2899577733
3nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8i/se/9x98/Hu8W5TpZV43RbX87KPd
8c5Hab6cVrNiefHZR+v2fPvgo7Rps+UsK6tl/tlH13nz0e9x9PjqUZO3LTVqUgKwbB4tpp99NG/b
1aO7d5vpPF9kzbha5Uv68ryqF1lLf9YXdxdZ/Xa92p5Wi1XWFpOiLNrru3s7O59+pGAq6rRePlIQ
24tiWldNdd7ilUfV+XkxzfWHeaO+Tb/yytNqul7ky5Z7vFvnJeFQLZt5sWoMtMXXhUZfzg2Qy02D
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
AAsACwDBAgAAbCwAAAAA";
                                #endregion

                                char[] base64CharArray = base64.Where(c => c != '\r' && c != '\n').ToArray();
                                byte[] byteArray       = System.Convert.FromBase64CharArray(base64CharArray, 0, base64CharArray.Length);
                                memoryStream.Write(byteArray, 0, byteArray.Length);

                                using (WordprocessingDocument defaultDotx = WordprocessingDocument.Open(memoryStream, true))
                                {
                                    //Get the specified style from Default.dotx template for paragraph
                                    Style templateStyle = defaultDotx.MainDocumentPart.StyleDefinitionsPart.Styles.Elements <Style>().Where(s => s.StyleId == styleName && s.Type == StyleValues.Paragraph).FirstOrDefault();

                                    //Check if the style is proper style. Ex, Heading1, Heading2
                                    if (templateStyle == null)
                                    {
                                        throw new OpenXmlPowerToolsException(String.Format("Add-DocxText: The specified style name {0} is unsupported, Please specify the valid style. Ex, Heading1, Heading2, Title", styleName));
                                    }
                                    else
                                    {
                                        part.Styles.Append((templateStyle.CloneNode(true)));
                                    }
                                }
                            }
                        }

                        paragraph.ParagraphProperties = new ParagraphProperties(new ParagraphStyleId()
                        {
                            Val = styleName
                        });
                    }

                    run.AppendChild(runProperties);
                    run.AppendChild(new Text(strParagraph));

                    if (sectionProperties != null)
                    {
                        body.InsertBefore(paragraph, sectionProperties);
                    }
                    else
                    {
                        body.AppendChild(paragraph);
                    }
                }
                return(streamDoc.GetModifiedWmlDocument());
            }
        }