How to Mail Merge Word Documents in C
O IronWord realiza mala direta em C# ao preencher marcadores MERGEFIELD em um modelo do Word com seus dados, retirados de dicionários, objetos DataSet ou tabelas de regiões repetidas, tudo isso sem o Microsoft Office Interop. Campos de mesclagem criados no Microsoft Word, ou qualquer ferramenta compatível, são detectados automaticamente.
Mala direta é a maneira padrão de gerar documentos personalizados em larga escala: cartas modelo, faturas, certificados, contratos e relatórios que compartilham um modelo, mas diferem por destinatário. Em vez de editar cada documento à mão, você cria um modelo .docx com campos de mesclagem e deixa o IronWord preenchê-los a partir de sua fonte de dados. Cada operação é alcançada através do ponto de entrada WordDocument.MailMerge.
Início Rápido: Fazer Mala Direta em um Documento do Word
Carregue um modelo que contém marcadores MERGEFIELD, passe um dicionário de nomes e valores de campos para Execute e salve o resultado.
-
Instale IronWord com o Gerenciador de Pacotes NuGet
-
Copie e execute este trecho de código.
WordDocument doc = new WordDocument("template.docx"); doc.MailMerge.Execute(new Dictionary<string, string> { { "FirstName", "Jane" }, { "Company", "Acme Corp" } }); doc.SaveAs("output.docx"); -
Implante para testar em seu ambiente de produção.
Comece a usar IronWord em seu projeto hoje com uma avaliação gratuita
Fluxo de trabalho mínimo (5 etapas)
- Baixe a biblioteca C# para mala direta de Word do NuGet
- Crie um modelo do Word com marcadores
MERGEFIELD - Carregue o modelo com o construtor
WordDocument - Chame
MailMerge.ExecuteouMailMerge.ExecuteWithRegionscom sua fonte de dados - Salve o documento preenchido
Como Fazer Mala Direta a Partir de um Dicionário?
A fonte de dados mais simples é um IDictionary<string, string> indexado pelo nome do campo de mesclagem. Execute substitui cada campo cujo nome corresponde a uma chave.
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Execute(new Dictionary<string, string>
{
{ "FirstName", "Jane" },
{ "LastName", "Smith" },
{ "Company", "Acme Corp" }
});
doc.SaveAs("output.docx");
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Execute(new Dictionary<string, string>
{
{ "FirstName", "Jane" },
{ "LastName", "Smith" },
{ "Company", "Acme Corp" }
});
doc.SaveAs("output.docx");
Dim doc As New WordDocument("template.docx")
doc.MailMerge.Execute(New Dictionary(Of String, String) From {
{"FirstName", "Jane"},
{"LastName", "Smith"},
{"Company", "Acme Corp"}
})
doc.SaveAs("output.docx")
MailMerge.Options.CaseInsensitiveFieldNames = false para exigir uma correspondência exata de caso.Você também pode fornecer duas sequências paralelas de nomes de campos e valores:
doc.MailMerge.Execute(
new[] { "FirstName", "LastName" },
new[] { "Jane", "Smith" });
doc.MailMerge.Execute(
new[] { "FirstName", "LastName" },
new[] { "Jane", "Smith" });
doc.MailMerge.Execute(
New String() { "FirstName", "LastName" },
New String() { "Jane", "Smith" })
Execute(fieldNames, values) lança um ArgumentException quando as duas sequências têm comprimentos diferentes.
Como Fazer Mala Direta a Partir de um DataTable ou DataRow?
Quando os dados vêm de um banco de dados ou de um DataSet existente, passe um DataTable ou DataRow diretamente para Execute. Os nomes dos campos de mesclagem são correspondidos aos nomes das colunas. Execute(DataTable) usa os valores da primeira linha da tabela, enquanto Execute(DataRow) usa os nomes das colunas da tabela pai da linha.
DataTable table = new DataTable();
table.Columns.Add("FirstName");
table.Columns.Add("LastName");
DataRow row = table.NewRow();
row["FirstName"] = "Jane";
row["LastName"] = "Smith";
table.Rows.Add(row);
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Execute(row);
doc.SaveAs("output.docx");
DataTable table = new DataTable();
table.Columns.Add("FirstName");
table.Columns.Add("LastName");
DataRow row = table.NewRow();
row["FirstName"] = "Jane";
row["LastName"] = "Smith";
table.Rows.Add(row);
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Execute(row);
doc.SaveAs("output.docx");
Imports System.Data
Dim table As New DataTable()
table.Columns.Add("FirstName")
table.Columns.Add("LastName")
Dim row As DataRow = table.NewRow()
row("FirstName") = "Jane"
row("LastName") = "Smith"
table.Rows.Add(row)
Dim doc As New WordDocument("template.docx")
doc.MailMerge.Execute(row)
doc.SaveAs("output.docx")
Como Preencher Regiões de Tabela Repetidas?
Regiões repetidas transformam uma linha de modelo em várias, o que é ideal para itens de linhas de faturas ou listas de pedidos. No modelo, envolva o conteúdo repetido entre dois campos marcadores nomeados TableStart:RegionName e TableEnd:RegionName. Então, chame ExecuteWithRegions, que repete o conteúdo da região uma vez por linha da tabela correspondente.
ExecuteWithRegions aceita um DataSet completo (expandindo cada região cujo nome corresponde a uma tabela), um único DataTable (expandindo a região cujo nome corresponde a dataTable.TableName) ou um nome de região junto com um DataTable.
DataTable orders = new DataTable("Orders");
orders.Columns.Add("Item");
orders.Columns.Add("Qty");
orders.Rows.Add("Widget A", "3");
orders.Rows.Add("Widget B", "1");
DataSet ds = new DataSet();
ds.Tables.Add(orders);
WordDocument doc = new WordDocument("invoice-template.docx");
doc.MailMerge.ExecuteWithRegions(ds);
doc.MailMerge.Execute(new Dictionary<string, string> { { "CustomerName", "Jane Smith" } });
doc.SaveAs("invoice.docx");
DataTable orders = new DataTable("Orders");
orders.Columns.Add("Item");
orders.Columns.Add("Qty");
orders.Rows.Add("Widget A", "3");
orders.Rows.Add("Widget B", "1");
DataSet ds = new DataSet();
ds.Tables.Add(orders);
WordDocument doc = new WordDocument("invoice-template.docx");
doc.MailMerge.ExecuteWithRegions(ds);
doc.MailMerge.Execute(new Dictionary<string, string> { { "CustomerName", "Jane Smith" } });
doc.SaveAs("invoice.docx");
Imports System.Data
Imports System.Collections.Generic
Dim orders As New DataTable("Orders")
orders.Columns.Add("Item")
orders.Columns.Add("Qty")
orders.Rows.Add("Widget A", "3")
orders.Rows.Add("Widget B", "1")
Dim ds As New DataSet()
ds.Tables.Add(orders)
Dim doc As New WordDocument("invoice-template.docx")
doc.MailMerge.ExecuteWithRegions(ds)
doc.MailMerge.Execute(New Dictionary(Of String, String) From {{"CustomerName", "Jane Smith"}})
doc.SaveAs("invoice.docx")
ExecuteWithRegions só preenche regiões repetidas. Para também preencher campos de mesclagem padrão fora das regiões, chame Execute(...) após expandir as regiões, como mostrado acima.Como Inspecionar os Campos de Mesclagem de um Modelo?
Antes de mesclar, você pode descobrir o que um modelo contém, o que é útil para validar modelos ou criar a fonte de dados dinamicamente.
GetFieldNames()retorna os nomes de todos os campos de mesclagem do tipo valor, na ordem do documento e sem duplicação.GetRegionNames()retorna os nomes de todas as regiõesTableStartdeclaradas no documento.GetFields()retorna cada campo, incluindo marcadoresTableEnd, como objetosMergeField.
WordDocument doc = new WordDocument("template.docx");
IReadOnlyList<string> fieldNames = doc.MailMerge.GetFieldNames();
IReadOnlyList<string> regionNames = doc.MailMerge.GetRegionNames();
// fieldNames: ["FirstName", "LastName", "Company"]
// regionNames: ["Orders", "LineItems"]
WordDocument doc = new WordDocument("template.docx");
IReadOnlyList<string> fieldNames = doc.MailMerge.GetFieldNames();
IReadOnlyList<string> regionNames = doc.MailMerge.GetRegionNames();
// fieldNames: ["FirstName", "LastName", "Company"]
// regionNames: ["Orders", "LineItems"]
Dim doc As New WordDocument("template.docx")
Dim fieldNames As IReadOnlyList(Of String) = doc.MailMerge.GetFieldNames()
Dim regionNames As IReadOnlyList(Of String) = doc.MailMerge.GetRegionNames()
' fieldNames: ["FirstName", "LastName", "Company"]
' regionNames: ["Orders", "LineItems"]
Cada MergeField expõe seu Name, o texto completo de Instruction como armazenado no documento (por exemplo, MERGEFIELD FirstName \* MERGEFORMAT), um RegionName que é definido apenas para marcadores de região (por exemplo, "Orders" de "TableStart:Orders"), e um Kind que classifica o campo como Value (texto substituído por um valor de dados), TableStart ou TableEnd (os limites de uma região repetida), ou NextRecord (um campo NEXT que avança para o próximo registro de dados dentro do mesmo corpo de modelo).
Como Controlar Campos Não Correspondidos e Valores Nulos?
O comportamento de mesclagem é configurado através de MailMerge.Options:
| Opção | Default | Comportamento |
|---|---|---|
RemoveUnusedFields |
true |
Remove campos de mesclagem que não têm chave correspondente na fonte de dados. Defina como false para deixá-los no lugar. |
RemoveUnusedRegions |
true |
Remove regiões TableEnd sem tabela correspondente na fonte de dados. |
NullValueReplacement |
"" |
Texto substituído quando a fonte de dados fornece um valor null para um campo. |
CaseInsensitiveFieldNames |
true |
Ignora o caso ao corresponder nomes de campo, correspondendo ao comportamento do Microsoft Word. |
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Options.RemoveUnusedFields = false;
doc.MailMerge.Execute(new Dictionary<string, string> { { "FirstName", "Jane" } });
doc.SaveAs("partial-output.docx");
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Options.RemoveUnusedFields = false;
doc.MailMerge.Execute(new Dictionary<string, string> { { "FirstName", "Jane" } });
doc.SaveAs("partial-output.docx");
Dim doc As New WordDocument("template.docx")
doc.MailMerge.Options.RemoveUnusedFields = False
doc.MailMerge.Execute(New Dictionary(Of String, String) From {{"FirstName", "Jane"}})
doc.SaveAs("partial-output.docx")
Para substituição de valor direta sem uma fonte de dados, veja como substituir texto em um documento do Word.
Perguntas frequentes
Como fazer uma mala direta em um documento Word em C#?
Carregue um modelo Word contendo espaços reservados MERGEFIELD com o construtor WordDocument, depois chame doc.MailMerge.Execute com um IDictionary, DataTable ou DataRow para substituir cada campo cujo nome corresponda a uma chave ou coluna, e salve o resultado com SaveAs. Os campos de mesclagem criados no Microsoft Word são detectados automaticamente, e nenhuma instalação do Microsoft Office é necessária.
Quais fontes de dados o IronWord para mala direta pode usar?
MailMerge.Execute aceita um IDictionary de nomes de campos e valores, duas sequências paralelas de nomes de campos e valores, um DataTable (usando a primeira linha) ou um DataRow (usando as colunas da tabela pai). MailMerge.ExecuteWithRegions aceita um DataSet ou DataTable para expandir regiões de tabela repetidas.
Como preencho regiões de tabela repetidas em uma mala direta do Word?
Envolva o conteúdo repetido no modelo entre os campos de mesclagem TableStart:RegionName e TableEnd:RegionName, depois chame MailMerge.ExecuteWithRegions com um DataSet ou DataTable. O conteúdo da região se repete uma vez por linha da tabela correspondente. Como ExecuteWithRegions só preenche regiões, chame Execute depois para preencher quaisquer campos de mesclagem padrão.
Posso inspecionar os campos de mesclagem de um modelo antes de mesclar?
Sim. MailMerge.GetFieldNames retorna os nomes dos campos no estilo valor em ordem do documento, GetRegionNames retorna os nomes das regiões TableStart e GetFields retorna objetos MergeField expondo o Nome, Instrução, Tipo (Valor, TableStart, TableEnd ou NextRecord) e Nome da Região de cada campo.
O que acontece com os campos de mesclagem sem dados correspondentes?
Por padrão, MailMergeOptions.RemoveUnusedFields é verdadeiro, então campos sem chave correspondente na fonte de dados são removidos da saída. Defina-o como falso para deixá-los no lugar. Regiões TableStart/TableEnd não correspondentes são removidas quando RemoveUnusedRegions é verdadeiro, e valores nulos são substituídos pela string NullValueReplacement.
O emparelhamento de campos de mesclagem é sensível a maiúsculas e minúsculas?
Não. As consultas de nomes de campos não diferenciam maiúsculas de minúsculas por padrão, correspondendo ao comportamento do Microsoft Word. Defina MailMerge.Options.CaseInsensitiveFieldNames como falso se precisar de uma correspondência exata de caso.

