Created
January 30, 2025 04:50
-
-
Save rickythefox/038f7a27856749314c2c55d187462498 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
├── OpenXmlPowerTools.Tests.OA | |
├── HtmlToWmlConverterTests2.cs | |
├── ListItemRetrieverTests.cs | |
└── WordAutomationUtilities.cs | |
├── OpenXmlPowerTools.Tests | |
├── ChartUpdaterTests.cs | |
├── DocumentAssemblerTests.cs | |
├── DocumentBuilderTests.cs | |
├── FormattingAssemblerTests.cs | |
├── HtmlConverterTests.cs | |
├── HtmlToWmlConverterTests.cs | |
├── HtmlToWmlReadAsXElement.cs | |
├── MarkupSimplifierTests.cs | |
├── MetricsGetterTests.cs | |
├── OpenXmlRegexTests.cs | |
├── PowerToolsBlockExtensionsTests.cs | |
├── PowerToolsBlockTests.cs | |
├── PresentationBuilderTests.cs | |
├── PtUtilTests.cs | |
├── RevisionAccepterTests.cs | |
├── RevisionProcessorTests.cs | |
├── SmlCellFormatterTests.cs | |
├── SmlToHtmlConverterTests.cs | |
├── SpreadsheetWriterTests.cs | |
├── StronglyTypedBlockTests.cs | |
├── TestsBase.cs | |
├── UnicodeMapperTests.cs | |
├── WmlComparerTests.cs | |
├── WmlComparerTests2.cs | |
└── WmlContentAtomListTests.cs | |
├── OpenXmlPowerTools | |
├── ChartUpdater.cs | |
├── ColorParser.cs | |
├── DocumentAssembler.cs | |
├── DocumentBuilder.cs | |
├── ExcelFormula.cs | |
├── FieldRetriever.cs | |
├── FormattingAssembler.cs | |
├── GetListItemText_Default.cs | |
├── GetListItemText_fr_FR.cs | |
├── GetListItemText_ru_RU.cs | |
├── GetListItemText_sv_SE.cs | |
├── GetListItemText_tr_TR.cs | |
├── GetListItemText_zh_CN.cs | |
├── HtmlToWmlConverter.cs | |
├── HtmlToWmlConverterCore.cs | |
├── HtmlToWmlCssApplier.cs | |
├── HtmlToWmlCssParser.cs | |
├── ListItemRetriever.cs | |
├── MarkupSimplifier.cs | |
├── MetricsGetter.cs | |
├── OpenXmlRegex.cs | |
├── OxPtHelpers.cs | |
├── PegBase.cs | |
├── PowerToolsBlock.cs | |
├── PowerToolsBlockExtensions.cs | |
├── PresentationBuilder.cs | |
├── Properties | |
│ └── AssemblyInfo.cs | |
├── PtOpenXmlDocument.cs | |
├── PtOpenXmlUtil.cs | |
├── PtUtil.cs | |
├── ReferenceAdder.cs | |
├── RevisionAccepter.cs | |
├── RevisionProcessor.cs | |
├── SSFormula.cs | |
├── ScalarTypes.cs | |
├── SmlCellFormatter.cs | |
├── SmlDataRetriever.cs | |
├── SmlToHtmlConverter.cs | |
├── SpreadsheetDocumentManager.cs | |
├── SpreadsheetWriter.cs | |
├── StronglyTypedBlock.cs | |
├── TestUtil.cs | |
├── TextReplacer.cs | |
├── UnicodeMapper.cs | |
├── WmlComparer.cs | |
├── WmlDocument.cs | |
├── WmlToHtmlConverter.cs | |
├── WmlToXml.cs | |
├── WorksheetAccessor.cs | |
└── XlsxTables.cs | |
└── OpenXmlPowerToolsExamples | |
├── ChartUpdater01 | |
└── ChartUpdater01.cs | |
├── DocumentAssembler | |
└── DocumentAssembler.cs | |
├── DocumentAssembler01 | |
└── DocumentAssembler01.cs | |
├── DocumentAssembler02 | |
└── DocumentAssembler02.cs | |
├── DocumentAssembler03 | |
└── DocumentAssembler03.cs | |
├── DocumentBuilder01 | |
└── DocumentBuilder01.cs | |
├── DocumentBuilder02 | |
└── DocumentBuilder02.cs | |
├── DocumentBuilder03 | |
└── DocumentBuilder03.cs | |
├── DocumentBuilder04 | |
└── DocumentBuilder04.cs | |
├── FieldRetriever01 | |
└── FieldRetriever01.cs | |
├── FormattingAssembler01 | |
└── FormattingAssembler01.cs | |
├── Formulas01 | |
└── Formulas01.cs | |
├── HtmlConverter01 | |
└── HtmlConverter01.cs | |
├── HtmlToWmlConverter01 | |
└── HtmlToWmlConverter01.cs | |
├── HtmlToWmlConverter02 | |
└── HtmlToWmlConverter02.cs | |
├── ListItemRetriever01 | |
└── ListItemRetriever01.cs | |
├── MarkupSimplifierApp | |
├── Form1.Designer.cs | |
├── Form1.cs | |
├── Program.cs | |
└── Properties | |
│ ├── Resources.Designer.cs | |
│ └── Settings.Designer.cs | |
├── MetricsGetter01 | |
└── MetricsGetter01.cs | |
├── OpenXmlRegex01 | |
└── OpenXmlRegex01.cs | |
├── OpenXmlRegex02 | |
└── OpenXmlRegex02.cs | |
├── PivotTables01 | |
└── PivotTables.cs | |
├── PresentationBuilder01 | |
└── PresentationBuilder01.cs | |
├── PresentationBuilder02 | |
└── PresentationBuilder02.cs | |
├── ReferenceAdder01 | |
└── ReferenceAdder01.cs | |
├── RevisionAccepter01 | |
└── RevisionAccepter01.cs | |
├── SmlDataRetriever01 | |
└── SmlDataRetriever01.cs | |
├── SpreadsheetWriter01 | |
└── SpreadsheetWriter01.cs | |
├── SpreadsheetWriter02 | |
└── SpreadsheetWriter02.cs | |
├── TextReplacer01 | |
└── TextReplacer01.cs | |
├── TextReplacer02 | |
└── TextReplacer02.cs | |
├── WmlComparer01 | |
└── WmlComparer01.cs | |
├── WmlComparer02 | |
└── WmlComparer02.cs | |
├── WmlToHtmlConverter01 | |
└── WmlToHtmlConverter01.cs | |
├── WmlToHtmlConverter02 | |
└── WmlToHtmlConverter02.cs | |
└── WordAutomationUtilities | |
└── WordAutomationUtilities.cs | |
/OpenXmlPowerTools.Tests.OA/WordAutomationUtilities.cs: | |
-------------------------------------------------------------------------------- | |
1 | /*************************************************************************** | |
2 | | |
3 | Copyright (c) Microsoft Corporation 2012-2015. | |
4 | | |
5 | This code is licensed using the Microsoft Public License (Ms-PL). The text of the license can be found here: | |
6 | | |
7 | http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx | |
8 | | |
9 | Published at http://OpenXmlDeveloper.org | |
10 | Resource Center and Documentation: http://openxmldeveloper.org/wiki/w/wiki/powertools-for-open-xml.aspx | |
11 | | |
12 | Developer: Eric White | |
13 | Blog: http://www.ericwhite.com | |
14 | Twitter: @EricWhiteDev | |
15 | Email: [email protected] | |
16 | | |
17 | ***************************************************************************/ | |
18 | | |
19 | using System; | |
20 | using System.Collections.Generic; | |
21 | using System.IO; | |
22 | using System.Linq; | |
23 | using System.Text; | |
24 | using System.Threading.Tasks; | |
25 | using System.Xml.Linq; | |
26 | using DocumentFormat.OpenXml.Packaging; | |
27 | using OpenXmlPowerTools; | |
28 | using Word = Microsoft.Office.Interop.Word; | |
29 | | |
30 | namespace OxPt | |
31 | { | |
32 | public class WordAutomationUtilities | |
33 | { | |
34 | public static void DoConversionViaWord(FileInfo newAltChunkBeforeFi, FileInfo newAltChunkAfterFi, XElement html) | |
35 | { | |
36 | var blankAltChunkFi = new DirectoryInfo(Path.Combine(TestUtil.SourceDir.FullName, "Blank-altchunk.docx")); | |
37 | File.Copy(blankAltChunkFi.FullName, newAltChunkBeforeFi.FullName); | |
38 | using (WordprocessingDocument myDoc = WordprocessingDocument.Open(newAltChunkBeforeFi.FullName, true)) | |
39 | { | |
40 | string altChunkId = "AltChunkId1"; | |
41 | MainDocumentPart mainPart = myDoc.MainDocumentPart; | |
42 | AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart( | |
43 | "application/xhtml+xml", altChunkId); | |
44 | using (Stream chunkStream = chunk.GetStream(FileMode.Create, FileAccess.Write)) | |
45 | using (StreamWriter stringStream = new StreamWriter(chunkStream)) | |
46 | stringStream.Write(html.ToString()); | |
47 | XElement altChunk = new XElement(W.altChunk, | |
48 | new XAttribute(R.id, altChunkId) | |
49 | ); | |
50 | XDocument mainDocumentXDoc = myDoc.MainDocumentPart.GetXDocument(); | |
51 | mainDocumentXDoc.Root | |
52 | .Element(W.body) | |
53 | .AddFirst(altChunk); | |
54 | myDoc.MainDocumentPart.PutXDocument(); | |
55 | } | |
56 | | |
57 | WordAutomationUtilities.OpenAndSaveAs(newAltChunkBeforeFi.FullName, newAltChunkAfterFi.FullName); | |
58 | | |
59 | while (true) | |
60 | { | |
61 | try | |
62 | { | |
63 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(newAltChunkAfterFi.FullName, true)) | |
64 | { | |
65 | SimplifyMarkupSettings settings2 = new SimplifyMarkupSettings | |
66 | { | |
67 | RemoveMarkupForDocumentComparison = true, | |
68 | }; | |
69 | MarkupSimplifier.SimplifyMarkup(wDoc, settings2); | |
70 | XElement newRoot = (XElement)RemoveDivTransform(wDoc.MainDocumentPart.GetXDocument().Root); | |
71 | wDoc.MainDocumentPart.GetXDocument().Root.ReplaceWith(newRoot); | |
72 | wDoc.MainDocumentPart.PutXDocumentWithFormatting(); | |
73 | } | |
74 | break; | |
75 | } | |
76 | catch (IOException) | |
77 | { | |
78 | System.Threading.Thread.Sleep(50); | |
79 | continue; | |
80 | } | |
81 | } | |
82 | } | |
83 | | |
84 | private static object RemoveDivTransform(XNode node) | |
85 | { | |
86 | XElement element = node as XElement; | |
87 | if (element != null) | |
88 | { | |
89 | if (element.Name == W.divId) | |
90 | return null; | |
91 | return new XElement(element.Name, | |
92 | element.Attributes(), | |
93 | element.Nodes().Select(n => RemoveDivTransform(n))); | |
94 | } | |
95 | return node; | |
96 | } | |
97 | | |
98 | public static void SaveAsHtmlUsingWord(FileInfo src, FileInfo dest) | |
99 | { | |
100 | Word.Application app = new Word.Application(); | |
101 | app.Visible = false; | |
102 | try | |
103 | { | |
104 | Word.Document doc = app.Documents.Open(src.FullName); | |
105 | doc.SaveAs2(dest.FullName, Word.WdSaveFormat.wdFormatFilteredHTML); | |
106 | } | |
107 | catch (System.Runtime.InteropServices.COMException) | |
108 | { | |
109 | Console.WriteLine("Caught unexpected COM exception."); | |
110 | ((Microsoft.Office.Interop.Word._Application)app).Quit(); | |
111 | Environment.Exit(0); | |
112 | } | |
113 | ((Microsoft.Office.Interop.Word._Application)app).Quit(); | |
114 | } | |
115 | | |
116 | public static void OpenAndSaveAs(string fromFileName, string toFileName) | |
117 | { | |
118 | Word.Application app = new Word.Application(); | |
119 | app.Visible = false; | |
120 | FileInfo fi = new FileInfo(fromFileName); | |
121 | try | |
122 | { | |
123 | FileInfo ffi = new FileInfo(fromFileName); | |
124 | Word.Document doc = app.Documents.Open(ffi.FullName); | |
125 | object FileFormat = Word.WdSaveFormat.wdFormatDocument; | |
126 | FileInfo tfi = new FileInfo(toFileName); | |
127 | object FileName = tfi.FullName; | |
128 | | |
129 | doc.SaveAs(tfi.FullName, Word.WdSaveFormat.wdFormatDocumentDefault); | |
130 | } | |
131 | catch (System.Runtime.InteropServices.COMException) | |
132 | { | |
133 | Console.WriteLine("Caught unexpected COM exception."); | |
134 | ((Microsoft.Office.Interop.Word._Application)app).Quit(); | |
135 | Environment.Exit(0); | |
136 | } | |
137 | ((Microsoft.Office.Interop.Word._Application)app).Quit(); | |
138 | } | |
139 | | |
140 | public static void OpenAndSaveAs(FileInfo src, FileInfo dest) | |
141 | { | |
142 | Word.Application app = new Word.Application(); | |
143 | app.Visible = false; | |
144 | try | |
145 | { | |
146 | Word.Document doc = app.Documents.Open(src.FullName); | |
147 | doc.SaveAs2(dest.FullName, Word.WdSaveFormat.wdFormatDocument); | |
148 | } | |
149 | catch (System.Runtime.InteropServices.COMException) | |
150 | { | |
151 | Console.WriteLine("Caught unexpected COM exception."); | |
152 | ((Microsoft.Office.Interop.Word._Application)app).Quit(); | |
153 | Environment.Exit(0); | |
154 | } | |
155 | ((Microsoft.Office.Interop.Word._Application)app).Quit(); | |
156 | } | |
157 | } | |
158 | } | |
159 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/HtmlToWmlReadAsXElement.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Threading.Tasks; | |
10 | using System.Xml; | |
11 | using System.Xml.Linq; | |
12 | using OpenXmlPowerTools; | |
13 | | |
14 | /******************************************************************************************* | |
15 | * HtmlToWmlConverter expects the HTML to be passed as an XElement, i.e. as XML. While the HTML test files that | |
16 | * are included in Open-Xml-PowerTools are able to be read as XML, most HTML is not able to be read as XML. | |
17 | * The best solution is to use the HtmlAgilityPack, which can parse HTML and save as XML. The HtmlAgilityPack | |
18 | * is licensed under the Ms-PL (same as Open-Xml-PowerTools) so it is convenient to include it in your solution, | |
19 | * and thereby you can convert HTML to XML that can be processed by the HtmlToWmlConverter. | |
20 | * | |
21 | * A convenient way to get the DLL that has been checked out with HtmlToWmlConverter is to clone the repo at | |
22 | * https://github.com/EricWhiteDev/HtmlAgilityPack | |
23 | * | |
24 | * That repo contains only the DLL that has been checked out with HtmlToWmlConverter. | |
25 | * | |
26 | * Of course, you can also get the HtmlAgilityPack source and compile it to get the DLL. You can find it at | |
27 | * http://codeplex.com/HtmlAgilityPack | |
28 | * | |
29 | * We don't include the HtmlAgilityPack in Open-Xml-PowerTools, to simplify installation. The XUnit tests in | |
30 | * this module do not require the HtmlAgilityPack to run. | |
31 | *******************************************************************************************/ | |
32 | | |
33 | #if USE_HTMLAGILITYPACK | |
34 | using HtmlAgilityPack; | |
35 | #endif | |
36 | | |
37 | namespace OpenXmlPowerTools | |
38 | { | |
39 | public class HtmlToWmlReadAsXElement | |
40 | { | |
41 | public static XElement ReadAsXElement(FileInfo sourceHtmlFi) | |
42 | { | |
43 | string htmlString = File.ReadAllText(sourceHtmlFi.FullName); | |
44 | XElement html = null; | |
45 | try | |
46 | { | |
47 | html = XElement.Parse(htmlString); | |
48 | } | |
49 | #if USE_HTMLAGILITYPACK | |
50 | catch (XmlException) | |
51 | { | |
52 | HtmlDocument hdoc = new HtmlDocument(); | |
53 | hdoc.Load(sourceHtmlFi.FullName, Encoding.Default); | |
54 | hdoc.OptionOutputAsXml = true; | |
55 | hdoc.Save(sourceHtmlFi.FullName, Encoding.Default); | |
56 | StringBuilder sb = new StringBuilder(File.ReadAllText(sourceHtmlFi.FullName, Encoding.Default)); | |
57 | sb.Replace("&", "&"); | |
58 | sb.Replace(" ", "\xA0"); | |
59 | sb.Replace(""", "\""); | |
60 | sb.Replace("<", "~lt;"); | |
61 | sb.Replace(">", "~gt;"); | |
62 | sb.Replace("&#", "~#"); | |
63 | sb.Replace("&", "&"); | |
64 | sb.Replace("~lt;", "<"); | |
65 | sb.Replace("~gt;", ">"); | |
66 | sb.Replace("~#", "&#"); | |
67 | File.WriteAllText(sourceHtmlFi.FullName, sb.ToString(), Encoding.Default); | |
68 | html = XElement.Parse(sb.ToString()); | |
69 | } | |
70 | #else | |
71 | catch (XmlException e) | |
72 | { | |
73 | throw e; | |
74 | } | |
75 | #endif | |
76 | html = (XElement)ConvertToNoNamespace(html); | |
77 | return html; | |
78 | } | |
79 | | |
80 | private static object ConvertToNoNamespace(XNode node) | |
81 | { | |
82 | XElement element = node as XElement; | |
83 | if (element != null) | |
84 | { | |
85 | return new XElement(element.Name.LocalName, | |
86 | element.Attributes().Where(a => !a.IsNamespaceDeclaration), | |
87 | element.Nodes().Select(n => ConvertToNoNamespace(n))); | |
88 | } | |
89 | return node; | |
90 | } | |
91 | } | |
92 | } | |
93 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/MarkupSimplifierTests.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System.IO; | |
5 | using System.Linq; | |
6 | using System.Xml.Linq; | |
7 | using DocumentFormat.OpenXml; | |
8 | using DocumentFormat.OpenXml.Packaging; | |
9 | using Xunit; | |
10 | | |
11 | #if !ELIDE_XUNIT_TESTS | |
12 | | |
13 | namespace OpenXmlPowerTools.Tests | |
14 | { | |
15 | public class MarkupSimplifierTests | |
16 | { | |
17 | private const WordprocessingDocumentType DocumentType = WordprocessingDocumentType.Document; | |
18 | | |
19 | private const string SmartTagDocumentTextValue = "The countries include Algeria, Botswana, and Sri Lanka."; | |
20 | private const string SmartTagDocumentXmlString = | |
21 | @"<w:document xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main""> | |
22 | <w:body> | |
23 | <w:p > | |
24 | <w:r> | |
25 | <w:t xml:space=""preserve"">The countries include </w:t> | |
26 | </w:r> | |
27 | <w:smartTag w:uri=""urn:schemas-microsoft-com:office:smarttags"" w:element=""country-region""> | |
28 | <w:r> | |
29 | <w:t>Algeria</w:t> | |
30 | </w:r> | |
31 | </w:smartTag> | |
32 | <w:r> | |
33 | <w:t xml:space=""preserve"">, </w:t> | |
34 | </w:r> | |
35 | <w:smartTag w:uri=""urn:schemas-microsoft-com:office:smarttags"" w:element=""country-region""> | |
36 | <w:r> | |
37 | <w:t>Botswana</w:t> | |
38 | </w:r> | |
39 | </w:smartTag> | |
40 | <w:r> | |
41 | <w:t xml:space=""preserve"">, and </w:t> | |
42 | </w:r> | |
43 | <w:smartTag w:uri=""urn:schemas-microsoft-com:office:smarttags"" w:element=""country-region""> | |
44 | <w:smartTag w:uri=""urn:schemas-microsoft-com:office:smarttags"" w:element=""place""> | |
45 | <w:r> | |
46 | <w:t>Sri Lanka</w:t> | |
47 | </w:r> | |
48 | </w:smartTag> | |
49 | </w:smartTag> | |
50 | <w:r> | |
51 | <w:t>.</w:t> | |
52 | </w:r> | |
53 | </w:p> | |
54 | </w:body> | |
55 | </w:document> | |
56 | "; | |
57 | | |
58 | private const string SdtDocumentXmlString = | |
59 | @"<w:document xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main""> | |
60 | <w:body> | |
61 | <w:sdt> | |
62 | <w:sdtPr> | |
63 | <w:text/> | |
64 | </w:sdtPr> | |
65 | <w:sdtContent> | |
66 | <w:p> | |
67 | <w:r> | |
68 | <w:t>Hello World!</w:t> | |
69 | </w:r> | |
70 | </w:p> | |
71 | </w:sdtContent> | |
72 | </w:sdt> | |
73 | </w:body> | |
74 | </w:document>"; | |
75 | | |
76 | private const string GoBackBookmarkDocumentXmlString = | |
77 | @"<w:document xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main""> | |
78 | <w:body> | |
79 | <w:p> | |
80 | <w:bookmarkStart w:id=""0"" w:name=""_GoBack""/> | |
81 | <w:bookmarkEnd w:id=""0""/> | |
82 | </w:p> | |
83 | </w:body> | |
84 | </w:document>"; | |
85 | | |
86 | [Fact] | |
87 | public void CanRemoveSmartTags() | |
88 | { | |
89 | XDocument partDocument = XDocument.Parse(SmartTagDocumentXmlString); | |
90 | Assert.True(partDocument.Descendants(W.smartTag).Any()); | |
91 | | |
92 | using (var stream = new MemoryStream()) | |
93 | using (WordprocessingDocument wordDocument = WordprocessingDocument.Create(stream, DocumentType)) | |
94 | { | |
95 | MainDocumentPart part = wordDocument.AddMainDocumentPart(); | |
96 | part.PutXDocument(partDocument); | |
97 | | |
98 | var settings = new SimplifyMarkupSettings { RemoveSmartTags = true }; | |
99 | MarkupSimplifier.SimplifyMarkup(wordDocument, settings); | |
100 | | |
101 | partDocument = part.GetXDocument(); | |
102 | XElement t = partDocument.Descendants(W.t).First(); | |
103 | | |
104 | Assert.False(partDocument.Descendants(W.smartTag).Any()); | |
105 | Assert.Equal(SmartTagDocumentTextValue, t.Value); | |
106 | } | |
107 | } | |
108 | | |
109 | [Fact] | |
110 | public void CanRemoveContentControls() | |
111 | { | |
112 | XDocument partDocument = XDocument.Parse(SdtDocumentXmlString); | |
113 | Assert.True(partDocument.Descendants(W.sdt).Any()); | |
114 | | |
115 | using (var stream = new MemoryStream()) | |
116 | using (WordprocessingDocument wordDocument = WordprocessingDocument.Create(stream, DocumentType)) | |
117 | { | |
118 | MainDocumentPart part = wordDocument.AddMainDocumentPart(); | |
119 | part.PutXDocument(partDocument); | |
120 | | |
121 | var settings = new SimplifyMarkupSettings { RemoveContentControls = true }; | |
122 | MarkupSimplifier.SimplifyMarkup(wordDocument, settings); | |
123 | | |
124 | partDocument = part.GetXDocument(); | |
125 | XElement element = partDocument | |
126 | .Descendants(W.body) | |
127 | .Descendants() | |
128 | .First(); | |
129 | | |
130 | Assert.False(partDocument.Descendants(W.sdt).Any()); | |
131 | Assert.Equal(W.p, element.Name); | |
132 | } | |
133 | } | |
134 | | |
135 | [Fact] | |
136 | public void CanRemoveGoBackBookmarks() | |
137 | { | |
138 | XDocument partDocument = XDocument.Parse(GoBackBookmarkDocumentXmlString); | |
139 | Assert.Contains(partDocument | |
140 | .Descendants(W.bookmarkStart) | |
141 | , e => e.Attribute(W.name).Value == "_GoBack" && e.Attribute(W.id).Value == "0"); | |
142 | Assert.Contains(partDocument | |
143 | .Descendants(W.bookmarkEnd) | |
144 | , e => e.Attribute(W.id).Value == "0"); | |
145 | | |
146 | using (var stream = new MemoryStream()) | |
147 | using (WordprocessingDocument wordDocument = WordprocessingDocument.Create(stream, DocumentType)) | |
148 | { | |
149 | MainDocumentPart part = wordDocument.AddMainDocumentPart(); | |
150 | part.PutXDocument(partDocument); | |
151 | | |
152 | var settings = new SimplifyMarkupSettings { RemoveGoBackBookmark = true }; | |
153 | MarkupSimplifier.SimplifyMarkup(wordDocument, settings); | |
154 | | |
155 | partDocument = part.GetXDocument(); | |
156 | Assert.False(partDocument.Descendants(W.bookmarkStart).Any()); | |
157 | Assert.False(partDocument.Descendants(W.bookmarkEnd).Any()); | |
158 | } | |
159 | } | |
160 | } | |
161 | } | |
162 | | |
163 | #endif | |
164 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/MetricsGetterTests.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Threading.Tasks; | |
10 | using System.Xml.Linq; | |
11 | using OpenXmlPowerTools; | |
12 | using Xunit; | |
13 | | |
14 | #if !ELIDE_XUNIT_TESTS | |
15 | | |
16 | namespace OxPt | |
17 | { | |
18 | public class MgTests | |
19 | { | |
20 | [Theory] | |
21 | [InlineData("Presentation.pptx")] | |
22 | [InlineData("Spreadsheet.xlsx")] | |
23 | [InlineData("DA001-TemplateDocument.docx")] | |
24 | [InlineData("DA002-TemplateDocument.docx")] | |
25 | [InlineData("DA003-Select-XPathFindsNoData.docx")] | |
26 | [InlineData("DA004-Select-XPathFindsNoDataOptional.docx")] | |
27 | [InlineData("DA005-SelectRowData-NoData.docx")] | |
28 | [InlineData("DA006-SelectTestValue-NoData.docx")] | |
29 | public void MG001(string name) | |
30 | { | |
31 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
32 | FileInfo fi = new FileInfo(Path.Combine(sourceDir.FullName, name)); | |
33 | | |
34 | MetricsGetterSettings settings = new MetricsGetterSettings() | |
35 | { | |
36 | IncludeTextInContentControls = false, | |
37 | IncludeXlsxTableCellData = false, | |
38 | RetrieveNamespaceList = true, | |
39 | RetrieveContentTypeList = true, | |
40 | }; | |
41 | | |
42 | var extension = fi.Extension.ToLower(); | |
43 | XElement metrics = null; | |
44 | if (Util.IsWordprocessingML(extension)) | |
45 | { | |
46 | WmlDocument wmlDocument = new WmlDocument(fi.FullName); | |
47 | metrics = MetricsGetter.GetDocxMetrics(wmlDocument, settings); | |
48 | } | |
49 | else if (Util.IsSpreadsheetML(extension)) | |
50 | { | |
51 | SmlDocument smlDocument = new SmlDocument(fi.FullName); | |
52 | metrics = MetricsGetter.GetXlsxMetrics(smlDocument, settings); | |
53 | } | |
54 | else if (Util.IsPresentationML(extension)) | |
55 | { | |
56 | PmlDocument pmlDocument = new PmlDocument(fi.FullName); | |
57 | metrics = MetricsGetter.GetPptxMetrics(pmlDocument, settings); | |
58 | } | |
59 | | |
60 | Assert.NotNull(metrics); | |
61 | } | |
62 | } | |
63 | } | |
64 | | |
65 | #endif | |
66 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/PowerToolsBlockExtensionsTests.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System.Collections.Generic; | |
5 | using System.IO; | |
6 | using System.Linq; | |
7 | using System.Xml.Linq; | |
8 | using DocumentFormat.OpenXml.Packaging; | |
9 | using DocumentFormat.OpenXml.Wordprocessing; | |
10 | using Xunit; | |
11 | | |
12 | #if !ELIDE_XUNIT_TESTS | |
13 | | |
14 | namespace OpenXmlPowerTools.Tests | |
15 | { | |
16 | public class PowerToolsBlockExtensionsTests : TestsBase | |
17 | { | |
18 | [Fact] | |
19 | public void MustBeginPowerToolsBlockToUsePowerTools() | |
20 | { | |
21 | using (var stream = new MemoryStream()) | |
22 | { | |
23 | CreateEmptyWordprocessingDocument(stream); | |
24 | | |
25 | using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(stream, true)) | |
26 | { | |
27 | MainDocumentPart part = wordDocument.MainDocumentPart; | |
28 | | |
29 | // Add a first paragraph through the SDK. | |
30 | Body body = part.Document.Body; | |
31 | body.AppendChild(new Paragraph(new Run(new Text("First")))); | |
32 | | |
33 | // This demonstrates the usage of the BeginPowerToolsBlock method to | |
34 | // demarcate blocks or regions of code where the PowerTools are used | |
35 | // in between usages of the strongly typed classes. | |
36 | wordDocument.BeginPowerToolsBlock(); | |
37 | | |
38 | // Get content through the PowerTools. We will see the one paragraph added | |
39 | // by using the strongly typed SDK classes. | |
40 | XDocument content = part.GetXDocument(); | |
41 | List<XElement> paragraphElements = content.Descendants(W.p).ToList(); | |
42 | Assert.Single(paragraphElements); | |
43 | Assert.Equal("First", paragraphElements[0].Value); | |
44 | | |
45 | // This demonstrates the usage of the EndPowerToolsBlock method to | |
46 | // demarcate blocks or regions of code where the PowerTools are used | |
47 | // in between usages of the strongly typed classes. | |
48 | wordDocument.EndPowerToolsBlock(); | |
49 | | |
50 | // Add a second paragraph through the SDK in the exact same way as above. | |
51 | body = part.Document.Body; | |
52 | body.AppendChild(new Paragraph(new Run(new Text("Second")))); | |
53 | part.Document.Save(); | |
54 | | |
55 | // Get content through the PowerTools in the exact same way as above, | |
56 | // noting that we have not used the BeginPowerToolsBlock method to | |
57 | // mark the beginning of the next PowerTools Block. | |
58 | // What we will see in this case is that we still only get the first | |
59 | // paragraph. This is caused by the GetXDocument method using the cached | |
60 | // XDocument, i.e., the annotation, rather reading the part's stream again. | |
61 | content = part.GetXDocument(); | |
62 | paragraphElements = content.Descendants(W.p).ToList(); | |
63 | Assert.Single(paragraphElements); | |
64 | Assert.Equal("First", paragraphElements[0].Value); | |
65 | | |
66 | // To make the GetXDocument read the parts' streams, we need to begin | |
67 | // the next PowerTools Block. This will remove the annotations from the | |
68 | // parts and make the PowerTools read the part's stream instead of | |
69 | // using the outdated annotation. | |
70 | wordDocument.BeginPowerToolsBlock(); | |
71 | | |
72 | // Get content through the PowerTools in the exact same way as above. | |
73 | // We should now see both paragraphs. | |
74 | content = part.GetXDocument(); | |
75 | paragraphElements = content.Descendants(W.p).ToList(); | |
76 | Assert.Equal(2, paragraphElements.Count); | |
77 | Assert.Equal("First", paragraphElements[0].Value); | |
78 | Assert.Equal("Second", paragraphElements[1].Value); | |
79 | } | |
80 | } | |
81 | } | |
82 | | |
83 | [Fact] | |
84 | public void MustEndPowerToolsBlockToUseStronglyTypedClasses() | |
85 | { | |
86 | using (var stream = new MemoryStream()) | |
87 | { | |
88 | CreateEmptyWordprocessingDocument(stream); | |
89 | | |
90 | using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(stream, true)) | |
91 | { | |
92 | MainDocumentPart part = wordDocument.MainDocumentPart; | |
93 | | |
94 | // Add a paragraph through the SDK. | |
95 | Body body = part.Document.Body; | |
96 | body.AppendChild(new Paragraph(new Run(new Text("Added through SDK")))); | |
97 | | |
98 | // Begin the PowerTools Block, which saves any changes made through the strongly | |
99 | // typed SDK classes to the parts of the WordprocessingDocument. | |
100 | // In this case, this could also be done by invoking the Save method on the | |
101 | // WordprocessingDocument, which will save all parts that had changes, or by | |
102 | // invoking part.RootElement.Save() for the one part that was changed. | |
103 | wordDocument.BeginPowerToolsBlock(); | |
104 | | |
105 | // Add a paragraph through the PowerTools. | |
106 | XDocument content = part.GetXDocument(); | |
107 | XElement bodyElement = content.Descendants(W.body).First(); | |
108 | bodyElement.Add(new XElement(W.p, new XElement(W.r, new XElement(W.t, "Added through PowerTools")))); | |
109 | part.PutXDocument(); | |
110 | | |
111 | // Get the part's content through the SDK. However, we will only see what we | |
112 | // added through the SDK, not what we added through the PowerTools functionality. | |
113 | body = part.Document.Body; | |
114 | List<Paragraph> paragraphs = body.Elements<Paragraph>().ToList(); | |
115 | Assert.Single(paragraphs); | |
116 | Assert.Equal("Added through SDK", paragraphs[0].InnerText); | |
117 | | |
118 | // Now, let's end the PowerTools Block, which reloads the root element of this | |
119 | // one part. Reloading those root elements this way is fine if you know exactly | |
120 | // which parts had their content changed by the Open XML PowerTools. | |
121 | wordDocument.EndPowerToolsBlock(); | |
122 | | |
123 | // Get the part's content through the SDK. Having reloaded the root element, | |
124 | // we should now see both paragraphs. | |
125 | body = part.Document.Body; | |
126 | paragraphs = body.Elements<Paragraph>().ToList(); | |
127 | Assert.Equal(2, paragraphs.Count); | |
128 | Assert.Equal("Added through SDK", paragraphs[0].InnerText); | |
129 | Assert.Equal("Added through PowerTools", paragraphs[1].InnerText); | |
130 | } | |
131 | } | |
132 | } | |
133 | } | |
134 | } | |
135 | | |
136 | #endif | |
137 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/PowerToolsBlockTests.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Xml.Linq; | |
9 | using DocumentFormat.OpenXml.Packaging; | |
10 | using DocumentFormat.OpenXml.Wordprocessing; | |
11 | using Xunit; | |
12 | | |
13 | #if !ELIDE_XUNIT_TESTS | |
14 | | |
15 | namespace OpenXmlPowerTools.Tests | |
16 | { | |
17 | public class PowerToolsBlockTests : TestsBase | |
18 | { | |
19 | [Fact] | |
20 | public void CanUsePowerToolsBlockToDemarcateApis() | |
21 | { | |
22 | using (var stream = new MemoryStream()) | |
23 | { | |
24 | CreateEmptyWordprocessingDocument(stream); | |
25 | | |
26 | using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(stream, true)) | |
27 | { | |
28 | MainDocumentPart part = wordDocument.MainDocumentPart; | |
29 | | |
30 | // Add a paragraph through the SDK. | |
31 | Body body = part.Document.Body; | |
32 | body.AppendChild(new Paragraph(new Run(new Text("Added through SDK")))); | |
33 | | |
34 | // This demonstrates the use of the PowerToolsBlock in a using statement to | |
35 | // demarcate the intermittent use of the PowerTools. | |
36 | using (new PowerToolsBlock(wordDocument)) | |
37 | { | |
38 | // Assert that we can see the paragraph added through the strongly typed classes. | |
39 | XDocument content = part.GetXDocument(); | |
40 | List<XElement> paragraphElements = content.Descendants(W.p).ToList(); | |
41 | Assert.Single(paragraphElements); | |
42 | Assert.Equal("Added through SDK", paragraphElements[0].Value); | |
43 | | |
44 | // Add a paragraph through the PowerTools. | |
45 | XElement bodyElement = content.Descendants(W.body).First(); | |
46 | bodyElement.Add(new XElement(W.p, new XElement(W.r, new XElement(W.t, "Added through PowerTools")))); | |
47 | part.PutXDocument(); | |
48 | } | |
49 | | |
50 | // Get the part's content through the SDK. Having used the PowerToolsBlock, | |
51 | // we should see both paragraphs. | |
52 | body = part.Document.Body; | |
53 | List<Paragraph> paragraphs = body.Elements<Paragraph>().ToList(); | |
54 | Assert.Equal(2, paragraphs.Count); | |
55 | Assert.Equal("Added through SDK", paragraphs[0].InnerText); | |
56 | Assert.Equal("Added through PowerTools", paragraphs[1].InnerText); | |
57 | } | |
58 | } | |
59 | } | |
60 | | |
61 | [Fact] | |
62 | public void ConstructorThrowsWhenPassingNull() | |
63 | { | |
64 | Assert.Throws<ArgumentNullException>(() => new PowerToolsBlock(null)); | |
65 | } | |
66 | } | |
67 | } | |
68 | | |
69 | #endif | |
70 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/PresentationBuilderTests.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Drawing; | |
7 | using System.Drawing.Imaging; | |
8 | using System.IO; | |
9 | using System.Linq; | |
10 | using System.Text; | |
11 | using System.Threading.Tasks; | |
12 | using System.Xml.Linq; | |
13 | using DocumentFormat.OpenXml.Packaging; | |
14 | using DocumentFormat.OpenXml.Validation; | |
15 | using OpenXmlPowerTools; | |
16 | using Xunit; | |
17 | | |
18 | #if !ELIDE_XUNIT_TESTS | |
19 | | |
20 | namespace OxPt | |
21 | { | |
22 | public class PbTests | |
23 | { | |
24 | [Fact] | |
25 | public void PB001_Formatting() | |
26 | { | |
27 | string name1 = "PB001-Input1.pptx"; | |
28 | string name2 = "PB001-Input2.pptx"; | |
29 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
30 | FileInfo source1Pptx = new FileInfo(Path.Combine(sourceDir.FullName, name1)); | |
31 | FileInfo source2Pptx = new FileInfo(Path.Combine(sourceDir.FullName, name2)); | |
32 | | |
33 | List<SlideSource> sources = null; | |
34 | sources = new List<SlideSource>() | |
35 | { | |
36 | new SlideSource(new PmlDocument(source1Pptx.FullName), 1, true), | |
37 | new SlideSource(new PmlDocument(source2Pptx.FullName), 0, true), | |
38 | }; | |
39 | var processedDestPptx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, "PB001-Formatting.pptx")); | |
40 | PresentationBuilder.BuildPresentation(sources, processedDestPptx.FullName); | |
41 | } | |
42 | | |
43 | [Fact] | |
44 | public void PB002_Formatting() | |
45 | { | |
46 | string name2 = "PB001-Input2.pptx"; | |
47 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
48 | FileInfo source2Pptx = new FileInfo(Path.Combine(sourceDir.FullName, name2)); | |
49 | | |
50 | List<SlideSource> sources = null; | |
51 | sources = new List<SlideSource>() | |
52 | { | |
53 | new SlideSource(new PmlDocument(source2Pptx.FullName), 0, true), | |
54 | }; | |
55 | var processedDestPptx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, "PB002-Formatting.pptx")); | |
56 | PresentationBuilder.BuildPresentation(sources, processedDestPptx.FullName); | |
57 | } | |
58 | | |
59 | [Fact] | |
60 | public void PB003_Formatting() | |
61 | { | |
62 | string name1 = "PB001-Input1.pptx"; | |
63 | string name2 = "PB001-Input3.pptx"; | |
64 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
65 | FileInfo source1Pptx = new FileInfo(Path.Combine(sourceDir.FullName, name1)); | |
66 | FileInfo source2Pptx = new FileInfo(Path.Combine(sourceDir.FullName, name2)); | |
67 | | |
68 | List<SlideSource> sources = null; | |
69 | sources = new List<SlideSource>() | |
70 | { | |
71 | new SlideSource(new PmlDocument(source1Pptx.FullName), 1, true), | |
72 | new SlideSource(new PmlDocument(source2Pptx.FullName), 0, true), | |
73 | }; | |
74 | var processedDestPptx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, "PB003-Formatting.pptx")); | |
75 | PresentationBuilder.BuildPresentation(sources, processedDestPptx.FullName); | |
76 | } | |
77 | | |
78 | [Fact] | |
79 | public void PB004_Formatting() | |
80 | { | |
81 | string name1 = "PB001-Input1.pptx"; | |
82 | string name2 = "PB001-Input3.pptx"; | |
83 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
84 | FileInfo source1Pptx = new FileInfo(Path.Combine(sourceDir.FullName, name1)); | |
85 | FileInfo source2Pptx = new FileInfo(Path.Combine(sourceDir.FullName, name2)); | |
86 | | |
87 | List<SlideSource> sources = null; | |
88 | sources = new List<SlideSource>() | |
89 | { | |
90 | new SlideSource(new PmlDocument(source2Pptx.FullName), 0, true), | |
91 | new SlideSource(new PmlDocument(source1Pptx.FullName), 1, true), | |
92 | }; | |
93 | var processedDestPptx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, "PB004-Formatting.pptx")); | |
94 | PresentationBuilder.BuildPresentation(sources, processedDestPptx.FullName); | |
95 | } | |
96 | | |
97 | [Fact] | |
98 | public void PB005_Formatting() | |
99 | { | |
100 | string name1 = "PB001-Input1.pptx"; | |
101 | string name2 = "PB001-Input3.pptx"; | |
102 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
103 | FileInfo source1Pptx = new FileInfo(Path.Combine(sourceDir.FullName, name1)); | |
104 | FileInfo source2Pptx = new FileInfo(Path.Combine(sourceDir.FullName, name2)); | |
105 | | |
106 | List<SlideSource> sources = null; | |
107 | sources = new List<SlideSource>() | |
108 | { | |
109 | new SlideSource(new PmlDocument(source2Pptx.FullName), 0, 0, true), | |
110 | new SlideSource(new PmlDocument(source1Pptx.FullName), 1, true), | |
111 | new SlideSource(new PmlDocument(source2Pptx.FullName), 0, true), | |
112 | }; | |
113 | var processedDestPptx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, "PB005-Formatting.pptx")); | |
114 | PresentationBuilder.BuildPresentation(sources, processedDestPptx.FullName); | |
115 | } | |
116 | | |
117 | #if NETCOREAPP2_0 | |
118 | [Fact(Skip="Bug in netcore 2.0 : https://github.com/OfficeDev/Open-Xml-PowerTools/pull/238#issuecomment-412375570")] | |
119 | #else | |
120 | [Fact] | |
121 | #endif | |
122 | public void PB006_VideoFormats() | |
123 | { | |
124 | // This presentation contains videos with content types video/mp4, video/quicktime, video/unknown, video/x-ms-asf, and video/x-msvideo. | |
125 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
126 | FileInfo sourcePptx = new FileInfo(Path.Combine(sourceDir.FullName, "PP006-Videos.pptx")); | |
127 | | |
128 | var oldMediaDataContentTypes = GetMediaDataContentTypes(sourcePptx); | |
129 | | |
130 | List<SlideSource> sources = null; | |
131 | sources = new List<SlideSource>() | |
132 | { | |
133 | new SlideSource(new PmlDocument(sourcePptx.FullName), true), | |
134 | }; | |
135 | var processedDestPptx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, "PB006-Videos.pptx")); | |
136 | PresentationBuilder.BuildPresentation(sources, processedDestPptx.FullName); | |
137 | | |
138 | var newMediaDataContentTypes = GetMediaDataContentTypes(processedDestPptx); | |
139 | | |
140 | Assert.Equal(oldMediaDataContentTypes, newMediaDataContentTypes); | |
141 | } | |
142 | | |
143 | private static string[] GetMediaDataContentTypes(FileInfo fi) | |
144 | { | |
145 | using (PresentationDocument ptDoc = PresentationDocument.Open(fi.FullName, false)) | |
146 | { | |
147 | return ptDoc.PresentationPart.SlideParts.SelectMany( | |
148 | p => p.DataPartReferenceRelationships.Select(d => d.DataPart.ContentType)) | |
149 | .Distinct() | |
150 | .OrderBy(m => m) | |
151 | .ToArray(); | |
152 | } | |
153 | } | |
154 | } | |
155 | } | |
156 | | |
157 | #endif | |
158 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/PtUtilTests.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Drawing; | |
7 | using System.Drawing.Imaging; | |
8 | using System.IO; | |
9 | using System.Linq; | |
10 | using System.Text; | |
11 | using System.Threading.Tasks; | |
12 | using System.Xml.Linq; | |
13 | using DocumentFormat.OpenXml.Packaging; | |
14 | using OpenXmlPowerTools; | |
15 | using Xunit; | |
16 | | |
17 | #if !ELIDE_XUNIT_TESTS | |
18 | | |
19 | namespace OxPt | |
20 | { | |
21 | public class PtUtilTests | |
22 | { | |
23 | [Theory(Skip = "This is failing on AppVeyor")] | |
24 | [InlineData("PU/PU001-Test001.mht")] | |
25 | public void PU001(string name) | |
26 | { | |
27 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
28 | FileInfo sourceMht = new FileInfo(Path.Combine(sourceDir.FullName, name)); | |
29 | var src = File.ReadAllText(sourceMht.FullName); | |
30 | var p = MhtParser.Parse(src); | |
31 | Assert.True(p.ContentType != null); | |
32 | Assert.True(p.MimeVersion != null); | |
33 | Assert.True(p.Parts.Length != 0); | |
34 | Assert.DoesNotContain(p.Parts, part => part.ContentType == null || part.ContentLocation == null); | |
35 | } | |
36 | | |
37 | } | |
38 | } | |
39 | | |
40 | #endif | |
41 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/RevisionAccepterTests.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Drawing; | |
7 | using System.Drawing.Imaging; | |
8 | using System.IO; | |
9 | using System.Linq; | |
10 | using System.Text; | |
11 | using System.Threading.Tasks; | |
12 | using System.Xml.Linq; | |
13 | using DocumentFormat.OpenXml.Packaging; | |
14 | using OpenXmlPowerTools; | |
15 | using Xunit; | |
16 | | |
17 | #if !ELIDE_XUNIT_TESTS | |
18 | | |
19 | namespace OxPt | |
20 | { | |
21 | public class RaTests | |
22 | { | |
23 | [Theory] | |
24 | [InlineData("RA001-Tracked-Revisions-01.docx")] | |
25 | [InlineData("RA001-Tracked-Revisions-02.docx")] | |
26 | | |
27 | public void RA001(string name) | |
28 | { | |
29 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
30 | FileInfo sourceDocx = new FileInfo(Path.Combine(sourceDir.FullName, name)); | |
31 | | |
32 | WmlDocument notAccepted = new WmlDocument(sourceDocx.FullName); | |
33 | WmlDocument afterAccepting = RevisionAccepter.AcceptRevisions(notAccepted); | |
34 | var processedDestDocx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", "-processed-by-RevisionAccepter.docx"))); | |
35 | afterAccepting.SaveAs(processedDestDocx.FullName); | |
36 | } | |
37 | | |
38 | } | |
39 | } | |
40 | | |
41 | #endif | |
42 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/StronglyTypedBlockTests.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Xml.Linq; | |
9 | using DocumentFormat.OpenXml.Packaging; | |
10 | using DocumentFormat.OpenXml.Wordprocessing; | |
11 | using Xunit; | |
12 | | |
13 | #if !ELIDE_XUNIT_TESTS | |
14 | | |
15 | namespace OpenXmlPowerTools.Tests | |
16 | { | |
17 | public class StronglyTypedBlockTests : TestsBase | |
18 | { | |
19 | [Fact] | |
20 | public void CanUseStronglyTypedBlockToDemarcateApis() | |
21 | { | |
22 | using (var stream = new MemoryStream()) | |
23 | { | |
24 | CreateEmptyWordprocessingDocument(stream); | |
25 | | |
26 | using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(stream, true)) | |
27 | { | |
28 | MainDocumentPart part = wordDocument.MainDocumentPart; | |
29 | | |
30 | // Add a paragraph through the PowerTools. | |
31 | XDocument content = part.GetXDocument(); | |
32 | XElement bodyElement = content.Descendants(W.body).First(); | |
33 | bodyElement.Add(new XElement(W.p, new XElement(W.r, new XElement(W.t, "Added through PowerTools")))); | |
34 | part.PutXDocument(); | |
35 | | |
36 | // This demonstrates the use of the StronglyTypedBlock in a using statement to | |
37 | // demarcate the intermittent use of the strongly typed classes. | |
38 | using (new StronglyTypedBlock(wordDocument)) | |
39 | { | |
40 | // Assert that we can see the paragraph added through the PowerTools. | |
41 | Body body = part.Document.Body; | |
42 | List<Paragraph> paragraphs = body.Elements<Paragraph>().ToList(); | |
43 | Assert.Single(paragraphs); | |
44 | Assert.Equal("Added through PowerTools", paragraphs[0].InnerText); | |
45 | | |
46 | // Add a paragraph through the SDK. | |
47 | body.AppendChild(new Paragraph(new Run(new Text("Added through SDK")))); | |
48 | } | |
49 | | |
50 | // Assert that we can see the paragraphs added through the PowerTools and the SDK. | |
51 | content = part.GetXDocument(); | |
52 | List<XElement> paragraphElements = content.Descendants(W.p).ToList(); | |
53 | Assert.Equal(2, paragraphElements.Count); | |
54 | Assert.Equal("Added through PowerTools", paragraphElements[0].Value); | |
55 | Assert.Equal("Added through SDK", paragraphElements[1].Value); | |
56 | } | |
57 | } | |
58 | } | |
59 | | |
60 | [Fact] | |
61 | public void ConstructorThrowsWhenPassingNull() | |
62 | { | |
63 | Assert.Throws<ArgumentNullException>(() => new StronglyTypedBlock(null)); | |
64 | } | |
65 | } | |
66 | } | |
67 | | |
68 | #endif | |
69 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/TestsBase.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System.IO; | |
5 | using DocumentFormat.OpenXml; | |
6 | using DocumentFormat.OpenXml.Packaging; | |
7 | using DocumentFormat.OpenXml.Wordprocessing; | |
8 | | |
9 | namespace OpenXmlPowerTools.Tests | |
10 | { | |
11 | /// <summary> | |
12 | /// Base class for unit tests providing utility methods. | |
13 | /// </summary> | |
14 | public class TestsBase | |
15 | { | |
16 | private const WordprocessingDocumentType DocumentType = WordprocessingDocumentType.Document; | |
17 | | |
18 | protected static void CreateEmptyWordprocessingDocument(Stream stream) | |
19 | { | |
20 | using (WordprocessingDocument wordDocument = WordprocessingDocument.Create(stream, DocumentType)) | |
21 | { | |
22 | MainDocumentPart part = wordDocument.AddMainDocumentPart(); | |
23 | part.Document = new Document(new Body()); | |
24 | } | |
25 | } | |
26 | } | |
27 | } | |
28 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/UnicodeMapperTests.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | /*************************************************************************** | |
5 | | |
6 | Copyright (c) Microsoft Corporation 2016. | |
7 | | |
8 | This code is licensed using the Microsoft Public License (Ms-PL). The text of the license can be found here: | |
9 | | |
10 | http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx | |
11 | | |
12 | Developer: Thomas Barnekow | |
13 | Email: [email protected] | |
14 | | |
15 | ***************************************************************************/ | |
16 | | |
17 | using System.Collections.Generic; | |
18 | using System.Linq; | |
19 | using System.Xml.Linq; | |
20 | using Xunit; | |
21 | | |
22 | #if !ELIDE_XUNIT_TESTS | |
23 | | |
24 | namespace OpenXmlPowerTools.Tests | |
25 | { | |
26 | public class UnicodeMapperTests | |
27 | { | |
28 | [Fact] | |
29 | public void CanStringifyRunAndTextElements() | |
30 | { | |
31 | const string textValue = "Hello World!"; | |
32 | var textElement = new XElement(W.t, textValue); | |
33 | var runElement = new XElement(W.r, textElement); | |
34 | var formattedRunElement = new XElement(W.r, new XElement(W.rPr, new XElement(W.b)), textElement); | |
35 | | |
36 | Assert.Equal(textValue, UnicodeMapper.RunToString(textElement)); | |
37 | Assert.Equal(textValue, UnicodeMapper.RunToString(runElement)); | |
38 | Assert.Equal(textValue, UnicodeMapper.RunToString(formattedRunElement)); | |
39 | } | |
40 | | |
41 | [Fact] | |
42 | public void CanStringifySpecialElements() | |
43 | { | |
44 | Assert.Equal(UnicodeMapper.CarriageReturn, | |
45 | UnicodeMapper.RunToString(new XElement(W.cr)).First()); | |
46 | Assert.Equal(UnicodeMapper.CarriageReturn, | |
47 | UnicodeMapper.RunToString(new XElement(W.br)).First()); | |
48 | Assert.Equal(UnicodeMapper.FormFeed, | |
49 | UnicodeMapper.RunToString(new XElement(W.br, new XAttribute(W.type, "page"))).First()); | |
50 | Assert.Equal(UnicodeMapper.NonBreakingHyphen, | |
51 | UnicodeMapper.RunToString(new XElement(W.noBreakHyphen)).First()); | |
52 | Assert.Equal(UnicodeMapper.SoftHyphen, | |
53 | UnicodeMapper.RunToString(new XElement(W.softHyphen)).First()); | |
54 | Assert.Equal(UnicodeMapper.HorizontalTabulation, | |
55 | UnicodeMapper.RunToString(new XElement(W.tab)).First()); | |
56 | } | |
57 | | |
58 | [Fact] | |
59 | public void CanCreateRunChildElementsFromSpecialCharacters() | |
60 | { | |
61 | Assert.Equal(W.br, UnicodeMapper.CharToRunChild(UnicodeMapper.CarriageReturn).Name); | |
62 | Assert.Equal(W.noBreakHyphen, UnicodeMapper.CharToRunChild(UnicodeMapper.NonBreakingHyphen).Name); | |
63 | Assert.Equal(W.softHyphen, UnicodeMapper.CharToRunChild(UnicodeMapper.SoftHyphen).Name); | |
64 | Assert.Equal(W.tab, UnicodeMapper.CharToRunChild(UnicodeMapper.HorizontalTabulation).Name); | |
65 | | |
66 | XElement element = UnicodeMapper.CharToRunChild(UnicodeMapper.FormFeed); | |
67 | Assert.Equal(W.br, element.Name); | |
68 | Assert.Equal("page", element.Attribute(W.type).Value); | |
69 | | |
70 | Assert.Equal(W.br, UnicodeMapper.CharToRunChild('\r').Name); | |
71 | } | |
72 | | |
73 | [Fact] | |
74 | public void CanCreateCoalescedRuns() | |
75 | { | |
76 | const string textString = "This is only text."; | |
77 | const string mixedString = "First\tSecond\tThird"; | |
78 | | |
79 | List<XElement> textRuns = UnicodeMapper.StringToCoalescedRunList(textString, null); | |
80 | List<XElement> mixedRuns = UnicodeMapper.StringToCoalescedRunList(mixedString, null); | |
81 | | |
82 | Assert.Single(textRuns); | |
83 | Assert.Equal(5, mixedRuns.Count); | |
84 | | |
85 | Assert.Equal("First", mixedRuns.Elements(W.t).Skip(0).First().Value); | |
86 | Assert.Equal("Second", mixedRuns.Elements(W.t).Skip(1).First().Value); | |
87 | Assert.Equal("Third", mixedRuns.Elements(W.t).Skip(2).First().Value); | |
88 | } | |
89 | | |
90 | [Fact] | |
91 | public void CanMapSymbols() | |
92 | { | |
93 | var sym1 = new XElement(W.sym, | |
94 | new XAttribute(W.font, "Wingdings"), | |
95 | new XAttribute(W._char, "F028")); | |
96 | char charFromSym1 = UnicodeMapper.SymToChar(sym1); | |
97 | XElement symFromChar1 = UnicodeMapper.CharToRunChild(charFromSym1); | |
98 | | |
99 | var sym2 = new XElement(W.sym, | |
100 | new XAttribute(W._char, "F028"), | |
101 | new XAttribute(W.font, "Wingdings")); | |
102 | char charFromSym2 = UnicodeMapper.SymToChar(sym2); | |
103 | | |
104 | var sym3 = new XElement(W.sym, | |
105 | new XAttribute(XNamespace.Xmlns + "w", W.w), | |
106 | new XAttribute(W.font, "Wingdings"), | |
107 | new XAttribute(W._char, "F028")); | |
108 | char charFromSym3 = UnicodeMapper.SymToChar(sym3); | |
109 | | |
110 | var sym4 = new XElement(W.sym, | |
111 | new XAttribute(XNamespace.Xmlns + "w", W.w), | |
112 | new XAttribute(W.font, "Webdings"), | |
113 | new XAttribute(W._char, "F028")); | |
114 | char charFromSym4 = UnicodeMapper.SymToChar(sym4); | |
115 | XElement symFromChar4 = UnicodeMapper.CharToRunChild(charFromSym4); | |
116 | | |
117 | Assert.Equal(charFromSym1, charFromSym2); | |
118 | Assert.Equal(charFromSym1, charFromSym3); | |
119 | Assert.NotEqual(charFromSym1, charFromSym4); | |
120 | | |
121 | Assert.Equal("F028", symFromChar1.Attribute(W._char).Value); | |
122 | Assert.Equal("Wingdings", symFromChar1.Attribute(W.font).Value); | |
123 | | |
124 | Assert.Equal("F028", symFromChar4.Attribute(W._char).Value); | |
125 | Assert.Equal("Webdings", symFromChar4.Attribute(W.font).Value); | |
126 | } | |
127 | | |
128 | [Fact] | |
129 | public void CanStringifySymbols() | |
130 | { | |
131 | char charFromSym1 = UnicodeMapper.SymToChar("Wingdings", '\uF028'); | |
132 | char charFromSym2 = UnicodeMapper.SymToChar("Wingdings", 0xF028); | |
133 | char charFromSym3 = UnicodeMapper.SymToChar("Wingdings", "F028"); | |
134 | | |
135 | XElement symFromChar1 = UnicodeMapper.CharToRunChild(charFromSym1); | |
136 | XElement symFromChar2 = UnicodeMapper.CharToRunChild(charFromSym2); | |
137 | XElement symFromChar3 = UnicodeMapper.CharToRunChild(charFromSym3); | |
138 | | |
139 | Assert.Equal(charFromSym1, charFromSym2); | |
140 | Assert.Equal(charFromSym1, charFromSym3); | |
141 | | |
142 | Assert.Equal(symFromChar1.ToString(SaveOptions.None), symFromChar2.ToString(SaveOptions.None)); | |
143 | Assert.Equal(symFromChar1.ToString(SaveOptions.None), symFromChar3.ToString(SaveOptions.None)); | |
144 | } | |
145 | } | |
146 | } | |
147 | | |
148 | #endif | |
149 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools.Tests/WmlContentAtomListTests.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | #define COPY_FILES_FOR_DEBUGGING | |
5 | | |
6 | using System; | |
7 | using System.Collections.Generic; | |
8 | using System.Drawing; | |
9 | using System.Drawing.Imaging; | |
10 | using System.IO; | |
11 | using System.Linq; | |
12 | using System.Text; | |
13 | using System.Threading.Tasks; | |
14 | using System.Xml.Linq; | |
15 | using DocumentFormat.OpenXml.Packaging; | |
16 | using OpenXmlPowerTools; | |
17 | using Xunit; | |
18 | | |
19 | #if !ELIDE_XUNIT_TESTS | |
20 | | |
21 | namespace OxPt | |
22 | { | |
23 | public class CaTests | |
24 | { | |
25 | /* | |
26 | * This test was removed because it depends on the Coalesce method, which is only ever used | |
27 | * by this test. | |
28 | * | |
29 | [Theory] | |
30 | [InlineData("CA/CA001-Plain.docx", 60)] | |
31 | [InlineData("CA/CA002-Bookmark.docx", 7)] | |
32 | [InlineData("CA/CA003-Numbered-List.docx", 8)] | |
33 | [InlineData("CA/CA004-TwoParas.docx", 88)] | |
34 | [InlineData("CA/CA005-Table.docx", 27)] | |
35 | [InlineData("CA/CA006-ContentControl.docx", 60)] | |
36 | [InlineData("CA/CA007-DayLong.docx", 10)] | |
37 | [InlineData("CA/CA008-Footnote-Reference.docx", 23)] | |
38 | [InlineData("CA/CA010-Delete-Run.docx", 16)] | |
39 | [InlineData("CA/CA011-Insert-Run.docx", 16)] | |
40 | [InlineData("CA/CA012-fldSimple.docx", 10)] | |
41 | [InlineData("CA/CA013-Lots-of-Stuff.docx", 168)] | |
42 | [InlineData("CA/CA014-Complex-Table.docx", 193)] | |
43 | [InlineData("WC/WC024-Table-Before.docx", 24)] | |
44 | [InlineData("WC/WC024-Table-After2.docx", 18)] | |
45 | //[InlineData("", 0)] | |
46 | //[InlineData("", 0)] | |
47 | //[InlineData("", 0)] | |
48 | //[InlineData("", 0)] | |
49 | | |
50 | public void CA001_ContentAtoms(string name, int contentAtomCount) | |
51 | { | |
52 | FileInfo sourceDocx = new FileInfo(Path.Combine(sourceDir.FullName, name)); | |
53 | | |
54 | var thisGuid = Guid.NewGuid().ToString().Replace("-", ""); | |
55 | var sourceCopiedToDestDocx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", string.Format("-{0}-1-Source.docx", thisGuid)))); | |
56 | if (!sourceCopiedToDestDocx.Exists) | |
57 | File.Copy(sourceDocx.FullName, sourceCopiedToDestDocx.FullName); | |
58 | | |
59 | var coalescedDocx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", string.Format("-{0}-2-Coalesced.docx", thisGuid)))); | |
60 | if (!coalescedDocx.Exists) | |
61 | File.Copy(sourceDocx.FullName, coalescedDocx.FullName); | |
62 | | |
63 | var contentAtomDataFi = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", string.Format("-{0}-3-ContentAtomData.txt", thisGuid)))); | |
64 | | |
65 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(coalescedDocx.FullName, true)) | |
66 | { | |
67 | var contentParent = wDoc.MainDocumentPart.GetXDocument().Root.Element(W.body); | |
68 | var settings = new WmlComparerSettings(); | |
69 | ComparisonUnitAtom[] contentAtomList = WmlComparer.CreateComparisonUnitAtomList(wDoc.MainDocumentPart, contentParent, settings); | |
70 | StringBuilder sb = new StringBuilder(); | |
71 | var part = wDoc.MainDocumentPart; | |
72 | | |
73 | sb.AppendFormat("Part: {0}", part.Uri.ToString()); | |
74 | sb.Append(Environment.NewLine); | |
75 | sb.Append(ComparisonUnit.ComparisonUnitListToString(contentAtomList.ToArray()) + Environment.NewLine); | |
76 | sb.Append(Environment.NewLine); | |
77 | | |
78 | XDocument newMainXDoc = WmlComparer.Coalesce(contentAtomList); | |
79 | var partXDoc = wDoc.MainDocumentPart.GetXDocument(); | |
80 | partXDoc.Root.ReplaceWith(newMainXDoc.Root); | |
81 | wDoc.MainDocumentPart.PutXDocument(); | |
82 | | |
83 | File.WriteAllText(contentAtomDataFi.FullName, sb.ToString()); | |
84 | | |
85 | Assert.Equal(contentAtomCount, contentAtomList.Count()); | |
86 | } | |
87 | } | |
88 | */ | |
89 | | |
90 | [Theory] | |
91 | [InlineData("HC009-Test-04.docx")] | |
92 | public void CA002_Annotations(string name) | |
93 | { | |
94 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
95 | FileInfo sourceDocx = new FileInfo(Path.Combine(sourceDir.FullName, name)); | |
96 | | |
97 | #if COPY_FILES_FOR_DEBUGGING | |
98 | var sourceCopiedToDestDocx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", "-1-Source.docx"))); | |
99 | if (!sourceCopiedToDestDocx.Exists) | |
100 | File.Copy(sourceDocx.FullName, sourceCopiedToDestDocx.FullName); | |
101 | | |
102 | var annotatedDocx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", "-2-Annotated.docx"))); | |
103 | if (!annotatedDocx.Exists) | |
104 | File.Copy(sourceDocx.FullName, annotatedDocx.FullName); | |
105 | | |
106 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(annotatedDocx.FullName, true)) | |
107 | { | |
108 | var contentParent = wDoc.MainDocumentPart.GetXDocument().Root.Element(W.body); | |
109 | var settings = new WmlComparerSettings(); | |
110 | WmlComparer.CreateComparisonUnitAtomList(wDoc.MainDocumentPart, contentParent, settings); | |
111 | } | |
112 | #endif | |
113 | } | |
114 | | |
115 | [Theory] | |
116 | [InlineData("CA/CA009-altChunk.docx")] | |
117 | //[InlineData("")] | |
118 | //[InlineData("")] | |
119 | //[InlineData("")] | |
120 | | |
121 | public void CA003_ContentAtoms_Throws(string name) | |
122 | { | |
123 | DirectoryInfo sourceDir = new DirectoryInfo("../../../../TestFiles/"); | |
124 | FileInfo sourceDocx = new FileInfo(Path.Combine(sourceDir.FullName, name)); | |
125 | var thisGuid = Guid.NewGuid().ToString().Replace("-", ""); | |
126 | var sourceCopiedToDestDocx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", string.Format("-{0}-1-Source.docx", thisGuid)))); | |
127 | if (!sourceCopiedToDestDocx.Exists) | |
128 | File.Copy(sourceDocx.FullName, sourceCopiedToDestDocx.FullName); | |
129 | | |
130 | var coalescedDocx = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", string.Format("-{0}-2-Coalesced.docx", thisGuid)))); | |
131 | if (!coalescedDocx.Exists) | |
132 | File.Copy(sourceDocx.FullName, coalescedDocx.FullName); | |
133 | | |
134 | var contentAtomDataFi = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", string.Format("-{0}-3-ContentAtomData.txt", thisGuid)))); | |
135 | | |
136 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(coalescedDocx.FullName, true)) | |
137 | { | |
138 | Assert.Throws<NotSupportedException>(() => | |
139 | { | |
140 | var contentParent = wDoc.MainDocumentPart.GetXDocument().Root.Element(W.body); | |
141 | var settings = new WmlComparerSettings(); | |
142 | WmlComparer.CreateComparisonUnitAtomList(wDoc.MainDocumentPart, contentParent, settings); | |
143 | }); | |
144 | } | |
145 | } | |
146 | } | |
147 | } | |
148 | | |
149 | #endif | |
150 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/ColorParser.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System.Drawing; | |
5 | | |
6 | namespace OpenXmlPowerTools | |
7 | { | |
8 | public static class ColorParser | |
9 | { | |
10 | public static Color FromName(string name) | |
11 | { | |
12 | return Color.FromName(name); | |
13 | } | |
14 | | |
15 | public static bool TryFromName(string name, out Color color) | |
16 | { | |
17 | try | |
18 | { | |
19 | color = Color.FromName(name); | |
20 | | |
21 | return color.IsNamedColor; | |
22 | } | |
23 | catch | |
24 | { | |
25 | color = default(Color); | |
26 | | |
27 | return false; | |
28 | } | |
29 | } | |
30 | | |
31 | public static bool IsValidName(string name) | |
32 | { | |
33 | return TryFromName(name, out _); | |
34 | } | |
35 | } | |
36 | } | |
37 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/GetListItemText_ru_RU.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Linq; | |
7 | using System.Text; | |
8 | | |
9 | namespace OpenXmlPowerTools | |
10 | { | |
11 | public class ListItemTextGetter_ru_RU | |
12 | { | |
13 | private static string[] OneThroughNineteen = { | |
14 | "один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь", | |
15 | "девять", "десять", "одиннадцать", "двенадцать", "тринадцать", "четырнадцать", | |
16 | "пятнадцать", "шестнадцать", "семнадцать", "восемнадцать", "девятнадцать" | |
17 | }; | |
18 | | |
19 | private static string[] Tens = { | |
20 | "десять", "двадцать", "тридцать", "сорок", "пятьдесят", "шестьдесят", "семьдесят", | |
21 | "восемьдесят", "девяносто" | |
22 | }; | |
23 | | |
24 | private static string[] OrdinalOneThroughNineteen = { | |
25 | "первый", "второй", "третий", "четвертый", "пятый", "шестой", | |
26 | "седьмой", "восьмой", "девятый", "десятый", "одиннадцатый", "двенадцатый", | |
27 | "тринадцатый", "четырнадцатый", "пятнадцатый", "шестнадцатый", | |
28 | "семнадцатый", "восемнадцатый", "девятнадцатый" | |
29 | }; | |
30 | | |
31 | private static string[] OrdinalTenths = { | |
32 | "десятый", "двадцатый", "тридцатый", "сороковой", "пятидесятый", | |
33 | "шестидесятый", "семидесятый", "восьмидесятый", "девяностый" | |
34 | }; | |
35 | | |
36 | // TODO this is not correct for values above 99 | |
37 | | |
38 | public static string GetListItemText(string languageCultureName, int levelNumber, string numFmt) | |
39 | { | |
40 | if (numFmt == "cardinalText") | |
41 | { | |
42 | string result = ""; | |
43 | int t1 = levelNumber / 1000; | |
44 | int t2 = levelNumber % 1000; | |
45 | if (t1 >= 1) | |
46 | result += OneThroughNineteen[t1 - 1] + " thousand"; | |
47 | if (t1 >= 1 && t2 == 0) | |
48 | return result.Substring(0, 1).ToUpper() + | |
49 | result.Substring(1); | |
50 | if (t1 >= 1) | |
51 | result += " "; | |
52 | int h1 = (levelNumber % 1000) / 100; | |
53 | int h2 = levelNumber % 100; | |
54 | if (h1 >= 1) | |
55 | result += OneThroughNineteen[h1 - 1] + " hundred"; | |
56 | if (h1 >= 1 && h2 == 0) | |
57 | return result.Substring(0, 1).ToUpper() + | |
58 | result.Substring(1); | |
59 | if (h1 >= 1) | |
60 | result += " "; | |
61 | int z = levelNumber % 100; | |
62 | if (z <= 19) | |
63 | result += OneThroughNineteen[z - 1]; | |
64 | else | |
65 | { | |
66 | int x = z / 10; | |
67 | int r = z % 10; | |
68 | result += Tens[x - 1]; | |
69 | if (r >= 1) | |
70 | result += "-" + OneThroughNineteen[r - 1]; | |
71 | } | |
72 | return result.Substring(0, 1).ToUpper() + | |
73 | result.Substring(1); | |
74 | } | |
75 | if (numFmt == "ordinalText") | |
76 | { | |
77 | string result = ""; | |
78 | int t1 = levelNumber / 1000; | |
79 | int t2 = levelNumber % 1000; | |
80 | if (t1 >= 1 && t2 != 0) | |
81 | result += OneThroughNineteen[t1 - 1] + " thousand"; | |
82 | if (t1 >= 1 && t2 == 0) | |
83 | { | |
84 | result += OneThroughNineteen[t1 - 1] + " thousandth"; | |
85 | return result.Substring(0, 1).ToUpper() + | |
86 | result.Substring(1); | |
87 | } | |
88 | if (t1 >= 1) | |
89 | result += " "; | |
90 | int h1 = (levelNumber % 1000) / 100; | |
91 | int h2 = levelNumber % 100; | |
92 | if (h1 >= 1 && h2 != 0) | |
93 | result += OneThroughNineteen[h1 - 1] + " hundred"; | |
94 | if (h1 >= 1 && h2 == 0) | |
95 | { | |
96 | result += OneThroughNineteen[h1 - 1] + " hundredth"; | |
97 | return result.Substring(0, 1).ToUpper() + | |
98 | result.Substring(1); | |
99 | } | |
100 | if (h1 >= 1) | |
101 | result += " "; | |
102 | int z = levelNumber % 100; | |
103 | if (z <= 19) | |
104 | result += OrdinalOneThroughNineteen[z - 1]; | |
105 | else | |
106 | { | |
107 | int x = z / 10; | |
108 | int r = z % 10; | |
109 | if (r == 0) | |
110 | result += OrdinalTenths[x - 1]; | |
111 | else | |
112 | result += Tens[x - 1]; | |
113 | if (r >= 1) | |
114 | result += " " + OrdinalOneThroughNineteen[r - 1]; | |
115 | } | |
116 | return result.Substring(0, 1).ToUpper() + | |
117 | result.Substring(1); | |
118 | } | |
119 | return null; | |
120 | } | |
121 | } | |
122 | } | |
123 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/GetListItemText_sv_SE.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Linq; | |
7 | using System.Text; | |
8 | | |
9 | namespace OpenXmlPowerTools | |
10 | { | |
11 | public class ListItemTextGetter_sv_SE | |
12 | { | |
13 | private static string[] OneThroughNineteen = { | |
14 | "", "ett", "två", "tre", "fyra", "fem", "sex", "sju", "åtta", | |
15 | "nio", "tio", "elva", "tolv", "tretton", "fjorton", | |
16 | "femton", "sexton", "sjutton", "arton", "nitton" | |
17 | }; | |
18 | | |
19 | private static string[] Tens = { | |
20 | "","tio", "tjugo", "trettio", "fyrtio", "femtio", "sextio", "sjuttio", "åttio", | |
21 | "nittio", "etthundra" | |
22 | }; | |
23 | | |
24 | private static string[] OrdinalOneThroughNineteen = { | |
25 | "", "första", "andra", "tredje", "fjärde", "femte", "sjätte", "sjunde", | |
26 | "åttonde", "nionde", "tionde", "elfte", "tolfte", "trettonde", | |
27 | "fjortonde", "femtonde", "sextonde", "sjuttonde", | |
28 | "artonde", "nittonde" | |
29 | }; | |
30 | | |
31 | public static string GetListItemText(string languageCultureName, int levelNumber, string numFmt) | |
32 | { | |
33 | switch (numFmt) | |
34 | { | |
35 | case "cardinalText": | |
36 | return NumberAsCardinalText(languageCultureName, levelNumber, numFmt); | |
37 | case "ordinalText": | |
38 | return NumberAsOrdinalText(languageCultureName, levelNumber, numFmt); | |
39 | case "ordinal": | |
40 | return NumberAsOrdinal(languageCultureName, levelNumber, numFmt); | |
41 | default: | |
42 | return null; | |
43 | } | |
44 | } | |
45 | private static string NumberAsCardinalText(string languageCultureName, int levelNumber, string numFmt) | |
46 | { | |
47 | string result = ""; | |
48 | | |
49 | var sLevel = (levelNumber + 10000).ToString(); | |
50 | int thousands = int.Parse(sLevel.Substring(1, 1)); | |
51 | int hundreds = int.Parse(sLevel.Substring(2, 1)); | |
52 | int tens = int.Parse(sLevel.Substring(3, 1)); | |
53 | int ones = int.Parse(sLevel.Substring(4, 1)); | |
54 | | |
55 | | |
56 | //Validation | |
57 | if (thousands > 19) | |
58 | throw new ArgumentOutOfRangeException("levelNumber", "Convering a levelNumber to ordinal text that is greater then 19 999 is not supported"); | |
59 | if (levelNumber == 0) | |
60 | return "Noll"; | |
61 | if (levelNumber < 0) | |
62 | throw new ArgumentOutOfRangeException("levelNumber", "Converting a negative levelNumber to ordinal text is not supported"); | |
63 | | |
64 | /* exact thousands */ | |
65 | if (levelNumber == 1000) | |
66 | return "Ettusen"; | |
67 | if (levelNumber > 1000 && hundreds == 0 && tens == 0 && ones == 0) | |
68 | { | |
69 | result = OneThroughNineteen[thousands] + "tusen"; | |
70 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
71 | } | |
72 | | |
73 | /* > 1000 */ | |
74 | if (levelNumber > 1000 && levelNumber < 2000) | |
75 | result = "ettusen"; | |
76 | else if (levelNumber > 2000 && levelNumber < 10000) | |
77 | result = OneThroughNineteen[thousands] + "tusen"; | |
78 | | |
79 | /* exact hundreds */ | |
80 | if (hundreds > 0 && tens == 0 && ones == 0) | |
81 | { | |
82 | if (hundreds == 1) | |
83 | result += "etthundra"; | |
84 | else | |
85 | result += OneThroughNineteen[hundreds] + "hundra"; | |
86 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
87 | } | |
88 | | |
89 | /* > 100 */ | |
90 | if (hundreds > 0) | |
91 | { | |
92 | if (hundreds == 1) | |
93 | result += "etthundra"; | |
94 | else | |
95 | result += OneThroughNineteen[hundreds] + "hundra"; | |
96 | } | |
97 | | |
98 | /* exact tens */ | |
99 | if (tens > 0 && ones == 0) | |
100 | { | |
101 | result += Tens[tens]; | |
102 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
103 | } | |
104 | | |
105 | /* > 20 */ | |
106 | if (tens == 1) | |
107 | { | |
108 | result += OneThroughNineteen[tens * 10 + ones]; | |
109 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
110 | } | |
111 | else if (tens > 1) | |
112 | { | |
113 | result += Tens[tens] + OneThroughNineteen[ones]; ; | |
114 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
115 | } | |
116 | else | |
117 | { | |
118 | result += OneThroughNineteen[ones]; | |
119 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
120 | } | |
121 | } | |
122 | private static string NumberAsOrdinalText(string languageCultureName, int levelNumber, string numFmt) | |
123 | { | |
124 | string result = ""; | |
125 | | |
126 | if (levelNumber <= 0) | |
127 | throw new ArgumentOutOfRangeException("levelNumber", "Converting a zero or negative levelNumber to ordinal text is not supported"); | |
128 | if(levelNumber >= 10000) | |
129 | throw new ArgumentOutOfRangeException("levelNumber", "Convering a levelNumber to ordinal text that is greater then 10000 is not supported"); | |
130 | | |
131 | if (levelNumber == 1) | |
132 | return "Första"; | |
133 | | |
134 | var sLevel = (levelNumber + 10000).ToString(); | |
135 | int thousands = int.Parse(sLevel.Substring(1, 1)); | |
136 | int hundreds = int.Parse(sLevel.Substring(2, 1)); | |
137 | int tens = int.Parse(sLevel.Substring(3, 1)); | |
138 | int ones = int.Parse(sLevel.Substring(4, 1)); | |
139 | | |
140 | | |
141 | /* exact thousands */ | |
142 | if (levelNumber == 1000) | |
143 | return "Ettusende"; | |
144 | if (levelNumber > 1000 && hundreds == 0 && tens == 0 && ones == 0) | |
145 | { | |
146 | result = OneThroughNineteen[thousands] + "tusende"; | |
147 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
148 | } | |
149 | | |
150 | /* > 1000 */ | |
151 | if (levelNumber > 1000 && levelNumber < 2000) | |
152 | result = "ettusen"; | |
153 | else if (levelNumber > 2000 && levelNumber < 10000) | |
154 | result = OneThroughNineteen[thousands] + "tusende"; | |
155 | | |
156 | /* exact hundreds */ | |
157 | if (hundreds > 0 && tens == 0 && ones == 0) | |
158 | { | |
159 | if (hundreds == 1) | |
160 | result += "etthundrade"; | |
161 | else | |
162 | result += OneThroughNineteen[hundreds] + "hundrade"; | |
163 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
164 | } | |
165 | | |
166 | /* > 100 */ | |
167 | if (hundreds > 0) | |
168 | { | |
169 | result += OneThroughNineteen[hundreds] + "hundra"; | |
170 | } | |
171 | | |
172 | /* exact tens */ | |
173 | if (tens > 0 && ones == 0) | |
174 | { | |
175 | result += Tens[tens] + "nde"; | |
176 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
177 | } | |
178 | | |
179 | /* > 20 */ | |
180 | if (tens == 1) | |
181 | { | |
182 | result += OrdinalOneThroughNineteen[tens * 10 + ones]; | |
183 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
184 | } | |
185 | else if (tens > 1) | |
186 | { | |
187 | result += Tens[tens] + OrdinalOneThroughNineteen[ones]; ; | |
188 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
189 | } | |
190 | else | |
191 | { | |
192 | result += OrdinalOneThroughNineteen[ones]; | |
193 | return result.Substring(0, 1).ToUpper() + result.Substring(1); | |
194 | } | |
195 | } | |
196 | private static string NumberAsOrdinal(string languageCultureName, int levelNumber, string numFmt) | |
197 | { | |
198 | string levelAsString = levelNumber.ToString(); | |
199 | | |
200 | if (levelAsString == null) | |
201 | return ""; | |
202 | if (levelAsString.Trim() == "") | |
203 | return ""; | |
204 | | |
205 | if(levelAsString.EndsWith("1")) | |
206 | return levelAsString + ":a"; | |
207 | else if(levelAsString.EndsWith("2")) | |
208 | return levelAsString + ":a"; | |
209 | else | |
210 | return levelAsString + ":e"; | |
211 | } | |
212 | } | |
213 | } | |
214 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/GetListItemText_zh_CN.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Linq; | |
7 | using System.Text; | |
8 | | |
9 | namespace OpenXmlPowerTools | |
10 | { | |
11 | public class ListItemTextGetter_zh_CN | |
12 | { | |
13 | public static string GetListItemText(string languageCultureName, int levelNumber, string numFmt) | |
14 | { | |
15 | string[] ccTDigitCharacters = new[] { | |
16 | "", | |
17 | "一", | |
18 | "二", | |
19 | "三", | |
20 | "四", | |
21 | "五", | |
22 | "六", | |
23 | "七", | |
24 | "八", | |
25 | "九", | |
26 | }; | |
27 | string tenCharacter = "十"; | |
28 | string hundredCharacter = "百"; | |
29 | string thousandCharacter = "千"; | |
30 | string andCharacter = "〇"; | |
31 | | |
32 | string[] ccDigitCharacters = new[] { | |
33 | "○", | |
34 | "一", | |
35 | "二", | |
36 | "三", | |
37 | "四", | |
38 | "五", | |
39 | "六", | |
40 | "七", | |
41 | "八", | |
42 | "九", | |
43 | }; | |
44 | | |
45 | int thousandsRemainder = levelNumber % 1000; | |
46 | int hundredsRemainder = levelNumber % 100; | |
47 | int thousands = levelNumber / 1000; | |
48 | int hundreds = (levelNumber % 1000) / 100; | |
49 | int tens = (levelNumber % 100) / 10; | |
50 | int ones = levelNumber % 10; | |
51 | | |
52 | if (numFmt == "chineseCounting") | |
53 | { | |
54 | if (levelNumber >= 1 && levelNumber <= 9) | |
55 | return ccDigitCharacters[levelNumber]; | |
56 | if (levelNumber >= 10 && levelNumber <= 19) | |
57 | { | |
58 | if (levelNumber == 10) | |
59 | return tenCharacter; | |
60 | return tenCharacter + ccDigitCharacters[ones]; | |
61 | } | |
62 | if (levelNumber >= 11 && levelNumber <= 99) | |
63 | { | |
64 | if (ones == 0) | |
65 | return ccDigitCharacters[tens] + tenCharacter; | |
66 | return ccDigitCharacters[tens] + tenCharacter + ccDigitCharacters[ones]; | |
67 | } | |
68 | if (levelNumber >= 100 && levelNumber <= 999) | |
69 | return ccDigitCharacters[hundreds] + ccDigitCharacters[tens] + ccDigitCharacters[ones]; | |
70 | if (levelNumber >= 1000 && levelNumber <= 9999) | |
71 | return ccDigitCharacters[thousands] + ccDigitCharacters[hundreds] + ccDigitCharacters[tens] + ccDigitCharacters[ones]; | |
72 | return levelNumber.ToString(); | |
73 | } | |
74 | if (numFmt == "chineseCountingThousand") | |
75 | { | |
76 | if (levelNumber >= 1 && levelNumber <= 9) | |
77 | return ccTDigitCharacters[levelNumber]; | |
78 | if (levelNumber >= 10 && levelNumber <= 19) | |
79 | return tenCharacter + ccTDigitCharacters[ones]; | |
80 | if (levelNumber >= 20 && levelNumber <= 99) | |
81 | return ccTDigitCharacters[tens] + tenCharacter + ccTDigitCharacters[ones]; | |
82 | if (levelNumber >= 100 && levelNumber <= 999) | |
83 | { | |
84 | if (hundredsRemainder == 0) | |
85 | return ccTDigitCharacters[hundreds] + hundredCharacter; | |
86 | if (hundredsRemainder >= 1 && hundredsRemainder <= 9) | |
87 | return ccTDigitCharacters[hundreds] + hundredCharacter + andCharacter + ccTDigitCharacters[levelNumber % 10]; | |
88 | if (ones == 0) | |
89 | return ccTDigitCharacters[hundreds] + hundredCharacter + ccTDigitCharacters[tens] + tenCharacter; | |
90 | return ccTDigitCharacters[hundreds] + hundredCharacter + ccTDigitCharacters[tens] + tenCharacter + ccTDigitCharacters[ones]; | |
91 | } | |
92 | if (levelNumber >= 1000 && levelNumber <= 9999) | |
93 | { | |
94 | if (thousandsRemainder == 0) | |
95 | return ccTDigitCharacters[thousands] + thousandCharacter; | |
96 | if (thousandsRemainder >= 1 && thousandsRemainder <= 9) | |
97 | return ccTDigitCharacters[thousands] + thousandCharacter + andCharacter + GetListItemText("zh_CN", thousandsRemainder, numFmt); | |
98 | if (thousandsRemainder >= 10 && thousandsRemainder <= 99) | |
99 | return ccTDigitCharacters[thousands] + thousandCharacter + andCharacter + ccTDigitCharacters[tens] + tenCharacter + ccTDigitCharacters[ones]; | |
100 | if (hundredsRemainder == 0) | |
101 | return ccTDigitCharacters[thousands] + thousandCharacter + ccTDigitCharacters[hundreds] + hundredCharacter; | |
102 | if (hundredsRemainder >= 1 && hundredsRemainder <= 9) | |
103 | return ccTDigitCharacters[thousands] + thousandCharacter + ccTDigitCharacters[hundreds] + hundredCharacter + andCharacter + ccTDigitCharacters[ones]; | |
104 | return ccTDigitCharacters[thousands] + thousandCharacter + ccTDigitCharacters[hundreds] + hundredCharacter + ccTDigitCharacters[tens] + tenCharacter + ccTDigitCharacters[ones]; | |
105 | } | |
106 | return levelNumber.ToString(); | |
107 | } | |
108 | if (numFmt == "ideographTraditional") | |
109 | { | |
110 | string[] iDigitCharacters = new[] { | |
111 | " ", | |
112 | "甲", | |
113 | "乙", | |
114 | "丙", | |
115 | "丁", | |
116 | "戊", | |
117 | "己", | |
118 | "庚", | |
119 | "辛", | |
120 | "壬", | |
121 | "癸", | |
122 | }; | |
123 | if (levelNumber >= 1 && levelNumber <= 10) | |
124 | return iDigitCharacters[levelNumber]; | |
125 | return levelNumber.ToString(); | |
126 | } | |
127 | return null; | |
128 | } | |
129 | } | |
130 | } | |
131 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/PowerToolsBlock.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using DocumentFormat.OpenXml.Packaging; | |
6 | | |
7 | namespace OpenXmlPowerTools | |
8 | { | |
9 | /// <summary> | |
10 | /// Provides an elegant way of wrapping a set of invocations of the PowerTools in a using | |
11 | /// statement that demarcates those invokations as one "block" before and after which the | |
12 | /// strongly typed classes provided by the Open XML SDK can be used safely. | |
13 | /// </summary> | |
14 | /// <remarks> | |
15 | /// <para> | |
16 | /// This class lends itself to scenarios where the PowerTools and Linq-to-XML are used as | |
17 | /// a secondary API for working with Open XML elements, next to the strongly typed classes | |
18 | /// provided by the Open XML SDK. In these scenarios, the class would be | |
19 | /// used as follows: | |
20 | /// </para> | |
21 | /// <code> | |
22 | /// [Your code using the strongly typed classes] | |
23 | /// | |
24 | /// using (new PowerToolsBlock(wordprocessingDocument)) | |
25 | /// { | |
26 | /// [Your code using the PowerTools] | |
27 | /// } | |
28 | /// | |
29 | /// [Your code using the strongly typed classes] | |
30 | /// </code> | |
31 | /// <para> | |
32 | /// Upon creation, instances of this class will invoke the | |
33 | /// <see cref="PowerToolsBlockExtensions.BeginPowerToolsBlock"/> method on the package | |
34 | /// to begin the transaction. Upon disposal, instances of this class will call the | |
35 | /// <see cref="PowerToolsBlockExtensions.EndPowerToolsBlock"/> method on the package | |
36 | /// to end the transaction. | |
37 | /// </para> | |
38 | /// </remarks> | |
39 | /// <seealso cref="StronglyTypedBlock" /> | |
40 | /// <seealso cref="PowerToolsBlockExtensions.BeginPowerToolsBlock"/> | |
41 | /// <seealso cref="PowerToolsBlockExtensions.EndPowerToolsBlock"/> | |
42 | public class PowerToolsBlock : IDisposable | |
43 | { | |
44 | private OpenXmlPackage _package; | |
45 | | |
46 | public PowerToolsBlock(OpenXmlPackage package) | |
47 | { | |
48 | if (package == null) throw new ArgumentNullException("package"); | |
49 | | |
50 | _package = package; | |
51 | _package.BeginPowerToolsBlock(); | |
52 | } | |
53 | | |
54 | public void Dispose() | |
55 | { | |
56 | if (_package == null) return; | |
57 | | |
58 | _package.EndPowerToolsBlock(); | |
59 | _package = null; | |
60 | } | |
61 | } | |
62 | } | |
63 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/PowerToolsBlockExtensions.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Linq; | |
6 | using System.Xml; | |
7 | using System.Xml.Linq; | |
8 | using DocumentFormat.OpenXml.Packaging; | |
9 | | |
10 | namespace OpenXmlPowerTools | |
11 | { | |
12 | public static class PowerToolsBlockExtensions | |
13 | { | |
14 | /// <summary> | |
15 | /// Begins a PowerTools Block by (1) removing annotations and, unless the package was | |
16 | /// opened in read-only mode, (2) saving the package. | |
17 | /// </summary> | |
18 | /// <remarks> | |
19 | /// Removes <see cref="XDocument" /> and <see cref="XmlNamespaceManager" /> instances | |
20 | /// added by <see cref="PtOpenXmlExtensions.GetXDocument(OpenXmlPart)" />, | |
21 | /// <see cref="PtOpenXmlExtensions.GetXDocument(OpenXmlPart, out XmlNamespaceManager)" />, | |
22 | /// <see cref="PtOpenXmlExtensions.PutXDocument(OpenXmlPart)" />, | |
23 | /// <see cref="PtOpenXmlExtensions.PutXDocument(OpenXmlPart, XDocument)" />, and | |
24 | /// <see cref="PtOpenXmlExtensions.PutXDocumentWithFormatting(OpenXmlPart)" />. | |
25 | /// methods. | |
26 | /// </remarks> | |
27 | /// <param name="package"> | |
28 | /// A <see cref="WordprocessingDocument" />, <see cref="SpreadsheetDocument" />, | |
29 | /// or <see cref="PresentationDocument" />. | |
30 | /// </param> | |
31 | public static void BeginPowerToolsBlock(this OpenXmlPackage package) | |
32 | { | |
33 | if (package == null) throw new ArgumentNullException("package"); | |
34 | | |
35 | package.RemovePowerToolsAnnotations(); | |
36 | package.Save(); | |
37 | } | |
38 | | |
39 | /// <summary> | |
40 | /// Ends a PowerTools Block by reloading the root elements of all package parts | |
41 | /// that were changed by the PowerTools. A part is deemed changed by the PowerTools | |
42 | /// if it has an annotation of type <see cref="XDocument" />. | |
43 | /// </summary> | |
44 | /// <param name="package"> | |
45 | /// A <see cref="WordprocessingDocument" />, <see cref="SpreadsheetDocument" />, | |
46 | /// or <see cref="PresentationDocument" />. | |
47 | /// </param> | |
48 | public static void EndPowerToolsBlock(this OpenXmlPackage package) | |
49 | { | |
50 | if (package == null) throw new ArgumentNullException("package"); | |
51 | | |
52 | foreach (OpenXmlPart part in package.GetAllParts()) | |
53 | { | |
54 | if (part.Annotations<XDocument>().Any() && part.RootElement != null) | |
55 | part.RootElement.Reload(); | |
56 | } | |
57 | } | |
58 | | |
59 | private static void RemovePowerToolsAnnotations(this OpenXmlPackage package) | |
60 | { | |
61 | if (package == null) throw new ArgumentNullException("package"); | |
62 | | |
63 | foreach (OpenXmlPart part in package.GetAllParts()) | |
64 | { | |
65 | part.RemoveAnnotations<XDocument>(); | |
66 | part.RemoveAnnotations<XmlNamespaceManager>(); | |
67 | } | |
68 | } | |
69 | } | |
70 | } | |
71 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/Properties/AssemblyInfo.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System.Runtime.CompilerServices; | |
5 | | |
6 | [assembly: InternalsVisibleTo("OpenXmlPowerTools.Tests")] | |
7 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/RevisionAccepter.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Linq; | |
7 | using System.Xml.Linq; | |
8 | using DocumentFormat.OpenXml.Packaging; | |
9 | | |
10 | namespace OpenXmlPowerTools | |
11 | { | |
12 | public class RevisionAccepter | |
13 | { | |
14 | public static WmlDocument AcceptRevisions(WmlDocument document) | |
15 | { | |
16 | using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(document)) | |
17 | { | |
18 | using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument()) | |
19 | { | |
20 | AcceptRevisions(doc); | |
21 | } | |
22 | return streamDoc.GetModifiedWmlDocument(); | |
23 | } | |
24 | } | |
25 | | |
26 | public static void AcceptRevisions(WordprocessingDocument doc) | |
27 | { | |
28 | RevisionProcessor.AcceptRevisions(doc); | |
29 | } | |
30 | | |
31 | public static bool PartHasTrackedRevisions(OpenXmlPart part) | |
32 | { | |
33 | return RevisionProcessor.PartHasTrackedRevisions(part); | |
34 | } | |
35 | | |
36 | public static bool HasTrackedRevisions(WmlDocument document) | |
37 | { | |
38 | return RevisionProcessor.HasTrackedRevisions(document); | |
39 | } | |
40 | | |
41 | public static bool HasTrackedRevisions(WordprocessingDocument doc) | |
42 | { | |
43 | return RevisionProcessor.HasTrackedRevisions(doc); | |
44 | } | |
45 | } | |
46 | } | |
47 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/SSFormula.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Linq; | |
7 | using System.Text; | |
8 | | |
9 | namespace ExcelFormula | |
10 | { | |
11 | public class ParseFormula | |
12 | { | |
13 | ExcelFormula parser; | |
14 | | |
15 | public ParseFormula(string formula) | |
16 | { | |
17 | parser = new ExcelFormula(formula, Console.Out); | |
18 | bool parserResult = false; | |
19 | try | |
20 | { | |
21 | parserResult = parser.Formula(); | |
22 | } | |
23 | catch (Peg.Base.PegException) | |
24 | { | |
25 | } | |
26 | if (!parserResult) | |
27 | { | |
28 | parser.Warning("Error processing " + formula); | |
29 | } | |
30 | } | |
31 | | |
32 | public string ReplaceSheetName(string oldName, string newName) | |
33 | { | |
34 | StringBuilder text = new StringBuilder(parser.GetSource()); | |
35 | ReplaceNode(parser.GetRoot(), (int)EExcelFormula.SheetName, oldName, newName, text); | |
36 | return text.ToString(); | |
37 | } | |
38 | | |
39 | public string ReplaceRelativeCell(int rowOffset, int colOffset) | |
40 | { | |
41 | StringBuilder text = new StringBuilder(parser.GetSource()); | |
42 | ReplaceRelativeCell(parser.GetRoot(), rowOffset, colOffset, text); | |
43 | return text.ToString(); | |
44 | } | |
45 | | |
46 | // Recursive function that will replace values from last to first | |
47 | private void ReplaceNode(Peg.Base.PegNode node, int id, string oldName, string newName, StringBuilder text) | |
48 | { | |
49 | if (node.next_ != null) | |
50 | ReplaceNode(node.next_, id, oldName, newName, text); | |
51 | if (node.id_ == id && parser.GetSource().Substring(node.match_.posBeg_, node.match_.Length) == oldName) | |
52 | { | |
53 | text.Remove(node.match_.posBeg_, node.match_.Length); | |
54 | text.Insert(node.match_.posBeg_, newName); | |
55 | } | |
56 | else if (node.child_ != null) | |
57 | ReplaceNode(node.child_, id, oldName, newName, text); | |
58 | } | |
59 | | |
60 | // Recursive function that will adjust relative cells from last to first | |
61 | private void ReplaceRelativeCell(Peg.Base.PegNode node, int rowOffset, int colOffset, StringBuilder text) | |
62 | { | |
63 | if (node.next_ != null) | |
64 | ReplaceRelativeCell(node.next_, rowOffset, colOffset, text); | |
65 | if (node.id_ == (int)EExcelFormula.A1Row && parser.GetSource().Substring(node.match_.posBeg_, 1) != " | |
quot;) | |
66 | { | |
67 | int rowNumber = Convert.ToInt32(parser.GetSource().Substring(node.match_.posBeg_, node.match_.Length)); | |
68 | text.Remove(node.match_.posBeg_, node.match_.Length); | |
69 | text.Insert(node.match_.posBeg_, Convert.ToString(rowNumber + rowOffset)); | |
70 | } | |
71 | else if (node.id_ == (int)EExcelFormula.A1Column && parser.GetSource().Substring(node.match_.posBeg_, 1) != " | |
quot;) | |
72 | { | |
73 | int colNumber = GetColumnNumber(parser.GetSource().Substring(node.match_.posBeg_, node.match_.Length)); | |
74 | text.Remove(node.match_.posBeg_, node.match_.Length); | |
75 | text.Insert(node.match_.posBeg_, GetColumnId(colNumber + colOffset)); | |
76 | } | |
77 | else if (node.child_ != null) | |
78 | ReplaceRelativeCell(node.child_, rowOffset, colOffset, text); | |
79 | } | |
80 | | |
81 | // Converts the column reference string to a column number (e.g. A -> 1, B -> 2) | |
82 | private static int GetColumnNumber(string cellReference) | |
83 | { | |
84 | int columnNumber = 0; | |
85 | foreach (char c in cellReference) | |
86 | { | |
87 | if (Char.IsLetter(c)) | |
88 | columnNumber = columnNumber * 26 + System.Convert.ToInt32(c) - System.Convert.ToInt32('A') + 1; | |
89 | } | |
90 | return columnNumber; | |
91 | } | |
92 | | |
93 | // Translates the column number to the column reference string (e.g. 1 -> A, 2-> B) | |
94 | private static string GetColumnId(int columnNumber) | |
95 | { | |
96 | string result = ""; | |
97 | do | |
98 | { | |
99 | result = ((char)((columnNumber - 1) % 26 + (int)'A')).ToString() + result; | |
100 | columnNumber = (columnNumber - 1) / 26; | |
101 | } while (columnNumber != 0); | |
102 | return result; | |
103 | } | |
104 | } | |
105 | } | |
106 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/ScalarTypes.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections; | |
6 | using System.Collections.ObjectModel; | |
7 | | |
8 | namespace OpenXmlPowerTools | |
9 | { | |
10 | internal static class DefaultScalarTypes | |
11 | { | |
12 | private static readonly Hashtable defaultScalarTypesHash; | |
13 | internal static bool IsTypeInList(Collection<string> typeNames) | |
14 | { | |
15 | string text = PSObjectIsOfExactType(typeNames); | |
16 | return !string.IsNullOrEmpty(text) && (PSObjectIsEnum(typeNames) || DefaultScalarTypes.defaultScalarTypesHash.ContainsKey(text)); | |
17 | } | |
18 | | |
19 | static DefaultScalarTypes() | |
20 | { | |
21 | DefaultScalarTypes.defaultScalarTypesHash = new Hashtable(StringComparer.OrdinalIgnoreCase); | |
22 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.String", null); | |
23 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.SByte", null); | |
24 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.Byte", null); | |
25 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.Int16", null); | |
26 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.UInt16", null); | |
27 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.Int32", 10); | |
28 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.UInt32", 10); | |
29 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.Int64", null); | |
30 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.UInt64", null); | |
31 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.Char", 1); | |
32 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.Single", null); | |
33 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.Double", null); | |
34 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.Boolean", 5); | |
35 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.Decimal", null); | |
36 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.IntPtr", null); | |
37 | DefaultScalarTypes.defaultScalarTypesHash.Add("System.Security.SecureString", null); | |
38 | } | |
39 | | |
40 | internal static string PSObjectIsOfExactType(Collection<string> typeNames) | |
41 | { | |
42 | if (typeNames.Count != 0) | |
43 | { | |
44 | return typeNames[0]; | |
45 | } | |
46 | return null; | |
47 | } | |
48 | | |
49 | internal static bool PSObjectIsEnum(Collection<string> typeNames) | |
50 | { | |
51 | return typeNames.Count >= 2 && !string.IsNullOrEmpty(typeNames[1]) && string.Equals(typeNames[1], "System.Enum", StringComparison.Ordinal); | |
52 | } | |
53 | } | |
54 | } | |
55 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/StronglyTypedBlock.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using DocumentFormat.OpenXml.Packaging; | |
6 | | |
7 | namespace OpenXmlPowerTools | |
8 | { | |
9 | /// <summary> | |
10 | /// Provides an elegant way of wrapping a set of invocations of the strongly typed | |
11 | /// classes provided by the Open XML SDK) in a using statement that demarcates those | |
12 | /// invokations as one "block" before and after which the PowerTools can be used safely. | |
13 | /// </summary> | |
14 | /// <remarks> | |
15 | /// <para> | |
16 | /// This class lends itself to scenarios where the PowerTools and Linq-to-XML are used as | |
17 | /// the primary API for working with Open XML elements, next to the strongly typed classes | |
18 | /// provided by the Open XML SDK. In these scenarios, the class would be used as follows: | |
19 | /// </para> | |
20 | /// <code> | |
21 | /// [Your code using the PowerTools] | |
22 | /// | |
23 | /// using (new NonPowerToolsBlock(wordprocessingDocument)) | |
24 | /// { | |
25 | /// [Your code using the strongly typed classes] | |
26 | /// } | |
27 | /// | |
28 | /// [Your code using the PowerTools] | |
29 | /// </code> | |
30 | /// <para> | |
31 | /// Upon creation, instances of this class will invoke the | |
32 | /// <see cref="PowerToolsBlockExtensions.EndPowerToolsBlock"/> method on the package | |
33 | /// to begin the block. Upon disposal, instances of this class will call the | |
34 | /// <see cref="PowerToolsBlockExtensions.BeginPowerToolsBlock"/> method on the package | |
35 | /// to end the block. | |
36 | /// </para> | |
37 | /// </remarks> | |
38 | /// <seealso cref="PowerToolsBlock"/> | |
39 | /// <seealso cref="PowerToolsBlockExtensions.BeginPowerToolsBlock"/> | |
40 | /// <seealso cref="PowerToolsBlockExtensions.EndPowerToolsBlock"/> | |
41 | public class StronglyTypedBlock : IDisposable | |
42 | { | |
43 | private OpenXmlPackage _package; | |
44 | | |
45 | public StronglyTypedBlock(OpenXmlPackage package) | |
46 | { | |
47 | if (package == null) throw new ArgumentNullException("package"); | |
48 | | |
49 | _package = package; | |
50 | _package.EndPowerToolsBlock(); | |
51 | } | |
52 | | |
53 | public void Dispose() | |
54 | { | |
55 | if (_package == null) return; | |
56 | | |
57 | _package.BeginPowerToolsBlock(); | |
58 | _package = null; | |
59 | } | |
60 | } | |
61 | } | |
62 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/TestUtil.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Diagnostics; | |
7 | using System.IO; | |
8 | using System.Linq; | |
9 | using System.Text; | |
10 | using System.Threading.Tasks; | |
11 | | |
12 | namespace OpenXmlPowerTools | |
13 | { | |
14 | public class TestUtil | |
15 | { | |
16 | private static bool? s_DeleteTempFiles = null; | |
17 | | |
18 | public static bool DeleteTempFiles | |
19 | { | |
20 | get | |
21 | { | |
22 | if (s_DeleteTempFiles != null) | |
23 | return (bool)s_DeleteTempFiles; | |
24 | FileInfo donotdelete = new FileInfo("donotdelete.txt"); | |
25 | s_DeleteTempFiles = !donotdelete.Exists; | |
26 | return (bool)s_DeleteTempFiles; | |
27 | } | |
28 | } | |
29 | | |
30 | private static DirectoryInfo s_TempDir = null; | |
31 | public static DirectoryInfo TempDir | |
32 | { | |
33 | get | |
34 | { | |
35 | if (s_TempDir != null) | |
36 | return s_TempDir; | |
37 | else | |
38 | { | |
39 | var now = DateTime.Now; | |
40 | var tempDirName = String.Format("Test-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", now.Year - 2000, now.Month, now.Day, now.Hour, now.Minute, now.Second); | |
41 | s_TempDir = new DirectoryInfo(Path.Combine(".", tempDirName)); | |
42 | s_TempDir.Create(); | |
43 | return s_TempDir; | |
44 | } | |
45 | } | |
46 | } | |
47 | | |
48 | public static void NotePad(string str) | |
49 | { | |
50 | var guidName = Guid.NewGuid().ToString().Replace("-", "") + ".txt"; | |
51 | var fi = new FileInfo(Path.Combine(TempDir.FullName, guidName)); | |
52 | File.WriteAllText(fi.FullName, str); | |
53 | var notepadExe = new FileInfo(@"C:\Program Files (x86)\Notepad++\notepad++.exe"); | |
54 | if (!notepadExe.Exists) | |
55 | notepadExe = new FileInfo(@"C:\Program Files\Notepad++\notepad++.exe"); | |
56 | if (!notepadExe.Exists) | |
57 | notepadExe = new FileInfo(@"C:\Windows\System32\notepad.exe"); | |
58 | ExecutableRunner.RunExecutable(notepadExe.FullName, fi.FullName, TempDir.FullName); | |
59 | } | |
60 | | |
61 | public static void KDiff3(FileInfo oldFi, FileInfo newFi) | |
62 | { | |
63 | var kdiffExe = new FileInfo(@"C:\Program Files (x86)\KDiff3\kdiff3.exe"); | |
64 | var result = ExecutableRunner.RunExecutable(kdiffExe.FullName, oldFi.FullName + " " + newFi.FullName, TempDir.FullName); | |
65 | } | |
66 | | |
67 | public static void Explorer(DirectoryInfo di) | |
68 | { | |
69 | Process.Start(di.FullName); | |
70 | } | |
71 | } | |
72 | } | |
73 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerTools/WmlDocument.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.IO.Packaging; | |
8 | using System.Linq; | |
9 | using System.Text; | |
10 | using System.Xml; | |
11 | using System.Xml.Linq; | |
12 | using DocumentFormat.OpenXml.Packaging; | |
13 | | |
14 | namespace OpenXmlPowerTools | |
15 | { | |
16 | public class PtMainDocumentPart : XElement | |
17 | { | |
18 | private WmlDocument ParentWmlDocument; | |
19 | | |
20 | public PtWordprocessingCommentsPart WordprocessingCommentsPart | |
21 | { | |
22 | get | |
23 | { | |
24 | using (MemoryStream ms = new MemoryStream(ParentWmlDocument.DocumentByteArray)) | |
25 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(ms, false)) | |
26 | { | |
27 | WordprocessingCommentsPart commentsPart = wDoc.MainDocumentPart.WordprocessingCommentsPart; | |
28 | if (commentsPart == null) | |
29 | return null; | |
30 | XElement partElement = commentsPart.GetXDocument().Root; | |
31 | var childNodes = partElement.Nodes().ToList(); | |
32 | foreach (var item in childNodes) | |
33 | item.Remove(); | |
34 | return new PtWordprocessingCommentsPart(this.ParentWmlDocument, commentsPart.Uri, partElement.Name, partElement.Attributes(), childNodes); | |
35 | } | |
36 | } | |
37 | } | |
38 | | |
39 | public PtMainDocumentPart(WmlDocument wmlDocument, Uri uri, XName name, params object[] values) | |
40 | : base(name, values) | |
41 | { | |
42 | ParentWmlDocument = wmlDocument; | |
43 | this.Add( | |
44 | new XAttribute(PtOpenXml.Uri, uri), | |
45 | new XAttribute(XNamespace.Xmlns + "pt", PtOpenXml.pt) | |
46 | ); | |
47 | } | |
48 | } | |
49 | | |
50 | public class PtWordprocessingCommentsPart : XElement | |
51 | { | |
52 | private WmlDocument ParentWmlDocument; | |
53 | | |
54 | public PtWordprocessingCommentsPart(WmlDocument wmlDocument, Uri uri, XName name, params object[] values) | |
55 | : base(name, values) | |
56 | { | |
57 | ParentWmlDocument = wmlDocument; | |
58 | this.Add( | |
59 | new XAttribute(PtOpenXml.Uri, uri), | |
60 | new XAttribute(XNamespace.Xmlns + "pt", PtOpenXml.pt) | |
61 | ); | |
62 | } | |
63 | } | |
64 | | |
65 | public partial class WmlDocument | |
66 | { | |
67 | public PtMainDocumentPart MainDocumentPart | |
68 | { | |
69 | get | |
70 | { | |
71 | using (MemoryStream ms = new MemoryStream(this.DocumentByteArray)) | |
72 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(ms, false)) | |
73 | { | |
74 | XElement partElement = wDoc.MainDocumentPart.GetXDocument().Root; | |
75 | var childNodes = partElement.Nodes().ToList(); | |
76 | foreach (var item in childNodes) | |
77 | item.Remove(); | |
78 | return new PtMainDocumentPart(this, wDoc.MainDocumentPart.Uri, partElement.Name, partElement.Attributes(), childNodes); | |
79 | } | |
80 | } | |
81 | } | |
82 | | |
83 | public WmlDocument(WmlDocument other, params XElement[] replacementParts) | |
84 | : base(other) | |
85 | { | |
86 | using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(this)) | |
87 | { | |
88 | using (Package package = streamDoc.GetPackage()) | |
89 | { | |
90 | foreach (var replacementPart in replacementParts) | |
91 | { | |
92 | XAttribute uriAttribute = replacementPart.Attribute(PtOpenXml.Uri); | |
93 | if (uriAttribute == null) | |
94 | throw new OpenXmlPowerToolsException("Replacement part does not contain a Uri as an attribute"); | |
95 | String uri = uriAttribute.Value; | |
96 | var part = package.GetParts().FirstOrDefault(p => p.Uri.ToString() == uri); | |
97 | using (Stream partStream = part.GetStream(FileMode.Create, FileAccess.Write)) | |
98 | using (XmlWriter partXmlWriter = XmlWriter.Create(partStream)) | |
99 | replacementPart.Save(partXmlWriter); | |
100 | } | |
101 | } | |
102 | this.DocumentByteArray = streamDoc.GetModifiedDocument().DocumentByteArray; | |
103 | } | |
104 | } | |
105 | } | |
106 | } | |
107 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/DocumentAssembler/DocumentAssembler.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.IO; | |
6 | using System.Xml.Linq; | |
7 | | |
8 | namespace OpenXmlPowerTools | |
9 | { | |
10 | class Program | |
11 | { | |
12 | static void Main(string[] args) | |
13 | { | |
14 | if (args.Length != 3) | |
15 | { | |
16 | PrintUsage(); | |
17 | Environment.Exit(0); | |
18 | } | |
19 | | |
20 | FileInfo templateDoc = new FileInfo(args[0]); | |
21 | if (!templateDoc.Exists) | |
22 | { | |
23 | Console.WriteLine("Error, {0} does not exist.", args[0]); | |
24 | PrintUsage(); | |
25 | Environment.Exit(0); | |
26 | } | |
27 | FileInfo dataFile = new FileInfo(args[1]); | |
28 | if (!dataFile.Exists) | |
29 | { | |
30 | Console.WriteLine("Error, {0} does not exist.", args[1]); | |
31 | PrintUsage(); | |
32 | Environment.Exit(0); | |
33 | } | |
34 | FileInfo assembledDoc = new FileInfo(args[2]); | |
35 | if (assembledDoc.Exists) | |
36 | { | |
37 | Console.WriteLine("Error, {0} exists.", args[2]); | |
38 | PrintUsage(); | |
39 | Environment.Exit(0); | |
40 | } | |
41 | | |
42 | WmlDocument wmlDoc = new WmlDocument(templateDoc.FullName); | |
43 | XElement data = XElement.Load(dataFile.FullName); | |
44 | bool templateError; | |
45 | WmlDocument wmlAssembledDoc = DocumentAssembler.AssembleDocument(wmlDoc, data, out templateError); | |
46 | if (templateError) | |
47 | { | |
48 | Console.WriteLine("Errors in template."); | |
49 | Console.WriteLine("See {0} to determine the errors in the template.", assembledDoc.Name); | |
50 | } | |
51 | | |
52 | wmlAssembledDoc.SaveAs(assembledDoc.FullName); | |
53 | } | |
54 | | |
55 | static void PrintUsage() | |
56 | { | |
57 | Console.WriteLine("Usage: DocumentAssembler TemplateDocument.docx Data.xml AssembledDoc.docx"); | |
58 | } | |
59 | } | |
60 | } | |
61 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/DocumentAssembler01/DocumentAssembler01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Threading.Tasks; | |
10 | using System.Xml.Linq; | |
11 | using DocumentFormat.OpenXml.Packaging; | |
12 | using OpenXmlPowerTools; | |
13 | | |
14 | namespace OpenXmlPowerTools | |
15 | { | |
16 | class Program | |
17 | { | |
18 | static void Main(string[] args) | |
19 | { | |
20 | var n = DateTime.Now; | |
21 | 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)); | |
22 | tempDi.Create(); | |
23 | | |
24 | FileInfo templateDoc = new FileInfo("../../TemplateDocument.docx"); | |
25 | FileInfo dataFile = new FileInfo("../../Data.xml"); | |
26 | | |
27 | WmlDocument wmlDoc = new WmlDocument(templateDoc.FullName); | |
28 | XElement data = XElement.Load(dataFile.FullName); | |
29 | bool templateError; | |
30 | WmlDocument wmlAssembledDoc = DocumentAssembler.AssembleDocument(wmlDoc, data, out templateError); | |
31 | if (templateError) | |
32 | { | |
33 | Console.WriteLine("Errors in template."); | |
34 | Console.WriteLine("See AssembledDoc.docx to determine the errors in the template."); | |
35 | } | |
36 | | |
37 | FileInfo assembledDoc = new FileInfo(Path.Combine(tempDi.FullName, "AssembledDoc.docx")); | |
38 | wmlAssembledDoc.SaveAs(assembledDoc.FullName); | |
39 | } | |
40 | } | |
41 | } | |
42 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/DocumentAssembler02/DocumentAssembler02.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Threading.Tasks; | |
10 | using System.Xml.Linq; | |
11 | using DocumentFormat.OpenXml.Packaging; | |
12 | using OpenXmlPowerTools; | |
13 | | |
14 | namespace OpenXmlPowerTools | |
15 | { | |
16 | class Program | |
17 | { | |
18 | static void Main(string[] args) | |
19 | { | |
20 | var n = DateTime.Now; | |
21 | 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)); | |
22 | tempDi.Create(); | |
23 | | |
24 | FileInfo templateDoc = new FileInfo("../../TemplateDocument.docx"); | |
25 | FileInfo dataFile = new FileInfo("../../Data.xml"); | |
26 | | |
27 | WmlDocument wmlDoc = new WmlDocument(templateDoc.FullName); | |
28 | XElement data = XElement.Load(dataFile.FullName); | |
29 | bool templateError; | |
30 | WmlDocument wmlAssembledDoc = DocumentAssembler.AssembleDocument(wmlDoc, data, out templateError); | |
31 | if (templateError) | |
32 | { | |
33 | Console.WriteLine("Errors in template."); | |
34 | Console.WriteLine("See AssembledDoc.docx to determine the errors in the template."); | |
35 | } | |
36 | | |
37 | FileInfo assembledDoc = new FileInfo(Path.Combine(tempDi.FullName, "AssembledDoc.docx")); | |
38 | wmlAssembledDoc.SaveAs(assembledDoc.FullName); | |
39 | } | |
40 | } | |
41 | } | |
42 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/DocumentAssembler03/DocumentAssembler03.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Threading.Tasks; | |
10 | using System.Xml.Linq; | |
11 | using DocumentFormat.OpenXml.Packaging; | |
12 | using OpenXmlPowerTools; | |
13 | | |
14 | namespace OpenXmlPowerTools | |
15 | { | |
16 | class Program | |
17 | { | |
18 | static void Main(string[] args) | |
19 | { | |
20 | var n = DateTime.Now; | |
21 | 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)); | |
22 | tempDi.Create(); | |
23 | | |
24 | FileInfo templateDoc = new FileInfo("../../TemplateDocument.docx"); | |
25 | FileInfo dataFile = new FileInfo(Path.Combine(tempDi.FullName, "Data.xml")); | |
26 | | |
27 | // The following method generates a large data file with random data. | |
28 | // In a real world scenario, this is where you would query your data source and produce XML that will drive your document generation process. | |
29 | XElement data = GenerateDataFromDataSource(dataFile); | |
30 | | |
31 | WmlDocument wmlDoc = new WmlDocument(templateDoc.FullName); | |
32 | int count = 1; | |
33 | foreach (var customer in data.Elements("Customer")) | |
34 | { | |
35 | FileInfo assembledDoc = new FileInfo(Path.Combine(tempDi.FullName, string.Format("Letter-{0:0000}.docx", count++))); | |
36 | Console.WriteLine(assembledDoc.Name); | |
37 | bool templateError; | |
38 | WmlDocument wmlAssembledDoc = DocumentAssembler.AssembleDocument(wmlDoc, customer, out templateError); | |
39 | if (templateError) | |
40 | { | |
41 | Console.WriteLine("Errors in template."); | |
42 | Console.WriteLine("See {0} to determine the errors in the template.", assembledDoc.Name); | |
43 | } | |
44 | wmlAssembledDoc.SaveAs(assembledDoc.FullName); | |
45 | } | |
46 | } | |
47 | | |
48 | private static string[] s_productNames = new[] { | |
49 | "Unicycle", | |
50 | "Bicycle", | |
51 | "Tricycle", | |
52 | "Skateboard", | |
53 | "Roller Blades", | |
54 | "Hang Glider", | |
55 | }; | |
56 | | |
57 | private static XElement GenerateDataFromDataSource(FileInfo dataFi) | |
58 | { | |
59 | int numberOfDocumentsToGenerate = 500; | |
60 | var customers = new XElement("Customers"); | |
61 | Random r = new Random(); | |
62 | for (int i = 0; i < numberOfDocumentsToGenerate; ++i) | |
63 | { | |
64 | var customer = new XElement("Customer", | |
65 | new XElement("CustomerID", i + 1), | |
66 | new XElement("Name", "Eric White"), | |
67 | new XElement("HighValueCustomer", r.Next(2) == 0 ? "True" : "False"), | |
68 | new XElement("Orders")); | |
69 | var orders = customer.Element("Orders"); | |
70 | int numberOfOrders = r.Next(10) + 1; | |
71 | for (int j = 0; j < numberOfOrders; j++) | |
72 | { | |
73 | var order = new XElement("Order", | |
74 | new XAttribute("Number", j + 1), | |
75 | new XElement("ProductDescription", s_productNames[r.Next(s_productNames.Length)]), | |
76 | new XElement("Quantity", r.Next(10)), | |
77 | new XElement("OrderDate", "September 26, 2015")); | |
78 | orders.Add(order); | |
79 | } | |
80 | customers.Add(customer); | |
81 | } | |
82 | customers.Save(dataFi.FullName); | |
83 | return customers; | |
84 | } | |
85 | } | |
86 | } | |
87 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/DocumentBuilder01/DocumentBuilder01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using DocumentFormat.OpenXml.Packaging; | |
10 | using DocumentFormat.OpenXml.Validation; | |
11 | using OpenXmlPowerTools; | |
12 | | |
13 | namespace DocumentBuilderExample | |
14 | { | |
15 | class DocumentBuilderExample | |
16 | { | |
17 | static void Main(string[] args) | |
18 | { | |
19 | var n = DateTime.Now; | |
20 | 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)); | |
21 | tempDi.Create(); | |
22 | | |
23 | string source1 = "../../Source1.docx"; | |
24 | string source2 = "../../Source2.docx"; | |
25 | string source3 = "../../Source3.docx"; | |
26 | List<Source> sources = null; | |
27 | | |
28 | // Create new document from 10 paragraphs starting at paragraph 5 of Source1.docx | |
29 | sources = new List<Source>() | |
30 | { | |
31 | new Source(new WmlDocument(source1), 5, 10, true), | |
32 | }; | |
33 | DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "Out1.docx")); | |
34 | | |
35 | // Create new document from paragraph 1, and paragraphs 5 through end of Source3.docx. | |
36 | // This effectively 'deletes' paragraphs 2-4 | |
37 | sources = new List<Source>() | |
38 | { | |
39 | new Source(new WmlDocument(source3), 0, 1, false), | |
40 | new Source(new WmlDocument(source3), 4, false), | |
41 | }; | |
42 | DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "Out2.docx")); | |
43 | | |
44 | // Create a new document that consists of the entirety of Source1.docx and Source2.docx. Use | |
45 | // the section information (headings and footers) from source1. | |
46 | sources = new List<Source>() | |
47 | { | |
48 | new Source(new WmlDocument(source1), true), | |
49 | new Source(new WmlDocument(source2), false), | |
50 | }; | |
51 | DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "Out3.docx")); | |
52 | | |
53 | // Create a new document that consists of the entirety of Source1.docx and Source2.docx. Use | |
54 | // the section information (headings and footers) from source2. | |
55 | sources = new List<Source>() | |
56 | { | |
57 | new Source(new WmlDocument(source1), false), | |
58 | new Source(new WmlDocument(source2), true), | |
59 | }; | |
60 | DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "Out4.docx")); | |
61 | | |
62 | // Create a new document that consists of the first 5 paragraphs of Source1.docx and the first | |
63 | // five paragraphs of Source2.docx. This example returns a new WmlDocument, when you then can | |
64 | // serialize to a SharePoint document library, or use in some other interesting scenario. | |
65 | sources = new List<Source>() | |
66 | { | |
67 | new Source(new WmlDocument(source1), 0, 5, false), | |
68 | new Source(new WmlDocument(source2), 0, 5, true), | |
69 | }; | |
70 | WmlDocument out5 = DocumentBuilder.BuildDocument(sources); | |
71 | out5.SaveAs(Path.Combine(tempDi.FullName, "Out5.docx")); // save it to the file system, but we could just as easily done something | |
72 | // else with it. | |
73 | } | |
74 | } | |
75 | } | |
76 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/DocumentBuilder02/DocumentBuilder02.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Xml.Linq; | |
10 | using DocumentFormat.OpenXml.Packaging; | |
11 | using OpenXmlPowerTools; | |
12 | | |
13 | // Insert content into a document | |
14 | // Delete content from a document | |
15 | // Shred a document | |
16 | // Assemble it again, insert TOC | |
17 | | |
18 | class DocumentBuilderExample02 | |
19 | { | |
20 | private class DocumentInfo | |
21 | { | |
22 | public int DocumentNumber; | |
23 | public int Start; | |
24 | public int Count; | |
25 | } | |
26 | | |
27 | static void Main(string[] args) | |
28 | { | |
29 | var n = DateTime.Now; | |
30 | 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)); | |
31 | tempDi.Create(); | |
32 | | |
33 | // Insert an abstract and author biography into a white paper. | |
34 | List<Source> sources = null; | |
35 | | |
36 | sources = new List<Source>() | |
37 | { | |
38 | new Source(new WmlDocument("../../WhitePaper.docx"), 0, 1, true), | |
39 | new Source(new WmlDocument("../../Abstract.docx"), false), | |
40 | new Source(new WmlDocument("../../AuthorBiography.docx"), false), | |
41 | new Source(new WmlDocument("../../WhitePaper.docx"), 1, false), | |
42 | }; | |
43 | DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "AssembledPaper.docx")); | |
44 | | |
45 | // Delete all paragraphs with a specific style. | |
46 | using (WordprocessingDocument doc = | |
47 | WordprocessingDocument.Open("../../Notes.docx", false)) | |
48 | { | |
49 | sources = doc | |
50 | .MainDocumentPart | |
51 | .GetXDocument() | |
52 | .Root | |
53 | .Element(W.body) | |
54 | .Elements() | |
55 | .Select((p, i) => new | |
56 | { | |
57 | Paragraph = p, | |
58 | Index = i, | |
59 | }) | |
60 | .GroupAdjacent(pi => (string)pi.Paragraph | |
61 | .Elements(W.pPr) | |
62 | .Elements(W.pStyle) | |
63 | .Attributes(W.val) | |
64 | .FirstOrDefault() != "Note") | |
65 | .Where(g => g.Key == true) | |
66 | .Select(g => new Source( | |
67 | new WmlDocument("../../Notes.docx"), g.First().Index, | |
68 | g.Last().Index - g.First().Index + 1, true)) | |
69 | .ToList(); | |
70 | } | |
71 | DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "NewNotes.docx")); | |
72 | | |
73 | // Shred a document into multiple parts for each section | |
74 | List<DocumentInfo> documentList; | |
75 | using (WordprocessingDocument doc = | |
76 | WordprocessingDocument.Open("../../Spec.docx", false)) | |
77 | { | |
78 | var sectionCounts = doc | |
79 | .MainDocumentPart | |
80 | .GetXDocument() | |
81 | .Root | |
82 | .Element(W.body) | |
83 | .Elements() | |
84 | .Rollup(0, (pi, last) => (string)pi | |
85 | .Elements(W.pPr) | |
86 | .Elements(W.pStyle) | |
87 | .Attributes(W.val) | |
88 | .FirstOrDefault() == "Heading1" ? last + 1 : last); | |
89 | var beforeZipped = doc | |
90 | .MainDocumentPart | |
91 | .GetXDocument() | |
92 | .Root | |
93 | .Element(W.body) | |
94 | .Elements() | |
95 | .Select((p, i) => new | |
96 | { | |
97 | Paragraph = p, | |
98 | Index = i, | |
99 | }); | |
100 | var zipped = PtExtensions.PtZip(beforeZipped, sectionCounts, (pi, sc) => new | |
101 | { | |
102 | Paragraph = pi.Paragraph, | |
103 | Index = pi.Index, | |
104 | SectionIndex = sc, | |
105 | }); | |
106 | documentList = zipped | |
107 | .GroupAdjacent(p => p.SectionIndex) | |
108 | .Select(g => new DocumentInfo | |
109 | { | |
110 | DocumentNumber = g.Key, | |
111 | Start = g.First().Index, | |
112 | Count = g.Last().Index - g.First().Index + 1, | |
113 | }) | |
114 | .ToList(); | |
115 | } | |
116 | foreach (var doc in documentList) | |
117 | { | |
118 | string fileName = String.Format("Section{0:000}.docx", doc.DocumentNumber); | |
119 | List<Source> documentSource = new List<Source> { | |
120 | new Source(new WmlDocument("../../Spec.docx"), doc.Start, doc.Count, true) | |
121 | }; | |
122 | DocumentBuilder.BuildDocument(documentSource, Path.Combine(tempDi.FullName, fileName)); | |
123 | } | |
124 | | |
125 | // Re-assemble the parts into a single document. | |
126 | sources = tempDi | |
127 | .GetFiles("Section*.docx") | |
128 | .Select(d => new Source(new WmlDocument(d.FullName), true)) | |
129 | .ToList(); | |
130 | DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "ReassembledSpec.docx")); | |
131 | } | |
132 | } | |
133 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/DocumentBuilder03/DocumentBuilder03.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Xml.Linq; | |
10 | using DocumentFormat.OpenXml.Packaging; | |
11 | using DocumentFormat.OpenXml.Validation; | |
12 | using OpenXmlPowerTools; | |
13 | | |
14 | class Program | |
15 | { | |
16 | static void Main(string[] args) | |
17 | { | |
18 | var n = DateTime.Now; | |
19 | 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)); | |
20 | tempDi.Create(); | |
21 | | |
22 | WmlDocument doc1 = new WmlDocument(@"..\..\Template.docx"); | |
23 | using (MemoryStream mem = new MemoryStream()) | |
24 | { | |
25 | mem.Write(doc1.DocumentByteArray, 0, doc1.DocumentByteArray.Length); | |
26 | using (WordprocessingDocument doc = WordprocessingDocument.Open(mem, true)) | |
27 | { | |
28 | XDocument xDoc = doc.MainDocumentPart.GetXDocument(); | |
29 | XElement frontMatterPara = xDoc.Root.Descendants(W.txbxContent).Elements(W.p).FirstOrDefault(); | |
30 | frontMatterPara.ReplaceWith( | |
31 | new XElement(PtOpenXml.Insert, | |
32 | new XAttribute("Id", "Front"))); | |
33 | XElement tbl = xDoc.Root.Element(W.body).Elements(W.tbl).FirstOrDefault(); | |
34 | XElement firstCell = tbl.Descendants(W.tr).First().Descendants(W.p).First(); | |
35 | firstCell.ReplaceWith( | |
36 | new XElement(PtOpenXml.Insert, | |
37 | new XAttribute("Id", "Liz"))); | |
38 | XElement secondCell = tbl.Descendants(W.tr).Skip(1).First().Descendants(W.p).First(); | |
39 | secondCell.ReplaceWith( | |
40 | new XElement(PtOpenXml.Insert, | |
41 | new XAttribute("Id", "Eric"))); | |
42 | doc.MainDocumentPart.PutXDocument(); | |
43 | } | |
44 | doc1.DocumentByteArray = mem.ToArray(); | |
45 | } | |
46 | | |
47 | string outFileName = Path.Combine(tempDi.FullName, "Out.docx"); | |
48 | List<Source> sources = new List<Source>() | |
49 | { | |
50 | new Source(doc1, true), | |
51 | new Source(new WmlDocument(@"..\..\Insert-01.docx"), "Liz"), | |
52 | new Source(new WmlDocument(@"..\..\Insert-02.docx"), "Eric"), | |
53 | new Source(new WmlDocument(@"..\..\FrontMatter.docx"), "Front"), | |
54 | }; | |
55 | DocumentBuilder.BuildDocument(sources, outFileName); | |
56 | } | |
57 | } | |
58 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/DocumentBuilder04/DocumentBuilder04.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Linq; | |
7 | using System.Text; | |
8 | using System.IO; | |
9 | using System.Xml; | |
10 | using System.Xml.Linq; | |
11 | using DocumentFormat.OpenXml.Packaging; | |
12 | using OpenXmlPowerTools; | |
13 | | |
14 | namespace ExampleDocumentBuilder04 | |
15 | { | |
16 | class ContentControlsExample | |
17 | { | |
18 | static void Main(string[] args) | |
19 | { | |
20 | var n = DateTime.Now; | |
21 | 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)); | |
22 | tempDi.Create(); | |
23 | | |
24 | WmlDocument solarSystemDoc = new WmlDocument("../../solar-system.docx"); | |
25 | using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(solarSystemDoc)) | |
26 | using (WordprocessingDocument solarSystem = streamDoc.GetWordprocessingDocument()) | |
27 | { | |
28 | // get children elements of the <w:body> element | |
29 | var q1 = solarSystem | |
30 | .MainDocumentPart | |
31 | .GetXDocument() | |
32 | .Root | |
33 | .Element(W.body) | |
34 | .Elements(); | |
35 | | |
36 | // project collection of tuples containing element and type | |
37 | var q2 = q1 | |
38 | .Select( | |
39 | e => | |
40 | { | |
41 | string keyForGroupAdjacent = ".NonContentControl"; | |
42 | if (e.Name == W.sdt) | |
43 | keyForGroupAdjacent = e.Element(W.sdtPr) | |
44 | .Element(W.tag) | |
45 | .Attribute(W.val) | |
46 | .Value; | |
47 | if (e.Name == W.sectPr) | |
48 | keyForGroupAdjacent = null; | |
49 | return new | |
50 | { | |
51 | Element = e, | |
52 | KeyForGroupAdjacent = keyForGroupAdjacent | |
53 | }; | |
54 | } | |
55 | ).Where(e => e.KeyForGroupAdjacent != null); | |
56 | | |
57 | // group by type | |
58 | var q3 = q2.GroupAdjacent(e => e.KeyForGroupAdjacent); | |
59 | | |
60 | // temporary code to dump q3 | |
61 | foreach (var g in q3) | |
62 | Console.WriteLine("{0}: {1}", g.Key, g.Count()); | |
63 | //Environment.Exit(0); | |
64 | | |
65 | | |
66 | // validate existence of files referenced in content controls | |
67 | foreach (var f in q3.Where(g => g.Key != ".NonContentControl")) | |
68 | { | |
69 | string filename = "../../" + f.Key + ".docx"; | |
70 | FileInfo fi = new FileInfo(filename); | |
71 | if (!fi.Exists) | |
72 | { | |
73 | Console.WriteLine("{0} doesn't exist.", filename); | |
74 | Environment.Exit(0); | |
75 | } | |
76 | } | |
77 | | |
78 | // project collection with opened WordProcessingDocument | |
79 | var q4 = q3 | |
80 | .Select(g => new | |
81 | { | |
82 | Group = g, | |
83 | Document = g.Key != ".NonContentControl" ? | |
84 | new WmlDocument("../../" + g.Key + ".docx") : | |
85 | solarSystemDoc | |
86 | }); | |
87 | | |
88 | // project collection of OpenXml.PowerTools.Source | |
89 | var sources = q4 | |
90 | .Select( | |
91 | g => | |
92 | { | |
93 | if (g.Group.Key == ".NonContentControl") | |
94 | return new Source( | |
95 | g.Document, | |
96 | g.Group | |
97 | .First() | |
98 | .Element | |
99 | .ElementsBeforeSelf() | |
100 | .Count(), | |
101 | g.Group | |
102 | .Count(), | |
103 | false); | |
104 | else | |
105 | return new Source(g.Document, false); | |
106 | } | |
107 | ).ToList(); | |
108 | | |
109 | DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "solar-system-new.docx")); | |
110 | } | |
111 | } | |
112 | } | |
113 | } | |
114 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/FieldRetriever01/FieldRetriever01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Xml.Linq; | |
10 | using DocumentFormat.OpenXml.Packaging; | |
11 | using OpenXmlPowerTools; | |
12 | | |
13 | class FieldRetriever01 | |
14 | { | |
15 | static void Main(string[] args) | |
16 | { | |
17 | var n = DateTime.Now; | |
18 | 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)); | |
19 | tempDi.Create(); | |
20 | | |
21 | var docWithFooter = new FileInfo("../../DocWithFooter1.docx"); | |
22 | var scrubbedDocument = new FileInfo(Path.Combine(tempDi.FullName, "DocWithFooterScrubbed1.docx")); | |
23 | File.Copy(docWithFooter.FullName, scrubbedDocument.FullName); | |
24 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(scrubbedDocument.FullName, true)) | |
25 | { | |
26 | ScrubFooter(wDoc, new [] { "PAGE" }); | |
27 | } | |
28 | | |
29 | docWithFooter = new FileInfo("../../DocWithFooter2.docx"); | |
30 | scrubbedDocument = new FileInfo(Path.Combine(tempDi.FullName, "DocWithFooterScrubbed2.docx")); | |
31 | File.Copy(docWithFooter.FullName, scrubbedDocument.FullName); | |
32 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(scrubbedDocument.FullName, true)) | |
33 | { | |
34 | ScrubFooter(wDoc, new[] { "PAGE", "DATE" }); | |
35 | } | |
36 | } | |
37 | | |
38 | private static void ScrubFooter(WordprocessingDocument wDoc, string[] fieldTypesToKeep) | |
39 | { | |
40 | foreach (var footer in wDoc.MainDocumentPart.FooterParts) | |
41 | { | |
42 | FieldRetriever.AnnotateWithFieldInfo(footer); | |
43 | XElement root = footer.GetXDocument().Root; | |
44 | RemoveAllButSpecificFields(root, fieldTypesToKeep); | |
45 | footer.PutXDocument(); | |
46 | } | |
47 | } | |
48 | | |
49 | private static void RemoveAllButSpecificFields(XElement root, string[] fieldTypesToRetain) | |
50 | { | |
51 | var cachedAnnotationInformation = root.Annotation<Dictionary<int, List<XElement>>>(); | |
52 | List<XElement> runsToKeep = new List<XElement>(); | |
53 | foreach (var item in cachedAnnotationInformation) | |
54 | { | |
55 | var runsForField = root | |
56 | .Descendants() | |
57 | .Where(d => | |
58 | { | |
59 | Stack<FieldRetriever.FieldElementTypeInfo> stack = d.Annotation<Stack<FieldRetriever.FieldElementTypeInfo>>(); | |
60 | if (stack == null) | |
61 | return false; | |
62 | if (stack.Any(stackItem => stackItem.Id == item.Key)) | |
63 | return true; | |
64 | return false; | |
65 | }) | |
66 | .Select(d => d.AncestorsAndSelf(W.r).FirstOrDefault()) | |
67 | .GroupAdjacent(o => o) | |
68 | .Select(g => g.First()) | |
69 | .ToList(); | |
70 | foreach (var r in runsForField) | |
71 | runsToKeep.Add(r); | |
72 | } | |
73 | foreach (var paragraph in root.Descendants(W.p).ToList()) | |
74 | { | |
75 | if (paragraph.Elements(W.r).Any(r => runsToKeep.Contains(r))) | |
76 | { | |
77 | paragraph.Elements(W.r) | |
78 | .Where(r => !runsToKeep.Contains(r) && | |
79 | !r.Elements(W.tab).Any()) | |
80 | .Remove(); | |
81 | paragraph.Elements(W.r) | |
82 | .Where(r => !runsToKeep.Contains(r)) | |
83 | .Elements() | |
84 | .Where(rc => rc.Name != W.rPr && | |
85 | rc.Name != W.tab) | |
86 | .Remove(); | |
87 | } | |
88 | else | |
89 | { | |
90 | paragraph.Remove(); | |
91 | } | |
92 | } | |
93 | root.Descendants(W.tbl).Remove(); | |
94 | } | |
95 | } | |
96 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/FormattingAssembler01/FormattingAssembler01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using DocumentFormat.OpenXml.Packaging; | |
10 | using OpenXmlPowerTools; | |
11 | | |
12 | namespace FormattingAssembler01 | |
13 | { | |
14 | class FormattingAssembler01 | |
15 | { | |
16 | static void Main(string[] args) | |
17 | { | |
18 | var n = DateTime.Now; | |
19 | 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)); | |
20 | tempDi.Create(); | |
21 | | |
22 | DirectoryInfo di = new DirectoryInfo("../../"); | |
23 | foreach (var file in di.GetFiles("*.docx")) | |
24 | { | |
25 | Console.WriteLine(file.Name); | |
26 | var newFile = new FileInfo(Path.Combine(tempDi.FullName, file.Name.Replace(".docx", "out.docx"))); | |
27 | File.Copy(file.FullName, newFile.FullName); | |
28 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(newFile.FullName, true)) | |
29 | { | |
30 | FormattingAssemblerSettings settings = new FormattingAssemblerSettings() | |
31 | { | |
32 | ClearStyles = true, | |
33 | RemoveStyleNamesFromParagraphAndRunProperties = true, | |
34 | CreateHtmlConverterAnnotationAttributes = true, | |
35 | OrderElementsPerStandard = true, | |
36 | RestrictToSupportedLanguages = true, | |
37 | RestrictToSupportedNumberingFormats = true, | |
38 | }; | |
39 | FormattingAssembler.AssembleFormatting(wDoc, settings); | |
40 | } | |
41 | } | |
42 | } | |
43 | } | |
44 | } | |
45 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/Formulas01/Formulas01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Linq; | |
7 | using System.Text; | |
8 | using System.IO; | |
9 | using ExcelFormula; | |
10 | using DocumentFormat.OpenXml.Packaging; | |
11 | using OpenXmlPowerTools; | |
12 | | |
13 | namespace ExampleFormulas | |
14 | { | |
15 | class ExampleFormulas | |
16 | { | |
17 | static void Main(string[] args) | |
18 | { | |
19 | var n = DateTime.Now; | |
20 | 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)); | |
21 | tempDi.Create(); | |
22 | | |
23 | // Change sheet name in formulas | |
24 | using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument( | |
25 | SmlDocument.FromFileName("../../Formulas.xlsx"))) | |
26 | { | |
27 | using (SpreadsheetDocument doc = streamDoc.GetSpreadsheetDocument()) | |
28 | { | |
29 | WorksheetAccessor.FormulaReplaceSheetName(doc, "Source", "'Source 2'"); | |
30 | } | |
31 | streamDoc.GetModifiedSmlDocument().SaveAs(Path.Combine(tempDi.FullName, "FormulasUpdated.xlsx")); | |
32 | } | |
33 | | |
34 | // Change sheet name in formulas | |
35 | using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument( | |
36 | SmlDocument.FromFileName("../../Formulas.xlsx"))) | |
37 | { | |
38 | using (SpreadsheetDocument doc = streamDoc.GetSpreadsheetDocument()) | |
39 | { | |
40 | WorksheetPart sheet = WorksheetAccessor.GetWorksheet(doc, "References"); | |
41 | WorksheetAccessor.CopyCellRange(doc, sheet, 1, 1, 7, 5, 4, 8); | |
42 | } | |
43 | streamDoc.GetModifiedSmlDocument().SaveAs(Path.Combine(tempDi.FullName, "FormulasCopied.xlsx")); | |
44 | } | |
45 | } | |
46 | } | |
47 | } | |
48 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/HtmlConverter01/HtmlConverter01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | /*************************************************************************** | |
5 | | |
6 | Copyright (c) Microsoft Corporation 2010. | |
7 | | |
8 | This code is licensed using the Microsoft Public License (Ms-PL). The text of the license | |
9 | can be found here: | |
10 | | |
11 | http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx | |
12 | | |
13 | ***************************************************************************/ | |
14 | | |
15 | /*************************************************************************** | |
16 | * IMPORTANT NOTE: | |
17 | * | |
18 | * With versions 4.1 and later, the name of the HtmlConverter class has been | |
19 | * changed to WmlToHtmlConverter, to make it orthogonal with HtmlToWmlConverter. | |
20 | * | |
21 | * There are thin wrapper classes, HtmlConverter, and HtmlConverterSettings, | |
22 | * which maintain backwards compat for code that uses the old name. | |
23 | * | |
24 | * Other than the name change of the classes themselves, the functionality | |
25 | * in WmlToHtmlConverter is identical to the old HtmlConverter class. | |
26 | ***************************************************************************/ | |
27 | | |
28 | using System; | |
29 | using System.Drawing.Imaging; | |
30 | using System.IO; | |
31 | using System.Linq; | |
32 | using System.Runtime.InteropServices; | |
33 | using System.Text; | |
34 | using System.Xml.Linq; | |
35 | using DocumentFormat.OpenXml.Packaging; | |
36 | using OpenXmlPowerTools; | |
37 | | |
38 | class HtmlConverterHelper | |
39 | { | |
40 | static void Main(string[] args) | |
41 | { | |
42 | var n = DateTime.Now; | |
43 | 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)); | |
44 | tempDi.Create(); | |
45 | | |
46 | /* | |
47 | * This example loads each document into a byte array, then into a memory stream, so that the document can be opened for writing without | |
48 | * modifying the source document. | |
49 | */ | |
50 | foreach (var file in Directory.GetFiles("../../", "*.docx")) | |
51 | { | |
52 | ConvertToHtml(file, tempDi.FullName); | |
53 | } | |
54 | } | |
55 | | |
56 | public static void ConvertToHtml(string file, string outputDirectory) | |
57 | { | |
58 | var fi = new FileInfo(file); | |
59 | Console.WriteLine(fi.Name); | |
60 | byte[] byteArray = File.ReadAllBytes(fi.FullName); | |
61 | using (MemoryStream memoryStream = new MemoryStream()) | |
62 | { | |
63 | memoryStream.Write(byteArray, 0, byteArray.Length); | |
64 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(memoryStream, true)) | |
65 | { | |
66 | var destFileName = new FileInfo(fi.Name.Replace(".docx", ".html")); | |
67 | if (outputDirectory != null && outputDirectory != string.Empty) | |
68 | { | |
69 | DirectoryInfo di = new DirectoryInfo(outputDirectory); | |
70 | if (!di.Exists) | |
71 | { | |
72 | throw new OpenXmlPowerToolsException("Output directory does not exist"); | |
73 | } | |
74 | destFileName = new FileInfo(Path.Combine(di.FullName, destFileName.Name)); | |
75 | } | |
76 | var imageDirectoryName = destFileName.FullName.Substring(0, destFileName.FullName.Length - 5) + "_files"; | |
77 | int imageCounter = 0; | |
78 | | |
79 | var pageTitle = fi.FullName; | |
80 | var part = wDoc.CoreFilePropertiesPart; | |
81 | if (part != null) | |
82 | { | |
83 | pageTitle = (string) part.GetXDocument().Descendants(DC.title).FirstOrDefault() ?? fi.FullName; | |
84 | } | |
85 | | |
86 | // TODO: Determine max-width from size of content area. | |
87 | HtmlConverterSettings settings = new HtmlConverterSettings() | |
88 | { | |
89 | AdditionalCss = "body { margin: 1cm auto; max-width: 20cm; padding: 0; }", | |
90 | PageTitle = pageTitle, | |
91 | FabricateCssClasses = true, | |
92 | CssClassPrefix = "pt-", | |
93 | RestrictToSupportedLanguages = false, | |
94 | RestrictToSupportedNumberingFormats = false, | |
95 | ImageHandler = imageInfo => | |
96 | { | |
97 | DirectoryInfo localDirInfo = new DirectoryInfo(imageDirectoryName); | |
98 | if (!localDirInfo.Exists) | |
99 | localDirInfo.Create(); | |
100 | ++imageCounter; | |
101 | string extension = imageInfo.ContentType.Split('/')[1].ToLower(); | |
102 | ImageFormat imageFormat = null; | |
103 | if (extension == "png") | |
104 | imageFormat = ImageFormat.Png; | |
105 | else if (extension == "gif") | |
106 | imageFormat = ImageFormat.Gif; | |
107 | else if (extension == "bmp") | |
108 | imageFormat = ImageFormat.Bmp; | |
109 | else if (extension == "jpeg") | |
110 | imageFormat = ImageFormat.Jpeg; | |
111 | else if (extension == "tiff") | |
112 | { | |
113 | // Convert tiff to gif. | |
114 | extension = "gif"; | |
115 | imageFormat = ImageFormat.Gif; | |
116 | } | |
117 | else if (extension == "x-wmf") | |
118 | { | |
119 | extension = "wmf"; | |
120 | imageFormat = ImageFormat.Wmf; | |
121 | } | |
122 | | |
123 | // If the image format isn't one that we expect, ignore it, | |
124 | // and don't return markup for the link. | |
125 | if (imageFormat == null) | |
126 | return null; | |
127 | | |
128 | string imageFileName = imageDirectoryName + "/image" + | |
129 | imageCounter.ToString() + "." + extension; | |
130 | try | |
131 | { | |
132 | imageInfo.Bitmap.Save(imageFileName, imageFormat); | |
133 | } | |
134 | catch (System.Runtime.InteropServices.ExternalException) | |
135 | { | |
136 | return null; | |
137 | } | |
138 | string imageSource = localDirInfo.Name + "/image" + | |
139 | imageCounter.ToString() + "." + extension; | |
140 | | |
141 | XElement img = new XElement(Xhtml.img, | |
142 | new XAttribute(NoNamespace.src, imageSource), | |
143 | imageInfo.ImgStyleAttribute, | |
144 | imageInfo.AltText != null ? | |
145 | new XAttribute(NoNamespace.alt, imageInfo.AltText) : null); | |
146 | return img; | |
147 | } | |
148 | }; | |
149 | XElement htmlElement = HtmlConverter.ConvertToHtml(wDoc, settings); | |
150 | | |
151 | // Produce HTML document with <!DOCTYPE html > declaration to tell the browser | |
152 | // we are using HTML5. | |
153 | var html = new XDocument( | |
154 | new XDocumentType("html", null, null, null), | |
155 | htmlElement); | |
156 | | |
157 | // Note: the xhtml returned by ConvertToHtmlTransform contains objects of type | |
158 | // XEntity. PtOpenXmlUtil.cs define the XEntity class. See | |
159 | // http://blogs.msdn.com/ericwhite/archive/2010/01/21/writing-entity-references-using-linq-to-xml.aspx | |
160 | // for detailed explanation. | |
161 | // | |
162 | // If you further transform the XML tree returned by ConvertToHtmlTransform, you | |
163 | // must do it correctly, or entities will not be serialized properly. | |
164 | | |
165 | var htmlString = html.ToString(SaveOptions.DisableFormatting); | |
166 | File.WriteAllText(destFileName.FullName, htmlString, Encoding.UTF8); | |
167 | } | |
168 | } | |
169 | } | |
170 | } | |
171 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/HtmlToWmlConverter01/HtmlToWmlConverter01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.IO; | |
6 | using System.Linq; | |
7 | using System.Runtime.InteropServices; | |
8 | using System.Text; | |
9 | using System.Xml; | |
10 | using System.Xml.Linq; | |
11 | using DocumentFormat.OpenXml.Packaging; | |
12 | using DocumentFormat.OpenXml.Validation; | |
13 | using OpenXmlPowerTools; | |
14 | using OpenXmlPowerTools.HtmlToWml; | |
15 | | |
16 | /******************************************************************************************* | |
17 | * HtmlToWmlConverter expects the HTML to be passed as an XElement, i.e. as XML. While the HTML test files that | |
18 | * are included in Open-Xml-PowerTools are able to be read as XML, most HTML is not able to be read as XML. | |
19 | * The best solution is to use the HtmlAgilityPack, which can parse HTML and save as XML. The HtmlAgilityPack | |
20 | * is licensed under the Ms-PL (same as Open-Xml-PowerTools) so it is convenient to include it in your solution, | |
21 | * and thereby you can convert HTML to XML that can be processed by the HtmlToWmlConverter. | |
22 | * | |
23 | * A convenient way to get the DLL that has been checked out with HtmlToWmlConverter is to clone the repo at | |
24 | * https://github.com/EricWhiteDev/HtmlAgilityPack | |
25 | * | |
26 | * That repo contains only the DLL that has been checked out with HtmlToWmlConverter. | |
27 | * | |
28 | * Of course, you can also get the HtmlAgilityPack source and compile it to get the DLL. You can find it at | |
29 | * http://codeplex.com/HtmlAgilityPack | |
30 | * | |
31 | * We don't include the HtmlAgilityPack in Open-Xml-PowerTools, to simplify installation. The example files | |
32 | * in this module do not require HtmlAgilityPack to run. | |
33 | *******************************************************************************************/ | |
34 | | |
35 | class HtmlToWmlConverterExample | |
36 | { | |
37 | static void Main(string[] args) | |
38 | { | |
39 | var n = DateTime.Now; | |
40 | 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)); | |
41 | tempDi.Create(); | |
42 | | |
43 | foreach (var file in Directory.GetFiles("../../", "*.html") /* .Where(f => f.Contains("Test-01")) */ ) | |
44 | { | |
45 | ConvertToDocx(file, tempDi.FullName); | |
46 | } | |
47 | } | |
48 | | |
49 | private static void ConvertToDocx(string file, string destinationDir) | |
50 | { | |
51 | bool s_ProduceAnnotatedHtml = true; | |
52 | | |
53 | var sourceHtmlFi = new FileInfo(file); | |
54 | Console.WriteLine("Converting " + sourceHtmlFi.Name); | |
55 | var sourceImageDi = new DirectoryInfo(destinationDir); | |
56 | | |
57 | var destCssFi = new FileInfo(Path.Combine(destinationDir, sourceHtmlFi.Name.Replace(".html", "-2.css"))); | |
58 | var destDocxFi = new FileInfo(Path.Combine(destinationDir, sourceHtmlFi.Name.Replace(".html", "-3-ConvertedByHtmlToWml.docx"))); | |
59 | var annotatedHtmlFi = new FileInfo(Path.Combine(destinationDir, sourceHtmlFi.Name.Replace(".html", "-4-Annotated.txt"))); | |
60 | | |
61 | XElement html = HtmlToWmlReadAsXElement.ReadAsXElement(sourceHtmlFi); | |
62 | | |
63 | string usedAuthorCss = HtmlToWmlConverter.CleanUpCss((string)html.Descendants().FirstOrDefault(d => d.Name.LocalName.ToLower() == "style")); | |
64 | File.WriteAllText(destCssFi.FullName, usedAuthorCss); | |
65 | | |
66 | HtmlToWmlConverterSettings settings = HtmlToWmlConverter.GetDefaultSettings(); | |
67 | // image references in HTML files contain the path to the subdir that contains the images, so base URI is the name of the directory | |
68 | // that contains the HTML files | |
69 | settings.BaseUriForImages = sourceHtmlFi.DirectoryName; | |
70 | | |
71 | WmlDocument doc = HtmlToWmlConverter.ConvertHtmlToWml(defaultCss, usedAuthorCss, userCss, html, settings, null, s_ProduceAnnotatedHtml ? annotatedHtmlFi.FullName : null); | |
72 | doc.SaveAs(destDocxFi.FullName); | |
73 | } | |
74 | | |
75 | public class HtmlToWmlReadAsXElement | |
76 | { | |
77 | public static XElement ReadAsXElement(FileInfo sourceHtmlFi) | |
78 | { | |
79 | string htmlString = File.ReadAllText(sourceHtmlFi.FullName); | |
80 | XElement html = null; | |
81 | try | |
82 | { | |
83 | html = XElement.Parse(htmlString); | |
84 | } | |
85 | #if USE_HTMLAGILITYPACK | |
86 | catch (XmlException) | |
87 | { | |
88 | HtmlDocument hdoc = new HtmlDocument(); | |
89 | hdoc.Load(sourceHtmlFi.FullName, Encoding.Default); | |
90 | hdoc.OptionOutputAsXml = true; | |
91 | hdoc.Save(sourceHtmlFi.FullName, Encoding.Default); | |
92 | StringBuilder sb = new StringBuilder(File.ReadAllText(sourceHtmlFi.FullName, Encoding.Default)); | |
93 | sb.Replace("&", "&"); | |
94 | sb.Replace(" ", "\xA0"); | |
95 | sb.Replace(""", "\""); | |
96 | sb.Replace("<", "~lt;"); | |
97 | sb.Replace(">", "~gt;"); | |
98 | sb.Replace("&#", "~#"); | |
99 | sb.Replace("&", "&"); | |
100 | sb.Replace("~lt;", "<"); | |
101 | sb.Replace("~gt;", ">"); | |
102 | sb.Replace("~#", "&#"); | |
103 | File.WriteAllText(sourceHtmlFi.FullName, sb.ToString(), Encoding.Default); | |
104 | html = XElement.Parse(sb.ToString()); | |
105 | } | |
106 | #else | |
107 | catch (XmlException e) | |
108 | { | |
109 | throw e; | |
110 | } | |
111 | #endif | |
112 | // HtmlToWmlConverter expects the HTML elements to be in no namespace, so convert all elements to no namespace. | |
113 | html = (XElement)ConvertToNoNamespace(html); | |
114 | return html; | |
115 | } | |
116 | | |
117 | private static object ConvertToNoNamespace(XNode node) | |
118 | { | |
119 | XElement element = node as XElement; | |
120 | if (element != null) | |
121 | { | |
122 | return new XElement(element.Name.LocalName, | |
123 | element.Attributes().Where(a => !a.IsNamespaceDeclaration), | |
124 | element.Nodes().Select(n => ConvertToNoNamespace(n))); | |
125 | } | |
126 | return node; | |
127 | } | |
128 | } | |
129 | | |
130 | static string defaultCss = | |
131 | @"html, address, | |
132 | blockquote, | |
133 | body, dd, div, | |
134 | dl, dt, fieldset, form, | |
135 | frame, frameset, | |
136 | h1, h2, h3, h4, | |
137 | h5, h6, noframes, | |
138 | ol, p, ul, center, | |
139 | dir, hr, menu, pre { display: block; unicode-bidi: embed } | |
140 | li { display: list-item } | |
141 | head { display: none } | |
142 | table { display: table } | |
143 | tr { display: table-row } | |
144 | thead { display: table-header-group } | |
145 | tbody { display: table-row-group } | |
146 | tfoot { display: table-footer-group } | |
147 | col { display: table-column } | |
148 | colgroup { display: table-column-group } | |
149 | td, th { display: table-cell } | |
150 | caption { display: table-caption } | |
151 | th { font-weight: bolder; text-align: center } | |
152 | caption { text-align: center } | |
153 | body { margin: auto; } | |
154 | h1 { font-size: 2em; margin: auto; } | |
155 | h2 { font-size: 1.5em; margin: auto; } | |
156 | h3 { font-size: 1.17em; margin: auto; } | |
157 | h4, p, | |
158 | blockquote, ul, | |
159 | fieldset, form, | |
160 | ol, dl, dir, | |
161 | menu { margin: auto } | |
162 | a { color: blue; } | |
163 | h5 { font-size: .83em; margin: auto } | |
164 | h6 { font-size: .75em; margin: auto } | |
165 | h1, h2, h3, h4, | |
166 | h5, h6, b, | |
167 | strong { font-weight: bolder } | |
168 | blockquote { margin-left: 40px; margin-right: 40px } | |
169 | i, cite, em, | |
170 | var, address { font-style: italic } | |
171 | pre, tt, code, | |
172 | kbd, samp { font-family: monospace } | |
173 | pre { white-space: pre } | |
174 | button, textarea, | |
175 | input, select { display: inline-block } | |
176 | big { font-size: 1.17em } | |
177 | small, sub, sup { font-size: .83em } | |
178 | sub { vertical-align: sub } | |
179 | sup { vertical-align: super } | |
180 | table { border-spacing: 2px; } | |
181 | thead, tbody, | |
182 | tfoot { vertical-align: middle } | |
183 | td, th, tr { vertical-align: inherit } | |
184 | s, strike, del { text-decoration: line-through } | |
185 | hr { border: 1px inset } | |
186 | ol, ul, dir, | |
187 | menu, dd { margin-left: 40px } | |
188 | ol { list-style-type: decimal } | |
189 | ol ul, ul ol, | |
190 | ul ul, ol ol { margin-top: 0; margin-bottom: 0 } | |
191 | u, ins { text-decoration: underline } | |
192 | br:before { content: ""\A""; white-space: pre-line } | |
193 | center { text-align: center } | |
194 | :link, :visited { text-decoration: underline } | |
195 | :focus { outline: thin dotted invert } | |
196 | /* Begin bidirectionality settings (do not change) */ | |
197 | BDO[DIR=""ltr""] { direction: ltr; unicode-bidi: bidi-override } | |
198 | BDO[DIR=""rtl""] { direction: rtl; unicode-bidi: bidi-override } | |
199 | *[DIR=""ltr""] { direction: ltr; unicode-bidi: embed } | |
200 | *[DIR=""rtl""] { direction: rtl; unicode-bidi: embed } | |
201 | | |
202 | "; | |
203 | | |
204 | static string userCss = @""; | |
205 | } | |
206 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/ListItemRetriever01/ListItemRetriever01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | /*************************************************************************** | |
5 | | |
6 | Copyright (c) Microsoft Corporation 2014. | |
7 | | |
8 | This code is licensed using the Microsoft Public License (Ms-PL). The text of the license | |
9 | can be found here: | |
10 | | |
11 | http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx | |
12 | | |
13 | ***************************************************************************/ | |
14 | | |
15 | using System; | |
16 | using System.Collections.Generic; | |
17 | using System.IO; | |
18 | using System.Linq; | |
19 | using System.Text; | |
20 | using System.Xml.Linq; | |
21 | using DocumentFormat.OpenXml.Packaging; | |
22 | using OpenXmlPowerTools; | |
23 | | |
24 | class ListItemRetriever01 | |
25 | { | |
26 | private class XmlStackItem | |
27 | { | |
28 | public XElement Element; | |
29 | public int[] LevelNumbers; | |
30 | } | |
31 | | |
32 | static void Main(string[] args) | |
33 | { | |
34 | var n = DateTime.Now; | |
35 | 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)); | |
36 | tempDi.Create(); | |
37 | | |
38 | using (WordprocessingDocument wDoc = | |
39 | WordprocessingDocument.Open("../../NumberedListTest.docx", false)) | |
40 | { | |
41 | int abstractNumId = 0; | |
42 | XElement xml = ConvertDocToXml(wDoc, abstractNumId); | |
43 | Console.WriteLine(xml); | |
44 | xml.Save(Path.Combine(tempDi.FullName, "Out.xml")); | |
45 | } | |
46 | } | |
47 | | |
48 | private static XElement ConvertDocToXml(WordprocessingDocument wDoc, int abstractNumId) | |
49 | { | |
50 | XDocument xd = wDoc.MainDocumentPart.GetXDocument(); | |
51 | | |
52 | // First, call RetrieveListItem so that all paragraphs are initialized with ListItemInfo | |
53 | var firstParagraph = xd.Descendants(W.p).FirstOrDefault(); | |
54 | var listItem = ListItemRetriever.RetrieveListItem(wDoc, firstParagraph); | |
55 | | |
56 | XElement xml = new XElement("Root"); | |
57 | var current = new Stack<XmlStackItem>(); | |
58 | current.Push( | |
59 | new XmlStackItem() | |
60 | { | |
61 | Element = xml, | |
62 | LevelNumbers = new int[] { }, | |
63 | }); | |
64 | foreach (var paragraph in xd.Descendants(W.p)) | |
65 | { | |
66 | // The following does not take into account documents that have tracked revisions. | |
67 | // As necessary, call RevisionAccepter.AcceptRevisions before converting to XML. | |
68 | var text = paragraph.Descendants(W.t).Select(t => (string)t).StringConcatenate(); | |
69 | ListItemRetriever.ListItemInfo lii = | |
70 | paragraph.Annotation<ListItemRetriever.ListItemInfo>(); | |
71 | if (lii.IsListItem && lii.AbstractNumId == abstractNumId) | |
72 | { | |
73 | ListItemRetriever.LevelNumbers levelNums = | |
74 | paragraph.Annotation<ListItemRetriever.LevelNumbers>(); | |
75 | if (levelNums.LevelNumbersArray.Length == current.Peek().LevelNumbers.Length) | |
76 | { | |
77 | current.Pop(); | |
78 | var levelNumsForThisIndent = levelNums.LevelNumbersArray; | |
79 | string levelText = levelNums | |
80 | .LevelNumbersArray | |
81 | .Select(l => l.ToString() + ".") | |
82 | .StringConcatenate() | |
83 | .TrimEnd('.'); | |
84 | var newCurrentElement = new XElement("Indent", | |
85 | new XAttribute("Level", levelText)); | |
86 | current.Peek().Element.Add(newCurrentElement); | |
87 | current.Push( | |
88 | new XmlStackItem() | |
89 | { | |
90 | Element = newCurrentElement, | |
91 | LevelNumbers = levelNumsForThisIndent, | |
92 | }); | |
93 | current.Peek().Element.Add(new XElement("Heading", text)); | |
94 | } | |
95 | else if (levelNums.LevelNumbersArray.Length > current.Peek().LevelNumbers.Length) | |
96 | { | |
97 | for (int i = current.Peek().LevelNumbers.Length; | |
98 | i < levelNums.LevelNumbersArray.Length; | |
99 | i++) | |
100 | { | |
101 | var levelNumsForThisIndent = levelNums | |
102 | .LevelNumbersArray | |
103 | .Take(i + 1) | |
104 | .ToArray(); | |
105 | string levelText = levelNums | |
106 | .LevelNumbersArray | |
107 | .Select(l => l.ToString() + ".") | |
108 | .StringConcatenate() | |
109 | .TrimEnd('.'); | |
110 | var newCurrentElement = new XElement("Indent", | |
111 | new XAttribute("Level", levelText)); | |
112 | current.Peek().Element.Add(newCurrentElement); | |
113 | current.Push( | |
114 | new XmlStackItem() | |
115 | { | |
116 | Element = newCurrentElement, | |
117 | LevelNumbers = levelNumsForThisIndent, | |
118 | }); | |
119 | current.Peek().Element.Add(new XElement("Heading", text)); | |
120 | } | |
121 | } | |
122 | else if (levelNums.LevelNumbersArray.Length < current.Peek().LevelNumbers.Length) | |
123 | { | |
124 | for (int i = current.Peek().LevelNumbers.Length; | |
125 | i > levelNums.LevelNumbersArray.Length; | |
126 | i--) | |
127 | current.Pop(); | |
128 | current.Pop(); | |
129 | var levelNumsForThisIndent = levelNums.LevelNumbersArray; | |
130 | string levelText = levelNums | |
131 | .LevelNumbersArray | |
132 | .Select(l => l.ToString() + ".") | |
133 | .StringConcatenate() | |
134 | .TrimEnd('.'); | |
135 | var newCurrentElement = new XElement("Indent", | |
136 | new XAttribute("Level", levelText)); | |
137 | current.Peek().Element.Add(newCurrentElement); | |
138 | current.Push( | |
139 | new XmlStackItem() | |
140 | { | |
141 | Element = newCurrentElement, | |
142 | LevelNumbers = levelNumsForThisIndent, | |
143 | }); | |
144 | current.Peek().Element.Add(new XElement("Heading", text)); | |
145 | } | |
146 | } | |
147 | else | |
148 | { | |
149 | current.Peek().Element.Add(new XElement("Paragraph", text)); | |
150 | } | |
151 | } | |
152 | return xml; | |
153 | } | |
154 | } | |
155 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/MarkupSimplifierApp/Form1.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.ComponentModel; | |
7 | using System.Data; | |
8 | using System.Drawing; | |
9 | using System.Linq; | |
10 | using System.Text; | |
11 | using System.Windows.Forms; | |
12 | using DocumentFormat.OpenXml.Packaging; | |
13 | using OpenXmlPowerTools; | |
14 | | |
15 | namespace MarkupSimplifierApp | |
16 | { | |
17 | public partial class Form1 : Form | |
18 | { | |
19 | public Form1() | |
20 | { | |
21 | InitializeComponent(); | |
22 | } | |
23 | | |
24 | private void btnApply_Click(object sender, EventArgs e) | |
25 | { | |
26 | OpenFileDialog ofd = new OpenFileDialog(); | |
27 | ofd.Multiselect = true; | |
28 | DialogResult dr = ofd.ShowDialog(); | |
29 | foreach (var item in ofd.FileNames) | |
30 | { | |
31 | using (WordprocessingDocument doc = | |
32 | WordprocessingDocument.Open(item, true)) | |
33 | { | |
34 | SimplifyMarkupSettings settings = new SimplifyMarkupSettings | |
35 | { | |
36 | RemoveContentControls = cbRemoveContentControls.Checked, | |
37 | RemoveSmartTags = cbRemoveSmartTags.Checked, | |
38 | RemoveRsidInfo = cbRemoveRsidInfo.Checked, | |
39 | RemoveComments = cbRemoveComments.Checked, | |
40 | RemoveEndAndFootNotes = cbRemoveEndAndFootNotes.Checked, | |
41 | ReplaceTabsWithSpaces = cbReplaceTabsWithSpaces.Checked, | |
42 | RemoveFieldCodes = cbRemoveFieldCodes.Checked, | |
43 | RemovePermissions = cbRemovePermissions.Checked, | |
44 | RemoveProof = cbRemoveProof.Checked, | |
45 | RemoveSoftHyphens = cbRemoveSoftHyphens.Checked, | |
46 | RemoveLastRenderedPageBreak = cbRemoveLastRenderedPageBreak.Checked, | |
47 | RemoveBookmarks = cbRemoveBookmarks.Checked, | |
48 | RemoveWebHidden = cbRemoveWebHidden.Checked, | |
49 | NormalizeXml = cbNormalize.Checked, | |
50 | }; | |
51 | OpenXmlPowerTools.MarkupSimplifier.SimplifyMarkup(doc, settings); | |
52 | } | |
53 | } | |
54 | } | |
55 | } | |
56 | } | |
57 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/MarkupSimplifierApp/Program.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Linq; | |
7 | using System.Windows.Forms; | |
8 | | |
9 | namespace MarkupSimplifierApp | |
10 | { | |
11 | static class Program | |
12 | { | |
13 | /// <summary> | |
14 | /// The main entry point for the application. | |
15 | /// </summary> | |
16 | [STAThread] | |
17 | static void Main() | |
18 | { | |
19 | Application.EnableVisualStyles(); | |
20 | Application.SetCompatibleTextRenderingDefault(false); | |
21 | Application.Run(new Form1()); | |
22 | } | |
23 | } | |
24 | } | |
25 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/MarkupSimplifierApp/Properties/Resources.Designer.cs: | |
-------------------------------------------------------------------------------- | |
1 | //------------------------------------------------------------------------------ | |
2 | // <auto-generated> | |
3 | // This code was generated by a tool. | |
4 | // Runtime Version:4.0.30319.34209 | |
5 | // | |
6 | // Changes to this file may cause incorrect behavior and will be lost if | |
7 | // the code is regenerated. | |
8 | // </auto-generated> | |
9 | //------------------------------------------------------------------------------ | |
10 | | |
11 | namespace MarkupSimplifierApp.Properties { | |
12 | using System; | |
13 | | |
14 | | |
15 | /// <summary> | |
16 | /// A strongly-typed resource class, for looking up localized strings, etc. | |
17 | /// </summary> | |
18 | // This class was auto-generated by the StronglyTypedResourceBuilder | |
19 | // class via a tool like ResGen or Visual Studio. | |
20 | // To add or remove a member, edit your .ResX file then rerun ResGen | |
21 | // with the /str option, or rebuild your VS project. | |
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] | |
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | |
25 | internal class Resources { | |
26 | | |
27 | private static global::System.Resources.ResourceManager resourceMan; | |
28 | | |
29 | private static global::System.Globalization.CultureInfo resourceCulture; | |
30 | | |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] | |
32 | internal Resources() { | |
33 | } | |
34 | | |
35 | /// <summary> | |
36 | /// Returns the cached ResourceManager instance used by this class. | |
37 | /// </summary> | |
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |
39 | internal static global::System.Resources.ResourceManager ResourceManager { | |
40 | get { | |
41 | if (object.ReferenceEquals(resourceMan, null)) { | |
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MarkupSimplifierApp.Properties.Resources", typeof(Resources).Assembly); | |
43 | resourceMan = temp; | |
44 | } | |
45 | return resourceMan; | |
46 | } | |
47 | } | |
48 | | |
49 | /// <summary> | |
50 | /// Overrides the current thread's CurrentUICulture property for all | |
51 | /// resource lookups using this strongly typed resource class. | |
52 | /// </summary> | |
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |
54 | internal static global::System.Globalization.CultureInfo Culture { | |
55 | get { | |
56 | return resourceCulture; | |
57 | } | |
58 | set { | |
59 | resourceCulture = value; | |
60 | } | |
61 | } | |
62 | } | |
63 | } | |
64 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/MarkupSimplifierApp/Properties/Settings.Designer.cs: | |
-------------------------------------------------------------------------------- | |
1 | //------------------------------------------------------------------------------ | |
2 | // <auto-generated> | |
3 | // This code was generated by a tool. | |
4 | // Runtime Version:4.0.30319.18033 | |
5 | // | |
6 | // Changes to this file may cause incorrect behavior and will be lost if | |
7 | // the code is regenerated. | |
8 | // </auto-generated> | |
9 | //------------------------------------------------------------------------------ | |
10 | | |
11 | namespace MarkupSimplifierApp.Properties | |
12 | { | |
13 | | |
14 | | |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | |
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] | |
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase | |
18 | { | |
19 | | |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); | |
21 | | |
22 | public static Settings Default | |
23 | { | |
24 | get | |
25 | { | |
26 | return defaultInstance; | |
27 | } | |
28 | } | |
29 | } | |
30 | } | |
31 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/MetricsGetter01/MetricsGetter01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using DocumentFormat.OpenXml.Packaging; | |
10 | using OpenXmlPowerTools; | |
11 | | |
12 | namespace OpenXmlPowerTools | |
13 | { | |
14 | class MetricsGetter01 | |
15 | { | |
16 | static void Main(string[] args) | |
17 | { | |
18 | MetricsGetterSettings settings = null; | |
19 | FileInfo fi = null; | |
20 | | |
21 | fi = new FileInfo("../../ContentControls.docx"); | |
22 | settings = new MetricsGetterSettings(); | |
23 | settings.IncludeTextInContentControls = false; | |
24 | Console.WriteLine("============== No text from content controls =============="); | |
25 | Console.WriteLine(fi.FullName); | |
26 | Console.WriteLine(MetricsGetter.GetMetrics(fi.FullName, settings)); | |
27 | Console.WriteLine(); | |
28 | | |
29 | fi = new FileInfo("../../ContentControls.docx"); | |
30 | settings = new MetricsGetterSettings(); | |
31 | settings.IncludeTextInContentControls = true; | |
32 | Console.WriteLine("============== With text from content controls =============="); | |
33 | Console.WriteLine(fi.FullName); | |
34 | Console.WriteLine(MetricsGetter.GetMetrics(fi.FullName, settings)); | |
35 | Console.WriteLine(); | |
36 | | |
37 | fi = new FileInfo("../../TrackedRevisions.docx"); | |
38 | settings = new MetricsGetterSettings(); | |
39 | settings.IncludeTextInContentControls = true; | |
40 | Console.WriteLine("============== Tracked Revisions =============="); | |
41 | Console.WriteLine(fi.FullName); | |
42 | Console.WriteLine(MetricsGetter.GetMetrics(fi.FullName, settings)); | |
43 | Console.WriteLine(); | |
44 | | |
45 | fi = new FileInfo("../../Styles.docx"); | |
46 | settings = new MetricsGetterSettings(); | |
47 | settings.IncludeTextInContentControls = false; | |
48 | Console.WriteLine("============== Style Hierarchy =============="); | |
49 | Console.WriteLine(fi.FullName); | |
50 | Console.WriteLine(MetricsGetter.GetMetrics(fi.FullName, settings)); | |
51 | Console.WriteLine(); | |
52 | | |
53 | fi = new FileInfo("../../Tables.xlsx"); | |
54 | settings = new MetricsGetterSettings(); | |
55 | settings.IncludeTextInContentControls = false; | |
56 | settings.IncludeXlsxTableCellData = true; | |
57 | Console.WriteLine("============== Spreadsheet Tables =============="); | |
58 | Console.WriteLine(fi.FullName); | |
59 | Console.WriteLine(MetricsGetter.GetMetrics(fi.FullName, settings)); | |
60 | Console.WriteLine(); | |
61 | } | |
62 | } | |
63 | } | |
64 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/OpenXmlRegex02/OpenXmlRegex02.cs: | |
-------------------------------------------------------------------------------- | |
1 | using System; | |
2 | using System.Collections.Generic; | |
3 | using System.IO; | |
4 | using System.Linq; | |
5 | using System.Text; | |
6 | using System.Text.RegularExpressions; | |
7 | using System.Threading.Tasks; | |
8 | using System.Xml.Linq; | |
9 | using DocumentFormat.OpenXml.Packaging; | |
10 | using OpenXmlPowerTools; | |
11 | | |
12 | class OpenXmlRegexExample | |
13 | { | |
14 | static void Main(string[] args) | |
15 | { | |
16 | var n = DateTime.Now; | |
17 | 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)); | |
18 | tempDi.Create(); | |
19 | | |
20 | var sourceDoc = new FileInfo("../../TestDocument.docx"); | |
21 | var newDoc = new FileInfo("Modified.docx"); | |
22 | if (newDoc.Exists) | |
23 | newDoc.Delete(); | |
24 | File.Copy(sourceDoc.FullName, newDoc.FullName); | |
25 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(newDoc.FullName, true)) | |
26 | { | |
27 | int count; | |
28 | var xDoc = wDoc.MainDocumentPart.GetXDocument(); | |
29 | Regex regex; | |
30 | IEnumerable<XElement> content; | |
31 | | |
32 | content = xDoc.Descendants(W.p); | |
33 | regex = new Regex("[.]\x020+"); | |
34 | count = OpenXmlRegex.Replace(content, regex, "." + Environment.NewLine, null); | |
35 | | |
36 | foreach (var para in content) | |
37 | { | |
38 | var newPara = (XElement)TransformEnvironmentNewLineToParagraph(para); | |
39 | para.ReplaceNodes(newPara.Nodes()); | |
40 | } | |
41 | | |
42 | wDoc.MainDocumentPart.PutXDocument(); | |
43 | } | |
44 | } | |
45 | | |
46 | private static object TransformEnvironmentNewLineToParagraph(XNode node) | |
47 | { | |
48 | var element = node as XElement; | |
49 | if (element != null) | |
50 | { | |
51 | if (element.Name == W.p) | |
52 | { | |
53 | | |
54 | } | |
55 | | |
56 | return new XElement(element.Name, | |
57 | element.Attributes(), | |
58 | element.Nodes().Select(n => TransformEnvironmentNewLineToParagraph(n))); | |
59 | } | |
60 | return node; | |
61 | } | |
62 | } | |
63 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/PresentationBuilder01/PresentationBuilder01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Linq; | |
7 | using System.Text; | |
8 | using System.IO; | |
9 | using OpenXmlPowerTools; | |
10 | | |
11 | namespace ExamplePresentatonBuilder01 | |
12 | { | |
13 | class ExamplePresentationBuilder01 | |
14 | { | |
15 | static void Main(string[] args) | |
16 | { | |
17 | var n = DateTime.Now; | |
18 | 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)); | |
19 | tempDi.Create(); | |
20 | | |
21 | string source1 = "../../Contoso.pptx"; | |
22 | string source2 = "../../Companies.pptx"; | |
23 | string source3 = "../../Customer Content.pptx"; | |
24 | string source4 = "../../Presentation One.pptx"; | |
25 | string source5 = "../../Presentation Two.pptx"; | |
26 | string source6 = "../../Presentation Three.pptx"; | |
27 | string contoso1 = "../../Contoso One.pptx"; | |
28 | string contoso2 = "../../Contoso Two.pptx"; | |
29 | string contoso3 = "../../Contoso Three.pptx"; | |
30 | List<SlideSource> sources = null; | |
31 | | |
32 | var sourceDoc = new PmlDocument(source1); | |
33 | sources = new List<SlideSource>() | |
34 | { | |
35 | new SlideSource(sourceDoc, 0, 1, false), // Title | |
36 | new SlideSource(sourceDoc, 1, 1, false), // First intro (of 3) | |
37 | new SlideSource(sourceDoc, 4, 2, false), // Sales bios | |
38 | new SlideSource(sourceDoc, 9, 3, false), // Content slides | |
39 | new SlideSource(sourceDoc, 13, 1, false), // Closing summary | |
40 | }; | |
41 | PresentationBuilder.BuildPresentation(sources, Path.Combine(tempDi.FullName, "Out1.pptx")); | |
42 | | |
43 | sources = new List<SlideSource>() | |
44 | { | |
45 | new SlideSource(new PmlDocument(source2), 2, 1, true), // Choose company | |
46 | new SlideSource(new PmlDocument(source3), false), // Content | |
47 | }; | |
48 | PresentationBuilder.BuildPresentation(sources, Path.Combine(tempDi.FullName, "Out2.pptx")); | |
49 | | |
50 | sources = new List<SlideSource>() | |
51 | { | |
52 | new SlideSource(new PmlDocument(source4), true), | |
53 | new SlideSource(new PmlDocument(source5), true), | |
54 | new SlideSource(new PmlDocument(source6), true), | |
55 | }; | |
56 | PresentationBuilder.BuildPresentation(sources, Path.Combine(tempDi.FullName, "Out3.pptx")); | |
57 | | |
58 | sources = new List<SlideSource>() | |
59 | { | |
60 | new SlideSource(new PmlDocument(contoso1), true), | |
61 | new SlideSource(new PmlDocument(contoso2), true), | |
62 | new SlideSource(new PmlDocument(contoso3), true), | |
63 | }; | |
64 | PresentationBuilder.BuildPresentation(sources, Path.Combine(tempDi.FullName, "Out4.pptx")); | |
65 | } | |
66 | } | |
67 | } | |
68 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/PresentationBuilder02/PresentationBuilder02.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Text.RegularExpressions; | |
10 | using System.Xml.Linq; | |
11 | using DocumentFormat.OpenXml.Packaging; | |
12 | using OpenXmlPowerTools; | |
13 | | |
14 | namespace PresentationBuilder02 | |
15 | { | |
16 | class PresentationBuilder02 | |
17 | { | |
18 | static void Main(string[] args) | |
19 | { | |
20 | var n = DateTime.Now; | |
21 | 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)); | |
22 | tempDi.Create(); | |
23 | | |
24 | string presentation = "../../Presentation1.pptx"; | |
25 | string hiddenPresentation = "../../HiddenPresentation.pptx"; | |
26 | | |
27 | // First, load both presentations into byte arrays, simulating retrieving presentations from some source | |
28 | // such as a SharePoint server | |
29 | var baPresentation = File.ReadAllBytes(presentation); | |
30 | var baHiddenPresentation = File.ReadAllBytes(hiddenPresentation); | |
31 | | |
32 | // Next, replace "thee" with "the" in the main presentation | |
33 | var pmlMainPresentation = new PmlDocument("Main.pptx", baPresentation); | |
34 | PmlDocument modifiedMainPresentation = null; | |
35 | using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(pmlMainPresentation)) | |
36 | { | |
37 | using (PresentationDocument document = streamDoc.GetPresentationDocument()) | |
38 | { | |
39 | var pXDoc = document.PresentationPart.GetXDocument(); | |
40 | foreach (var slideId in pXDoc.Root.Elements(P.sldIdLst).Elements(P.sldId)) | |
41 | { | |
42 | var slideRelId = (string)slideId.Attribute(R.id); | |
43 | var slidePart = document.PresentationPart.GetPartById(slideRelId); | |
44 | var slideXDoc = slidePart.GetXDocument(); | |
45 | var paragraphs = slideXDoc.Descendants(A.p).ToList(); | |
46 | OpenXmlRegex.Replace(paragraphs, new Regex("thee"), "the", null); | |
47 | slidePart.PutXDocument(); | |
48 | } | |
49 | } | |
50 | modifiedMainPresentation = streamDoc.GetModifiedPmlDocument(); | |
51 | } | |
52 | | |
53 | // Combine the two presentations into a single presentation | |
54 | var slideSources = new List<SlideSource>() { | |
55 | new SlideSource(modifiedMainPresentation, 0, 1, true), | |
56 | new SlideSource(new PmlDocument("Hidden.pptx", baHiddenPresentation), true), | |
57 | new SlideSource(modifiedMainPresentation, 1, true), | |
58 | }; | |
59 | PmlDocument combinedPresentation = PresentationBuilder.BuildPresentation(slideSources); | |
60 | | |
61 | // Replace <# TRADEMARK #> with AdventureWorks (c) | |
62 | PmlDocument modifiedCombinedPresentation = null; | |
63 | using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(combinedPresentation)) | |
64 | { | |
65 | using (PresentationDocument document = streamDoc.GetPresentationDocument()) | |
66 | { | |
67 | var pXDoc = document.PresentationPart.GetXDocument(); | |
68 | foreach (var slideId in pXDoc.Root.Elements(P.sldIdLst).Elements(P.sldId).Skip(1).Take(1)) | |
69 | { | |
70 | var slideRelId = (string)slideId.Attribute(R.id); | |
71 | var slidePart = document.PresentationPart.GetPartById(slideRelId); | |
72 | var slideXDoc = slidePart.GetXDocument(); | |
73 | var paragraphs = slideXDoc.Descendants(A.p).ToList(); | |
74 | OpenXmlRegex.Replace(paragraphs, new Regex("<# TRADEMARK #>"), "AdventureWorks (c)", null); | |
75 | slidePart.PutXDocument(); | |
76 | } | |
77 | } | |
78 | modifiedCombinedPresentation = streamDoc.GetModifiedPmlDocument(); | |
79 | } | |
80 | | |
81 | // we now have a PmlDocument (which is essentially a byte array) that can be saved as necessary. | |
82 | modifiedCombinedPresentation.SaveAs(Path.Combine(tempDi.FullName, "Modified.pptx")); | |
83 | } | |
84 | } | |
85 | } | |
86 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/ReferenceAdder01/ReferenceAdder01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Xml.Linq; | |
9 | using DocumentFormat.OpenXml.Packaging; | |
10 | using OpenXmlPowerTools; | |
11 | | |
12 | class TestTocAdder | |
13 | { | |
14 | static void Main(string[] args) | |
15 | { | |
16 | var n = DateTime.Now; | |
17 | 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)); | |
18 | tempDi.Create(); | |
19 | | |
20 | DirectoryInfo di2 = new DirectoryInfo("../../"); | |
21 | foreach (var file in di2.GetFiles("*.docx")) | |
22 | file.CopyTo(Path.Combine(tempDi.FullName, file.Name)); | |
23 | | |
24 | List<string> filesToProcess = new List<string>(); | |
25 | | |
26 | // Inserts a basic TOC before the first paragraph of the document | |
27 | using (WordprocessingDocument wdoc = | |
28 | WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test01.docx"), true)) | |
29 | { | |
30 | ReferenceAdder.AddToc(wdoc, "/w:document/w:body/w:p[1]", | |
31 | @"TOC \o '1-3' \h \z \u", null, null); | |
32 | } | |
33 | | |
34 | // Inserts a TOC after the title of the document | |
35 | using (WordprocessingDocument wdoc = | |
36 | WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test02.docx"), true)) | |
37 | { | |
38 | ReferenceAdder.AddToc(wdoc, "/w:document/w:body/w:p[2]", | |
39 | @"TOC \o '1-3' \h \z \u", null, null); | |
40 | } | |
41 | | |
42 | // Inserts a TOC with a different title | |
43 | using (WordprocessingDocument wdoc = | |
44 | WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test03.docx"), true)) | |
45 | { | |
46 | ReferenceAdder.AddToc(wdoc, "/w:document/w:body/w:p[1]", | |
47 | @"TOC \o '1-3' \h \z \u", "Table of Contents", null); | |
48 | } | |
49 | | |
50 | // Inserts a TOC that includes headings through level 4 | |
51 | using (WordprocessingDocument wdoc = | |
52 | WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test04.docx"), true)) | |
53 | { | |
54 | ReferenceAdder.AddToc(wdoc, "/w:document/w:body/w:p[1]", | |
55 | @"TOC \o '1-4' \h \z \u", null, null); | |
56 | } | |
57 | | |
58 | // Inserts a table of figures | |
59 | using (WordprocessingDocument wdoc = | |
60 | WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test05.docx"), true)) | |
61 | { | |
62 | ReferenceAdder.AddTof(wdoc, "/w:document/w:body/w:p[2]", | |
63 | @"TOC \h \z \c ""Figure""", null); | |
64 | } | |
65 | | |
66 | // Inserts a basic TOC before the first paragraph of the document. | |
67 | // Test06.docx does not include a StylesWithEffects part. | |
68 | using (WordprocessingDocument wdoc = | |
69 | WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test06.docx"), true)) | |
70 | { | |
71 | ReferenceAdder.AddToc(wdoc, "/w:document/w:body/w:p[1]", | |
72 | @"TOC \o '1-3' \h \z \u", null, null); | |
73 | } | |
74 | | |
75 | // Inserts a TOA before the first paragraph of the document. | |
76 | using (WordprocessingDocument wdoc = | |
77 | WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test07.docx"), true)) | |
78 | { | |
79 | ReferenceAdder.AddToa(wdoc, "/w:document/w:body/w:p[2]", | |
80 | @"TOA \h \c ""1"" \p", null); | |
81 | } | |
82 | } | |
83 | } | |
84 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/RevisionAccepter01/RevisionAccepter01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using OpenXmlPowerTools; | |
10 | | |
11 | namespace RevisionAccepterExample | |
12 | { | |
13 | class RevisionAccepterExample | |
14 | { | |
15 | static void Main(string[] args) | |
16 | { | |
17 | var n = DateTime.Now; | |
18 | 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)); | |
19 | tempDi.Create(); | |
20 | | |
21 | // Accept all revisions, save result as a new document | |
22 | WmlDocument result = RevisionAccepter.AcceptRevisions(new WmlDocument("../../Source1.docx")); | |
23 | result.SaveAs(Path.Combine(tempDi.FullName, "Out1.docx")); | |
24 | } | |
25 | } | |
26 | } | |
27 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/SmlDataRetriever01/SmlDataRetriever01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Xml.Linq; | |
10 | using DocumentFormat.OpenXml.Packaging; | |
11 | using OpenXmlPowerTools; | |
12 | | |
13 | namespace OpenXmlPowerTools | |
14 | { | |
15 | class SmlDataRetriever01 | |
16 | { | |
17 | static void Main(string[] args) | |
18 | { | |
19 | FileInfo fi = null; | |
20 | fi = new FileInfo("../../SampleSpreadsheet.xlsx"); | |
21 | | |
22 | // Retrieve range from Sheet1 | |
23 | XElement data = SmlDataRetriever.RetrieveRange(fi.FullName, "Sheet1", "A1:C3"); | |
24 | Console.WriteLine(data); | |
25 | | |
26 | // Retrieve entire sheet | |
27 | data = SmlDataRetriever.RetrieveSheet(fi.FullName, "Sheet1"); | |
28 | Console.WriteLine(data); | |
29 | | |
30 | // Retrieve table | |
31 | data = SmlDataRetriever.RetrieveTable(fi.FullName, "VehicleTable"); | |
32 | Console.WriteLine(data); | |
33 | } | |
34 | } | |
35 | } | |
36 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/SpreadsheetWriter01/SpreadsheetWriter01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Threading.Tasks; | |
10 | using System.Xml.Linq; | |
11 | using DocumentFormat.OpenXml.Packaging; | |
12 | using OpenXmlPowerTools; | |
13 | | |
14 | namespace SpreadsheetWriterExample | |
15 | { | |
16 | class Program | |
17 | { | |
18 | static void Main(string[] args) | |
19 | { | |
20 | var n = DateTime.Now; | |
21 | 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)); | |
22 | tempDi.Create(); | |
23 | | |
24 | WorkbookDfn wb = new WorkbookDfn | |
25 | { | |
26 | Worksheets = new WorksheetDfn[] | |
27 | { | |
28 | new WorksheetDfn | |
29 | { | |
30 | Name = "MyFirstSheet", | |
31 | TableName = "NamesAndRates", | |
32 | ColumnHeadings = new CellDfn[] | |
33 | { | |
34 | new CellDfn | |
35 | { | |
36 | Value = "Name", | |
37 | Bold = true, | |
38 | }, | |
39 | new CellDfn | |
40 | { | |
41 | Value = "Age", | |
42 | Bold = true, | |
43 | HorizontalCellAlignment = HorizontalCellAlignment.Left, | |
44 | }, | |
45 | new CellDfn | |
46 | { | |
47 | Value = "Rate", | |
48 | Bold = true, | |
49 | HorizontalCellAlignment = HorizontalCellAlignment.Left, | |
50 | } | |
51 | }, | |
52 | Rows = new RowDfn[] | |
53 | { | |
54 | new RowDfn | |
55 | { | |
56 | Cells = new CellDfn[] | |
57 | { | |
58 | new CellDfn { | |
59 | CellDataType = CellDataType.String, | |
60 | Value = "Eric", | |
61 | }, | |
62 | new CellDfn { | |
63 | CellDataType = CellDataType.Number, | |
64 | Value = 50, | |
65 | }, | |
66 | new CellDfn { | |
67 | CellDataType = CellDataType.Number, | |
68 | Value = (decimal)45.00, | |
69 | FormatCode = "0.00", | |
70 | }, | |
71 | } | |
72 | }, | |
73 | new RowDfn | |
74 | { | |
75 | Cells = new CellDfn[] | |
76 | { | |
77 | new CellDfn { | |
78 | CellDataType = CellDataType.String, | |
79 | Value = "Bob", | |
80 | }, | |
81 | new CellDfn { | |
82 | CellDataType = CellDataType.Number, | |
83 | Value = 42, | |
84 | }, | |
85 | new CellDfn { | |
86 | CellDataType = CellDataType.Number, | |
87 | Value = (decimal)78.00, | |
88 | FormatCode = "0.00", | |
89 | }, | |
90 | } | |
91 | }, | |
92 | } | |
93 | } | |
94 | } | |
95 | }; | |
96 | SpreadsheetWriter.Write(Path.Combine(tempDi.FullName, "Test1.xlsx"), wb); | |
97 | } | |
98 | } | |
99 | } | |
100 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/TextReplacer01/TextReplacer01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using DocumentFormat.OpenXml.Packaging; | |
10 | using OpenXmlPowerTools; | |
11 | | |
12 | class TestPmlTextReplacer | |
13 | { | |
14 | static void Main(string[] args) | |
15 | { | |
16 | var n = DateTime.Now; | |
17 | 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)); | |
18 | tempDi.Create(); | |
19 | | |
20 | File.Copy("../../Test01.pptx", Path.Combine(tempDi.FullName, "Test01out.pptx")); | |
21 | using (PresentationDocument pDoc = | |
22 | PresentationDocument.Open(Path.Combine(tempDi.FullName, "Test01out.pptx"), true)) | |
23 | { | |
24 | TextReplacer.SearchAndReplace(pDoc, "Hello", "Goodbye", true); | |
25 | } | |
26 | File.Copy("../../Test02.pptx", Path.Combine(tempDi.FullName, "Test02out.pptx")); | |
27 | using (PresentationDocument pDoc = | |
28 | PresentationDocument.Open(Path.Combine(tempDi.FullName, "Test02out.pptx"), true)) | |
29 | { | |
30 | TextReplacer.SearchAndReplace(pDoc, "Hello", "Goodbye", true); | |
31 | } | |
32 | File.Copy("../../Test03.pptx", Path.Combine(tempDi.FullName, "Test03out.pptx")); | |
33 | using (PresentationDocument pDoc = | |
34 | PresentationDocument.Open(Path.Combine(tempDi.FullName, "Test03out.pptx"), true)) | |
35 | { | |
36 | TextReplacer.SearchAndReplace(pDoc, "Hello", "Goodbye", false); | |
37 | } | |
38 | } | |
39 | } | |
40 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/TextReplacer02/TextReplacer02.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Xml.Linq; | |
10 | using DocumentFormat.OpenXml.Packaging; | |
11 | using OpenXmlPowerTools; | |
12 | | |
13 | namespace OpenXmlPowerTools | |
14 | { | |
15 | class Program | |
16 | { | |
17 | static void Main(string[] args) | |
18 | { | |
19 | var n = DateTime.Now; | |
20 | 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)); | |
21 | tempDi.Create(); | |
22 | | |
23 | DirectoryInfo di2 = new DirectoryInfo("../../"); | |
24 | foreach (var file in di2.GetFiles("*.docx")) | |
25 | file.CopyTo(Path.Combine(tempDi.FullName, file.Name)); | |
26 | | |
27 | using (WordprocessingDocument doc = WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test01.docx"), true)) | |
28 | TextReplacer.SearchAndReplace(doc, "the", "this", false); | |
29 | try | |
30 | { | |
31 | using (WordprocessingDocument doc = WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test02.docx"), true)) | |
32 | TextReplacer.SearchAndReplace(doc, "the", "this", false); | |
33 | } | |
34 | catch (Exception) { } | |
35 | try | |
36 | { | |
37 | using (WordprocessingDocument doc = WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test03.docx"), true)) | |
38 | TextReplacer.SearchAndReplace(doc, "the", "this", false); | |
39 | } | |
40 | catch (Exception) { } | |
41 | using (WordprocessingDocument doc = WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test04.docx"), true)) | |
42 | TextReplacer.SearchAndReplace(doc, "the", "this", true); | |
43 | using (WordprocessingDocument doc = WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test05.docx"), true)) | |
44 | TextReplacer.SearchAndReplace(doc, "is on", "is above", true); | |
45 | using (WordprocessingDocument doc = WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test06.docx"), true)) | |
46 | TextReplacer.SearchAndReplace(doc, "the", "this", false); | |
47 | using (WordprocessingDocument doc = WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test07.docx"), true)) | |
48 | TextReplacer.SearchAndReplace(doc, "the", "this", true); | |
49 | using (WordprocessingDocument doc = WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test08.docx"), true)) | |
50 | TextReplacer.SearchAndReplace(doc, "the", "this", true); | |
51 | using (WordprocessingDocument doc = WordprocessingDocument.Open(Path.Combine(tempDi.FullName, "Test09.docx"), true)) | |
52 | TextReplacer.SearchAndReplace(doc, "===== Replace this text =====", "***zzz***", true); | |
53 | } | |
54 | } | |
55 | } | |
56 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/WmlComparer01/WmlComparer01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.IO; | |
7 | using System.Linq; | |
8 | using System.Text; | |
9 | using System.Xml.Linq; | |
10 | using DocumentFormat.OpenXml.Packaging; | |
11 | using OpenXmlPowerTools; | |
12 | | |
13 | namespace OpenXmlPowerTools | |
14 | { | |
15 | class WmlComparer01 | |
16 | { | |
17 | static void Main(string[] args) | |
18 | { | |
19 | var n = DateTime.Now; | |
20 | 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)); | |
21 | tempDi.Create(); | |
22 | | |
23 | WmlComparerSettings settings = new WmlComparerSettings(); | |
24 | WmlDocument result = WmlComparer.Compare( | |
25 | new WmlDocument("../../Source1.docx"), | |
26 | new WmlDocument("../../Source2.docx"), | |
27 | settings); | |
28 | result.SaveAs(Path.Combine(tempDi.FullName, "Compared.docx")); | |
29 | | |
30 | var revisions = WmlComparer.GetRevisions(result, settings); | |
31 | foreach (var rev in revisions) | |
32 | { | |
33 | Console.WriteLine("Author: " + rev.Author); | |
34 | Console.WriteLine("Revision type: " + rev.RevisionType); | |
35 | Console.WriteLine("Revision text: " + rev.Text); | |
36 | Console.WriteLine(); | |
37 | } | |
38 | } | |
39 | } | |
40 | } | |
41 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/WmlComparer02/WmlComparer02.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | using System; | |
5 | using System.Collections.Generic; | |
6 | using System.Drawing; | |
7 | using System.Drawing.Imaging; | |
8 | using System.IO; | |
9 | using System.Linq; | |
10 | using System.Text; | |
11 | using System.Threading.Tasks; | |
12 | using System.Xml.Linq; | |
13 | using DocumentFormat.OpenXml.Packaging; | |
14 | using OpenXmlPowerTools; | |
15 | | |
16 | namespace OpenXmlPowerTools | |
17 | { | |
18 | class WmlComparer02 | |
19 | { | |
20 | static void Main(string[] args) | |
21 | { | |
22 | var n = DateTime.Now; | |
23 | 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)); | |
24 | tempDi.Create(); | |
25 | | |
26 | WmlDocument originalWml = new WmlDocument("../../Original.docx"); | |
27 | List<WmlRevisedDocumentInfo> revisedDocumentInfoList = new List<WmlRevisedDocumentInfo>() | |
28 | { | |
29 | new WmlRevisedDocumentInfo() | |
30 | { | |
31 | RevisedDocument = new WmlDocument("../../RevisedByBob.docx"), | |
32 | Revisor = "Bob", | |
33 | Color = Color.LightBlue, | |
34 | }, | |
35 | new WmlRevisedDocumentInfo() | |
36 | { | |
37 | RevisedDocument = new WmlDocument("../../RevisedByMary.docx"), | |
38 | Revisor = "Mary", | |
39 | Color = Color.LightYellow, | |
40 | }, | |
41 | }; | |
42 | WmlComparerSettings settings = new WmlComparerSettings(); | |
43 | WmlDocument consolidatedWml = WmlComparer.Consolidate( | |
44 | originalWml, | |
45 | revisedDocumentInfoList, | |
46 | settings); | |
47 | consolidatedWml.SaveAs(Path.Combine(tempDi.FullName, "Consolidated.docx")); | |
48 | } | |
49 | } | |
50 | } | |
51 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/WmlToHtmlConverter01/WmlToHtmlConverter01.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | /*************************************************************************** | |
5 | | |
6 | Copyright (c) Microsoft Corporation 2010. | |
7 | | |
8 | This code is licensed using the Microsoft Public License (Ms-PL). The text of the license | |
9 | can be found here: | |
10 | | |
11 | http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx | |
12 | | |
13 | ***************************************************************************/ | |
14 | | |
15 | using System; | |
16 | using System.Drawing.Imaging; | |
17 | using System.IO; | |
18 | using System.Linq; | |
19 | using System.Runtime.InteropServices; | |
20 | using System.Text; | |
21 | using System.Xml.Linq; | |
22 | using DocumentFormat.OpenXml.Packaging; | |
23 | using OpenXmlPowerTools; | |
24 | | |
25 | class WmlToHtmlConverterHelper | |
26 | { | |
27 | static void Main(string[] args) | |
28 | { | |
29 | var n = DateTime.Now; | |
30 | 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)); | |
31 | tempDi.Create(); | |
32 | | |
33 | /* | |
34 | * This example loads each document into a byte array, then into a memory stream, so that the document can be opened for writing without | |
35 | * modifying the source document. | |
36 | */ | |
37 | foreach (var file in Directory.GetFiles("../../", "*.docx")) | |
38 | { | |
39 | ConvertToHtml(file, tempDi.FullName); | |
40 | } | |
41 | } | |
42 | | |
43 | public static void ConvertToHtml(string file, string outputDirectory) | |
44 | { | |
45 | var fi = new FileInfo(file); | |
46 | Console.WriteLine(fi.Name); | |
47 | byte[] byteArray = File.ReadAllBytes(fi.FullName); | |
48 | using (MemoryStream memoryStream = new MemoryStream()) | |
49 | { | |
50 | memoryStream.Write(byteArray, 0, byteArray.Length); | |
51 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(memoryStream, true)) | |
52 | { | |
53 | var destFileName = new FileInfo(fi.Name.Replace(".docx", ".html")); | |
54 | if (outputDirectory != null && outputDirectory != string.Empty) | |
55 | { | |
56 | DirectoryInfo di = new DirectoryInfo(outputDirectory); | |
57 | if (!di.Exists) | |
58 | { | |
59 | throw new OpenXmlPowerToolsException("Output directory does not exist"); | |
60 | } | |
61 | destFileName = new FileInfo(Path.Combine(di.FullName, destFileName.Name)); | |
62 | } | |
63 | var imageDirectoryName = destFileName.FullName.Substring(0, destFileName.FullName.Length - 5) + "_files"; | |
64 | int imageCounter = 0; | |
65 | | |
66 | var pageTitle = fi.FullName; | |
67 | var part = wDoc.CoreFilePropertiesPart; | |
68 | if (part != null) | |
69 | { | |
70 | pageTitle = (string)part.GetXDocument().Descendants(DC.title).FirstOrDefault() ?? fi.FullName; | |
71 | } | |
72 | | |
73 | // TODO: Determine max-width from size of content area. | |
74 | WmlToHtmlConverterSettings settings = new WmlToHtmlConverterSettings() | |
75 | { | |
76 | AdditionalCss = "body { margin: 1cm auto; max-width: 20cm; padding: 0; }", | |
77 | PageTitle = pageTitle, | |
78 | FabricateCssClasses = true, | |
79 | CssClassPrefix = "pt-", | |
80 | RestrictToSupportedLanguages = false, | |
81 | RestrictToSupportedNumberingFormats = false, | |
82 | ImageHandler = imageInfo => | |
83 | { | |
84 | DirectoryInfo localDirInfo = new DirectoryInfo(imageDirectoryName); | |
85 | if (!localDirInfo.Exists) | |
86 | localDirInfo.Create(); | |
87 | ++imageCounter; | |
88 | string extension = imageInfo.ContentType.Split('/')[1].ToLower(); | |
89 | ImageFormat imageFormat = null; | |
90 | if (extension == "png") | |
91 | imageFormat = ImageFormat.Png; | |
92 | else if (extension == "gif") | |
93 | imageFormat = ImageFormat.Gif; | |
94 | else if (extension == "bmp") | |
95 | imageFormat = ImageFormat.Bmp; | |
96 | else if (extension == "jpeg") | |
97 | imageFormat = ImageFormat.Jpeg; | |
98 | else if (extension == "tiff") | |
99 | { | |
100 | // Convert tiff to gif. | |
101 | extension = "gif"; | |
102 | imageFormat = ImageFormat.Gif; | |
103 | } | |
104 | else if (extension == "x-wmf") | |
105 | { | |
106 | extension = "wmf"; | |
107 | imageFormat = ImageFormat.Wmf; | |
108 | } | |
109 | | |
110 | // If the image format isn't one that we expect, ignore it, | |
111 | // and don't return markup for the link. | |
112 | if (imageFormat == null) | |
113 | return null; | |
114 | | |
115 | string imageFileName = imageDirectoryName + "/image" + | |
116 | imageCounter.ToString() + "." + extension; | |
117 | try | |
118 | { | |
119 | imageInfo.Bitmap.Save(imageFileName, imageFormat); | |
120 | } | |
121 | catch (System.Runtime.InteropServices.ExternalException) | |
122 | { | |
123 | return null; | |
124 | } | |
125 | string imageSource = localDirInfo.Name + "/image" + | |
126 | imageCounter.ToString() + "." + extension; | |
127 | | |
128 | XElement img = new XElement(Xhtml.img, | |
129 | new XAttribute(NoNamespace.src, imageSource), | |
130 | imageInfo.ImgStyleAttribute, | |
131 | imageInfo.AltText != null ? | |
132 | new XAttribute(NoNamespace.alt, imageInfo.AltText) : null); | |
133 | return img; | |
134 | } | |
135 | }; | |
136 | XElement htmlElement = WmlToHtmlConverter.ConvertToHtml(wDoc, settings); | |
137 | | |
138 | // Produce HTML document with <!DOCTYPE html > declaration to tell the browser | |
139 | // we are using HTML5. | |
140 | var html = new XDocument( | |
141 | new XDocumentType("html", null, null, null), | |
142 | htmlElement); | |
143 | | |
144 | // Note: the xhtml returned by ConvertToHtmlTransform contains objects of type | |
145 | // XEntity. PtOpenXmlUtil.cs define the XEntity class. See | |
146 | // http://blogs.msdn.com/ericwhite/archive/2010/01/21/writing-entity-references-using-linq-to-xml.aspx | |
147 | // for detailed explanation. | |
148 | // | |
149 | // If you further transform the XML tree returned by ConvertToHtmlTransform, you | |
150 | // must do it correctly, or entities will not be serialized properly. | |
151 | | |
152 | var htmlString = html.ToString(SaveOptions.DisableFormatting); | |
153 | File.WriteAllText(destFileName.FullName, htmlString, Encoding.UTF8); | |
154 | } | |
155 | } | |
156 | } | |
157 | } | |
158 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/WmlToHtmlConverter02/WmlToHtmlConverter02.cs: | |
-------------------------------------------------------------------------------- | |
1 | // Copyright (c) Microsoft. All rights reserved. | |
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. | |
3 | | |
4 | /*************************************************************************** | |
5 | | |
6 | Copyright (c) Microsoft Corporation 2010. | |
7 | | |
8 | This code is licensed using the Microsoft Public License (Ms-PL). The text of the license | |
9 | can be found here: | |
10 | | |
11 | http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx | |
12 | | |
13 | ***************************************************************************/ | |
14 | | |
15 | using System; | |
16 | using System.Drawing.Imaging; | |
17 | using System.IO; | |
18 | using System.Linq; | |
19 | using System.Runtime.InteropServices; | |
20 | using System.Text; | |
21 | using System.Xml.Linq; | |
22 | using DocumentFormat.OpenXml.Packaging; | |
23 | using OpenXmlPowerTools; | |
24 | using System.Collections.Generic; | |
25 | | |
26 | class WmlToHtmlConverterHelper | |
27 | { | |
28 | static void Main(string[] args) | |
29 | { | |
30 | var n = DateTime.Now; | |
31 | 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)); | |
32 | tempDi.Create(); | |
33 | | |
34 | /* | |
35 | * This example loads each document into a byte array, then into a memory stream, so that the document can be opened for writing without | |
36 | * modifying the source document. | |
37 | */ | |
38 | foreach (var file in Directory.GetFiles("../../", "*.docx")) | |
39 | { | |
40 | ConvertToHtml(file, tempDi.FullName); | |
41 | } | |
42 | } | |
43 | | |
44 | public static void ConvertToHtml(string file, string outputDirectory) | |
45 | { | |
46 | var fi = new FileInfo(file); | |
47 | Console.WriteLine(fi.Name); | |
48 | byte[] byteArray = File.ReadAllBytes(fi.FullName); | |
49 | using (MemoryStream memoryStream = new MemoryStream()) | |
50 | { | |
51 | memoryStream.Write(byteArray, 0, byteArray.Length); | |
52 | using (WordprocessingDocument wDoc = WordprocessingDocument.Open(memoryStream, true)) | |
53 | { | |
54 | var destFileName = new FileInfo(fi.Name.Replace(".docx", ".html")); | |
55 | if (outputDirectory != null && outputDirectory != string.Empty) | |
56 | { | |
57 | DirectoryInfo di = new DirectoryInfo(outputDirectory); | |
58 | if (!di.Exists) | |
59 | { | |
60 | throw new OpenXmlPowerToolsException("Output directory does not exist"); | |
61 | } | |
62 | destFileName = new FileInfo(Path.Combine(di.FullName, destFileName.Name)); | |
63 | } | |
64 | var imageDirectoryName = destFileName.FullName.Substring(0, destFileName.FullName.Length - 5) + "_files"; | |
65 | int imageCounter = 0; | |
66 | | |
67 | var pageTitle = fi.FullName; | |
68 | var part = wDoc.CoreFilePropertiesPart; | |
69 | if (part != null) | |
70 | { | |
71 | pageTitle = (string)part.GetXDocument().Descendants(DC.title).FirstOrDefault() ?? fi.FullName; | |
72 | } | |
73 | | |
74 | // TODO: Determine max-width from size of content area. | |
75 | WmlToHtmlConverterSettings settings = new WmlToHtmlConverterSettings() | |
76 | { | |
77 | AdditionalCss = "body { margin: 1cm auto; max-width: 20cm; padding: 0; }", | |
78 | PageTitle = pageTitle, | |
79 | FabricateCssClasses = true, | |
80 | CssClassPrefix = "pt-", | |
81 | RestrictToSupportedLanguages = false, | |
82 | RestrictToSupportedNumberingFormats = false, | |
83 | ImageHandler = imageInfo => | |
84 | { | |
85 | ++imageCounter; | |
86 | string extension = imageInfo.ContentType.Split('/')[1].ToLower(); | |
87 | ImageFormat imageFormat = null; | |
88 | if (extension == "png") | |
89 | imageFormat = ImageFormat.Png; | |
90 | else if (extension == "gif") | |
91 | imageFormat = ImageFormat.Gif; | |
92 | else if (extension == "bmp") | |
93 | imageFormat = ImageFormat.Bmp; | |
94 | else if (extension == "jpeg") | |
95 | imageFormat = ImageFormat.Jpeg; | |
96 | else if (extension == "tiff") | |
97 | { | |
98 | // Convert tiff to gif. | |
99 | extension = "gif"; | |
100 | imageFormat = ImageFormat.Gif; | |
101 | } | |
102 | else if (extension == "x-wmf") | |
103 | { | |
104 | extension = "wmf"; | |
105 | imageFormat = ImageFormat.Wmf; | |
106 | } | |
107 | | |
108 | // If the image format isn't one that we expect, ignore it, | |
109 | // and don't return markup for the link. | |
110 | if (imageFormat == null) | |
111 | return null; | |
112 | | |
113 | string base64 = null; | |
114 | try | |
115 | { | |
116 | using (MemoryStream ms = new MemoryStream()) | |
117 | { | |
118 | imageInfo.Bitmap.Save(ms, imageFormat); | |
119 | var ba = ms.ToArray(); | |
120 | base64 = System.Convert.ToBase64String(ba); | |
121 | } | |
122 | } | |
123 | catch (System.Runtime.InteropServices.ExternalException) | |
124 | { | |
125 | return null; | |
126 | } | |
127 | | |
128 | ImageFormat format = imageInfo.Bitmap.RawFormat; | |
129 | ImageCodecInfo codec = ImageCodecInfo.GetImageDecoders().First(c => c.FormatID == format.Guid); | |
130 | string mimeType = codec.MimeType; | |
131 | | |
132 | string imageSource = string.Format("data:{0};base64,{1}", mimeType, base64); | |
133 | | |
134 | XElement img = new XElement(Xhtml.img, | |
135 | new XAttribute(NoNamespace.src, imageSource), | |
136 | imageInfo.ImgStyleAttribute, | |
137 | imageInfo.AltText != null ? | |
138 | new XAttribute(NoNamespace.alt, imageInfo.AltText) : null); | |
139 | return img; | |
140 | } | |
141 | }; | |
142 | XElement htmlElement = WmlToHtmlConverter.ConvertToHtml(wDoc, settings); | |
143 | | |
144 | // Produce HTML document with <!DOCTYPE html > declaration to tell the browser | |
145 | // we are using HTML5. | |
146 | var html = new XDocument( | |
147 | new XDocumentType("html", null, null, null), | |
148 | htmlElement); | |
149 | | |
150 | // Note: the xhtml returned by ConvertToHtmlTransform contains objects of type | |
151 | // XEntity. PtOpenXmlUtil.cs define the XEntity class. See | |
152 | // http://blogs.msdn.com/ericwhite/archive/2010/01/21/writing-entity-references-using-linq-to-xml.aspx | |
153 | // for detailed explanation. | |
154 | // | |
155 | // If you further transform the XML tree returned by ConvertToHtmlTransform, you | |
156 | // must do it correctly, or entities will not be serialized properly. | |
157 | | |
158 | var htmlString = html.ToString(SaveOptions.DisableFormatting); | |
159 | File.WriteAllText(destFileName.FullName, htmlString, Encoding.UTF8); | |
160 | } | |
161 | } | |
162 | } | |
163 | } | |
164 | | |
-------------------------------------------------------------------------------- | |
/OpenXmlPowerToolsExamples/WordAutomationUtilities/WordAutomationUtilities.cs: | |
-------------------------------------------------------------------------------- | |
1 | using System; | |
2 | using System.Collections.Generic; | |
3 | using System.IO; | |
4 | using System.Linq; | |
5 | using System.Text; | |
6 | using Word = Microsoft.Office.Interop.Word; | |
7 | | |
8 | namespace OpenXmlPowerTools | |
9 | { | |
10 | public class WordAutomationUtilities | |
11 | { | |
12 | public static void ProcessFilesUsingWordAutomation(List<string> fileNames) | |
13 | { | |
14 | Word.Application app = new Word.Application(); | |
15 | app.Visible = false; | |
16 | foreach (string fileName in fileNames) | |
17 | { | |
18 | FileInfo fi = new FileInfo(fileName); | |
19 | try | |
20 | { | |
21 | Word.Document doc = app.Documents.Open(fi.FullName); | |
22 | doc.Save(); | |
23 | } | |
24 | catch (System.Runtime.InteropServices.COMException) | |
25 | { | |
26 | Console.WriteLine("Caught unexpected COM exception."); | |
27 | ((Microsoft.Office.Interop.Word._Application)app).Quit(); | |
28 | Environment.Exit(0); | |
29 | } | |
30 | } | |
31 | ((Microsoft.Office.Interop.Word._Application)app).Quit(); | |
32 | } | |
33 | } | |
34 | } | |
35 | | |
-------------------------------------------------------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment