├── output.docx
├── template1.docx
├── utilities
└── NuGet.exe
├── template-malformed-xml.docx
├── docxtemplateenginetest.bat
├── swxben.docxtemplateengine.0.1.0.nupkg
├── swxben.docxtemplateengine.0.1.1.nupkg
├── swxben.docxtemplateengine.0.1.2.nupkg
├── swxben.docxtemplateengine.0.1.3.nupkg
├── swxben.docxtemplateengine.0.1.4.nupkg
├── swxben.docxtemplateengine.0.1.5.nupkg
├── .nuget
└── packages.config
├── src
├── swxben.docxtemplateengine
│ ├── packages.config
│ ├── IDocXTemplateEngine.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── swxben.docxtemplateengine.csproj
│ └── DocXTemplateEngine.cs
├── docxtemplateenginetest
│ ├── packages.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Program.cs
│ └── docxtemplateenginetest.csproj
└── Tests
│ ├── packages.config
│ ├── TestHelpers.cs
│ ├── when_replacing_template_field.cs
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── when_reading_to_and_from_a_stream.cs
│ ├── Tests.csproj
│ └── when_parsing_simple_template.cs
├── tests.bat
├── swxben.docxtemplateengine.nuspec
├── .gitignore
├── DocXTemplateEngine.sln
└── README.md
/output.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swxben/docx-template-engine/HEAD/output.docx
--------------------------------------------------------------------------------
/template1.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swxben/docx-template-engine/HEAD/template1.docx
--------------------------------------------------------------------------------
/utilities/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swxben/docx-template-engine/HEAD/utilities/NuGet.exe
--------------------------------------------------------------------------------
/template-malformed-xml.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swxben/docx-template-engine/HEAD/template-malformed-xml.docx
--------------------------------------------------------------------------------
/docxtemplateenginetest.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | src\docxtemplateenginetest\bin\Debug\docxtemplateenginetest.exe %*
3 |
4 |
--------------------------------------------------------------------------------
/swxben.docxtemplateengine.0.1.0.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swxben/docx-template-engine/HEAD/swxben.docxtemplateengine.0.1.0.nupkg
--------------------------------------------------------------------------------
/swxben.docxtemplateengine.0.1.1.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swxben/docx-template-engine/HEAD/swxben.docxtemplateengine.0.1.1.nupkg
--------------------------------------------------------------------------------
/swxben.docxtemplateengine.0.1.2.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swxben/docx-template-engine/HEAD/swxben.docxtemplateengine.0.1.2.nupkg
--------------------------------------------------------------------------------
/swxben.docxtemplateengine.0.1.3.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swxben/docx-template-engine/HEAD/swxben.docxtemplateengine.0.1.3.nupkg
--------------------------------------------------------------------------------
/swxben.docxtemplateengine.0.1.4.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swxben/docx-template-engine/HEAD/swxben.docxtemplateengine.0.1.4.nupkg
--------------------------------------------------------------------------------
/swxben.docxtemplateengine.0.1.5.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swxben/docx-template-engine/HEAD/swxben.docxtemplateengine.0.1.5.nupkg
--------------------------------------------------------------------------------
/.nuget/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/swxben.docxtemplateengine/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/docxtemplateenginetest/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tests.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | if /i "%1" == "gui" goto :gui
3 |
4 | :console
5 | packages\NUnit.Runners.2.6.2\tools\nunit-console.exe src\Tests\bin\Debug\Tests.dll
6 | goto :done
7 |
8 | :gui
9 | packages\NUnit.Runners.2.6.2\tools\nunit.exe src\Tests\bin\Debug\Tests.dll
10 | goto :done
11 |
12 | :done
13 | del /Q TestResult.xml
--------------------------------------------------------------------------------
/src/swxben.docxtemplateengine/IDocXTemplateEngine.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace swxben.docxtemplateengine
4 | {
5 | public interface IDocXTemplateEngine
6 | {
7 | void Process(string source, string destination, object data);
8 | void Process(string source, Stream destination, object data);
9 | void Process(Stream source, Stream destination, object data);
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Tests/TestHelpers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace Tests
8 | {
9 | public static class TestHelpers
10 | {
11 | public static string GetRootPath()
12 | {
13 | var currentDirectory = Directory.GetCurrentDirectory();
14 | var rootDir = currentDirectory.Substring(0, currentDirectory.IndexOf(@"\src\Tests\bin\", StringComparison.Ordinal));
15 | return rootDir;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Tests/when_replacing_template_field.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Shouldly;
3 | using swxben.docxtemplateengine;
4 |
5 | namespace Tests
6 | {
7 | [TestFixture]
8 | class when_replacing_template_field
9 | {
10 | [Test]
11 | public void simple_value_is_replaced()
12 | {
13 | var template = "this is an " + DocXTemplateEngine.TOKEN_START + "tmpl" + DocXTemplateEngine.TOKEN_END + " template";
14 |
15 | var result = DocXTemplateEngine.ReplaceTemplateField(template, "tmpl", "example");
16 |
17 | result.ShouldBe("this is an example template");
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/swxben.docxtemplateengine.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | swxben.docxtemplateengine
5 | 0.1.5
6 | DocXTemplateEngine
7 | Ben Scott, contributors
8 | Ben Scott
9 | http://creativecommons.org/licenses/by-sa/3.0/
10 | https://github.com/swxben/docx-template-engine
11 | false
12 | A template engine for the .NET platform which takes a DOCX file and applies a data object to generate reports, do mail merges, etc. No dependency on MS Word.
13 | A template engine for the .NET platform which takes a DOCX file and applies a data object to generate reports, do mail merges, etc. No dependency on MS Word.
14 | Safe handling of null values in the source data @MarkKGreenway
15 | word msword template docx
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Tests")]
13 | [assembly: AssemblyCopyright("Copyright © 2012")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("462c4948-5bb8-488e-849d-bce51a2fe3ea")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/src/docxtemplateenginetest/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("docxtemplateenginetest")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("docxtemplateenginetest")]
13 | [assembly: AssemblyCopyright("Copyright © 2012")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a4ea6626-2598-472a-8bcd-71ab229d0f94")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/src/swxben.docxtemplateengine/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("swxben.docxtemplateengine")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Software by Ben Pty Ltd")]
12 | [assembly: AssemblyProduct("swxben.docxtemplateengine")]
13 | [assembly: AssemblyCopyright("CC BY-SA 3.0")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("57016d23-cc1f-4a41-b56f-8358cd3438b7")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("0.1.3.0")]
36 | [assembly: AssemblyFileVersion("0.1.3.0")]
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Bb]in/
3 | [Oo]bj/
4 |
5 | # mstest test results
6 | TestResults
7 |
8 | ## Ignore Visual Studio temporary files, build results, and
9 | ## files generated by popular Visual Studio add-ons.
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.sln.docstates
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Rr]elease/
19 | x64/
20 | *_i.c
21 | *_p.c
22 | *.ilk
23 | *.meta
24 | *.obj
25 | *.pch
26 | *.pdb
27 | *.pgc
28 | *.pgd
29 | *.rsp
30 | *.sbr
31 | *.tlb
32 | *.tli
33 | *.tlh
34 | *.tmp
35 | *.log
36 | *.vspscc
37 | *.vssscc
38 | .builds
39 |
40 | # Visual C++ cache files
41 | ipch/
42 | *.aps
43 | *.ncb
44 | *.opensdf
45 | *.sdf
46 |
47 | # Visual Studio profiler
48 | *.psess
49 | *.vsp
50 | *.vspx
51 |
52 | # Guidance Automation Toolkit
53 | *.gpState
54 |
55 | # ReSharper is a .NET coding add-in
56 | _ReSharper*
57 |
58 | # NCrunch
59 | *.ncrunch*
60 | .*crunch*.local.xml
61 |
62 | # Installshield output folder
63 | [Ee]xpress
64 |
65 | # DocProject is a documentation generator add-in
66 | DocProject/buildhelp/
67 | DocProject/Help/*.HxT
68 | DocProject/Help/*.HxC
69 | DocProject/Help/*.hhc
70 | DocProject/Help/*.hhk
71 | DocProject/Help/*.hhp
72 | DocProject/Help/Html2
73 | DocProject/Help/html
74 |
75 | # Click-Once directory
76 | publish
77 |
78 | # Publish Web Output
79 | *.Publish.xml
80 |
81 | # NuGet Packages Directory
82 | packages
83 |
84 | # Windows Azure Build Output
85 | csx
86 | *.build.csdef
87 |
88 | # Windows Store app package directory
89 | AppPackages/
90 |
91 | # Others
92 | [Bb]in
93 | [Oo]bj
94 | sql
95 | TestResults
96 | [Tt]est[Rr]esult*
97 | *.Cache
98 | ClientBin
99 | [Ss]tyle[Cc]op.*
100 | ~$*
101 | *.dbmdl
102 | Generated_Code #added for RIA/Silverlight projects
103 |
104 | # Backup & report files from converting an old project file to a newer
105 | # Visual Studio version. Backup files are not needed, because we have git ;-)
106 | _UpgradeReport_Files/
107 | Backup*/
108 | UpgradeLog*.XML
109 |
--------------------------------------------------------------------------------
/src/Tests/when_reading_to_and_from_a_stream.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using NUnit.Framework;
7 | using Shouldly;
8 | using swxben.docxtemplateengine;
9 |
10 | namespace Tests
11 | {
12 | public class when_reading_to_and_from_a_stream
13 | {
14 | readonly IDocXTemplateEngine _templateEngine = new DocXTemplateEngine();
15 | private readonly string _pathToTemplateDoc = Path.Combine(TestHelpers.GetRootPath(), "template1.docx");
16 |
17 | [Test]
18 | public void the_output_stream_is_the_same_length_as_the_output_when_reading_from_a_file()
19 | {
20 | byte[] bufferFromFile, bufferFromStream;
21 | GetTestBuffers(out bufferFromFile, out bufferFromStream);
22 |
23 | bufferFromStream.Length.ShouldBe(bufferFromFile.Length);
24 | }
25 |
26 | [Test]
27 | public void the_output_stream_matches_the_output_when_reading_from_a_file()
28 | {
29 | byte[] bufferFromFile, bufferFromStream;
30 | GetTestBuffers(out bufferFromFile, out bufferFromStream);
31 |
32 | for (var i = 0; i < bufferFromFile.Length; i++)
33 | {
34 | bufferFromStream[i].ShouldBe(bufferFromFile[i]);
35 | }
36 | }
37 |
38 | private void GetTestBuffers(out byte[] bufferFromFile, out byte[] bufferFromStream)
39 | {
40 | var data = new {Name = "Bar"};
41 | using (var streamFromFile = new MemoryStream())
42 | using (var streamFromStream = new MemoryStream())
43 | {
44 | _templateEngine.Process(_pathToTemplateDoc, streamFromFile, data);
45 | streamFromFile.Close();
46 |
47 | _templateEngine.Process(File.OpenRead(_pathToTemplateDoc), streamFromStream, data);
48 | streamFromStream.Close();
49 |
50 | bufferFromFile = streamFromFile.GetBuffer();
51 | bufferFromStream = streamFromStream.GetBuffer();
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/docxtemplateenginetest/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Newtonsoft.Json;
4 | using swxben.docxtemplateengine;
5 | using Newtonsoft.Json.Linq;
6 | using System.Dynamic;
7 | using System.Collections.Generic;
8 |
9 | namespace docxtemplateenginetest
10 | {
11 | class Program
12 | {
13 | static void Main(string[] args)
14 | {
15 | Console.WriteLine("docxtemplateenginetest, CC BY-SA 3.0, swxben.com");
16 |
17 | if (args.Count() != 3)
18 | {
19 | Console.WriteLine("Usage: docxtemplateenginetest \"\"");
20 | Console.WriteLine("Eg: docxtemplateenginetest input.docx output.docx { name: 'Software by Ben' }");
21 | return;
22 | }
23 |
24 | var source = args[0];
25 | var destination = args[1];
26 | var json = args[2];
27 |
28 | var data = JsonToDynamic((JToken)JsonConvert.DeserializeObject(json));
29 |
30 | var templateEngine = new DocXTemplateEngine();
31 |
32 | Console.WriteLine("Processing...");
33 |
34 | templateEngine.Process(source, destination, data);
35 |
36 | Console.WriteLine("Complete");
37 | Console.WriteLine();
38 | }
39 |
40 | static dynamic JsonToDynamic(JToken token)
41 | {
42 | if (token is JValue) return ((JValue)token).Value;
43 |
44 | if (token is JObject)
45 | {
46 | var expando = new ExpandoObject();
47 | foreach (var childToken in token.OfType())
48 | {
49 | ((IDictionary)expando).Add(childToken.Name, JsonToDynamic(childToken.Value));
50 | }
51 | return expando;
52 | }
53 |
54 | if (token is JArray)
55 | {
56 | var items = new List();
57 | foreach (var arrayItem in ((JArray)token))
58 | {
59 | items.Add(JsonToDynamic(arrayItem));
60 | }
61 | return items;
62 | }
63 |
64 | throw new ArgumentException(string.Format("Unknown token type {0}", token.GetType()), "token");
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/swxben.docxtemplateengine/swxben.docxtemplateengine.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}
9 | Library
10 | Properties
11 | swxben.docxtemplateengine
12 | swxben.docxtemplateengine
13 | v4.0
14 | 512
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 | ..\..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
61 |
--------------------------------------------------------------------------------
/src/docxtemplateenginetest/docxtemplateenginetest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}
9 | Exe
10 | Properties
11 | docxtemplateenginetest
12 | docxtemplateenginetest
13 | v4.0
14 | Client
15 | 512
16 |
17 |
18 | x86
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | x86
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 | ..\..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}
58 | swxben.docxtemplateengine
59 |
60 |
61 |
62 |
69 |
--------------------------------------------------------------------------------
/src/Tests/Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}
9 | Library
10 | Properties
11 | Tests
12 | Tests
13 | v4.0
14 | 512
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 | ..\..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll
36 |
37 |
38 | ..\..\packages\NUnit.2.6.2\lib\nunit.framework.dll
39 |
40 |
41 | ..\..\packages\Shouldly.1.1.1.1\lib\35\Shouldly.dll
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}
64 | swxben.docxtemplateengine
65 |
66 |
67 |
68 |
69 |
70 |
71 |
78 |
--------------------------------------------------------------------------------
/DocXTemplateEngine.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "swxben.docxtemplateengine", "src\swxben.docxtemplateengine\swxben.docxtemplateengine.csproj", "{F639F573-6CB2-4500-A5BD-C0C31E0A279D}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "src\Tests\Tests.csproj", "{55CA6250-4469-43F9-BA9E-C4E42F8959F5}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{A47A9431-0FEE-41EF-B3EA-FC5989AC7CBA}"
9 | ProjectSection(SolutionItems) = preProject
10 | .nuget\packages.config = .nuget\packages.config
11 | EndProjectSection
12 | EndProject
13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "docxtemplateenginetest", "src\docxtemplateenginetest\docxtemplateenginetest.csproj", "{6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}"
14 | EndProject
15 | Global
16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
17 | Debug|Any CPU = Debug|Any CPU
18 | Debug|Mixed Platforms = Debug|Mixed Platforms
19 | Debug|x86 = Debug|x86
20 | Release|Any CPU = Release|Any CPU
21 | Release|Mixed Platforms = Release|Mixed Platforms
22 | Release|x86 = Release|x86
23 | EndGlobalSection
24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
25 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}.Debug|Any CPU.Build.0 = Debug|Any CPU
27 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
28 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
29 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}.Debug|x86.ActiveCfg = Debug|Any CPU
30 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
33 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
34 | {F639F573-6CB2-4500-A5BD-C0C31E0A279D}.Release|x86.ActiveCfg = Release|Any CPU
35 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
38 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
39 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}.Debug|x86.ActiveCfg = Debug|Any CPU
40 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
43 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
44 | {55CA6250-4469-43F9-BA9E-C4E42F8959F5}.Release|x86.ActiveCfg = Release|Any CPU
45 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}.Debug|Any CPU.ActiveCfg = Debug|x86
46 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
47 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}.Debug|Mixed Platforms.Build.0 = Debug|x86
48 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}.Debug|x86.ActiveCfg = Debug|x86
49 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}.Debug|x86.Build.0 = Debug|x86
50 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}.Release|Any CPU.ActiveCfg = Release|x86
51 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}.Release|Mixed Platforms.ActiveCfg = Release|x86
52 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}.Release|Mixed Platforms.Build.0 = Release|x86
53 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}.Release|x86.ActiveCfg = Release|x86
54 | {6CC9B1B0-FF5E-48F3-B4E8-B0BDA46868CE}.Release|x86.Build.0 = Release|x86
55 | EndGlobalSection
56 | GlobalSection(SolutionProperties) = preSolution
57 | HideSolutionNode = FALSE
58 | EndGlobalSection
59 | EndGlobal
60 |
--------------------------------------------------------------------------------
/src/swxben.docxtemplateengine/DocXTemplateEngine.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Security.Cryptography;
6 | using System.Text;
7 | using ICSharpCode.SharpZipLib.Zip;
8 |
9 | namespace swxben.docxtemplateengine
10 | {
11 | public class DocXTemplateEngine : IDocXTemplateEngine
12 | {
13 | const string DocumentXmlPath = @"word/document.xml";
14 | public const string TOKEN_START = "«";
15 | public const string TOKEN_END = "»";
16 |
17 | public void Process(string source, Stream destination, object data)
18 | {
19 | var sourceData = File.ReadAllBytes(source);
20 | destination.Write(sourceData, 0, sourceData.Length);
21 | destination.Seek(0, SeekOrigin.Begin);
22 | using (var zipFile = new ZipFile(destination))
23 | {
24 | ProcessZip(data, zipFile);
25 | }
26 | }
27 |
28 | public void Process(string source, string destination, object data)
29 | {
30 | if (File.Exists(destination)) File.Delete(destination);
31 |
32 | File.Copy(source, destination);
33 |
34 | using (var zipFile = new ZipFile(destination))
35 | {
36 | ProcessZip(data, zipFile);
37 | }
38 | }
39 |
40 | public void Process(Stream sourceStream, Stream destinationStream, object data)
41 | {
42 | sourceStream.CopyTo(destinationStream);
43 | destinationStream.Seek(0, SeekOrigin.Begin);
44 |
45 | using (var zipFile = new ZipFile(destinationStream))
46 | {
47 | ProcessZip(data, zipFile);
48 | }
49 | }
50 |
51 | private static void ProcessZip(object data, ZipFile zipFile)
52 | {
53 | zipFile.BeginUpdate();
54 |
55 | var document = "";
56 | var entry = zipFile.GetEntry(DocumentXmlPath);
57 | if (entry == null)
58 | {
59 | throw new Exception(string.Format("Can't find {0} in template zip", DocumentXmlPath));
60 | }
61 |
62 | using (var s = zipFile.GetInputStream(entry))
63 | using (var reader = new StreamReader(s, Encoding.UTF8))
64 | {
65 | document = reader.ReadToEnd();
66 | }
67 |
68 | var newDocument = ParseTemplate(document, data);
69 |
70 | zipFile.Add(new StringStaticDataSource(newDocument), DocumentXmlPath, CompressionMethod.Deflated, true);
71 |
72 | zipFile.CommitUpdate();
73 |
74 | }
75 |
76 | class StringStaticDataSource : IStaticDataSource
77 | {
78 | readonly string _source;
79 |
80 | public StringStaticDataSource(string source)
81 | {
82 | _source = source;
83 | }
84 |
85 | public Stream GetSource()
86 | {
87 | return new MemoryStream(Encoding.UTF8.GetBytes(_source));
88 | }
89 | }
90 |
91 | public static string ParseTemplate(string document, object data)
92 | {
93 | document = data.GetType().GetFields().Aggregate(document,
94 | (current, field) => ReplaceTemplateField(current, field.Name, field.GetValue(data)));
95 | document = data.GetType().GetProperties().Aggregate(document,
96 | (current, property) => ReplaceTemplateField(current, property.Name, property.GetValue(data, null)));
97 |
98 | var dictionary = data as IDictionary;
99 |
100 | if (dictionary != null)
101 | {
102 | document = dictionary.Keys.Aggregate(document, (current, key) => ReplaceTemplateField(current, key, dictionary[key]));
103 | }
104 |
105 | return document;
106 | }
107 |
108 | public static string ReplaceTemplateField(string document, string fieldName, object fieldValue)
109 | {
110 | return document.Replace(TOKEN_START + fieldName + TOKEN_END, fieldValue == null ? string.Empty : fieldValue.ToString());
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | DocX Template Engine
2 | ====================
3 |
4 | A template engine for the .NET platform which takes a DOCX file and applies a data object to generate reports, do mail merges, etc. All without introducing a dependency on MS Word.
5 |
6 |
7 | ## Installation
8 |
9 | Install the engine via [NuGet](http://nuget.org/packages/swxben.docxtemplateengine), either in Visual Studio (right-click project, Manage NuGet Packages, search for docxtemplateengine) or via the package manager console using `Install-Package DocXTemplateEngine`.
10 |
11 |
12 | ## Usage
13 |
14 | In `template.docx` - use a field (Insert / Quick Parts / Field), _Field type_ is `MergeField` and enter the field or property name in _Field_:
15 |
16 | Brought to you by «Name»!
17 |
18 | In code:
19 |
20 | var templateEngine = new swxben.docxtemplateengine.DocXTemplateEngine();
21 | templateEngine.Process(
22 | source = "template.docx",
23 | destination = "dest.docx",
24 | data = new {
25 | Name = "SWXBEN"
26 | });
27 |
28 | `data` can be just about any data type. Fields and properties are iterated, and if it can be cast to `IDictionary