Skip to content

Instantly share code, notes, and snippets.

@rickythefox
Created January 30, 2025 04:50
Show Gist options
  • Save rickythefox/038f7a27856749314c2c55d187462498 to your computer and use it in GitHub Desktop.
Save rickythefox/038f7a27856749314c2c55d187462498 to your computer and use it in GitHub Desktop.
├── 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("&amp;", "&");
94 | sb.Replace("&nbsp;", "\xA0");
95 | sb.Replace("&quot;", "\"");
96 | sb.Replace("&lt;", "~lt;");
97 | sb.Replace("&gt;", "~gt;");
98 | sb.Replace("&#", "~#");
99 | sb.Replace("&", "&amp;");
100 | sb.Replace("~lt;", "&lt;");
101 | sb.Replace("~gt;", "&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