Mail Merge з регіонами

Ви можете створювати різні області у своєму шаблоні, щоб мати спеціальні області, які ви можете просто заповнити своїми даними. Використовуйте Mail Merge з регіонами, якщо ви хочете вставляти таблиці, рядки з повторюваними даними, щоб ваші документи динамічно розширювалися, вказавши ці області у вашому шаблоні.

Ви можете створювати вкладені (дочірні) області, а також об’єднувати області. Основна перевага використання цього типу полягає в динамічному збільшенні частин всередині документа. Більш детальну інформацію дивіться в наступній статті “вкладені Mail Merge області з областями”.

Як виконати Mail Merge з регіонами

Область Mail Merge - це певна частина документа, що має початкову та кінцеву точки. Обидві точки представлені у вигляді Mail Merge полів з певними іменами “TableStart:XXX” і “TableEnd:XXX”. Весь вміст, включений в область Mail Merge, буде автоматично повторюватися для кожного запису в джерелі даних.

Aspose.Words дозволяє виконувати Mail Merge з регіонами, використовуючи один із методів ExecuteWithRegions, який приймає IMailMergeDataSource спеціальне джерело даних.

Наступний приклад коду показує, як виконати Mail Merge з регіонами з бази даних sqlite за допомогою SQLiteCpp:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
void NestedMailMerge()
{
auto doc = MakeObject<Document>();
auto builder = MakeObject<DocumentBuilder>(doc);
builder->InsertField(u" MERGEFIELD TableStart:Customers");
builder->Write(u"Full name:\t");
builder->InsertField(u" MERGEFIELD FullName ");
builder->Write(u"\nAddress:\t");
builder->InsertField(u" MERGEFIELD Address ");
builder->Write(u"\nOrders:\n");
builder->InsertField(u" MERGEFIELD TableStart:Orders");
builder->Write(u"\tItem name:\t");
builder->InsertField(u" MERGEFIELD ItemName ");
builder->Write(u"\n\tQuantity:\t");
builder->InsertField(u" MERGEFIELD Quantity ");
builder->InsertParagraph();
builder->InsertField(u" MERGEFIELD TableEnd:Orders");
builder->InsertField(u" MERGEFIELD TableEnd:Customers");
SQLite::Database database((std::string)(DatabaseDir + u"customers.db3"));
// To be able to mail merge from your data source,
// it must be wrapped into an object that implements the IMailMergeDataSource interface.
auto customersDataSource = MakeObject<NestedMailMergeCustom::CustomersDataSource>(database);
doc->get_MailMerge()->ExecuteWithRegions(customersDataSource);
doc->Save(ArtifactsDir + u"NestedMailMergeCustom.CustomMailMerge.docx");
}
class OrdersDataSource : public MailMerging::IMailMergeDataSource
{
public:
OrdersDataSource(SQLite::Database& database, int32_t id)
: mQuery(database, "SELECT ItemName, Quantity FROM Orders WHERE CustomerId = ?")
{
mQuery.bind(1, id);
}
String get_TableName() override
{
return u"Orders";
}
bool GetValue(String fieldName, SharedPtr<Object>& fieldValue) override
{
if (fieldName == u"ItemName")
{
fieldValue = System::ObjectExt::Box<String>(String::FromUtf8(mQuery.getColumn(0).getString()));
return true;
}
if (fieldName == u"Quantity")
{
fieldValue = System::ObjectExt::Box<int32_t>(mQuery.getColumn(1).getInt());
return true;
}
fieldValue.reset();
return false;
}
bool MoveNext() override
{
return mQuery.executeStep();
}
SharedPtr<IMailMergeDataSource> GetChildDataSource(String tableName) override
{
return nullptr;
}
private:
SQLite::Statement mQuery;
};
class CustomersDataSource : public MailMerging::IMailMergeDataSource
{
public:
CustomersDataSource(SQLite::Database& database)
: mDatabase{ database }
, mQuery{ mDatabase, "SELECT * FROM Customers" }
{
}
String get_TableName() override
{
return u"Customers";
}
bool GetValue(String fieldName, SharedPtr<Object>& fieldValue) override
{
if (fieldName == u"FullName")
{
fieldValue = System::ObjectExt::Box<String>(String::FromUtf8(mQuery.getColumn(1).getString()));
return true;
}
if (fieldName == u"Address")
{
fieldValue = System::ObjectExt::Box<String>(String::FromUtf8(mQuery.getColumn(2).getString()));
return true;
}
fieldValue.reset();
return false;
}
bool MoveNext() override
{
return mQuery.executeStep();
}
SharedPtr<IMailMergeDataSource> GetChildDataSource(String tableName) override
{
if (tableName == u"Orders")
{
return MakeObject<OrdersDataSource>(mDatabase, mQuery.getColumn(0).getInt());
}
return nullptr;
}
private:
SQLite::Database& mDatabase;
SQLite::Statement mQuery;
};

Ви можете помітити різницю між документами перед виконанням Mail Merge з регіонами:

mail_merge_with_regions_template

І після виконання Mail Merge з регіонами:

mail_merge_with_regions_execute

Обмеження Mail Merge для регіонів

Є кілька важливих моментів, які необхідно враховувати при виконанні Mail Merge з регіонами:

  • Початкова точка TableStart:Orders і кінцева точка TableEnd:Orders повинні знаходитися в одному рядку або комірці. Наприклад, якщо область об’єднання починається в комірці таблиці, то область об’єднання повинна закінчуватися в тому ж рядку, що і перша комірка. Ім’я об’єднуваного поля має збігатися з ім’ям стовпця у вашому DataTable. Якщо ви не вказали зіставлені поля, Mail Merge з регіонами не буде успішним для будь-якого об’єднаного поля, ім’я Якого відрізняється від імені стовпця.
  • Aspose.Words для C++ підтримує лише джерела даних на основі IMailMergeDataSource та IMailMergeDataSourceRoot. На відміну від .NET та Java, C++ не має загальноприйнятої міжплатформенності API для роботи з базами даних (як ADODB, ODBC або JDBC). Щоб працювати з певним джерелом даних, вам потрібно реалізувати інтерфейс IMailMergeDataSource або IMailMergeDataSourceRoot.

Якщо одне з цих правил буде порушено, Ви отримаєте несподівані результати або може виникнути виняток.