Merge word docx documents from a template and replace words

12

I need to get the contents of a docx file like template , which contains as text content and some identifiers to be changed with other data , and from that template create a single docx with the same content but replicated and with changed values.

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

  

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

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

  

Hello Fulano 1 ! You're welcome ... Your address ENDERECO 1 .   Hello Fulano 2 ! You're 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'm trying something (MAKING A TEST) using the DocX

My example to show 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();
}

While using a simple data source, built with a Dictionary , the data source will be from the system database where it should be deployed.

The temp_1.docx , temp_2.docx and temp_3.docx files 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 string contains no elements . And with that the "merge" is not done.

How do I resolve the issue?

    
asked by anonymous 01.06.2014 / 21:33

4 answers

2

I would use the Office API provided by Microsoft itself, and then:

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

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

Read on Microsoft's website, you'll find everything you need about it.

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

Long, long ago I made a dll for a personal project ( link ) that can help you .. do not judge the code kk I was 15 yet, but it can serve as a guide.

    
04.06.2014 / 16:12
2

There is a discussion on the developer page explaining that this method is not good and should not be used.

I would leave for another package . This one seemed to me very promising: link

    
04.06.2014 / 19:17
2

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();
}

Template structure template.docx :

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

The newDoc.docx file should look similar to 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.

    
07.06.2014 / 00:06
1

This is a simple way I've been able 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);
    }
}

The Merge class:

...
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();
        }
    }
}
    
08.06.2014 / 17:27