W tym poście opisano, jak wykonywać operacje korespondencji seryjnej w dokumentach MS Word przy użyciu języka Java. Pod koniec tego artykułu dowiesz się, jak tworzyć szablony korespondencji seryjnej i programowo wykonywać korespondencję seryjną.

Informacje o korespondencji seryjnej

Mail Merge to wygodny sposób dynamicznego generowania listów, kopert, faktur, raportów i innych typów dokumentów. Korzystając z korespondencji seryjnej, tworzysz plik szablonu zawierający pola korespondencji seryjnej, a następnie wypełniasz te pola przy użyciu danych ze źródła danych. Załóżmy, że musisz wysłać list do 20 różnych osób i wystarczy zmienić nazwiska i adresy odbiorców na każdym egzemplarzu. W takim przypadku możesz utworzyć szablon korespondencji seryjnej dla listu, a następnie wygenerować 20 listów, dynamicznie wypełniając pola nazwy i adresu.

Java Mail Merge API — bezpłatne pobieranie

Aspose.Words for Java to dobrze znany interfejs API edytora tekstu, który umożliwia tworzenie od podstaw różnych typów dokumentów. Interfejs API zapewnia wbudowane funkcje korespondencji seryjnej, które umożliwiają dynamiczne generowanie dokumentów przy użyciu szablonów i źródeł danych. Aspose.Words for Java można pobrać jako JAR lub zainstalować w aplikacjach opartych na 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>

Źródła danych dla korespondencji seryjnej

Dane w korespondencji seryjnej można pobrać z dowolnego źródła danych, takiego jak JSON, XML, arkusz kalkulacyjny lub baza danych.

Utwórz szablon korespondencji seryjnej w MS Word

Szablon używany w korespondencji seryjnej może być prostym dokumentem programu Word (np. DOCX) i nie musi być w formacie szablonu. Dokument szablonu zawiera pola korespondencji seryjnej, które są wypełniane danymi podczas wykonywania korespondencji seryjnej. Poniżej przedstawiono kroki przygotowania szablonu korespondencji seryjnej za pomocą programu MS Word.

  • Utwórz nowy dokument w MS Word.
  • Umieść kursor w miejscu, w którym chcesz dodać pole scalania.
  • Z menu Wstaw wybierz opcję Pole.
  • Z listy Nazwy pól wybierz opcję MergeField.
  • Wprowadź nazwę pola scalania w polu Nazwa pola i naciśnij OK.
  • Zapisz dokument jako DOCX.

Poniżej znajduje się zrzut ekranu dokumentu przykładowy szablon.

szablon programu Word korespondencji seryjnej

Utwórz szablon korespondencji seryjnej przy użyciu języka Java

Szablon korespondencji seryjnej można również wygenerować programowo. Oto kroki, które należy wykonać.

Poniższy przykładowy kod pokazuje, jak utworzyć szablon korespondencji seryjnej przy użyciu języka Java.

// Utwórz narzędzie do tworzenia dokumentów
DocumentBuilder builder = new DocumentBuilder();

// Wstaw pole wprowadzania tekstu. Unikalna nazwa tego pola to „Hello”, inne parametry określają
// jaki to typ FormField, format tekstu, wynik pola i maksymalna długość tekstu (0 = bez limitu)
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);

// Wstaw podział akapitu do dokumentu
builder.insertParagraph();

// Wstaw treść wiadomości
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();

// Wstaw zakończenie wiadomości
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");

// Zapisz dokument
builder.getDocument().save("document.docx");

Wykonaj korespondencję seryjną w dokumencie programu Word przy użyciu języka Java

Gdy szablon jest gotowy, możesz wypełnić pola scalania danymi. Poniżej przedstawiono kroki przeprowadzania korespondencji seryjnej na szablonie programu Word.

Poniższy przykładowy kod pokazuje, jak przeprowadzić korespondencję seryjną w dokumentach programu Word przy użyciu języka Java.

// Dołącz kod do naszego szablonu
Document doc = new Document();

// Przekaż dokument do konstruktora dokumentów
DocumentBuilder builder = new DocumentBuilder(doc);

// Utwórz pola scalania
builder.insertField(" MERGEFIELD CustomerName ");
builder.insertParagraph();
builder.insertField(" MERGEFIELD Item ");
builder.insertParagraph();
builder.insertField(" MERGEFIELD Quantity ");

// Zapisz szablon
builder.getDocument().save("MailMerge.TestTemplate.docx");

// Wypełnij pola w dokumencie danymi użytkownika
doc.getMailMerge().execute(new String[] { "CustomerName", "Item", "Quantity" },
		new Object[] { "John Doe", "Hawaiian", "2" });

// Zapisz dokument 
builder.getDocument().save("MailMerge.Simple.docx");

Szablon

prosta korespondencja seryjna w java

Wyjście

prosta korespondencja seryjna

Wykonaj korespondencję seryjną przy użyciu źródła danych XML

W poprzednim przykładzie przeprowadziliśmy korespondencję seryjną przy użyciu obiektów Java. Jednak w większości przypadków do wypełnienia pól scalania używane jest źródło danych. Aby zademonstrować, zobaczmy, jak używać źródła danych XML w korespondencji seryjnej. Oto kroki, które należy wykonać.

  • Załaduj źródło danych XML przy użyciu klasy DataSet.
  • Załaduj szablon korespondencji seryjnej, używając klasy Document.
  • Użyj funkcji wykonywania, aby wypełnić pola scalania przy użyciu żądanej tabeli danych w źródle danych.
  • Zapisz wygenerowany dokument Worda metodą Document.save(String).

Poniżej przedstawiono źródło danych XML używane w tym przykładzie.

<?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> 

Poniższy przykładowy kod pokazuje, jak wypełnić szablon korespondencji seryjnej przy użyciu tabeli danych klienta w dostarczonym źródle danych XML.

// Utwórz zestaw danych i przeczytaj plik XML
DataSet customersDs = new DataSet();
customersDs.readXml("Customers.xml");

// Otwórz dokument szablonu
Document doc = new Document("TestFile XML.docx");

// Wykonaj korespondencję seryjną, aby wypełnić szablon danymi z XML przy użyciu DataTable.
// Należy zauważyć, że ta klasa działa również z pojedynczym regionem powtarzalnym (i dowolnymi regionami zagnieżdżonymi).
// Aby scalić wiele regionów jednocześnie z jednego źródła danych XML, użyj klasy XmlMailMergeDataSet.
// np. doc.getMailMerge().executeWithRegions(new XmlMailMergeDataSet(xmlData));
doc.getMailMerge().execute(customersDs.getTables().get("Customer"));

// Zapisz dokument wyjściowy
doc.save("generated-document.docx");

Szablon

korespondencji seryjnej z XML

Wyjście

korespondencja seryjna xml

Korespondencja seryjna z regionami w Javie

W niektórych przypadkach może być konieczne powtórzenie określonego regionu w dokumencie. Na przykład chcesz wyświetlić zamówienia złożone przez każdego klienta w osobnej tabeli. W takich przypadkach możesz skorzystać z regionów korespondencji seryjnej. Aby utworzyć region, możesz określić początek i koniec regionu. W rezultacie region zostanie powtórzony dla każdego wystąpienia danych podczas wykonywania korespondencji seryjnej.

Poniższy zrzut ekranu przedstawia szablon, w którym region składa się z tabeli. Zaczyna się od „TableStart:Customers”, a kończy na „TableEnd:Customers”.

szablon regionu korespondencji seryjnej

Poniższy przykład kodu pokazuje, jak utworzyć szablon z regionami i wypełnić go danymi.

// Utwórz dokument
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);

// Punkt początkowy korespondencji seryjnej z regionami zestawu danych.
builder.insertField(" MERGEFIELD TableStart:Customers");
// Dane z wierszy kolumny „CustomerName” tabeli „Customers” zostaną przeniesione
// w tym MERGEFIELD.
builder.write("Orders for ");
builder.insertField(" MERGEFIELD CustomerName");
builder.write(":");

// Utwórz nagłówki kolumn
builder.startTable();
builder.insertCell();
builder.write("Item");
builder.insertCell();
builder.write("Quantity");
builder.endRow();

// Mamy drugą tabelę danych o nazwie „Zamówienia”, która ma wiele do jednego
// relacje z „Klientami”
// pobieranie wierszy o tej samej wartości 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();

// Punkt końcowy korespondencji seryjnej z regionami.
builder.insertField(" MERGEFIELD TableEnd:Customers");

// Przekaż nasz zestaw danych, aby przeprowadzić korespondencję seryjną z regionami.
DataSet customersAndOrders = CreateDataSet();
doc.getMailMerge().executeWithRegions(customersAndOrders);

// Zapisz wynik
doc.save("MailMerge.ExecuteWithRegions.docx");

Wyjście

region korespondencji seryjnej

Tworzenie zagnieżdżonych regionów korespondencji seryjnej przy użyciu języka Java

Innym popularnym scenariuszem w korespondencji seryjnej są regiony zagnieżdżone. Na przykład, gdy musisz wymienić zamówienia i pozycje w każdym zamówieniu, możesz użyć regionów zagnieżdżonych. Poniższy obraz sprawia, że obraz zagnieżdżonych regionów jest bardziej przejrzysty.

Na powyższym obrazku mamy tabelę Orders i Items, gdzie każdy rekord w Items jest połączony z rekordem w Orders. W związku z tym istnieje relacja jeden do wielu między tymi dwiema tabelami. W takich przypadkach Aspose.Words wykonuje Mail Merge dbając o relacje zdefiniowane w DataSet. Na przykład, jeśli mamy źródło danych XML, Aspose.Words użyje informacji o schemacie lub struktury XML, aby znaleźć relacje. Dzięki temu nie będziesz musiał zajmować się tym ręcznie i zadziała metoda Document.getMailMerge().executeWithRegions(DataSet) (jak w poprzednim przykładzie).

Zastosuj niestandardowe formatowanie w polach scalania

Aby zapewnić większą kontrolę nad korespondencją seryjną, Aspose.Words for Java umożliwia dostosowanie pól korespondencji seryjnej podczas wykonywania korespondencji seryjnej. Metoda setFieldMergingCallback(IFieldMergingCallback) akceptuje klasę, która implementuje metody fieldMerging(FieldMergingArgs) i imageFieldMerging(ImageFieldMergingArgs) do niestandardowej kontroli nad procesem korespondencji seryjnej. Zdarzenie fieldMerging(FieldMergingArgs) występuje w przypadku napotkania pola korespondencji seryjnej podczas wykonywania korespondencji seryjnej.

Poniżej znajduje się kompletny przykład kodu, jak dostosować operację korespondencji seryjnej i zastosować formatowanie do komórek.

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");

        // Dodaj procedurę obsługi zdarzenia MergeField.
        doc.getMailMerge().setFieldMergingCallback(new HandleMergeFieldAlternatingRows());

        // Wykonaj korespondencję seryjną z regionami.
        DataTable dataTable = getSuppliersDataTable();
        doc.getMailMerge().executeWithRegions(dataTable);

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

    /**
     * Zwraca true, jeśli wartość jest nieparzysta; false, jeśli wartość jest parzysta.
     */
    public static boolean isOdd(int value) throws Exception {
        return (value % 2 != 0);
    }

    /**
     * Utwórz DataTable i wypełnij ją danymi. W prawdziwym życiu ten DataTable
     * należy wypełnić z bazy danych.
     */
    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");
    }

    /**
     * Metoda pomocnicza, która tworzy pustą Javę odłączoną ResultSet z
     * określone kolumny.
     */
    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;
    }

    /**
     * Metoda pomocnicza, która dodaje nowy wiersz z określonymi wartościami do a
     * odłączony zestaw wyników.
     */
    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();

        // Ten „taniec” jest potrzebny do prawidłowego dodania wierszy na końcu zestawu wyników.
        // Jeśli zrobię coś innego, wiersze zostaną dodane z przodu lub w wyniku
        // set zgłasza wyjątek dotyczący usuniętego wiersza podczas korespondencji seryjnej.
        resultSet.moveToCurrentRow();
        resultSet.last();
    }
}

class HandleMergeFieldAlternatingRows implements IFieldMergingCallback {
    /**
     * Wywoływana dla każdego pola scalania napotkanego w dokumencie. Możemy albo
     * zwróć niektóre dane do mechanizmu korespondencji seryjnej lub zrób coś innego z plikiem
     * dokument. W tym przypadku modyfikujemy formatowanie komórek.
     */
    public void fieldMerging(FieldMergingArgs e) throws Exception {
        if (mBuilder == null)
            mBuilder = new DocumentBuilder(e.getDocument());

        // W ten sposób łapiemy początek nowego rzędu.
        if (e.getFieldName().equals("CompanyName")) {
            // Wybierz kolor w zależności od tego, czy numer wiersza jest parzysty, czy nieparzysty.
            Color rowColor;
            if (ApplyCustomFormattingDuringMailMerge.isOdd(mRowIdx))
                rowColor = new Color(213, 227, 235);
            else
                rowColor = new Color(242, 242, 242);

            // W tej chwili nie ma możliwości ustawienia właściwości komórki dla całego wiersza,
            // więc musimy iterować po wszystkich komórkach w wierszu.
           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 {
        // Nic nie robić.
    }

    private DocumentBuilder mBuilder;
    private int mRowIdx;
}

Wniosek

Mail Merge zapewnia szeroki zakres funkcji do dynamicznego generowania dokumentów MS Word. Możesz generować zarówno proste, jak i złożone raporty na podstawie danych w bazach danych lub innych źródłach danych. W tym artykule dowiesz się, jak programowo zaimplementować funkcje korespondencji seryjnej przy użyciu języka Java. Możesz dowiedzieć się więcej o Java Mail Merge API, korzystając z dokumentacji.

Zobacz też