Insert Checkboxes, Text Input, or Images

The merge engine takes a document as input, looks for MERGEFIELD fields in it, and replaces them with the data obtained from the data source. Typically, plain text and HTML are inserted, but Aspose.Words users can also generate a document that handles more unusual scenarios for Mail Merge fields.

Powerful Aspose.Words functionality allows you to extend the Mail Merge process:

  • insert checkboxes and text input form fields into the document during a mail merge
  • insert images from any custom storage (files, BLOB fields, etc.)

Insert Checkboxes and Text Input during Mail Merge

Sometimes it is necessary to perform a Mail Merge operation so that not text is substituted in the merge field, but a checkbox or text input field. Even though this is not the most common scenario, it is very handy for some tasks.

The following screenshot of a Word document shows a template with merge fields:

insert-checkboxes-or-images-mail-merge-aspose-words

This screenshot of the Word document below shows the already generated document:

insert-checkboxes-html-or-images-mail-merge-aspose-words

The following code example shows how to insert checkboxes and input text fields into a document during a mail merge:

//For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
auto doc = MakeObject<Document>(MyDir + u"Mail merge destinations - Fax.docx");
// Setup mail merge event handler to do the custom work.
doc->get_MailMerge()->set_FieldMergingCallback(MakeObject<WorkingWithFields_::HandleMergeField>());
// Trim trailing and leading whitespaces mail merge values.
doc->get_MailMerge()->set_TrimWhitespaces(false);
ArrayPtr<String> fieldNames =
MakeArray<String>({u"RecipientName", u"SenderName", u"FaxNumber", u"PhoneNumber", u"Subject", u"Body", u"Urgent", u"ForReview", u"PleaseComment"});
ArrayPtr<SharedPtr<System::Object>> fieldValues = MakeArray<SharedPtr<System::Object>>(
{System::ObjectExt::Box<String>(u"Josh"), System::ObjectExt::Box<String>(u"Jenny"), System::ObjectExt::Box<String>(u"123456789"),
System::ObjectExt::Box<String>(u""), System::ObjectExt::Box<String>(u"Hello"), System::ObjectExt::Box<String>(u"<b>HTML Body Test message 1</b>"),
System::ObjectExt::Box<bool>(true), System::ObjectExt::Box<bool>(false), System::ObjectExt::Box<bool>(true)});
doc->get_MailMerge()->Execute(fieldNames, fieldValues);
doc->Save(ArtifactsDir + u"WorkingWithFields.MailMergeFormFields.docx");
//For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
class HandleMergeField : public IFieldMergingCallback
{
private:
SharedPtr<DocumentBuilder> mBuilder;
/// <summary>
/// This handler is called for every mail merge field found in the document,
/// for every record found in the data source.
/// </summary>
void FieldMerging(SharedPtr<FieldMergingArgs> e) override
{
if (mBuilder == nullptr)
{
mBuilder = MakeObject<DocumentBuilder>(e->get_Document());
}
// We decided that we want all boolean values to be output as check box form fields.
if (System::ObjectExt::Is<bool>(e->get_FieldValue()))
{
// Move the "cursor" to the current merge field.
mBuilder->MoveToMergeField(e->get_FieldName());
String checkBoxName = String::Format(u"{0}{1}", e->get_FieldName(), e->get_RecordIndex());
mBuilder->InsertCheckBox(checkBoxName, System::ObjectExt::Unbox<bool>(e->get_FieldValue()), 0);
return;
}
if (e->get_FieldName() == u"Body")
{
mBuilder->MoveToMergeField(e->get_FieldName());
mBuilder->InsertHtml(System::ObjectExt::Unbox<String>(e->get_FieldValue()));
}
else if (e->get_FieldName() == u"Subject")
{
mBuilder->MoveToMergeField(e->get_FieldName());
String textInputName = String::Format(u"{0}{1}", e->get_FieldName(), e->get_RecordIndex());
mBuilder->InsertTextInput(textInputName, TextFormFieldType::Regular, u"", System::ObjectExt::Unbox<String>(e->get_FieldValue()), 0);
}
}
void ImageFieldMerging(SharedPtr<ImageFieldMergingArgs> args) override
{
args->set_ImageFileName(u"Image.png");
args->get_ImageWidth()->set_Value(200);
args->set_ImageHeight(MakeObject<MergeFieldImageDimension>(200, MergeFieldImageDimensionUnit::Percent));
}
};

Insert Images during Mail Merge

When performing a Mail Merge operation, you can insert images from the database into the document using special image Mail Merge fields. The image Mail Merge field is a merge field named Image:MyFieldName.

Insert Images from a Database

During a mail merge, when an image Mail Merge field is encountered in a document, the FieldMergingCallback event is fired. You can respond to this event to return a filename, stream, or image object to the Mail Merge engine so it can be inserted into the document.

The following code example shows how to insert images stored in a database BLOB field into a report:

//For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
auto doc = MakeObject<Document>();
auto builder = MakeObject<DocumentBuilder>(doc);
// MERGEFIELDs with "Image:" tags will receive an image during a mail merge.
// The string after the colon in the "Image:" tag corresponds to a column name
// in the data source whose cells contain URIs of image files.
builder->InsertField(u"MERGEFIELD Image:logo_FromWeb ");
builder->InsertField(u"MERGEFIELD Image:logo_FromFileSystem ");
// Create a data source that contains URIs of images that we will merge.
// A URI can be a web URL that points to an image, or a local file system filename of an image file.
ArrayPtr<String> columns = MakeArray<String>({u"logo_FromWeb", u"logo_FromFileSystem"});
ArrayPtr<SharedPtr<System::Object>> URIs =
MakeArray<SharedPtr<System::Object>>({System::ObjectExt::Box<String>(ImageUrl), System::ObjectExt::Box<String>(ImageDir + u"Logo.jpg")});
// Execute a mail merge on a data source with one row.
doc->get_MailMerge()->Execute(columns, URIs);
doc->Save(ArtifactsDir + u"MailMergeEvent.ImageFromUrl.docx");

Set Image Properties during Mail Merge

While merging an image merge field, you may sometimes need to control various image properties, such as WrapType.

Currently, using ImageFieldMergingArgs you can only set image width or height properties, respectively. To overcome this issue, Aspose.Words provides the Shape property, which facilitates to get full control over the inserted image or any other shape.

The following code example shows how to set various image properties:

//For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
auto doc = MakeObject<Document>();
auto builder = MakeObject<DocumentBuilder>(doc);
builder->Writeln(u"{{#foreach example}}");
builder->Writeln(u"{{Image(126pt;126pt):stempel}}");
builder->Writeln(u"{{/foreach example}}");
doc->get_MailMerge()->set_UseNonMergeFields(true);
doc->get_MailMerge()->set_TrimWhitespaces(true);
doc->get_MailMerge()->set_UseWholeParagraphAsRegion(false);
doc->get_MailMerge()->set_CleanupOptions(MailMergeCleanupOptions::RemoveEmptyTableRows | MailMergeCleanupOptions::RemoveContainingFields |
MailMergeCleanupOptions::RemoveUnusedRegions | MailMergeCleanupOptions::RemoveUnusedFields);
doc->get_MailMerge()->set_FieldMergingCallback(MakeObject<WorkingWithFields_::ImageFieldMergingHandler>());
doc->get_MailMerge()->ExecuteWithRegions(MakeObject<WorkingWithFields_::DataSourceRoot>());
doc->Save(ArtifactsDir + u"WorkingWithFields.MailMergeImageField.docx");
//For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
class ImageFieldMergingHandler : public IFieldMergingCallback
{
private:
void FieldMerging(SharedPtr<FieldMergingArgs> args) override
{
ASPOSE_UNUSED(args);
// Implementation is not required.
}
void ImageFieldMerging(SharedPtr<ImageFieldMergingArgs> args) override
{
auto shape = MakeObject<Shape>(args->get_Document(), ShapeType::Image);
shape->set_Width(126);
shape->set_Height(126);
shape->set_WrapType(WrapType::Square);
shape->get_ImageData()->SetImage(MyDir + u"Mail merge image.png");
args->set_Shape(shape);
}
};
//For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
class DataSourceRoot : public IMailMergeDataSourceRoot
{
private:
class DataSource : public IMailMergeDataSource
{
public:
bool MoveNext() override
{
bool result = next;
next = false;
return result;
}
SharedPtr<IMailMergeDataSource> GetChildDataSource(String s) override
{
ASPOSE_UNUSED(s);
return nullptr;
}
bool GetValue(String fieldName, SharedPtr<System::Object>& fieldValue) override
{
ASPOSE_UNUSED(fieldName);
fieldValue.reset();
return false;
}
DataSource() : next(true)
{
}
private:
bool next;
String get_TableName() override
{
return TableName();
}
String TableName()
{
return u"example";
}
};
public:
SharedPtr<IMailMergeDataSource> GetDataSource(String s) override
{
ASPOSE_UNUSED(s);
return MakeObject<WorkingWithFields_::DataSourceRoot::DataSource>();
}
};