Join word docx documents from a template and replace words

I Need to get the contents of a file word as the template, which contains the content of a text, and some of the handles to change any other data and the template create a one-of another word with the same content, however, replicate, and the appropriate values are changed.

As an example, I have in my document a text containing the following content:

Hello <NOME>! Welcome ... Your address <ENDERECO>.

And then I need to create another unique docx containing something like:

Hello Fulano 1! Welcome ... Your address ENDERECO 1.
Hello Fulano 2! Welcome ... Your address ENDERECO 2.
Hello Fulano 3! Welcome ... Your address ENDERECO 3.

Where each line would be at the beginning of a new page.

For this I am trying something (doing a Test) using the plugin DocX installed in project via NuGet.
another way to carry out the process will be welcome!

My example for presenting the problem:

public static void Main(string[] args)
{
    var dictionary = new Dictionary<string, string>();
    dictionary.Add("Fulano 1", "Endereco 1");
    dictionary.Add("Fulano 2", "Endereco 2");
    dictionary.Add("Fulano 3", "Endereco 3");

    var template = new FileStream("D:\\template.docx", FileMode.Open, FileAccess.Read);
    var docs = new List<DocX>();

    var x = 0;
    foreach (var item in dictionary)
    {
        x++;
        var doc = DocX.Create("D:\\temp_NUM.docx".Replace("NUM", x.ToString()));
        doc.ApplyTemplate(template, true);
        doc.ReplaceText("<NOME>", item.Key);
        doc.ReplaceText("<ENDERECO>", item.Value);
        doc.Save();
        docs.Add(doc);
    }

    var newDoc = DocX.Create("D:\\newDoc.docx");
    foreach (var doc in docs)
        newDoc.InsertDocument(doc);

    newDoc.Save();
}

Although you are using a simple data source, built with a Dictionary, the data source will be from the system database where this is to be implemented.

The files temp_1.docx, temp_2.docx and temp_3.docx are created and the content appears correctly.
But in line newDoc.InsertDocument(doc); in:

foreach (var doc in docs)
    newDoc.InsertDocument(doc);

I get the following error: the sequence does not contain elements . And with this the "merge" is not done.

How can I solve the problem?

Author: carla, 2014-06-01

4 answers

I would use the office API made available by Microsoft itself, and then:

    wordApp = New Microsoft.Office.Interop.Word.Application;
    oDoc = New Microsoft.Office.Interop.Word.Document;

    oDoc = wordApp.Documents.Open("c:\....");

Take a look at the Microsoft website, you will find everything you need about it.

With this tool you can from adding macros (VB) to doing merge.

Very, very long ago I made a DLL for a personal project ( http://pastebin.com/kDZVhpiz ) that can help you.. do not judge the code kk I was 15 years old yet, but it can serve you as a guide.

 2
Author: brhvitor6, 2014-06-04 14:34:40

There is a discussion on the developer page in which they explain that this method is not good and that it should not be used.

I would leave for another package . This one seemed very promising to me: http://www.nuget.org/packages/TemplateEngine.Docx

 2
Author: Leonel Sanches da Silva, 2014-06-04 17:17:57

Example using the library DocX.

static void Main(string[] args)
{
    string templatePath = @"D:\\template.docx";
    string newFile = @"D:\\newDoc.docx";

    var template = new FileStream(templatePath, FileMode.Open, FileAccess.Read);

    string[] aNomes = { "Fulano1", "Fulano2", "Fulano3" };
    string[] aLocais = { "Endereco1", "Endereco2", "Endereco3" };

    using (DocX doc = DocX.Create(newFile))
    {
        doc.ApplyTemplate(template, true);
        int items = aNomes.Length;
        int x = 0;
        string modelo = "";

        while (items > x)
        {
            Paragraph par = doc.InsertParagraph();
            par.AppendLine(modelo);
            par.InsertPageBreakAfterSelf();

            foreach (var p in doc.Paragraphs)
            {
                if (p.Text.Contains("<NOME>") && (p.Text.Contains("<ENDERECO>")))
                {
                    modelo = p.Text;

                    p.ReplaceText("<NOME>", aNomes[x]);
                    p.ReplaceText("<ENDERECO>", aLocais[x]);
                    x++;
                 }

             }                   
          }
          doc.Save();
      }

      Console.WriteLine("Pressione alguma tecla para sair...");
      Console.ReadKey();
}

File structure template.docx :

--> Página 1:
    Olá <NOME>!  Seja bem vindo... Seu endereço <ENDERECO>.

The newdoc file.docx should look like this:

--> Página 1:
    Olá Fulano1! Seja bem vindo ... Seu endereço Endereco1
--> Página 2:
    Olá Fulano2! Seja bem vindo ... Seu endereço Endereco2
--> Página 3:
    Olá Fulano3! Seja bem vindo ... Seu endereço Endereco3

I believe this should work the way you expect.

 2
Author: stderr, 2017-09-11 02:11:20

This is a simple way I managed to solve the problem:

using Novacode;
using System.Collections.Generic;
using Word = Microsoft.Office.Interop.Word;   
public class Program
{
    public static void Main(string[] args)
    {
        var docList = new List<string>();
        var templatePath = @"D:\template.docx";

        var fakeDAO = new Dictionary<string, string>();
        fakeDAO.Add("Fulano 1", "Endereco 1");
        fakeDAO.Add("Fulano 2", "Endereco 2");
        fakeDAO.Add("Fulano 3", "Endereco 3");

        var x = 0;
        foreach (var item in fakeDAO) {
            x++;
            var docFilePath = @"D:\temp_NUM.docx".Replace("NUM", x.ToString());
            var doc = DocX.Create(docFilePath);
            doc.ApplyTemplate(templatePath);

            doc.ReplaceText("<NOME>", item.Key);
            doc.ReplaceText("<ENDERECO>", item.Value);

            doc.Save();
            docList.Add(docFilePath);
        }
        Merge.DoMerge(@"D:\newFile.docx", docList);
    }
}

A Class Go:

...
public static class Merge
{
    public static void DoMerge(string newFilePath, List<string> docList)
    {
        object sectionBreak = Word.WdBreakType.wdSectionBreakNextPage;
        Word.Application app = new Word.Application();
        try {
            var doc = app.Documents.Add();
            var selection = app.Selection;
            var x = 0;
            foreach (var file in docList) {
                selection.InsertFile(file);
                x++;
                if (x < docList.Count)
                    selection.InsertBreak(ref sectionBreak);
            }
            doc.SaveAs(newFilePath);
        }
        finally {
            app.Quit();
        }
    }
}
 1
Author: , 2014-06-08 15:27:06