В этой статье я покажу вам, как выполнять слияние почты MS Word с помощью C# или VB.NET без MS Word или Office Interop. Aspose.Words for .NET — это многофункциональный и мощный API Word, который предоставляет все базовые, а также расширенные функции MS Word Mail Merge. Он позволяет создавать письма, конверты, отчеты, счета и другие типы документов в Windows Forms, веб-приложениях ASP.NET или любом приложении .NET/.NET Core.
Эта статья, посвященная основным функциям нашего .NET Mail Merge API, состоит из следующих разделов:
- Что такое слияние почты?
- Источники данных для слияния
- Подготовка шаблона для слияния
- .NET Mail Merge API — установка
- Выполнение слияния почты в документе Word с помощью C#
- Слияние почты с использованием источника данных XML
- Пользовательское форматирование полей слияния
- Слияние почты с регионами
- Вложенные области слияния почты
Что такое слияние почты?
Mail Merge — это способ автоматической генерации отчетов, писем, конвертов, счетов и других типов документов. Mail Merge в MS Word позволяет создать шаблон документа, содержащий поля слияния, а затем заполнить эти поля, используя записи в источнике данных. Чтобы понять Mail Merge, предположим, что вам нужно отправить письмо десяти разным людям, и нужно обновить только поля имени и адреса. В таком случае просто создайте шаблон письма, а затем динамически сгенерируйте письма, заполнив поля слияния имени и адреса с помощью источника данных.
Источники данных для слияния
Данные для слияния могут быть получены из любого источника данных, например XML, JSON или базы данных. Что касается Aspose.Words for .NET, вы можете использовать любой источник данных, поддерживаемый ADO.NET. Данные можно загрузить в DataSet, DataTable, DataView или массив значений.
Подготовка шаблона для слияния
Шаблон слияния — это документ, содержащий поля слияния. Затем эти поля заполняются данными из источника данных при выполнении слияния. Документ-шаблон не обязательно должен быть в формате шаблона, это может быть документ в формате DOC/DOCX. Вот как вы можете подготовить шаблон для слияния.
- Откройте свой документ или создайте новый в MS Word.
- Поместите курсор туда, где вы хотите добавить поле слияния.
- В меню «Вставка» выберите «Поле».
- В списке Имена полей выберите MergeField.
- Введите имя поля слияния в поле Имя поля и нажмите OK.
- Сохраните документ.
Ниже приведен скриншот документа пример шаблона.
.NET Mail Merge API — установка
Aspose.Words для .NET можно загрузить или установить следующими способами:
Выполнение слияния почты в документе Word с помощью C#
Когда у вас есть готовый шаблон, вы можете выполнить слияние для создания документов. Ниже приведены шаги для выполнения слияния в вышеупомянутом шаблоне.
- Загрузите документ шаблона, используя класс Document.
- Установите необходимые параметры слияния, например Document.MailMerge.TrimWhitespaces.
- Выполните слияние с помощью метода Document.MailMerge.Execute() и передайте источник данных в качестве параметра.
- Сохраните сгенерированный документ методом Document.Save(String).
В следующем примере кода показано, как выполнить слияние MS Word с использованием массива значений в C#.
// Полные примеры и файлы данных см. на странице https://github.com/aspose-words/Aspose.Words-for-.NET.
// Путь к каталогу документов.
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting();
// Откройте существующий документ.
Document doc = new Document(dataDir + "MailMerge.ExecuteArray.doc");
// Обрезать конечные и начальные пробелы в значениях слияния почты
doc.MailMerge.TrimWhitespaces = false;
// Заполните поля документа данными пользователя.
doc.MailMerge.Execute(
new string[] { "FullName", "Company", "Address", "Address2", "City" },
new object[] { "James Bond", "MI5 Headquarters", "Milbank", "", "London" });
dataDir = dataDir + "MailMerge.ExecuteArray_out.doc";
// Отправьте документ в формате Word в клиентский браузер с возможностью сохранения на диск или открытия в текущем браузере.
doc.Save(dataDir);
Документ Word после слияния почты
Выполнение слияния почты с использованием источника данных XML в C#
Файлы XML широко используются для хранения, а также импорта/экспорта данных. Aspose.Words для .NET также поддерживает XML в качестве источника данных для слияния. Просто прочитайте XML в объект DataSet и выполните слияние. Ниже приведен пример XML-файла, который мы собираемся использовать.
<customers>
<customer Name="John Ben Jan" ID="1" Domain="History" City="Boston"/>
<customer Name="Lisa Lane" ID="2" Domain="Chemistry" City="LA"/>
<customer Name="Dagomir Zits" ID="3" Domain="Heraldry" City="Milwaukee"/>
<customer Name="Sara Careira Santy" ID="4" Domain="IT" City="Miami"/>
</customers>
Следующий пример кода извлекает данные из источника данных XML и выполняет слияние с помощью C#.
// Полные примеры и файлы данных см. на странице https://github.com/aspose-words/Aspose.Words-for-.NET.
// Путь к каталогу документов.
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting();
// Создайте набор данных и прочитайте XML.
DataSet customersDs = new DataSet();
customersDs.ReadXml(dataDir + "Customers.xml");
string fileName = "TestFile XML.doc";
// Откройте шаблон документа.
Document doc = new Document(dataDir + fileName);
// Выполните слияние почты, чтобы заполнить шаблон данными из XML с помощью DataTable.
doc.MailMerge.Execute(customersDs.Tables["Customer"]);
dataDir = dataDir + RunExamples.GetOutputFilePath(fileName);
// Сохраните выходной документ.
doc.Save(dataDir);
Ниже приведено почтовое слияние шаблон, которое будет заполнено XML-данными.
Ниже приведена страница 1 результирующего документа Word, который мы получаем после выполнения слияния.
Пользовательское форматирование полей слияния
Aspose.Words для .NET дает вам больший контроль над слиянием во время выполнения. Свойство MailMerge.FieldMergingCallback позволяет настроить слияние почты при обнаружении любого поля слияния. MailMerge.FieldMergingCallback принимает класс, реализующий методы IFieldMergingCallback.FieldMerging и IFieldMergingCallback.ImageFieldMerging.
В следующем примере кода показано, как настроить операцию слияния и применить форматирование к ячейкам в этом шаблоне.
// Полные примеры и файлы данных см. на странице https://github.com/aspose-words/Aspose.Words-for-.NET.
// Путь к каталогу документов.
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting();
Document doc = new Document(dataDir + "MailMerge.AlternatingRows.doc");
// Добавьте обработчик события MergeField.
doc.MailMerge.FieldMergingCallback = new HandleMergeFieldAlternatingRows();
// Выполните слияние почты с регионами.
DataTable dataTable = GetSuppliersDataTable();
doc.MailMerge.ExecuteWithRegions(dataTable);
dataDir = dataDir + "MailMerge.AlternatingRows_out.doc";
doc.Save(dataDir);
Ниже приведена реализация класса HandleMergeFieldAlternatingRows.
// Полные примеры и файлы данных см. на странице https://github.com/aspose-words/Aspose.Words-for-.NET.
private class HandleMergeFieldAlternatingRows : IFieldMergingCallback
{
///<summary>
/// Вызывается для каждого поля слияния, встречающегося в документе.
/// Мы можем либо вернуть какие-то данные в движок слияния, либо что-то сделать
/// Остальное с документом. В этом случае мы изменяем форматирование ячейки.
///</summary>
void IFieldMergingCallback.FieldMerging(FieldMergingArgs e)
{
if (mBuilder == null)
mBuilder = new DocumentBuilder(e.Document);
// Таким образом мы ловим начало нового ряда.
if (e.FieldName.Equals("CompanyName"))
{
// Выберите цвет в зависимости от того, является ли номер строки четным или нечетным.
Color rowColor;
if (IsOdd(mRowIdx))
rowColor = Color.FromArgb(213, 227, 235);
else
rowColor = Color.FromArgb(242, 242, 242);
// На данный момент нет возможности установить свойства ячейки для всей строки,
// Таким образом, мы должны перебрать все ячейки в строке.
for (int colIdx = 0; colIdx < 4; colIdx++)
{
mBuilder.MoveToCell(0, mRowIdx, colIdx, 0);
mBuilder.CellFormat.Shading.BackgroundPatternColor = rowColor;
}
mRowIdx++;
}
}
void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs args)
{
// Ничего не делать.
}
private DocumentBuilder mBuilder;
private int mRowIdx;
}
///<summary>
/// Возвращает true, если значение нечетное; false, если значение четное.
///</summary>
private static bool IsOdd(int value)
{
// Код немного сложный, но в остальном автоматическое преобразование в VB не работает.
return ((value / 2) * 2).Equals(value);
}
///<summary>
/// Создайте DataTable и заполните его данными.
/// В реальной жизни эта DataTable должна быть заполнена из базы данных.
///</summary>
private static DataTable GetSuppliersDataTable()
{
DataTable dataTable = new DataTable("Suppliers");
dataTable.Columns.Add("CompanyName");
dataTable.Columns.Add("ContactName");
for (int i = 0; i < 10; i++)
{
DataRow datarow = dataTable.NewRow();
dataTable.Rows.Add(datarow);
datarow[0] = "Company " + i.ToString();
datarow[1] = "Contact " + i.ToString();
}
return dataTable;
}
Слияние почты с регионами с использованием C#
Может быть случай, когда вам нужно заполнить и повторить определенную область в документе Word. Для такого случая вы можете использовать Mail Merge с регионами. Чтобы создать регион, вам нужно указать начало и конец региона, после чего Mail Megre будет повторять этот регион для каждой записи в источнике данных. Например, следующий шаблон содержит две области, Orders и OrderDetails с полями слияния «TableStart:Orders», «TableEnd:Orders» и «TableStart:OrderDetails», «TableEnd:OrderDetails» соответственно.
Ниже приведен пример кода, который выполняет Mail Megre в регионах для вышеупомянутого template.
// Полные примеры и файлы данных см. на странице https://github.com/aspose-words/Aspose.Words-for-.NET.
// Путь к каталогу документов.
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting();
string fileName = "MailMerge.ExecuteWithRegions.doc";
Document doc = new Document(dataDir + fileName);
// Используйте DataTable в качестве источника данных.
int orderId = 10444;
DataTable orderTable = GetTestOrder(orderId);
doc.MailMerge.ExecuteWithRegions(orderTable);
// Вместо использования DataTable вы можете создать DataView для пользовательской сортировки или фильтра, а затем слить почту.
DataView orderDetailsView = new DataView(GetTestOrderDetails(orderId));
orderDetailsView.Sort = "ExtendedPrice DESC";
// Выполните операцию слияния почты.
doc.MailMerge.ExecuteWithRegions(orderDetailsView);
// Сохраните объединенный документ.
dataDir = dataDir + RunExamples.GetOutputFilePath(fileName);
doc.Save(dataDir);
Ниже приведены методы чтения данных из базы данных.
// Полные примеры и файлы данных см. на странице https://github.com/aspose-words/Aspose.Words-for-.NET.
private static DataTable GetTestOrder(int orderId)
{
DataTable table = ExecuteDataTable(string.Format(
"SELECT * FROM AsposeWordOrders WHERE OrderId = {0}", orderId));
table.TableName = "Orders";
return table;
}
private static DataTable GetTestOrderDetails(int orderId)
{
DataTable table = ExecuteDataTable(string.Format(
"SELECT * FROM AsposeWordOrderDetails WHERE OrderId = {0} ORDER BY ProductID", orderId));
table.TableName = "OrderDetails";
return table;
}
///<summary>
/// Вспомогательная функция, создающая соединение, команду,
/// Выполняет команду и возвращает результат в DataTable.
///</summary>
private static DataTable ExecuteDataTable(string commandText)
{
// Откройте соединение с базой данных.
string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
RunExamples.GetDataDir_Database() + "Northwind.mdb";
OleDbConnection conn = new OleDbConnection(connString);
conn.Open();
// Создайте и выполните команду.
OleDbCommand cmd = new OleDbCommand(commandText, conn);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
DataTable table = new DataTable();
da.Fill(table);
// Закройте базу данных.
conn.Close();
return table;
}
Вложенные области слияния почты
Чаще всего данные, которые мы имеем в источнике данных, поступают в виде отношений. Например, таблица «Заказ» будет иметь связь «один ко многим» с «Детали заказа», в которой будут храниться записи об элементах заказа. Чтобы иметь дело с такими отношениями родитель-потомок, используется вложенное слияние. Ниже приведен пример шаблона счета, который хорошо подходит для этого сценария.
Ниже приведен пример источника данных XML, который мы будем использовать для вложенного слияния.
<?xml version="1.0" encoding="utf-8"?>
<Orders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="OrdersSchema.xsd">
<Order>
<Number>23</Number>
<Address>Nelson Street</Address>
<Suburb>Howick</Suburb>
<City>Auckland</City>
<Phonenumber>543 1234</Phonenumber>
<Date>03/01/2010</Date>
<Total>14.00</Total>
<Item>
<Name>BBQ Chicken Pizza</Name>
<Price>6.00</Price>
<Quantity>1</Quantity>
<ItemTotal>6.00</ItemTotal>
</Item>
<Item>
<Name>1.5 Litre Coke</Name>
<Price>4.00</Price>
<Quantity>2</Quantity>
<ItemTotal>8.00</ItemTotal>
</Item>
</Order>
<Order>
<Number>10</Number>
<Address>Parkville Avenue</Address>
<Suburb>Pakuranga</Suburb>
<City>Auckland</City>
<Phonenumber>548 7342</Phonenumber>
<Date>05/03/2010</Date>
<Total>6.00</Total>
<Item>
<Name>Hawaiian Pizza</Name>
<Price>4.00</Price>
<Quantity>1</Quantity>
<ItemTotal>4.00</ItemTotal>
</Item>
<Item>
<Name>Fries</Name>
<Price>1.00</Price>
<Quantity>2</Quantity>
<ItemTotal>2.00</ItemTotal>
</Item>
</Order>
</Orders>
Принимая во внимание, что OrderSchema.xsd для этого XML:
<?xml version="1.0" encoding ="utf-8"?>
<xs:schema id="OrdersSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Orders">
<xs:complexType>
<xs:sequence>
<xs:element name="Order">
<xs:complexType>
<xs:sequence>
<xs:element name="Number"/>
<xs:element name="Address"/>
<xs:element name="Suburb"/>
<xs:element name="City"/>
<xs:element name="Phonenumber">
<xs:element name="Date"/>
<xs:element name="Total"/>
<xs:element name="Item">
<xs:complexType>
<xs:sequence>
<xs:element name="Name"/>
<xs:element name="Price"/>
<xs:element name="Quantity"/>
<xs:element name="ItemTotal"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Следующий пример кода используется для выполнения вложенного слияния с использованием C#.
// Полные примеры и файлы данных см. на странице https://github.com/aspose-words/Aspose.Words-for-.NET.
// Путь к каталогу документов.
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting();
// Создайте набор данных и прочитайте XML.
DataSet pizzaDs = new DataSet();
// Datatable.TableNames и DataSet.Relations неявно определяются .NET через ReadXml.
pizzaDs.ReadXml(dataDir + "CustomerData.xml");
string fileName = "Invoice Template.doc";
// Откройте шаблон документа.
Document doc = new Document(dataDir + fileName);
// Обрежьте конечные и начальные пробелы в значениях слияния.
doc.MailMerge.TrimWhitespaces = false;
// Выполните вложенное слияние почты с регионами.
doc.MailMerge.ExecuteWithRegions(pizzaDs);
dataDir = dataDir + RunExamples.GetOutputFilePath(fileName);
// Сохраните вывод в файл.
doc.Save(dataDir);
Debug.Assert(doc.MailMerge.GetFieldNames().Length == 0, "There was a problem with mail merge");
Console.WriteLine("\nMail merge performed with nested data successfully.\nFile saved at " + dataDir);
Документ Word после слияния почты
Ниже представлена первая страница результирующего документа Word после выполнения слияния.
Вывод
Aspose.Words for .NET — это многофункциональный API слияния, который предоставляет все стандартные, а также расширенные функции слияния для приложений .NET. С помощью нескольких строк кода вы можете легко создавать простые или сложные отчеты из различных типов источников данных. Подробнее об .NET Mail Merge API можно прочитать в документации. Чтобы узнать об Aspose.Words для .NET, начните работу с руководств разработчика и примеров кода GitHub.
Попробуйте Aspose.Words для .NET бесплатно
Вы можете получить бесплатную временную лицензию, чтобы попробовать Aspose.Words для .NET без каких-либо ограничений. Получите временную лицензию сейчас.