Insert documents from database in another by mail merge

Hello, I want to insert documents from database to another documents by mail merge.

I’ve find this code in the forum and I’m looking for it
But how can I use this function to build the document report.

private void HandleMergeFieldEvent(object sender, MergeFieldEventArgs e)
{
    //This creates a new document builder for every event.
    //Although DocumentBuilder is a lightweight object, it still
    //might be better to cache it in a field of this class.
    DocumentBuilder builder = new DocumentBuilder(e.Document);
    if (e.FieldName == "Description")
    {
        builder.MoveToMergeField(e.FieldName);
        string fieldValue = e.FieldValue.ToString();
        if (fieldValue.IndexOf("Blue") != -1)
            builder.Font.Color = System.Drawing.Color.Blue;
        else
            builder.Font.Color = System.Drawing.Color.Red;
        //Write the text using the builder, don’t let the mail merge engine to insert text too.
        builder.Write(fieldValue);
        e.Text = "";
    }
}

Hello,
You should use a bit different code if you want to insert documents from database. Something like this:

void DoMerge()
{
    Document doc = new Document("template.doc");
    doc.MailMerge.MergeField +=new MergeFieldEventHandler(MailMerge_MergeField);
    doc.MailMerge.Execute(new string[] {"FieldName1", "FieldName2" }, new object[] {0, 0});
    doc.Save("result.doc");
}


void AppendDoc(Document dstDoc, Document srcDoc)
{
    while (srcDoc.Sections.Count 0)
{
        Section section = srcDoc.Sections[0];
        srcDoc.Sections.RemoveAt(0);
        dstDoc.Sections.Add(section);
    }
}

void MailMerge_MergeField(object sender, MergeFieldEventArgs e)
{
    Document doc = LoadDocumentFromBLOBField(e.FieldName);
    AppendDoc(e.Document, doc);
    e.Text = String.Empty;
}

You have to write the LoadDocumentFromBLOBField(string) method that loads appropriate document from the database depending on the merge field name.

Another way you can use to accomplish your task is using the DocumentBuilder.MoveToMergeField method.

You can obtain some more information here:
INFO: How to combine documents

Thank you for your reply,
The differend is my documents is not stored on a blob fields but I’ve a single document stored in disk server.
I read this document, extract the appropriate section and insert it to my report document.

Like explain in attached file

So simply replace the LoadDocumentFromBlobField method with a code that extracts the section from your document. The details depend on the way you perform the extraction.

Thank you,
The way I extract section is:
I read document, if I find —xxxx— then I extract the text between [ ].

example
—Code—
[texte]

But I don’t know how to extract section. Do you have any code or example.

Regards.

Do you really need to use the TextePrepa field? I think it’s redundant. You can populate the Code fields with the extracted sections. By the way, I guess you could simply extract plain text enclosed in [ ] since there is no need to copy multiple sections:

void DoMerge(DataTable table)
{
    Document doc = new Document("template.doc");
    doc.MailMerge.MergeField += new MergeFieldEventHandler(MailMerge_MergeField);
    doc.MailMerge.ExecuteWithRegions(table);
}

void MailMerge_MergeField(object sender, MergeFieldEventArgs e)
{
    e.Text = ExtractPlainText(e.FieldValue);
}

string ExtractPlainText(string sectionName)
{
    // Here we search the string —sectionName— in the second document
    // and return the text located between square brackets
}

Thank you, No I don’t need TextePrepa field but I need only code to extract section between Brackets.

Thank you for your help.

Hello,
We need help,

What’s wrong?

How can we code this, I’m a beginner in aspose.word

// Here we search the string —sectionName— in the second document
// and return the text located between square brackets

Here is a working console application that shows how you can solve your problem. The only thing you should change is to pass your own DataTable object to the DoMerge method.

The main disadvantage of the application is loosing text formatting when inserting it into the bookmarks. If you still need to keep the formatting, I think you should place the source sections into separate documents instead of keeping it in the same doc. It will significantly simplify the code. Please tell me if it suits you and I’ll update the sample.

using System;
using System.Data;
using System.Text.RegularExpressions;
using Aspose.Word;
namespace ConsoleApplication
{
    class Class1
    {
        static Document docWithSections;

        [STAThread]
        static void Main(string[] args)
        {
            docWithSections = new Document("sections.doc");
            DataTable table = new DataTable("Test");
            table.Columns.Add("Code", typeof(string));
            table.Rows.Add(new object[] { "PREPLAVAGEHP" });
            table.Rows.Add(new object[] { "PREPREPRISEMACON" });
            DoMerge(table);
        }

        static void DoMerge(DataTable table)
        {
            Document doc = new Document("template.doc");
            doc.MailMerge.MergeField +=
            new MergeFieldEventHandler(MailMerge_MergeField);
            doc.MailMerge.ExecuteWithRegions(table);
            doc.Save("result.doc");
        }

        static void MailMerge_MergeField(object sender, MergeFieldEventArgs e)
        {
            e.Text = ExtractPlainText(e.FieldValue.ToString());
        }

        static string ExtractPlainText(string sectionName)
        {
            string input = docWithSections.Range.Text;
            string pattern = @"-+\s*" + sectionName + @"\s*-+.*[(?.+)]";
            Match match = Regex.Match(input, pattern, RegexOptions.Singleline);
            if (match.Success)
                return match.Result("${text}");
            return null;
        }
    }
}

Thank you, yes it suits me well,
I can use separate source documents to insert in my report doc, because I want to keep format text.

Regards

Okay. So create the separate documents, put the sections there and give them names of the sections, e.g. PREPLAVAGEHP.doc. We’re back to the sections copying in order to preserve the formatting. Here’s the updated application:

using System;
using System.Data;
using System.IO;
using Aspose.Word;

namespace ConsoleApplication
{
    class Class1
    {
        [STAThread]
        static void Main(string[] args)
        {
            DataTable table = new DataTable("Test");
            table.Columns.Add("Code", typeof(string));
            table.Rows.Add(new object[] { "PREPLAVAGEHP" });
            table.Rows.Add(new object[] { "PREPREPRISEMACON" });
            DoMerge(table);
        }

        static void DoMerge(DataTable table)
        {
            Document doc = new Document("template.doc");
            doc.MailMerge.MergeField += new MergeFieldEventHandler(MailMerge_MergeField);
            doc.MailMerge.ExecuteWithRegions(table);
            doc.Save("result.doc");
        }

        static void AppendDoc(Document dstDoc, Document srcDoc)
        {
            while (srcDoc.Sections.Count > 0)
            {
                Section section = srcDoc.Sections[0];
                srcDoc.Sections.RemoveAt(0);
                dstDoc.Sections.Add(section);
            }
        }

        static void MailMerge_MergeField(object sender, MergeFieldEventArgs e)
        {
            string fileName = e.FieldValue.ToString() + ".doc";
            if (!File.Exists(fileName))
                return;
            Document doc = new Document(fileName);
            AppendDoc(e.Document, doc);
            e.Text = String.Empty;
        }
    }
}

Thanks, how have you defined your mail field in template.doc.

Me I define mergefield and “TableStart:Test” “Code” “TableEnd:Test” but sections in PREPBETREVORGCONS.doc and PREPLAVAGEHP.doc are not inserted.
But it only insert this lines

PREPBETREVORGCONS

PREPLAVAGEHP in template.doc

Why are you add this two rows :

table.Rows.Add(new object[] {"PREPBETREVORGCONS"});
table.Rows.Add(new object[] {"PREPLAVAGEHP"});

I simulate your data table, you have to pass your own one. And don’t forget to put the docs into the bin/Debug subdirectory or specify the path when constructing the file name of the document being processed.

Thanks,
I think that it is because I’ve cathed the line doc.Save(“result.doc”);
But if I don’t catch this line, I have error Access Denied pointed to this line Why ?

Check your configuration/permissions. The application should work correctly.

You need to specify path where you save the file, otherwise you don’t know where it gets saved, maybe in System32 where you probably don’t have permissions.

I have a problem. I need to insert a word document into another word document and I am using pretty much the same method you specified:

Section sourceDocSection = doc.Sections[ 0 ];
doc.Sections.RemoveAt ( 0 );
reportDocument.Sections.Add ( sourceDocSection );

But I receive this Exception:

“The newChild was created from a different document than the one that created this node.”

What am I doing wrong? Thanks!

Hi,

This happens because you should import a section (and any node actually) to the destination document using Document.InsertNode. We have a number of code samples in Aspose.Words documentation that show how to perform the insertion properly, please take a look:
https://docs.aspose.com/words/net/insert-and-append-documents/