diff --git a/EasyDox.Tests/DocxTests.cs b/EasyDox.Tests/DocxTests.cs index 7f98d85..1c076b4 100644 --- a/EasyDox.Tests/DocxTests.cs +++ b/EasyDox.Tests/DocxTests.cs @@ -12,117 +12,122 @@ public class DocxTests [TestMethod] public void TestMethod1() { - var match = Docx.regex.Match (" MERGEFIELD Должность "); + var match = Docx.regex.Match(" MERGEFIELD Должность "); - Assert.IsTrue (match.Success); + Assert.IsTrue(match.Success); - Assert.AreEqual ("Должность", match.Groups ["name"].Value); + Assert.AreEqual("Должность", match.Groups["name"].Value); } [TestMethod] public void TestMethod2() { - var match = Docx.regex.Match (" MERGEFIELD \"Должность представителя Лицензиата\" "); + var match = Docx.regex.Match(" MERGEFIELD \"Должность представителя Лицензиата\" "); - Assert.IsTrue (match.Success); + Assert.IsTrue(match.Success); - Assert.AreEqual ("Должность представителя Лицензиата", match.Groups ["name"].Value); + Assert.AreEqual("Должность представителя Лицензиата", match.Groups["name"].Value); } [TestMethod] public void TestMethod3() { - var match = Docx.regex.Match (" MERGEFIELD \"Должность представителя Лицензиата\" \\* MERGEFORMAT"); + var match = Docx.regex.Match(" MERGEFIELD \"Должность представителя Лицензиата\" \\* MERGEFORMAT"); - Assert.IsTrue (match.Success); + Assert.IsTrue(match.Success); - Assert.AreEqual ("Должность представителя Лицензиата", match.Groups ["name"].Value); + Assert.AreEqual("Должность представителя Лицензиата", match.Groups["name"].Value); - Assert.AreEqual ("MERGEFORMAT", match.Groups ["format"].Value); + Assert.AreEqual("MERGEFORMAT", match.Groups["format"].Value); } [TestMethod] public void TestMethod4() { - var match = Docx.regex.Match (" MERGEFIELD \"Должность представителя Лицензиата\" \\* MERGEFORMAT \\* FirstCap"); + var match = Docx.regex.Match( + " MERGEFIELD \"Должность представителя Лицензиата\" \\* MERGEFORMAT \\* FirstCap"); - Assert.IsTrue (match.Success); + Assert.IsTrue(match.Success); - Assert.AreEqual ("Должность представителя Лицензиата", match.Groups ["name"].Value); + Assert.AreEqual("Должность представителя Лицензиата", match.Groups["name"].Value); - Assert.AreEqual ("MERGEFORMAT", match.Groups ["format"].Captures [0].Value); - Assert.AreEqual ("FirstCap", match.Groups ["format"].Captures [1].Value); + Assert.AreEqual("MERGEFORMAT", match.Groups["format"].Captures[0].Value); + Assert.AreEqual("FirstCap", match.Groups["format"].Captures[1].Value); } [TestMethod] public void TestMethod5() { - var match = Docx.regex.Match (" MERGEFIELD \"Родительный (Должность представителя Лицензиата)\" \\* MERGEFORMAT "); + var match = Docx.regex.Match( + " MERGEFIELD \"Родительный (Должность представителя Лицензиата)\" \\* MERGEFORMAT "); - Assert.IsTrue (match.Success); + Assert.IsTrue(match.Success); - Assert.AreEqual ("Родительный (Должность представителя Лицензиата)", match.Groups ["name"].Value); + Assert.AreEqual("Родительный (Должность представителя Лицензиата)", match.Groups["name"].Value); - Assert.AreEqual ("MERGEFORMAT", match.Groups ["format"].Captures [0].Value); + Assert.AreEqual("MERGEFORMAT", match.Groups["format"].Captures[0].Value); } - + [TestMethod] - public void MatchQuote () + public void MatchQuote() { - Assert.AreEqual ("asdf", Regex.Match ("\"asdf\"", @"^""(?[^""]+)""$").Groups ["name"].Value); + Assert.AreEqual("asdf", Regex.Match("\"asdf\"", @"^""(?[^""]+)""$").Groups["name"].Value); } [TestMethod] - public void MatchNonSpace () + public void MatchNonSpace() { - Assert.AreEqual ("asdf x", Regex.Match ("\"asdf x\"", @"^(?[^\s""]+)|(""(?[^""]+)"")$").Groups ["name"].Value); + Assert.AreEqual("asdf x", + Regex.Match("\"asdf x\"", @"^(?[^\s""]+)|(""(?[^""]+)"")$").Groups["name"].Value); } [TestMethod] - [DeploymentItem ("DocxComplexField.xml")] - public void TestMethod6 () + [DeploymentItem("DocxComplexField.xml")] + public void TestMethod6() { - var xdoc = new XmlDocument (); - xdoc.Load ("DocxComplexField.xml"); - var fields = Docx.GetFields (xdoc); - Assert.IsTrue (fields.Select (f => f.InstrText).SequenceEqual (new [] { - " MERGEFIELD \"Родительный (Должность представителя Лицензиата)\" \\* MERGEFORMAT ", - " MERGEFIELD \"Родительный (ФИО представителя Лицензиата)\" \\* MERGEFORMAT ", - " MERGEFIELD \"Полное наименование компании Лицензиата\" \\* MERGEFORMAT "})); + var xdoc = new XmlDocument(); + xdoc.Load("DocxComplexField.xml"); + var fields = Docx.GetFields(xdoc); + Assert.IsTrue(fields.Select(f => f.InstrText).SequenceEqual(new[] + { + " MERGEFIELD \"Родительный (Должность представителя Лицензиата)\" \\* MERGEFORMAT ", + " MERGEFIELD \"Родительный (ФИО представителя Лицензиата)\" \\* MERGEFORMAT ", + " MERGEFIELD \"Полное наименование компании Лицензиата\" \\* MERGEFORMAT " + })); } [TestMethod] - [DeploymentItem ("DocxComplexField2.xml")] - public void TestMethod8 () + [DeploymentItem("DocxComplexField2.xml")] + public void TestMethod8() { - var xdoc = new XmlDocument (); - xdoc.Load ("DocxComplexField2.xml"); - var fields = Docx.GetFields (xdoc); + var xdoc = new XmlDocument(); + xdoc.Load("DocxComplexField2.xml"); + var fields = Docx.GetFields(xdoc); var instrText = fields.Single().InstrText; Assert.AreEqual(" MERGEFIELD Продукт \\* MERGEFORMAT ", instrText); } [TestMethod] - [DeploymentItem ("DocxSimpleField.xml")] - public void SimpleField () + [DeploymentItem("DocxSimpleField.xml")] + public void SimpleField() { - var xdoc = new XmlDocument (); - xdoc.Load ("DocxSimpleField.xml"); - var fields = Docx.GetFields (xdoc); + var xdoc = new XmlDocument(); + xdoc.Load("DocxSimpleField.xml"); + var fields = Docx.GetFields(xdoc); var instrText = fields.Single().InstrText; Assert.AreEqual(" MERGEFIELD \"№ паспорта Лицензиара\" \\* MERGEFORMAT ", instrText); } [TestMethod] - [DeploymentItem ("DocxSimpleField.xml")] - public void SimpleFieldSetValue () + [DeploymentItem("DocxSimpleField.xml")] + public void SimpleFieldSetValue() { - var xdoc = new XmlDocument (); - xdoc.Load ("DocxSimpleField.xml"); - var fields = Docx.GetFields (xdoc); + var xdoc = new XmlDocument(); + xdoc.Load("DocxSimpleField.xml"); + var fields = Docx.GetFields(xdoc); var field = fields.Single(); field.Value = "new value"; @@ -130,36 +135,36 @@ public void SimpleFieldSetValue () } [TestMethod] - [DeploymentItem ("Dogovor.xml")] - public void Dogovor () + [DeploymentItem("Dogovor.xml")] + public void Dogovor() { - var xdoc = new XmlDocument (); - xdoc.Load ("Dogovor.xml"); - var fields = Docx.GetFields (xdoc); + var xdoc = new XmlDocument(); + xdoc.Load("Dogovor.xml"); + var fields = Docx.GetFields(xdoc); const string instrText = " MERGEFIELD \"Цена (цифрами и прописью)\" \\* MERGEFORMAT "; var field = fields.Single(f => f.InstrText == instrText); field.Value = "123456"; var buffer = new MemoryStream(); xdoc.Save(buffer); - var xdoc2 = new XmlDocument (); + var xdoc2 = new XmlDocument(); buffer.Position = 0; xdoc2.Load(buffer); - var fields2 = Docx.GetFields (xdoc); + var fields2 = Docx.GetFields(xdoc); var field2 = fields2.Single(f => f.InstrText == instrText); - + Assert.AreEqual("123456", field2.Value); } [TestMethod] - [DeploymentItem ("DocxComplexField.xml")] - public void TestMethod7 () + [DeploymentItem("DocxComplexField.xml")] + public void TestMethod7() { - var xdoc = new XmlDocument (); - xdoc.Load ("DocxComplexField.xml"); - var fields = Docx.GetFields (xdoc); - fields.First ().Value = "Иванов И.И."; + var xdoc = new XmlDocument(); + xdoc.Load("DocxComplexField.xml"); + var fields = Docx.GetFields(xdoc); + fields.First().Value = "Иванов И.И."; } } } \ No newline at end of file diff --git a/EasyDox.Tests/EasyDox.Tests.csproj b/EasyDox.Tests/EasyDox.Tests.csproj index 7b9d325..34dc421 100644 --- a/EasyDox.Tests/EasyDox.Tests.csproj +++ b/EasyDox.Tests/EasyDox.Tests.csproj @@ -1,101 +1,50 @@ - - + - Debug - AnyCPU - - - 2.0 - {C224E6DE-D77A-489E-8C2F-D300C585542C} - Library - Properties - EasyDox.Tests - EasyDox.Tests - v4.0 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + net6.0 - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true - - - - - - 3.5 - - - - - - False - - - - - - + + + - - {0A470181-7A69-4288-AAB4-C062E18BDD07} - EasyDox - + - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - + + Always + + + Always + - - PreserveNewest - + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + - - - \ No newline at end of file + diff --git a/EasyDox.Tests/Properties/AssemblyInfo.cs b/EasyDox.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 7ba6d02..0000000 --- a/EasyDox.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle ("EasyDox.Tests")] -[assembly: AssemblyDescription ("")] -[assembly: AssemblyConfiguration ("")] -[assembly: AssemblyCompany ("")] -[assembly: AssemblyProduct ("EasyDox.Tests")] -[assembly: AssemblyCopyright ("Copyright © 2012")] -[assembly: AssemblyTrademark ("")] -[assembly: AssemblyCulture ("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible (false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid ("9ab02e26-5acd-4546-b0f7-42d7cc698f1e")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion ("1.0.0.0")] - diff --git a/EasyDox.Tests/XlsxTests.cs b/EasyDox.Tests/XlsxTests.cs index 08ecdfb..bf083bc 100644 --- a/EasyDox.Tests/XlsxTests.cs +++ b/EasyDox.Tests/XlsxTests.cs @@ -33,7 +33,7 @@ public void XlsxRegexMethod2() public void XlsxRegexMethod3() { var match = Xlsx.regex.Match("ООО \"Самая лучшая компания\", [[Адрес]] "); - + Assert.IsTrue(match.Success); Assert.AreEqual("Адрес", match.Groups["name"].Value); Assert.AreEqual("[[Адрес]]", match.Groups["template"].Value); @@ -76,7 +76,8 @@ public void XlsxRegexMethod6() [TestMethod] public void XlsxRegexMethod7() { - var match = Xlsx.regex.Match(" На основании доверенности № [[Доверенность]] в лице [[ Фамилия ]], проживающий по адресу:[[ Адрес]] "); + var match = Xlsx.regex.Match( + " На основании доверенности № [[Доверенность]] в лице [[ Фамилия ]], проживающий по адресу:[[ Адрес]] "); Assert.IsTrue(match.Success); Assert.AreEqual(3, match.Groups["name"].Captures.Count); @@ -104,7 +105,9 @@ public void XlsxParseSharedStrings() Assert.AreEqual("[[Родительный (Должность представителя Лицензиата) ]]", fields[0].Text); Assert.AreEqual("[[ Родительный (ФИО представителя Лицензиата) ]] ", fields[1].Text); Assert.AreEqual("[[Полное наименование компании Лицензиата]]", fields[2].Text); - Assert.AreEqual(" На основании доверенности № [[Доверенность]] в лице [[ Фамилия ]], проживающий по адресу:[[ Адрес]] ", fields[3].Text); + Assert.AreEqual( + " На основании доверенности № [[Доверенность]] в лице [[ Фамилия ]], проживающий по адресу:[[ Адрес]] ", + fields[3].Text); } [TestMethod] @@ -124,7 +127,7 @@ public void XlsxSubstituteSharedStrings() var replacements = new Dictionary() { {"Доверенность", "123-456/АГ"}, - {"Адрес", "Петропавловск-Камчатский"}, + {"Адрес", "Петропавловск-Камчатский"}, {"Фамилия", "Иванов И.П."}, }; @@ -134,7 +137,9 @@ public void XlsxSubstituteSharedStrings() var fields = Xlsx.GetSharedStrings(xdoc2); - Assert.AreEqual(" На основании доверенности № 123-456/АГ в лице Иванов И.П., проживающий по адресу: Петропавловск-Камчатский ", fields.Single().StringValue); + Assert.AreEqual( + " На основании доверенности № 123-456/АГ в лице Иванов И.П., проживающий по адресу: Петропавловск-Камчатский ", + fields.Single().StringValue); } [TestMethod] @@ -195,7 +200,7 @@ public void SmokeTest() var dict = new Dictionary { {"№ счета", "123"}, - {"Лицензиат", "ООО \"Тюльпан\""}, + {"Лицензиат", "ООО \"Тюльпан\""}, {"Дата счета", "8 марта 2017"}, {"Продукт", "Право использования библиотеки \"Морфер\""}, {"Цена", "1500"}, @@ -208,4 +213,4 @@ public void SmokeTest() Assert.IsFalse(errors.Any()); } } -} +} \ No newline at end of file diff --git a/EasyDox/Docx.cs b/EasyDox/Docx.cs index 0e06750..7d35f83 100644 --- a/EasyDox/Docx.cs +++ b/EasyDox/Docx.cs @@ -18,27 +18,29 @@ public static class Docx /// Template and output path. /// A dictionary of field values keyed by field name. /// - public static IEnumerable MergeInplace (Engine engine, string docxPath, Dictionary fieldValues) + public static IEnumerable MergeInplace(Engine engine, string docxPath, + Dictionary fieldValues) { - using (var pkg = Package.Open (docxPath, FileMode.Open, FileAccess.ReadWrite)) + using (var pkg = Package.Open(docxPath, FileMode.Open, FileAccess.ReadWrite)) { // Specify the URI of the part to be read - PackagePart part = pkg.GetPart (new Uri ("/word/document.xml", UriKind.Relative)); + PackagePart part = pkg.GetPart(new Uri("/word/document.xml", UriKind.Relative)); // Get the document part from the package. // Load the XML in the part into an XmlDocument instance. - var xdoc = new XmlDocument (); + var xdoc = new XmlDocument(); using (var partStream = part.GetStream(FileMode.Open, FileAccess.Read)) { xdoc.Load(partStream); } - var fields = ReplaceMergeFieldsAndReturnMissingFieldNames (xdoc, fieldValues, engine); + var fields = ReplaceMergeFieldsAndReturnMissingFieldNames(xdoc, fieldValues, engine); - using (var partWrt = new StreamWriter (part.GetStream (FileMode.Open, FileAccess.Write))) + using (var partStream = part.GetStream(FileMode.Open, FileAccess.Write)) + using (var partWrt = new StreamWriter(partStream)) { - xdoc.Save (partWrt); + xdoc.Save(partWrt); } return fields; @@ -47,9 +49,9 @@ public static class Docx class MergeError : IMergeError { - private readonly Func callback; + private readonly Func callback; - public MergeError (Func callback) + public MergeError(Func callback) { this.callback = callback; } @@ -60,42 +62,42 @@ public string Accept(IMergeErrorVisitor visitor) } } - static IEnumerable ReplaceMergeFieldsAndReturnMissingFieldNames (XmlDocument xdoc, Dictionary dict, Engine engine) + static IEnumerable ReplaceMergeFieldsAndReturnMissingFieldNames(XmlDocument xdoc, + Dictionary dict, Engine engine) { - var fields = GetFields (xdoc); + var fields = GetFields(xdoc); - var errors = new List (); + var errors = new List(); - var properties = new Properties (dict); + var properties = new Properties(dict); foreach (var field in fields) { - var matches = regex.Match (field.InstrText); + var matches = regex.Match(field.InstrText); - if (matches.Success) - { - var fieldName = matches.Groups ["name"].Value; + if (!matches.Success) continue; - var format = matches.Groups ["format"].Captures; + var fieldName = matches.Groups["name"].Value; - var exp = engine.Parse (fieldName); + var format = matches.Groups["format"].Captures; - if (exp == null) - { - errors.Add (new MergeError (v => v.InvalidExpression (fieldName))); - } - else - { - var missingProperties = new List (); + var exp = engine.Parse(fieldName); - properties.FindMissingProperties (exp, missingProperties); + if (exp == null) + { + errors.Add(new MergeError(v => v.InvalidExpression(fieldName))); + } + else + { + var missingProperties = new List(); - errors.AddRange (missingProperties.Select (p => new MergeError (v => v.MissingField(p)))); + properties.FindMissingProperties(exp, missingProperties); - if (missingProperties.Count == 0) // otherwise Eval will throw - { - field.Value = ApplyFormat (properties.Eval (exp), format); - } + errors.AddRange(missingProperties.Select(p => new MergeError(v => v.MissingField(p)))); + + if (missingProperties.Count == 0) // otherwise Eval will throw + { + field.Value = ApplyFormat(properties.Eval(exp), format); } } } @@ -103,61 +105,61 @@ public string Accept(IMergeErrorVisitor visitor) return errors; } - private static string ApplyFormat (string s, CaptureCollection format) + private static string ApplyFormat(string s, CaptureCollection format) { foreach (Capture capture in format) { - switch (capture.Value.ToUpperInvariant ()) + switch (capture.Value.ToUpperInvariant()) { case "FIRSTCAP": - s = s.Substring (0,1).ToUpperInvariant () + s.Substring (1); + s = s.Substring(0, 1).ToUpperInvariant() + s.Substring(1); break; - } + } } return s; } - internal static IEnumerable GetFields (XmlDocument xdoc) + internal static IEnumerable GetFields(XmlDocument xdoc) { - var nsManager = new XmlNamespaceManager (new NameTable ()); - nsManager.AddNamespace ("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main"); + var nsManager = new XmlNamespaceManager(new NameTable()); + nsManager.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main"); - XPathNavigator xDocNavigator = xdoc.CreateNavigator (); + XPathNavigator xDocNavigator = xdoc.CreateNavigator(); - var nodes = xDocNavigator.Select ("//w:r[w:fldChar/@w:fldCharType='begin']", - nsManager); + var nodes = xDocNavigator.Select("//w:r[w:fldChar/@w:fldCharType='begin']", + nsManager); foreach (XPathNavigator navigator in nodes) { - yield return new ComplexField (navigator, nsManager); + yield return new ComplexField(navigator, nsManager); } - var simpleNodes = xDocNavigator.Select ("//w:fldSimple[starts-with(@w:instr,' MERGEFIELD')]", - nsManager); + var simpleNodes = xDocNavigator.Select("//w:fldSimple[starts-with(@w:instr,' MERGEFIELD')]", + nsManager); foreach (XPathNavigator navigator in simpleNodes) { - yield return new SimpleField (navigator, nsManager); + yield return new SimpleField(navigator, nsManager); } } - internal static readonly Regex regex = new Regex ( + internal static readonly Regex regex = new Regex( @"^[\s]*MERGEFIELD[\s]+(?[^\s""]+)|([""](?[^""]+)[""]) ([\s]*\\\*[\s]*(?\w+))*[\s]*?", - RegexOptions.Compiled - | RegexOptions.CultureInvariant - | RegexOptions.ExplicitCapture - | RegexOptions.IgnoreCase - | RegexOptions.IgnorePatternWhitespace + RegexOptions.Compiled + | RegexOptions.CultureInvariant + | RegexOptions.ExplicitCapture + | RegexOptions.IgnoreCase + | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); internal interface IField { - string InstrText {get;} - string Value {get; set;} + string InstrText { get; } + string Value { get; set; } } internal class SimpleField : IField @@ -165,35 +167,21 @@ internal class SimpleField : IField private readonly XPathNavigator node; private readonly XmlNamespaceManager namespaceManager; - public SimpleField (XPathNavigator node, XmlNamespaceManager namespaceManager) + public SimpleField(XPathNavigator node, XmlNamespaceManager namespaceManager) { this.node = node; this.namespaceManager = namespaceManager; } - string IField.InstrText - { - // ReSharper disable AssignNullToNotNullAttribute - get { return node.GetAttribute ("instr", namespaceManager.LookupNamespace ("w")); } - // ReSharper restore AssignNullToNotNullAttribute - } + string IField.InstrText => node.GetAttribute("instr", namespaceManager.LookupNamespace("w")); string IField.Value { - get - { - return ValueNode.Value; - } - set - { - ValueNode.SetValue (value); - } + get => ValueNode.Value; + set => ValueNode.SetValue(value); } - private XPathNavigator ValueNode - { - get { return node.Select ("w:r/w:t", namespaceManager).Cast ().Single (); } - } + private XPathNavigator ValueNode => node.Select("w:r/w:t", namespaceManager).Cast().Single(); } internal class ComplexField : IField @@ -201,7 +189,7 @@ internal class ComplexField : IField private readonly XPathNavigator begin; private readonly XmlNamespaceManager nsManager; - public ComplexField (XPathNavigator begin, XmlNamespaceManager nsManager) + public ComplexField(XPathNavigator begin, XmlNamespaceManager nsManager) { this.begin = begin; this.nsManager = nsManager; @@ -212,24 +200,24 @@ string IField.InstrText get { // TODO: change this to look for w:fldCharType="separate" and get rid of the hard coded 5. - var nodes = begin.Select ("following-sibling::w:r[position() <= 5]/w:instrText", nsManager); - return String.Join ("", nodes.Cast ().Select (n => n.Value)); + var nodes = begin.Select("following-sibling::w:r[position() <= 5]/w:instrText", nsManager); + + return string.Join("", nodes.Cast().Select(n => n.Value)); } } string IField.Value { - get - { - throw new NotImplementedException (); - } + get => throw new NotImplementedException(); set { - var nodes = begin.Select ("following-sibling::w:r[w:fldChar/@w:fldCharType='separate']/following-sibling::w:r/w:t", nsManager); + var nodes = begin.Select( + "following-sibling::w:r[w:fldChar/@w:fldCharType='separate']/following-sibling::w:r/w:t", + nsManager); - var mode = nodes.Cast ().First (); + var mode = nodes.Cast().First(); - mode.SetValue (value); + mode.SetValue(value); } } } diff --git a/EasyDox/EasyDox.csproj b/EasyDox/EasyDox.csproj index 135b129..b279658 100644 --- a/EasyDox/EasyDox.csproj +++ b/EasyDox/EasyDox.csproj @@ -1,85 +1,14 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {0A470181-7A69-4288-AAB4-C062E18BDD07} - Library - Properties - EasyDox - EasyDox - v4.0 - Client - 512 - - - - - - true - bin\Debug\ - DEBUG;TRACE - full - AnyCPU - bin\Debug\EasyDox.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - false - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - false - bin\Debug\EasyDox.xml - 1591 - true - - - bin\Release\ - TRACE - true - pdbonly - AnyCPU - bin\Release\EasyDox.dll.CodeAnalysisLog.xml - true - GlobalSuppressions.cs - prompt - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - false - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - bin\Release\EasyDox.xml - 1591 - true + netstandard2.0;net6.0 - - - - + + - - - - - - - - - - - - + - - - \ No newline at end of file + + + diff --git a/EasyDox/Engine.cs b/EasyDox/Engine.cs index 4ff38aa..0ce5cf8 100644 --- a/EasyDox/Engine.cs +++ b/EasyDox/Engine.cs @@ -6,69 +6,69 @@ namespace EasyDox { public class Engine { - private readonly Dictionary functions; + private readonly Dictionary functions; /// /// Creates the templating engine with a specified set of user-defined functions. /// - public Engine (params Dictionary [] functionPacks) + public Engine(params Dictionary[] functionPacks) { this.functions = functionPacks - .SelectMany (p => p) - .ToDictionary (kvp => kvp.Key, kvp => kvp.Value); + .SelectMany(p => p) + .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } - internal string Eval (string expression, Properties properties) + internal string Eval(string expression, Properties properties) { - IExpression exp = Parse (expression); + IExpression exp = Parse(expression); - return exp == null ? null : properties.Eval (exp); + return exp == null ? null : properties.Eval(exp); } internal IExpression Parse(string expression) { - var parts = expression.Split ('(').Select (p => p.Trim()).ToList(); + var parts = expression.Split('(').Select(p => p.Trim()).ToList(); - IExpression exp = ParsePropertyOrLiteral (parts.First ()); + IExpression exp = ParsePropertyOrLiteral(parts.First()); - foreach (var part in parts.Skip (1)) + foreach (var part in parts.Skip(1)) { - if (! part.EndsWith (")")) return null; + if (!part.EndsWith(")")) return null; - string funcArgs = part.Substring (0, part.Length - 1); + var funcArgs = part.Substring(0, part.Length - 1); - int i=0; + int i = 0; for (; i < funcArgs.Length; ++i) { - if (char.IsUpper (funcArgs [i]) || funcArgs [i] == '\"') break; + if (char.IsUpper(funcArgs[i]) || funcArgs[i] == '\"') break; } - string func = funcArgs.Substring (0, i).Trim (); + string func = funcArgs.Substring(0, i).Trim(); - var args = new List {exp}; + var args = new List {exp}; - string arg2 = funcArgs.Substring (i).Trim (); + string arg2 = funcArgs.Substring(i).Trim(); - if (!string.IsNullOrEmpty (arg2)) + if (!string.IsNullOrEmpty(arg2)) { - args.Add (ParsePropertyOrLiteral (arg2)); + args.Add(ParsePropertyOrLiteral(arg2)); } Delegate def; - if (!functions.TryGetValue (func, out def)) return null; + if (!functions.TryGetValue(func, out def)) return null; if (def.Method.GetParameters().Length != args.Count) return null; - exp = new Function (def, args); + exp = new Function(def, args); } return exp; } - private static IExpression ParsePropertyOrLiteral (string s) + private static IExpression ParsePropertyOrLiteral(string s) { - return (s [0] == '\"') ? (IExpression) new Literal (s.Substring (1, s.Length-2)) : new Field (s); + return (s[0] == '\"') ? (IExpression) new Literal(s.Substring(1, s.Length - 2)) : new Field(s); } } } \ No newline at end of file diff --git a/EasyDox/EngineExtensions.cs b/EasyDox/EngineExtensions.cs index 0f39192..b1037d0 100644 --- a/EasyDox/EngineExtensions.cs +++ b/EasyDox/EngineExtensions.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; +using EasyDox; +using System.Collections.Generic; using System.IO; -using EasyDox; public static class EngineExtensions { @@ -22,6 +22,7 @@ public static class EngineExtensions public static IEnumerable MergeXL(this Engine engine, string templatePath, Dictionary fieldValues, string outputPath) { File.Copy(templatePath, outputPath, true); + return Xlsx.MergeInplace(engine, outputPath, fieldValues); } } \ No newline at end of file diff --git a/EasyDox/ExpressionEvaluator.cs b/EasyDox/ExpressionEvaluator.cs index 54e6052..f3fcf3e 100644 --- a/EasyDox/ExpressionEvaluator.cs +++ b/EasyDox/ExpressionEvaluator.cs @@ -8,17 +8,14 @@ class ExpressionEvaluator : IExpressionVisitor string result; - public ExpressionEvaluator (Properties properties, IExpression expression) + public ExpressionEvaluator(Properties properties, IExpression expression) { this.properties = properties; - expression.Accept (this); + expression.Accept(this); } - public string Result - { - get { return result; } - } + public string Result => result; void IExpressionVisitor.Visit(Literal literal) { @@ -27,12 +24,13 @@ void IExpressionVisitor.Visit(Literal literal) void IExpressionVisitor.Visit(Field field) { - result = properties [field.Name]; + result = properties[field.Name]; } void IExpressionVisitor.Visit(Function function) { - result = (string) function.Definition.DynamicInvoke(function.Args.Select (a => (object) new ExpressionEvaluator (properties, a).result).ToArray()); + result = (string) function.Definition.DynamicInvoke(function.Args + .Select(a => (object) new ExpressionEvaluator(properties, a).result).ToArray()); } } } \ No newline at end of file diff --git a/EasyDox/Expressions.cs b/EasyDox/Expressions.cs index b2cb4e6..12167f2 100644 --- a/EasyDox/Expressions.cs +++ b/EasyDox/Expressions.cs @@ -5,14 +5,14 @@ namespace EasyDox { interface IExpression { - void Accept (IExpressionVisitor visitor); + void Accept(IExpressionVisitor visitor); } interface IExpressionVisitor { - void Visit (Literal literal); - void Visit (Field field); - void Visit (Function function); + void Visit(Literal literal); + void Visit(Field field); + void Visit(Function function); } /// @@ -20,14 +20,14 @@ interface IExpressionVisitor /// class Literal : IExpression { - public Literal (string s) + public Literal(string s) { Value = s; } void IExpression.Accept(IExpressionVisitor visitor) { - visitor.Visit (this); + visitor.Visit(this); } public string Value { get; } @@ -45,7 +45,7 @@ public Field(string name) void IExpression.Accept(IExpressionVisitor visitor) { - visitor.Visit (this); + visitor.Visit(this); } /// @@ -56,7 +56,7 @@ void IExpression.Accept(IExpressionVisitor visitor) class Function : IExpression { - public Function (Delegate def, IEnumerable args) + public Function(Delegate def, IEnumerable args) { Definition = def; Args = args; @@ -64,11 +64,11 @@ public Function (Delegate def, IEnumerable args) public Delegate Definition { get; } - public IEnumerable Args { get; } + public IEnumerable Args { get; } void IExpression.Accept(IExpressionVisitor visitor) { - visitor.Visit (this); + visitor.Visit(this); } } } \ No newline at end of file diff --git a/EasyDox/IMergeError.cs b/EasyDox/IMergeError.cs index 01ffac6..0e4b576 100644 --- a/EasyDox/IMergeError.cs +++ b/EasyDox/IMergeError.cs @@ -2,6 +2,6 @@ namespace EasyDox { public interface IMergeError { - string Accept (IMergeErrorVisitor visitor); + string Accept(IMergeErrorVisitor visitor); } } \ No newline at end of file diff --git a/EasyDox/IMergeErrorVisitor.cs b/EasyDox/IMergeErrorVisitor.cs index bca5e7f..f7fdba7 100644 --- a/EasyDox/IMergeErrorVisitor.cs +++ b/EasyDox/IMergeErrorVisitor.cs @@ -2,7 +2,7 @@ namespace EasyDox { public interface IMergeErrorVisitor { - string InvalidExpression (string expr); - string MissingField (string fieldName); + string InvalidExpression(string expr); + string MissingField(string fieldName); } } \ No newline at end of file diff --git a/EasyDox/MissingPropertiesFinder.cs b/EasyDox/MissingPropertiesFinder.cs index 99e7813..5bfcf58 100644 --- a/EasyDox/MissingPropertiesFinder.cs +++ b/EasyDox/MissingPropertiesFinder.cs @@ -6,23 +6,21 @@ class MissingPropertiesFinder : IExpressionVisitor { private readonly Properties properties; - private readonly List missingProperties; + private readonly List missingProperties; - public MissingPropertiesFinder (Properties properties, List missingProperties) + public MissingPropertiesFinder(Properties properties, List missingProperties) { this.properties = properties; this.missingProperties = missingProperties; } - void IExpressionVisitor.Visit(Literal literal) - { - } + void IExpressionVisitor.Visit(Literal literal) { } void IExpressionVisitor.Visit(Field field) { - if (!properties.ContainsKey (field.Name) && !missingProperties.Contains (field.Name)) + if (!properties.ContainsKey(field.Name) && !missingProperties.Contains(field.Name)) { - missingProperties.Add (field.Name); + missingProperties.Add(field.Name); } } @@ -30,7 +28,7 @@ void IExpressionVisitor.Visit(Function function) { foreach (var arg in function.Args) { - arg.Accept (this); + arg.Accept(this); } } } diff --git a/EasyDox/Properties.cs b/EasyDox/Properties.cs index 571ff47..963734f 100644 --- a/EasyDox/Properties.cs +++ b/EasyDox/Properties.cs @@ -2,24 +2,19 @@ namespace EasyDox { - class Properties : Dictionary + class Properties : Dictionary { - public Properties() - { - } - - public Properties (Dictionary dict) : base (dict) - { - } + public Properties() {} + public Properties(Dictionary dict) : base(dict) { } - public string Eval (IExpression exp) + public string Eval(IExpression exp) { - return new ExpressionEvaluator (this, exp).Result; + return new ExpressionEvaluator(this, exp).Result; } - public void FindMissingProperties (IExpression exp, List missingProperties) + public void FindMissingProperties(IExpression exp, List missingProperties) { - exp.Accept (new MissingPropertiesFinder (this, missingProperties)); + exp.Accept(new MissingPropertiesFinder(this, missingProperties)); } } } \ No newline at end of file diff --git a/EasyDox/Properties/AssemblyInfo.cs b/EasyDox/Properties/AssemblyInfo.cs deleted file mode 100644 index 677db65..0000000 --- a/EasyDox/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle ("EasyDox")] -[assembly: AssemblyDescription ("")] -[assembly: AssemblyConfiguration ("")] -[assembly: AssemblyCompany ("")] -[assembly: AssemblyProduct ("EasyDox")] -[assembly: AssemblyCopyright ("Copyright © 2012 Morpher.ru")] -[assembly: AssemblyTrademark ("")] -[assembly: AssemblyCulture ("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible (false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid ("b963d1af-f5af-497e-8ee1-3c29f024ff80")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion ("1.0.0.0")] - - -[assembly: InternalsVisibleTo("EasyDox.Tests")] diff --git a/EasyDox/Xlsx.cs b/EasyDox/Xlsx.cs index 9904829..f82ea19 100644 --- a/EasyDox/Xlsx.cs +++ b/EasyDox/Xlsx.cs @@ -2,10 +2,10 @@ using System.Collections.Generic; using System.IO; using System.IO.Packaging; +using System.Linq; +using System.Text.RegularExpressions; using System.Xml; using System.Xml.XPath; -using System.Text.RegularExpressions; -using System.Linq; namespace EasyDox { @@ -19,19 +19,17 @@ public static class Xlsx /// Template and output path. /// A dictionary of field values keyed by field name. /// - public static IEnumerable MergeInplace( - Engine engine, - string xlsxPath, + public static IEnumerable MergeInplace(Engine engine, string xlsxPath, Dictionary fieldValues) { using (var pkg = Package.Open(xlsxPath, FileMode.Open, FileAccess.ReadWrite)) { // Specify the URI of the part to be read - PackagePart part = pkg.GetPart(new Uri ("/xl/sharedStrings.xml", UriKind.Relative)); + PackagePart part = pkg.GetPart(new Uri("/xl/sharedStrings.xml", UriKind.Relative)); var sheetParts = pkg.GetParts() - .Where(p => - p.Uri.OriginalString.StartsWith("/xl/worksheets") && + .Where(p => + p.Uri.OriginalString.StartsWith("/xl/worksheets") && p.Uri.OriginalString.EndsWith(".xml")) .ToList(); @@ -39,14 +37,20 @@ public static IEnumerable MergeInplace( foreach (var sheet in sheetParts) { var sheetDoc = new XmlDocument(); - sheetDoc.Load(sheet.GetStream(FileMode.Open, FileAccess.Read)); - sheetDocList.Add(sheetDoc); + using (var partStream = sheet.GetStream(FileMode.Open, FileAccess.Read)) + { + sheetDoc.Load(partStream); + sheetDocList.Add(sheetDoc); + } } // Get the document part from the package. // Load the XML in the part into an XmlDocument instance. var sharedStringsDoc = new XmlDocument(); - sharedStringsDoc.Load(part.GetStream(FileMode.Open, FileAccess.Read)); + using (var partStream = part.GetStream(FileMode.Open, FileAccess.Read)) + { + sharedStringsDoc.Load(partStream); + } var fields = ReplaceMergeFieldsAndReturnMissingFieldNames(sharedStringsDoc, sheetDocList, fieldValues, engine); @@ -64,7 +68,8 @@ public static IEnumerable MergeInplace( private static void SaveDocPart(PackagePart part, XmlDocument xmlDoc) { - using (var partWrt = new StreamWriter(part.GetStream(FileMode.Open, FileAccess.Write))) + using (var stream = part.GetStream(FileMode.Open, FileAccess.Write)) + using (var partWrt = new StreamWriter(stream)) { xmlDoc.Save(partWrt); } @@ -86,7 +91,8 @@ public string Accept(IMergeErrorVisitor visitor) } public static IEnumerable ReplaceMergeFieldsAndReturnMissingFieldNames( - XmlDocument sharedStringsDoc, List sheetDocList, Dictionary replacements, Engine engine) + XmlDocument sharedStringsDoc, List sheetDocList, Dictionary replacements, + Engine engine) { var fields = GetSharedStrings(sharedStringsDoc); @@ -105,7 +111,7 @@ public static IEnumerable ReplaceMergeFieldsAndReturnMissingFieldNa var fieldNames = matches.Groups["name"].Captures; var fieldTemplates = matches.Groups["template"].Captures; - for(var fieldIdx = 0; fieldIdx < fieldNames.Count; ++fieldIdx ) + for (var fieldIdx = 0; fieldIdx < fieldNames.Count; ++fieldIdx) { var fieldName = fieldNames[fieldIdx].ToString(); var fieldTemlate = fieldTemplates[fieldIdx].ToString(); @@ -129,12 +135,11 @@ public static IEnumerable ReplaceMergeFieldsAndReturnMissingFieldNa } } - if(value != field.Text) + if (value != field.Text) { - double dresult; - if (Double.TryParse(value.Trim(), out dresult)) + if (double.TryParse(value.Trim(), out double dresult)) { - foreach(var sheetDoc in sheetDocList) + foreach (var sheetDoc in sheetDocList) { var cells = GetStringCells(sheetDoc, stringIdx); foreach (var cell in cells) @@ -142,13 +147,14 @@ public static IEnumerable ReplaceMergeFieldsAndReturnMissingFieldNa cell.DoubleValue = dresult; } } - + value = ""; } } field.StringValue = value; } + ++stringIdx; } @@ -162,7 +168,7 @@ internal static IEnumerable GetStringCells(XmlDocument xdoc, int stringId XPathNavigator xDocNavigator = xdoc.CreateNavigator(); //var nodePath = String.Format("//s:worksheet/s:sheetData/s:row/s:cr[s:@t='s'/s:v={0}]", stringIdx); - var nodePath = String.Format("//d:sheetData/d:row/d:c[@t='s' and d:v='{0}']", stringIdx); + var nodePath = $"//d:sheetData/d:row/d:c[@t='s' and d:v='{stringIdx}']"; var nodes = xDocNavigator.Select(nodePath, nsManager); foreach (XPathNavigator navigator in nodes) @@ -212,29 +218,18 @@ public SimpleSharedString(XPathNavigator node) this.node = node; } - string ISharedString.Text - { - // ReSharper disable AssignNullToNotNullAttribute - get { return node.InnerXml; } - // ReSharper restore AssignNullToNotNullAttribute - } + string ISharedString.Text => node.InnerXml; string ISharedString.StringValue { - get - { - return node.Value; - } - set - { - node.SetValue(value); - } + get => node.Value; + set => node.SetValue(value); } } internal interface ICell { - double DoubleValue { get; set; } + double DoubleValue { get; set; } } internal class SimpleCell : ICell @@ -253,16 +248,18 @@ double ICell.DoubleValue get { var child = node.Select("d:v", namespaceManager).Cast().Single(); - return Double.Parse(child.Value); + + return double.Parse(child.Value); } set { - XmlNode curNode = ((IHasXmlNode)node).GetNode(); + XmlNode curNode = ((IHasXmlNode) node).GetNode(); XmlAttribute attrib = curNode?.Attributes?["t"]; if (attrib != null) { curNode.Attributes.Remove(attrib); } + var child = node.Select("d:v", namespaceManager).Cast().Single(); child.SetValue(value.ToString("G17")); }