diff --git a/src/MiniWord/MiniWord.Implment.cs b/src/MiniWord/MiniWord.Implment.cs index d730274..d48e5f4 100644 --- a/src/MiniWord/MiniWord.Implment.cs +++ b/src/MiniWord/MiniWord.Implment.cs @@ -1,4 +1,4 @@ -namespace MiniSoftware +namespace MiniSoftware { using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Packaging; @@ -18,6 +18,8 @@ using System.Xml; using System.Xml.Linq; using DocumentFormat.OpenXml.Drawing.Charts; + using System.Threading.Tasks; + using System.Threading; public static partial class MiniWord { @@ -47,6 +49,33 @@ private static void SaveAsByTemplateImpl(Stream stream, byte[] template, Diction stream.Write(bytes, 0, bytes.Length); } + private static async Task SaveAsByTemplateImplAsync(Stream stream, byte[] template, Dictionary data, CancellationToken token) + { + var value = data; //TODO: support dynamic and poco value + byte[] bytes = null; + using (var ms = new MemoryStream()) + { + await ms.WriteAsync(template, 0, template.Length).ConfigureAwait(false); + ms.Position = 0; + using (var docx = WordprocessingDocument.Open(ms, true)) + { + var hc = docx.MainDocumentPart.HeaderParts.Count(); + var fc = docx.MainDocumentPart.FooterParts.Count(); + for (int i = 0; i < hc; i++) + docx.MainDocumentPart.HeaderParts.ElementAt(i).Header.Generate(docx, value); + for (int i = 0; i < fc; i++) + docx.MainDocumentPart.FooterParts.ElementAt(i).Footer.Generate(docx, value); + docx.MainDocumentPart.Document.Body.Generate(docx, value); + docx.Save(); + } + + bytes = ms.ToArray(); + } + + await stream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + } + + private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocument docx, Dictionary tags) { @@ -1125,12 +1154,17 @@ private static void AddPictureAnchor(OpenXmlElement appendElement, string relati private static byte[] GetBytes(string path) { - using (var st = Helpers.OpenSharedRead(path)) + return GetByteAsync(path).GetAwaiter().GetResult(); + } + + private static async Task GetByteAsync(string path) + { + using (var st = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, true)) using (var ms = new MemoryStream()) { - st.CopyTo(ms); + await st.CopyToAsync(ms).ConfigureAwait(false); return ms.ToArray(); } } } -} \ No newline at end of file +} diff --git a/src/MiniWord/MiniWord.cs b/src/MiniWord/MiniWord.cs index d308ced..3ca2706 100644 --- a/src/MiniWord/MiniWord.cs +++ b/src/MiniWord/MiniWord.cs @@ -1,7 +1,16 @@ namespace MiniSoftware { + using DocumentFormat.OpenXml.Office2013.Excel; using MiniSoftware.Extensions; + using MiniSoftware.Utility; + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Dynamic; using System.IO; + using System.Linq.Expressions; + using System.Threading; + using System.Threading.Tasks; public static partial class MiniWord { @@ -26,5 +35,27 @@ public static void SaveAsByTemplate(this Stream stream, byte[] templateBytes, ob { SaveAsByTemplateImpl(stream, templateBytes, value.ToDictionary()); } + + public static async Task SaveAsByTemplateAsync(this Stream stream, byte[] templateBytes, object value,CancellationToken token = default(CancellationToken)) + { + await SaveAsByTemplateImplAsync(stream, templateBytes, value.ToDictionary(),token).ConfigureAwait(false); + } + + public static async Task SaveAsByTemplateAsync(this Stream stream, string templatePath, object value,CancellationToken token = default(CancellationToken)) + { + await SaveAsByTemplateImplAsync(stream, await GetByteAsync(templatePath), value.ToDictionary(),token).ConfigureAwait(false); + } + + public static async Task SaveAsByTemplateAsync(string path, string templatePath, object value,CancellationToken token = default(CancellationToken)) + { + using (var stream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, true)) + await SaveAsByTemplateImplAsync(stream, await GetByteAsync(templatePath), value.ToDictionary(),token); + } + + public static async Task SaveAsByTemplateAsync(string path, byte[] templateBytes, object value,CancellationToken token = default(CancellationToken)) + { + using (var stream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, true)) + await SaveAsByTemplateImplAsync(stream, templateBytes, value.ToDictionary(),token); + } } } \ No newline at end of file diff --git a/src/MiniWord/MiniWord.csproj b/src/MiniWord/MiniWord.csproj index 05a9975..1a018be 100644 --- a/src/MiniWord/MiniWord.csproj +++ b/src/MiniWord/MiniWord.csproj @@ -32,6 +32,6 @@ - + diff --git a/tests/MiniWordTests/IssueTestsAsync.cs b/tests/MiniWordTests/IssueTestsAsync.cs index 27db920..1667da6 100644 --- a/tests/MiniWordTests/IssueTestsAsync.cs +++ b/tests/MiniWordTests/IssueTestsAsync.cs @@ -43,7 +43,7 @@ public async Task TestIssue69() } } }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); // TODO: waiting solution //var xml = Helpers.GetZipFileContent(path, "word/document.xml"); //Assert.Contains(@"MiniWord", xml); @@ -60,7 +60,7 @@ public async Task TaskSplitTag() { ["title"] = "Hello MiniWord", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"MiniWord", xml); } @@ -81,7 +81,7 @@ public async Task TestIssue37() ["Content"] = "Test", ["Content2"] = "Test2", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Test", xml); Assert.Contains(@"Test2", xml); @@ -103,7 +103,7 @@ public async Task TestIssue37() Text = "Test2!!" }, }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Test", xml); Assert.Contains(@"Test2", xml); @@ -116,7 +116,7 @@ public async Task TestDemo04() var outputPath = PathHelper.GetTempFilePath(); var templatePath = PathHelper.GetFile("TestDemo04.docx"); var value = new Dictionary() { ["title"] = "Hello MiniWord" }; - MiniWord.SaveAsByTemplate(outputPath, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(outputPath, templatePath, value); } [Fact] @@ -125,7 +125,7 @@ public async Task TestDemo04_new() var outputPath = PathHelper.GetTempFilePath(); var templatePath = PathHelper.GetFile("TestDemo04.docx"); var value = new { title = "Hello MiniWord" }; - MiniWord.SaveAsByTemplate(outputPath, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(outputPath, templatePath, value); } @@ -150,7 +150,7 @@ public async Task TestIssue18() new Dictionary {{ "name", "Keaton" },{ "department", "IT" } } } }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Keaton", xml); Assert.Contains(@"Eric", xml); @@ -174,7 +174,7 @@ public async Task TestIssue18() new {name="Keaton",department="IT" }, }, }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Keaton", xml); Assert.Contains(@"Eric", xml); @@ -198,7 +198,7 @@ public async Task TestIssue18() new User (){ name="Keaton",department="IT"}, }, }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Keaton", xml); Assert.Contains(@"Eric", xml); @@ -219,7 +219,7 @@ public async Task TestIssue17() ["Content"] = "Test", ["Content2"] = "Test2", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Test", xml); Assert.Contains(@"Test2", xml); @@ -239,7 +239,7 @@ public async Task TestIssue17_new() Content = "Test", Content2 = "Test2", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Test", xml); Assert.Contains(@"Test2", xml); @@ -275,7 +275,7 @@ public async Task TestIssue13() }, } }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); //System.Diagnostics.Process.Start("explorer.exe", path); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Discussion requirement part2 and development", xml); @@ -311,7 +311,7 @@ public async Task TestIssue13_new() }, } }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); //System.Diagnostics.Process.Start("explorer.exe", path); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Discussion requirement part2 and development", xml); @@ -333,7 +333,7 @@ public async Task TestDemo01_Tag_Text() ["Approved"] = true, ["Total_Amount"] = 123456, }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); } @@ -352,7 +352,7 @@ public async Task TestDemo01_Tag_Text_new() Approved = true, Total_Amount = 123456, }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); } /// @@ -372,7 +372,7 @@ public async Task TestIssue12() ["Points"] = 123, ["APP"] = "Demo APP\n", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"MiniSofteware", xml); Assert.Contains(@"", xml); @@ -395,7 +395,7 @@ public async Task TestIssue12_dynamic() value.Points = 123; value.APP = "Demo APP\n"; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"MiniSofteware", xml); Assert.Contains(@"", xml); @@ -420,7 +420,7 @@ public async Task TestIssue12_new() APP = "Demo APP\n", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"MiniSofteware", xml); Assert.Contains(@"", xml); @@ -469,7 +469,7 @@ Lorem Ipsum has been the industry's standard dummy text ", ["Image"] = new MiniWordPicture() { Path = PathHelper.GetFile("demo01.png"), Width = 160, Height = 90 }, }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); //System.Diagnostics.Process.Start("explorer.exe", path); } @@ -515,7 +515,7 @@ Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took. "; value.Image = new MiniWordPicture() { Path = PathHelper.GetFile("demo01.png"), Width = 160, Height = 90 }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); //System.Diagnostics.Process.Start("explorer.exe", path); } @@ -534,7 +534,7 @@ public async Task TestIssue11() ["managers"] = new[] { "Jack", "Alan" }, ["employees"] = new[] { "Mike", "Henry" }, }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains("Jack", xml); } @@ -546,7 +546,7 @@ public async Task TestIssue11() ["managers"] = new List { "Jack", "Alan" }, ["employees"] = new List { "Mike", "Henry" }, }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains("Jack", xml); } @@ -567,7 +567,7 @@ public async Task TestIssue11_new() // managers = new[] { "Jack", "Alan" }, // employees = new[] { "Mike", "Henry" }, // }; - // MiniWord.SaveAsByTemplate(path, templatePath, value); + // await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); // var xml = Helpers.GetZipFileContent(path, "word/document.xml"); // Assert.Contains("Jack", xml); //} @@ -579,7 +579,7 @@ public async Task TestIssue11_new() managers = new List { "Jack", "Alan" }, employees = new List { "Mike", "Henry" }, }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains("Jack", xml); } @@ -598,7 +598,7 @@ public async Task TestIssue3() { ["Logo"] = new MiniWordPicture() { Path = PathHelper.GetFile("DemoLogo.png"), Width = 180, Height = 180 } }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains("", xml); } @@ -624,7 +624,7 @@ public async Task TestIssue5() ["Points"] = 123, ["APP"] = "Demo APP", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); //Console.WriteLine(path); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.DoesNotContain("Jack Demo APP Account Data", xml); @@ -656,7 +656,7 @@ public async Task MiniWordHyperLink_List() ["Points"] = 123, ["APP"] = "Demo APP", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); //Console.WriteLine(path); var docXml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.DoesNotContain("Jack Demo APP Account Data", docXml); @@ -692,7 +692,7 @@ public async Task MiniWordHyperLink_Array() ["Points"] = 123, ["APP"] = "Demo APP", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var docXml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.DoesNotContain("Jack Demo APP Account Data", docXml); @@ -728,7 +728,7 @@ public async Task MiniWordHyperLink_AnonymousArray() ["Points"] = 123, ["APP"] = "Demo APP", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); var docXml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.DoesNotContain("Jack Demo APP Account Data", docXml); @@ -762,7 +762,7 @@ public async Task TestIssue5_new() Points = 123, APP = "Demo APP", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); //Console.WriteLine(path); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.DoesNotContain("Jack Demo APP Account Data", xml); @@ -788,7 +788,7 @@ public async Task TestIssue4() ["Points"] = 123, ["APP"] = "Demo APP", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); } /// @@ -808,7 +808,7 @@ public async Task TestIssue4_new() Points = 123, APP = "Demo APP", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); } [Fact] public async Task TestColor() @@ -830,7 +830,7 @@ public async Task TestColor() Points = 123, APP = "Demo APP", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); } [Fact] @@ -855,7 +855,7 @@ public async Task TestMultipleColorWordByWord() Points = 123, APP = "Demo APP", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); } diff --git a/tests/MiniWordTests/MiniWordTestAsync.cs b/tests/MiniWordTests/MiniWordTestAsync.cs index 8eb1af0..d2dfa9a 100644 --- a/tests/MiniWordTests/MiniWordTestAsync.cs +++ b/tests/MiniWordTests/MiniWordTestAsync.cs @@ -114,7 +114,7 @@ public async void TestForeachLoopInTablesAsync() } } }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); //System.Diagnostics.Process.Start("explorer.exe", path); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Discussion requirement part2 and development", xml); @@ -146,7 +146,7 @@ public async void MiniWordIfStatement_FirstIfAsync() ["Points"] = 123, ["APP"] = "Demo APP", }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); //Console.WriteLine(path); var docXml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains("First if chosen: MiniSofteware", docXml); @@ -261,7 +261,7 @@ public async void TestForeachLoopInTablesWithIfStatementAsync() } } }; - MiniWord.SaveAsByTemplate(path, templatePath, value); + await MiniWord.SaveAsByTemplateAsync(path, templatePath, value); //System.Diagnostics.Process.Start("explorer.exe", path); var xml = Helpers.GetZipFileContent(path, "word/document.xml"); Assert.Contains(@"Discussion requirement part2 and development", xml); diff --git a/tests/MiniWordTests/MiniWordTests.cs b/tests/MiniWordTests/MiniWordTests.cs index 7f87b4f..a55d028 100644 --- a/tests/MiniWordTests/MiniWordTests.cs +++ b/tests/MiniWordTests/MiniWordTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using DocumentFormat.OpenXml.Office2010.ExcelAc; using MiniSoftware; @@ -153,8 +153,6 @@ public void MiniWordIfStatement_FirstIf() Assert.Contains("Points are greater than 100", docXml); Assert.Contains("CreateDate is not less than 2021", docXml); Assert.DoesNotContain("CreateDate is not greater than 2021", docXml); - //Assert.Contains("Foo is undefined", docXml); //TODO: Not working - //Assert.Contains("Bar is undefined", docXml); //TODO: Not working } [Fact] @@ -270,4 +268,4 @@ public void TestForeachLoopInTablesWithIfStatement() Assert.Contains("Air way to the Airplane | Hotel way to the Room", xml); } } -} \ No newline at end of file +}