В этом посте рассказывается, как выполнять операции слияния в документах MS Word с использованием Java. К концу этой статьи вы узнаете, как создавать шаблоны слияния и программно выполнять слияние.

О слиянии почты

Mail Merge — это удобный способ динамического создания писем, конвертов, счетов, отчетов и других типов документов. Используя слияние, вы создаете файл шаблона, содержащий поля слияния, а затем заполняете эти поля, используя данные из источника данных. Предположим, вам нужно отправить письмо 20 разным людям, и вам нужно только изменить имя и адрес получателей на каждом экземпляре. В этом случае вы можете создать шаблон Mail Merge для письма, а затем сгенерировать 20 писем, динамически заполняя поля имени и адреса.

Java Mail Merge API — скачать бесплатно

Aspose.Words for Java — это хорошо известный API для обработки текстов, который позволяет создавать различные типы документов с нуля. API предоставляет встроенные функции слияния, которые позволяют динамически создавать документы с использованием шаблонов и источников данных. Aspose.Words for Java можно загрузить как JAR или установить в приложениях на основе Maven.

<repository>
    <id>AsposeJavaAPI</id>
    <name>Aspose Java API</name>
    <url>https://repository.aspose.com/repo/</url>
</repository>
<dependency>
    <groupId>com.aspose</groupId>
    <artifactId>aspose-words</artifactId>
    <version>20.11</version>
    <classifier>jdk17</classifier>
</dependency>

Источники данных для слияния

Данные в слиянии могут быть получены из любого источника данных, такого как JSON, XML, электронная таблица или база данных.

Создать шаблон для слияния писем в MS Word

Шаблон, используемый в Mail Merge, может быть простым документом Word (например, DOCX), и он не обязательно должен быть в формате шаблона. Документ-шаблон содержит поля слияния, которые заполняются данными при выполнении слияния. Ниже приведены шаги по подготовке шаблона слияния с помощью MS Word.

  • Создайте новый документ в MS Word.
  • Поместите курсор туда, где вы хотите добавить поле слияния.
  • В меню «Вставка» выберите параметр «Поле».
  • В списке Имена полей выберите MergeField.
  • Введите имя поля слияния в поле Имя поля и нажмите OK.
  • Сохраните документ как DOCX.

Ниже приведен скриншот документа образец шаблона.

шаблон слова слияния почты

Создайте шаблон слияния с помощью Java

Вы также можете сгенерировать шаблон Mail Merge программно. Ниже приведены шаги для этого.

В следующем примере кода показано, как создать шаблон слияния с помощью Java.

// Создать конструктор документов
DocumentBuilder builder = new DocumentBuilder();

// Вставьте поле ввода текста, уникальное имя этого поля — «Привет», остальные параметры определяют
// какой это тип FormField, формат текста, результат поля и максимальная длина текста (0 = без ограничений)
builder.insertTextInput("TextInput", TextFormFieldType.REGULAR, "", "Hello", 0);
builder.insertField("MERGEFIELD CustomerFirstName \\* MERGEFORMAT");

builder.insertTextInput("TextInput1", TextFormFieldType.REGULAR, "", " ", 0);
builder.insertField("MERGEFIELD CustomerLastName \\* MERGEFORMAT");

builder.insertTextInput("TextInput1", TextFormFieldType.REGULAR, "", " , ", 0);

// Вставить разрыв абзаца в документ
builder.insertParagraph();

// Вставить тело письма
builder.insertTextInput("TextInput", TextFormFieldType.REGULAR, "", "Thanks for purchasing our ", 0);
builder.insertField("MERGEFIELD ProductName \\* MERGEFORMAT");

builder.insertTextInput("TextInput", TextFormFieldType.REGULAR, "", ", please download your Invoice at ",
	0);
builder.insertField("MERGEFIELD InvoiceURL \\* MERGEFORMAT");

builder.insertTextInput("TextInput", TextFormFieldType.REGULAR, "",
	". If you have any questions please call ", 0);
builder.insertField("MERGEFIELD Supportphone \\* MERGEFORMAT");

builder.insertTextInput("TextInput", TextFormFieldType.REGULAR, "", ", or email us at ", 0);
builder.insertField("MERGEFIELD SupportEmail \\* MERGEFORMAT");

builder.insertTextInput("TextInput", TextFormFieldType.REGULAR, "", ".", 0);

builder.insertParagraph();

// Вставьте почтовое окончание
builder.insertTextInput("TextInput", TextFormFieldType.REGULAR, "", "Best regards,", 0);
builder.insertBreak(BreakType.LINE_BREAK);
builder.insertField("MERGEFIELD EmployeeFullname \\* MERGEFORMAT");

builder.insertTextInput("TextInput1", TextFormFieldType.REGULAR, "", " ", 0);
builder.insertField("MERGEFIELD EmployeeDepartment \\* MERGEFORMAT");

// Сохранить документ
builder.getDocument().save("document.docx");

Выполнение слияния почты в документе Word с использованием Java

Как только шаблон будет готов, вы можете заполнить поля слияния данными. Ниже приведены шаги выполнения слияния в шаблоне Word.

  • Создайте новый шаблон с помощью класса Document (или загрузите существующий шаблон).
  • Создайте экземпляр класса DocumentBuilder и передайте объект Document его конструктору.
  • Выполните слияние с помощью метода Document.getMailMerge().execute() и передайте источник данных в качестве параметра.
  • Сохраните сгенерированный документ Word с помощью метода DocumentBuilder.getDocument().save(String).

В следующем примере кода показано, как выполнять слияние почты в документах Word с помощью Java.

// Включите код для нашего шаблона
Document doc = new Document();

// Передать документ в конструктор документов
DocumentBuilder builder = new DocumentBuilder(doc);

// Создать поля слияния
builder.insertField(" MERGEFIELD CustomerName ");
builder.insertParagraph();
builder.insertField(" MERGEFIELD Item ");
builder.insertParagraph();
builder.insertField(" MERGEFIELD Quantity ");

// Сохраните шаблон
builder.getDocument().save("MailMerge.TestTemplate.docx");

// Заполнить поля в документе данными пользователя
doc.getMailMerge().execute(new String[] { "CustomerName", "Item", "Quantity" },
		new Object[] { "John Doe", "Hawaiian", "2" });

// Сохраните документ 
builder.getDocument().save("MailMerge.Simple.docx");

Шаблон

простое слияние почты в java

Выход

простое слияние почты

Выполнение слияния почты с использованием источника данных XML

В предыдущем примере мы выполнили слияние с использованием объектов Java. Однако в большинстве случаев для заполнения полей слияния используется источник данных. Для демонстрации давайте посмотрим, как использовать источник данных XML в Mail Merge. Ниже приведены шаги для этого.

  • Загрузите источник данных XML с помощью класса DataSet.
  • Загрузите шаблон слияния, используя класс Document.
  • Используйте функцию выполнения, чтобы заполнить поля слияния, используя нужную таблицу данных в источнике данных.
  • Сохраните сгенерированный документ Word, используя метод Document.save(String).

Ниже приведен источник данных XML, используемый в этом примере.

<?xml version="1.0" encoding="utf-8"?>
<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> 

В следующем примере кода показано, как заполнить шаблон слияния, используя таблицу данных Customer в предоставленном источнике данных XML.

// Создайте набор данных и прочитайте XML
DataSet customersDs = new DataSet();
customersDs.readXml("Customers.xml");

// Откройте шаблон документа
Document doc = new Document("TestFile XML.docx");

// Выполните слияние почты, чтобы заполнить шаблон данными из XML с помощью DataTable.
// Обратите внимание, что этот класс также работает с одной повторяющейся областью (и любыми вложенными областями).
// Чтобы одновременно объединить несколько регионов из одного источника данных XML, используйте класс XmlMailMergeDataSet.
// например, doc.getMailMerge().executeWithRegions(новый XmlMailMergeDataSet(xmlData));
doc.getMailMerge().execute(customersDs.getTables().get("Customer"));

// Сохраните выходной документ
doc.save("generated-document.docx");

Шаблон

слияние почты с XML

Выход

слияние почты xml

Слияние почты с регионами в Java

В некоторых случаях может потребоваться повторение определенной области в документе. Например, вы хотите отобразить заказы, сделанные каждым клиентом, в отдельной таблице. В таких случаях вы можете воспользоваться регионами Mail Merge. Чтобы создать регион, вы можете указать начало и конец региона. В результате регион будет повторяться для каждого экземпляра данных во время выполнения слияния.

На следующем снимке экрана показан шаблон, в котором область состоит из таблицы. Он начинается с «TableStart:Customers» и заканчивается «TableEnd:Customers».

шаблон области слияния почты

В следующем примере кода показано, как создать шаблон с областями и заполнить его данными.

// Создать документ
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);

// Начальная точка почтового слияния с регионами набора данных.
builder.insertField(" MERGEFIELD TableStart:Customers");
// Данные из строк столбца "CustomerName" таблицы "Customers" будут идти
// в этом MERGEFIELD.
builder.write("Orders for ");
builder.insertField(" MERGEFIELD CustomerName");
builder.write(":");

// Создать заголовки столбцов
builder.startTable();
builder.insertCell();
builder.write("Item");
builder.insertCell();
builder.write("Quantity");
builder.endRow();

// У нас есть вторая таблица данных под названием «Заказы», которая имеет отношение «многие к одному».
// отношения с «Клиентами»
// подбор строк с одинаковым значением CustomerID.
builder.insertCell();
builder.insertField(" MERGEFIELD TableStart:Orders");
builder.insertField(" MERGEFIELD ItemName");
builder.insertCell();
builder.insertField(" MERGEFIELD Quantity");
builder.insertField(" MERGEFIELD TableEnd:Orders");
builder.endTable();

// Конечная точка слияния почты с регионами.
builder.insertField(" MERGEFIELD TableEnd:Customers");

// Передайте наш набор данных, чтобы выполнить слияние почты с регионами.
DataSet customersAndOrders = CreateDataSet();
doc.getMailMerge().executeWithRegions(customersAndOrders);

// Сохранить результат
doc.save("MailMerge.ExecuteWithRegions.docx");

Выход

область слияния почты

Создание вложенных областей слияния почты с использованием Java

Другой популярный сценарий в Mail Merge — когда у вас есть вложенные регионы. Например, когда вам нужно перечислить заказы и элементы в каждом заказе, вы можете использовать вложенные области. Следующее изображение проясняет картину вложенных регионов.

На изображении выше у нас есть таблица Orders и таблица Items, где каждая запись в Items связана с записью в Orders. Следовательно, между этими двумя таблицами существует отношение «один ко многим». В таких случаях Aspose.Words выполняет слияние, заботясь об отношениях, определенных в наборе данных. Например, если у нас есть источник данных XML, Aspose.Words будет использовать либо информацию о схеме, либо структуру XML, чтобы выяснить отношения. Таким образом, вам не придется заниматься этим вручную самостоятельно, а за вас будет работать метод Document.getMailMerge().executeWithRegions(DataSet) (как в предыдущем примере).

Применение пользовательского форматирования к полям слияния

Чтобы дать вам больше контроля над слиянием, Aspose.Words для Java позволяет настраивать поля слияния во время выполнения слияния. Метод setFieldMergingCallback(IFieldMergingCallback) принимает класс, который реализует методы fieldMerging(FieldMergingArgs) и imageFieldMerging(ImageFieldMergingArgs) для пользовательского управления процессом слияния. Событие fieldMerging(FieldMergingArgs) возникает, когда во время выполнения слияния встречается поле слияния.

Ниже приведен полный пример кода для настройки операции слияния и применения форматирования к ячейкам.

public class ApplyCustomFormattingDuringMailMerge {

    private static final String dataDir = Utils.getSharedDataDir(ApplyCustomFormattingDuringMailMerge.class) + "MailMerge/";

    public static void main(String[] args) throws Exception {
        Document doc = new Document(dataDir + "MailMerge.AlternatingRows.doc");

        // Добавьте обработчик события MergeField.
        doc.getMailMerge().setFieldMergingCallback(new HandleMergeFieldAlternatingRows());

        // Выполните слияние почты с регионами.
        DataTable dataTable = getSuppliersDataTable();
        doc.getMailMerge().executeWithRegions(dataTable);

        doc.save(dataDir + "MailMerge.AlternatingRows Out.doc");
    }

    /**
     * Возвращает true, если значение нечетное; false, если значение четное.
     */
    public static boolean isOdd(int value) throws Exception {
        return (value % 2 != 0);
    }

    /**
     * Создайте DataTable и заполните его данными. В реальной жизни этот DataTable
     * должны быть заполнены из базы данных.
     */
    private static DataTable getSuppliersDataTable() throws Exception {
        java.sql.ResultSet resultSet = createCachedRowSet(new String[]{"CompanyName", "ContactName"});

        for (int i = 0; i < 10; i++)
            addRow(resultSet, new String[]{"Company " + Integer.toString(i), "Contact " + Integer.toString(i)});

        return new DataTable(resultSet, "Suppliers");
    }

    /**
     * Вспомогательный метод, создающий пустой несвязанный набор результатов Java с
     * указанные столбцы.
     */
    private static ResultSet createCachedRowSet(String[] columnNames) throws Exception {
        RowSetMetaDataImpl metaData = new RowSetMetaDataImpl();
        metaData.setColumnCount(columnNames.length);
        for (int i = 0; i < columnNames.length; i++) {
            metaData.setColumnName(i + 1, columnNames[i]);
            metaData.setColumnType(i + 1, java.sql.Types.VARCHAR);
        }

        CachedRowSet rowSet = RowSetProvider.newFactory().createCachedRowSet();
        ;
        rowSet.setMetaData(metaData);

        return rowSet;
    }

    /**
     * Вспомогательный метод, который добавляет новую строку с указанными значениями в
     * отключил ResultSet.
     */
    private static void addRow(ResultSet resultSet, String[] values) throws Exception {
        resultSet.moveToInsertRow();

        for (int i = 0; i < values.length; i++)
            resultSet.updateString(i + 1, values[i]);

        resultSet.insertRow();

        // Этот «танец» необходим для правильного добавления строк в конец результирующего набора.
        // Если я делаю что-то еще, то строки либо добавляются спереди, либо результат
        // set генерирует исключение об удаленной строке во время слияния почты.
        resultSet.moveToCurrentRow();
        resultSet.last();
    }
}

class HandleMergeFieldAlternatingRows implements IFieldMergingCallback {
    /**
     * Вызывается для каждого поля слияния, встречающегося в документе. Мы можем либо
     * вернуть некоторые данные в механизм слияния или сделать что-то еще с
     * документ. В этом случае мы изменяем форматирование ячейки.
     */
    public void fieldMerging(FieldMergingArgs e) throws Exception {
        if (mBuilder == null)
            mBuilder = new DocumentBuilder(e.getDocument());

        // Таким образом мы ловим начало нового ряда.
        if (e.getFieldName().equals("CompanyName")) {
            // Выберите цвет в зависимости от того, является ли номер строки четным или нечетным.
            Color rowColor;
            if (ApplyCustomFormattingDuringMailMerge.isOdd(mRowIdx))
                rowColor = new Color(213, 227, 235);
            else
                rowColor = new Color(242, 242, 242);

            // На данный момент нет возможности установить свойства ячейки для всей строки,
            // поэтому нам нужно перебрать все ячейки в строке.
            for (int colIdx = 0; colIdx < 4; colIdx++) {
                mBuilder.moveToCell(0, mRowIdx, colIdx, 0);
                mBuilder.getCellFormat().getShading().setBackgroundPatternColor(rowColor);
            }

            mRowIdx++;
        }
    }

    public void imageFieldMerging(ImageFieldMergingArgs args) throws Exception {
        // Ничего не делать.
    }

    private DocumentBuilder mBuilder;
    private int mRowIdx;
}

Вывод

Mail Merge предоставляет вам широкий спектр функций для динамического создания документов MS Word. Вы можете создавать как простые, так и сложные отчеты на основе данных из баз данных или других источников данных. В этой статье вы увидели, как программно реализовать функции слияния с помощью Java. Вы можете узнать больше о Java Mail Merge API, используя документацию.

Смотрите также