Home |
Search |
Today's Posts |
#1
![]()
Posted to microsoft.public.word.mailmerge.fields
|
|||
|
|||
![]()
Hello
I'm pretty new to the whole mailmerge deal and the various guides to mail merge haven't really helped me. I need to print out a series of documents each containing 3 "post cards", now I need to fill out the the names and adresses and other various information for each card. I have a Word template containing these 3 "cards" with a series of merge fields. I need to be able to fill out these fields from a DataSet (DataTable with n number of rows) using C#. All the guides I have been over all use some form of SQL datasource. How can I fill out eg. 13 of those "cards" using C# and a DataSet, and is there special requirements to the type of mailmerge fields I use ? Hope someone can help..... ![]() -- Sparre |
#2
![]()
Posted to microsoft.public.word.mailmerge.fields
|
|||
|
|||
![]() I need to be able to fill out these fields from a DataSet (DataTable with n number of rows) using C#. All the guides I have been over all use some form of SQL datasource. That's because Word Mailmerge has no way to connect or bind to the data stored in internal objects in your program. It can only connect to data using a Word converter (internal/external), DDE, in the case of Access databases and Excel workbooks, ODBC and OLEDB (and it can't yet use an ADO.NET source, just in case you were wondering). Prior to Word 2007, you really have two options: a. turn your data source into something that Word can use, and use MailMerge b. don't use MailMerge - use C# to get the data from your DataSet and use methods in the Word object to insert that data into your postcasrd document. For example, you might be able to: - use a { DOCVARIABLE } field instead of a { MERGEFIELD { field as a "placeholder" for each item you want to insert - in C#, for each 3 rows in your DataSet, - copy the data in the DataSet into the relvant Word document variables - update the fields in the document - print/output the document There are other possibilities. A lot depends on whether you are trying to create a completely automated process or whether you are trying to create something where the users can edit the document and so on (in which case things obviously get a lot more complicated). In Word 2007 you have at least one other option, because you can bind things called "content controls" to data stored in your docx. However, that's about as much as I know about content controls - I suspect you would still have to serialize your DataSet into XML at some point to make use of them, but I really don't know yet. Peter Jamieson "Sparre" wrote in message oups.com... Hello I'm pretty new to the whole mailmerge deal and the various guides to mail merge haven't really helped me. I need to print out a series of documents each containing 3 "post cards", now I need to fill out the the names and adresses and other various information for each card. I have a Word template containing these 3 "cards" with a series of merge fields. I need to be able to fill out these fields from a DataSet (DataTable with n number of rows) using C#. All the guides I have been over all use some form of SQL datasource. How can I fill out eg. 13 of those "cards" using C# and a DataSet, and is there special requirements to the type of mailmerge fields I use ? Hope someone can help..... ![]() -- Sparre |
#3
![]()
Posted to microsoft.public.word.mailmerge.fields
|
|||
|
|||
![]()
//Example Usage
DataSet ds = new DataSet(); ds.Tables.Add("Leads"); ds.Tables[0].Columns.Add("Lead.Fullname"); ds.Tables[0].Columns.Add("Lead.Address1"); ds.Tables[0].Columns.Add("Lead.Address2"); ds.Tables[0].Columns.Add("Lead.City"); ds.Tables[0].Columns.Add("Lead.State"); ds.Tables[0].Columns.Add("Lead.Zip"); ds.Tables[0].Columns.Add("Lead.Country"); ds.Tables[0].Columns.Add("Owner.Fullname"); ds.Tables[0].Columns.Add("Owner.Phone1"); ds.Tables[0].Columns.Add("Owner.Email"); //generate sample data ds.Tables[0].Rows.Add("Dr. James Brown", "3456 Madison Ave.", "Suite 250", "New York", "NY", "10003", "USA", "Jason Jakob", "519-841-8617", "); ds.Tables[0].Rows.Add("Dr. Barry White", "The Bellagio", "Room 1021", "Las Vegas", "NV", "28011", "USA", "Jason Jakob", "519-841-8617", "); //now merge string errorString = ""; string templateFilename = @"C:\jason\Personal\MailMergeWebApp\bin\intro_lett er.dot"; string outputFilename = @"C:\jason\Personal\MailMergeWebApp\bin\intro_lett er_merged.doc"; if (!MailMerge.MergeDataWithWordTemplate(templateFile name, outputFilename, ds, out errorString)) { Console.WriteLine("Error"); } //Utility class to do the merging using System; using System.Collections.Generic; using System.Text; using System.Data; using System.IO; using TMMC.CommonLibrary; using Microsoft.Office; using Word = Microsoft.Office.Interop.Word; namespace MailMergeWebApp { public class MailMerge { public static bool MergeDataWithWordTemplate(string sourceTemplatePath, string outputDocPath, DataSet sourceData, out string errorString) { #region Declares errorString = ""; Object oMissing = System.Reflection.Missing.Value; //null value Object oTrue = true; Object oFalse = false; Object oTemplatePath = sourceTemplatePath; Object oOutputPath = outputDocPath; Object oOutputPathTemp = outputDocPath.Substring(0, outputDocPath.IndexOf(".doc")) + "_temp.doc"; Object sectionStart = (Object)Microsoft.Office.Interop.Word.WdSectionSta rt.wdSectionNewPage; Word.Application oWord = null; Word.Document oWordDoc = null; //the document to load into word application Word.Document oFinalWordDoc = null; //the document to load into word application #endregion try { oWord = new Word.Application(); //starts an instance of word oWord.Visible = false; //don't show the UI //create an empty document that we will insert all the merge docs into oFinalWordDoc = oWord.Documents.Add(ref oMissing, ref oMissing, ref oMissing, ref oMissing); //for each record in the dataset int count = 1; foreach (DataRow dr in sourceData.Tables[0].Rows) { Log.Out("MailMerge:CreateMergeDoc() adding a document for this record"); //insert a document for each record oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing); if (oWordDoc.Fields.Count == 0) { Log.Out("MailMerge:CreateMergeDoc() No template fields found in document:" + sourceTemplatePath); return false; } oWordDoc.Activate(); //make current // Perform mail merge field foreach (Word.Field myMergeField in oWordDoc.Fields) { Word.Range rngFieldCode = myMergeField.Code; String fieldText = rngFieldCode.Text; // ONLY GET THE MAILMERGE FIELDS if (fieldText.StartsWith(" MERGEFIELD")) { // THE TEXT COMES IN THE FORMAT OF // MERGEFIELD MyFieldName \\* MERGEFORMAT // THIS HAS TO BE EDITED TO GET ONLY THE FIELDNAME "MyFieldName" Int32 endMerge = fieldText.IndexOf("\\"); Int32 fieldNameLength = fieldText.Length - endMerge; String fieldName = fieldText.Substring(11, endMerge - 11); // GIVES THE FIELDNAMES AS THE USER HAD ENTERED IN .dot FILE //field names with spaces in them have quotes on either end, so strip those fieldName = fieldName.Trim().Replace("\"", ""); Log.Out(Log.LOGLEVEL_STANDARD, "DeviceLabelPrinter:SendAndReceive() found word template field: " + fieldName); //find a matching dataset column foreach (DataColumn col in sourceData.Tables[0].Columns) { string key = col.ColumnName; string value = dr[key].ToString(); // **** FIELD REPLACEMENT IMPLEMENTATION GOES HERE ****// // THE PROGRAMMER CAN HAVE HIS OWN IMPLEMENTATIONS HERE if (fieldName == key) { Log.Out(Log.LOGLEVEL_STANDARD, "DeviceLabelPrinter:SendAndReceive() setting value: " + value); myMergeField.Select(); oWord.Selection.TypeText(value); } } } } Log.Out(Log.LOGLEVEL_STANDARD, "DeviceLabelPrinter:SendAndReceive() saving the doc"); //SAVE THE DOCUMENT as temp oWordDoc.SaveAs(ref oOutputPathTemp, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing); Log.Out(Log.LOGLEVEL_STANDARD, "DeviceLabelPrinter:SendAndReceive() closing the doc"); //CLOSE THE DOCUMENT oWordDoc.Close(ref oFalse, ref oMissing, ref oMissing); System.Runtime.InteropServices.Marshal.ReleaseComO bject(oWordDoc); oWordDoc = null; //NOW ADD THE NEW DOC TO THE MAIN DOC oFinalWordDoc.Activate(); //make current oWord.Selection.InsertFile(oOutputPathTemp.ToStrin g(), ref oMissing, ref oMissing, ref oMissing, ref oMissing); if(count sourceData.Tables[0].Rows.Count) oWord.Selection.InsertBreak(ref sectionStart); count++; } //SAVE THE FINAL DOC oFinalWordDoc.SaveAs(ref oOutputPath, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing); //CLOSE THE FINAL DOC oFinalWordDoc.Close(ref oFalse, ref oMissing, ref oMissing); System.Runtime.InteropServices.Marshal.ReleaseComO bject(oFinalWordDoc); oFinalWordDoc = null; //now delete the temp file File.Delete(oOutputPathTemp.ToString()); Log.Out(Log.LOGLEVEL_STANDARD, "DeviceLabelPrinter:SendAndReceive() Merge complete, printing document"); return true; } catch (System.Exception ex) { errorString = ex.Message; } finally { //RELEASE WORD ITSELF oWord.Quit(ref oMissing, ref oMissing, ref oMissing); System.Runtime.InteropServices.Marshal.ReleaseComO bject(oWord); oWord = null; GC.Collect(); } return false; } } } Peter Jamieson wrote: I need to be able to fill out these fields from a DataSet (DataTablewith n 29-Jan-07 I need to be able to fill out these fields from a DataSet (DataTable with n number of rows) using C#. All the guides I have been over all use some form of SQL datasource. That's because Word Mailmerge has no way to connect or bind to the data stored in internal objects in your program. It can only connect to data using a Word converter (internal/external), DDE, in the case of Access databases and Excel workbooks, ODBC and OLEDB (and it can't yet use an ADO.NET source, just in case you were wondering). Prior to Word 2007, you really have two options: a. turn your data source into something that Word can use, and use MailMerge b. don't use MailMerge - use C# to get the data from your DataSet and use methods in the Word object to insert that data into your postcasrd document. For example, you might be able to: - use a { DOCVARIABLE } field instead of a { MERGEFIELD { field as a "placeholder" for each item you want to insert - in C#, for each 3 rows in your DataSet, - copy the data in the DataSet into the relvant Word document variables - update the fields in the document - print/output the document There are other possibilities. A lot depends on whether you are trying to create a completely automated process or whether you are trying to create something where the users can edit the document and so on (in which case things obviously get a lot more complicated). In Word 2007 you have at least one other option, because you can bind things called "content controls" to data stored in your docx. However, that's about as much as I know about content controls - I suspect you would still have to serialize your DataSet into XML at some point to make use of them, but I really don't know yet. Peter Jamieson "Sparre" wrote in message oups.com... Previous Posts In This Thread: On Monday, January 29, 2007 4:03 AM Sparre wrote: Mail merge from C# using DataSet as datasource Hello I'm pretty new to the whole mailmerge deal and the various guides to mail merge haven't really helped me. I need to print out a series of documents each containing 3 "post cards", now I need to fill out the the names and adresses and other various information for each card. I have a Word template containing these 3 "cards" with a series of merge fields. I need to be able to fill out these fields from a DataSet (DataTable with n number of rows) using C#. All the guides I have been over all use some form of SQL datasource. How can I fill out eg. 13 of those "cards" using C# and a DataSet, and is there special requirements to the type of mailmerge fields I use ? Hope someone can help..... ![]() -- Sparre On Monday, January 29, 2007 6:51 AM Peter Jamieson wrote: I need to be able to fill out these fields from a DataSet (DataTablewith n I need to be able to fill out these fields from a DataSet (DataTable with n number of rows) using C#. All the guides I have been over all use some form of SQL datasource. That's because Word Mailmerge has no way to connect or bind to the data stored in internal objects in your program. It can only connect to data using a Word converter (internal/external), DDE, in the case of Access databases and Excel workbooks, ODBC and OLEDB (and it can't yet use an ADO.NET source, just in case you were wondering). Prior to Word 2007, you really have two options: a. turn your data source into something that Word can use, and use MailMerge b. don't use MailMerge - use C# to get the data from your DataSet and use methods in the Word object to insert that data into your postcasrd document. For example, you might be able to: - use a { DOCVARIABLE } field instead of a { MERGEFIELD { field as a "placeholder" for each item you want to insert - in C#, for each 3 rows in your DataSet, - copy the data in the DataSet into the relvant Word document variables - update the fields in the document - print/output the document There are other possibilities. A lot depends on whether you are trying to create a completely automated process or whether you are trying to create something where the users can edit the document and so on (in which case things obviously get a lot more complicated). In Word 2007 you have at least one other option, because you can bind things called "content controls" to data stored in your docx. However, that's about as much as I know about content controls - I suspect you would still have to serialize your DataSet into XML at some point to make use of them, but I really don't know yet. Peter Jamieson "Sparre" wrote in message oups.com... Submitted via EggHeadCafe - Software Developer Portal of Choice MSDE (Microsoft Data Engine) Performance http://www.eggheadcafe.com/tutorials...data-engi.aspx |
#4
![]()
Posted to microsoft.public.word.mailmerge.fields
|
|||
|
|||
![]()
A handy chunk of code, thanks!
Peter Jamieson http://tips.pjmsn.me.uk On 06/02/2010 17:35, Jason Jakob wrote: //Example Usage DataSet ds = new DataSet(); ds.Tables.Add("Leads"); ds.Tables[0].Columns.Add("Lead.Fullname"); ds.Tables[0].Columns.Add("Lead.Address1"); ds.Tables[0].Columns.Add("Lead.Address2"); ds.Tables[0].Columns.Add("Lead.City"); ds.Tables[0].Columns.Add("Lead.State"); ds.Tables[0].Columns.Add("Lead.Zip"); ds.Tables[0].Columns.Add("Lead.Country"); ds.Tables[0].Columns.Add("Owner.Fullname"); ds.Tables[0].Columns.Add("Owner.Phone1"); ds.Tables[0].Columns.Add("Owner.Email"); //generate sample data ds.Tables[0].Rows.Add("Dr. James Brown", "3456 Madison Ave.", "Suite 250", "New York", "NY", "10003", "USA", "Jason Jakob", "519-841-8617", "); ds.Tables[0].Rows.Add("Dr. Barry White", "The Bellagio", "Room 1021", "Las Vegas", "NV", "28011", "USA", "Jason Jakob", "519-841-8617", "); //now merge string errorString = ""; string templateFilename = @"C:\jason\Personal\MailMergeWebApp\bin\intro_lett er.dot"; string outputFilename = @"C:\jason\Personal\MailMergeWebApp\bin\intro_lett er_merged.doc"; if (!MailMerge.MergeDataWithWordTemplate(templateFile name, outputFilename, ds, out errorString)) { Console.WriteLine("Error"); } //Utility class to do the merging using System; using System.Collections.Generic; using System.Text; using System.Data; using System.IO; using TMMC.CommonLibrary; using Microsoft.Office; using Word = Microsoft.Office.Interop.Word; namespace MailMergeWebApp { public class MailMerge { public static bool MergeDataWithWordTemplate(string sourceTemplatePath, string outputDocPath, DataSet sourceData, out string errorString) { #region Declares errorString = ""; Object oMissing = System.Reflection.Missing.Value; //null value Object oTrue = true; Object oFalse = false; Object oTemplatePath = sourceTemplatePath; Object oOutputPath = outputDocPath; Object oOutputPathTemp = outputDocPath.Substring(0, outputDocPath.IndexOf(".doc")) + "_temp.doc"; Object sectionStart = (Object)Microsoft.Office.Interop.Word.WdSectionSta rt.wdSectionNewPage; Word.Application oWord = null; Word.Document oWordDoc = null; //the document to load into word application Word.Document oFinalWordDoc = null; //the document to load into word application #endregion try { oWord = new Word.Application(); //starts an instance of word oWord.Visible = false; //don't show the UI //create an empty document that we will insert all the merge docs into oFinalWordDoc = oWord.Documents.Add(ref oMissing, ref oMissing, ref oMissing, ref oMissing); //for each record in the dataset int count = 1; foreach (DataRow dr in sourceData.Tables[0].Rows) { Log.Out("MailMerge:CreateMergeDoc() adding a document for this record"); //insert a document for each record oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing); if (oWordDoc.Fields.Count == 0) { Log.Out("MailMerge:CreateMergeDoc() No template fields found in document:" + sourceTemplatePath); return false; } oWordDoc.Activate(); //make current // Perform mail merge field foreach (Word.Field myMergeField in oWordDoc.Fields) { Word.Range rngFieldCode = myMergeField.Code; String fieldText = rngFieldCode.Text; // ONLY GET THE MAILMERGE FIELDS if (fieldText.StartsWith(" MERGEFIELD")) { // THE TEXT COMES IN THE FORMAT OF // MERGEFIELD MyFieldName \\* MERGEFORMAT // THIS HAS TO BE EDITED TO GET ONLY THE FIELDNAME "MyFieldName" Int32 endMerge = fieldText.IndexOf("\\"); Int32 fieldNameLength = fieldText.Length - endMerge; String fieldName = fieldText.Substring(11, endMerge - 11); // GIVES THE FIELDNAMES AS THE USER HAD ENTERED IN .dot FILE //field names with spaces in them have quotes on either end, so strip those fieldName = fieldName.Trim().Replace("\"", ""); Log.Out(Log.LOGLEVEL_STANDARD, "DeviceLabelPrinter:SendAndReceive() found word template field: " + fieldName); //find a matching dataset column foreach (DataColumn col in sourceData.Tables[0].Columns) { string key = col.ColumnName; string value = dr[key].ToString(); // **** FIELD REPLACEMENT IMPLEMENTATION GOES HERE ****// // THE PROGRAMMER CAN HAVE HIS OWN IMPLEMENTATIONS HERE if (fieldName == key) { Log.Out(Log.LOGLEVEL_STANDARD, "DeviceLabelPrinter:SendAndReceive() setting value: " + value); myMergeField.Select(); oWord.Selection.TypeText(value); } } } } Log.Out(Log.LOGLEVEL_STANDARD, "DeviceLabelPrinter:SendAndReceive() saving the doc"); //SAVE THE DOCUMENT as temp oWordDoc.SaveAs(ref oOutputPathTemp, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing); Log.Out(Log.LOGLEVEL_STANDARD, "DeviceLabelPrinter:SendAndReceive() closing the doc"); //CLOSE THE DOCUMENT oWordDoc.Close(ref oFalse, ref oMissing, ref oMissing); System.Runtime.InteropServices.Marshal.ReleaseComO bject(oWordDoc); oWordDoc = null; //NOW ADD THE NEW DOC TO THE MAIN DOC oFinalWordDoc.Activate(); //make current oWord.Selection.InsertFile(oOutputPathTemp.ToStrin g(), ref oMissing, ref oMissing, ref oMissing, ref oMissing); if(count sourceData.Tables[0].Rows.Count) oWord.Selection.InsertBreak(ref sectionStart); count++; } //SAVE THE FINAL DOC oFinalWordDoc.SaveAs(ref oOutputPath, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing , ref oMissing, ref oMissing, ref oMissing, ref oMissing); //CLOSE THE FINAL DOC oFinalWordDoc.Close(ref oFalse, ref oMissing, ref oMissing); System.Runtime.InteropServices.Marshal.ReleaseComO bject(oFinalWordDoc); oFinalWordDoc = null; //now delete the temp file File.Delete(oOutputPathTemp.ToString()); Log.Out(Log.LOGLEVEL_STANDARD, "DeviceLabelPrinter:SendAndReceive() Merge complete, printing document"); return true; } catch (System.Exception ex) { errorString = ex.Message; } finally { //RELEASE WORD ITSELF oWord.Quit(ref oMissing, ref oMissing, ref oMissing); System.Runtime.InteropServices.Marshal.ReleaseComO bject(oWord); oWord = null; GC.Collect(); } return false; } } } Peter Jamieson wrote: I need to be able to fill out these fields from a DataSet (DataTablewith n 29-Jan-07 I need to be able to fill out these fields from a DataSet (DataTable with n number of rows) using C#. All the guides I have been over all use some form of SQL datasource. That's because Word Mailmerge has no way to connect or bind to the data stored in internal objects in your program. It can only connect to data using a Word converter (internal/external), DDE, in the case of Access databases and Excel workbooks, ODBC and OLEDB (and it can't yet use an ADO.NET source, just in case you were wondering). Prior to Word 2007, you really have two options: a. turn your data source into something that Word can use, and use MailMerge b. don't use MailMerge - use C# to get the data from your DataSet and use methods in the Word object to insert that data into your postcasrd document. For example, you might be able to: - use a { DOCVARIABLE } field instead of a { MERGEFIELD { field as a "placeholder" for each item you want to insert - in C#, for each 3 rows in your DataSet, - copy the data in the DataSet into the relvant Word document variables - update the fields in the document - print/output the document There are other possibilities. A lot depends on whether you are trying to create a completely automated process or whether you are trying to create something where the users can edit the document and so on (in which case things obviously get a lot more complicated). In Word 2007 you have at least one other option, because you can bind things called "content controls" to data stored in your docx. However, that's about as much as I know about content controls - I suspect you would still have to serialize your DataSet into XML at some point to make use of them, but I really don't know yet. Peter Jamieson wrote in message oups.com... Previous Posts In This Thread: On Monday, January 29, 2007 4:03 AM Sparre wrote: Mail merge from C# using DataSet as datasource Hello I'm pretty new to the whole mailmerge deal and the various guides to mail merge haven't really helped me. I need to print out a series of documents each containing 3 "post cards", now I need to fill out the the names and adresses and other various information for each card. I have a Word template containing these 3 "cards" with a series of merge fields. I need to be able to fill out these fields from a DataSet (DataTable with n number of rows) using C#. All the guides I have been over all use some form of SQL datasource. How can I fill out eg. 13 of those "cards" using C# and a DataSet, and is there special requirements to the type of mailmerge fields I use ? Hope someone can help..... ![]() -- Sparre On Monday, January 29, 2007 6:51 AM Peter Jamieson wrote: I need to be able to fill out these fields from a DataSet (DataTablewith n I need to be able to fill out these fields from a DataSet (DataTable with n number of rows) using C#. All the guides I have been over all use some form of SQL datasource. That's because Word Mailmerge has no way to connect or bind to the data stored in internal objects in your program. It can only connect to data using a Word converter (internal/external), DDE, in the case of Access databases and Excel workbooks, ODBC and OLEDB (and it can't yet use an ADO.NET source, just in case you were wondering). Prior to Word 2007, you really have two options: a. turn your data source into something that Word can use, and use MailMerge b. don't use MailMerge - use C# to get the data from your DataSet and use methods in the Word object to insert that data into your postcasrd document. For example, you might be able to: - use a { DOCVARIABLE } field instead of a { MERGEFIELD { field as a "placeholder" for each item you want to insert - in C#, for each 3 rows in your DataSet, - copy the data in the DataSet into the relvant Word document variables - update the fields in the document - print/output the document There are other possibilities. A lot depends on whether you are trying to create a completely automated process or whether you are trying to create something where the users can edit the document and so on (in which case things obviously get a lot more complicated). In Word 2007 you have at least one other option, because you can bind things called "content controls" to data stored in your docx. However, that's about as much as I know about content controls - I suspect you would still have to serialize your DataSet into XML at some point to make use of them, but I really don't know yet. Peter Jamieson wrote in message oups.com... Submitted via EggHeadCafe - Software Developer Portal of Choice MSDE (Microsoft Data Engine) Performance http://www.eggheadcafe.com/tutorials...data-engi.aspx |
Reply |
Thread Tools | |
Display Modes | |
|
|
![]() |
||||
Thread | Forum | |||
Heavy Mail Merge Application | Mailmerge | |||
Can't get Word 2003 to keep data file with mail merge main documen | Mailmerge | |||
Editing Mail Merge Recipients | Mailmerge | |||
Word datasource sort doesn't sort all records in mail merge | Mailmerge | |||
Word-Excel 2003 - Mail Merge Recipients problem | Mailmerge |