我编写了以下代码,允许用户根据将要打印的word文档和数据源(不同系统)查询数据,他们可以选择SOURCE1,SOURCE2或BOTH。查询数据,将其放入ODBC DataReader中,然后循环以填充ListView控件。
然后,我允许用户选择要打印的记录,并将这些记录作为邮件合并操作处理到选定的Word文档中。
我现在要做的是将每个单词文档页面(邮件合并的每个记录)保存到具有自己名称的特定文件夹位置。
代码:
private void btnSearch_Click(object sender, EventArgs e)
{
lvData.Clear();
string qryCmd = "";
createColumns();
switch (cmbLetterType.SelectedIndex)
{
case 0:
qryCmd = chkSystem("oldAddr");
break;
case 1:
qryCmd = chkSystem("newAddr");
break;
case 2:
qryCmd = chkSystem("nameChg");
break;
}
// If the option for BOTH is selected, qryCmd is a long string containing the individual queries for SOURCE1 and SOURCE2.
// Here I check if a semicolon (;) exists, denoting that there are 2 cmd queries in the string.
// If so, I split the query calling GetiSeriesData() with the first query string, then assigning qryCmd the second
// strings value and continuing processing as normal.
if (qryCmd.Contains(";"))
{
char[] delimitChar = { ';' };
string[] splitQueries = qryCmd.Split(delimitChar);
qryCmd = splitQueries[0];
GetiSeriesData(qryCmd);
qryCmd = splitQueries[1];
}
GetiSeriesData(qryCmd);
// Display message if no records found.
if (lvData.Items.Count == 0)
{
MessageBox.Show("No records found.");
}
lblRecCnt.Text = lvData.Items.Count.ToString();
this.lvData.CheckBoxes = true;
}
public void GetiSeriesData(string query)
{
OdbcDataReader dr;
try
{
//Set value of system based on table being looked at in ConnectionString
string sysValue = "";
if (query.Contains("lib1"))
{
sysValue = "P";
}
if (query.Contains("lib2"))
{
sysValue = "N";
}
MergeDocLibrary mdl = new MergeDocLibrary();
dr = mdl.GetData(query);
Int16 x = 0;
string gndr = "";
// Fill ListView Control lvData
while (dr.Read())
{
lvData.Items.Add(dr["MEMNO"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["NAME"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["ADDR1"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["ADDR2"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["CITY"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["STATE"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["ZIP"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["OLD_ADDR1"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["OLD_ADDR2"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["OLD_CITY"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["OLD_STATE"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["OLD_ZIP"].ToString().Trim());
lvData.Items[x].SubItems.Add(sysValue.ToString().Trim());
lvData.Items[x].SubItems.Add(DateTime.Today.ToString("d"));
lvData.Items[x].SubItems.Add(dr["SEX"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["LNAME"].ToString().Trim());
if (dr["SEX"].ToString().Trim() == "M")
{
gndr = "Mr.";
}
else // (dr["SEX"].ToString().Trim() == "F)
{
gndr = "Ms.";
}
lvData.Items[x].SubItems.Add(gndr + dr["LNAME"].ToString().Trim());
lvData.Items[x].SubItems.Add(dr["CITY"].ToString().Trim() + ", " + dr["STATE"].ToString().Trim() + " " + dr["ZIP"].ToString().Trim());
x += 1;
}
mdl.closeConn();
}
catch (Exception ex)
{
MessageBox.Show("Source:\t" + ex.Source + "\nMessage: \t" + ex.Message + "\nData:\t" + ex.Data);
}
finally
{
}
}
public void OpenAndReview()
{
try
{
string docSave = @"C:\Users\NAME\Desktop\Test.doc";
//MergeDocLibrary mdl = new MergeDocLibrary();
//mdl.mergeDocument(docSource, docLoc);
// Original Mail Merge Document
Word.Range rng;
object start = 0;
object end = 0;
Word.Range newWrdRng;
Word.Application oWord = new Word.Application();
Word.Document oWrdDoc = new Word.Document();
// New Document Instance
Word.Application oNewWord = new Word.Application();
Word.Document oNewWrdDoc = new Word.Document();
// Set 'False' in PROD, 'True' in DEV
oWord.Visible = true;
oNewWord.Visible = true;
Object oTemplatePath = docLoc;
// Open Mail Merge Doc
oWrdDoc = oWord.Documents.Open(oTemplatePath);
// Open New Document
oNewWrdDoc = oNewWord.Documents.Open(docSave);
Object oMissing = System.Reflection.Missing.Value;
// Open Mail Merge Datasource
oWrdDoc.MailMerge.OpenDataSource(docSource, oMissing, oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);
// Execute Mail Merge
oWrdDoc.MailMerge.Execute();
// Set Mail Merge Document as Active Doc
//oWrdDoc.Activate();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MessageBox.Show(oWord.ActiveDocument.Sections.Count.ToString());
// 3 Records selected gives 4 Sections Counted??
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Subtract 1 to account for the extra section being counted?
int docCnt = oWord.ActiveDocument.Sections.Count - 1;
int cnt = 0;
while (cnt != docCnt)
{
cnt++;
// Copy Desired Section from Mail Merge
oWord.ActiveDocument.Sections[cnt].Range.Copy();
// Set focus to the New Word Doc instance
oNewWord.Activate();
// Paste copied range to New Word Doc
oNewWord.ActiveDocument.Range(0, 0).Paste();
// Save New Word Doc
oNewWord.ActiveDocument.SaveAs2(@"C:\Users\NAME\Desktop\SuccesfullySavedDoc-" + cnt + ".doc");
// Clear New Word Doc
oNewWord.ActiveDocument.Content.Select();
oNewWord.Selection.TypeBackspace();
// Set Mail Merge as Active Document
oWord.Activate();
}
// .............
// Save new docuemnt...?
oNewWrdDoc.SaveAs2("SuccesfullySavedTest.doc");
}
catch (Exception ex)
{
MessageBox.Show("Source:\t" + ex.Source + "\nMessage: \t" + ex.Message + "\nData:\t" + ex.Data);
}
finally
{
//
}
}
...
EDIT3 :我已经清除了每个新循环迭代的文档。现在试图找出为什么每个文档都使用额外的空白页2进行保存。
粗略大纲:
Doc 1:记录1 +一个额外的空白页面(不确定为什么?)
文件2:记录2 +一个额外的空白页面(不确定为什么?)
Doc 3:REcord 3 +一个额外的空白页面(不确定为什么?)
答案 0 :(得分:0)
几点:
一个或两个常用的免费第三方Addin用于保存多个命名文档,确实有可见的VBA代码,您可以考虑在C#中重新设计/重写。
我以前使用的是一段代码,它为数据源中的每条记录执行一次合并。有人发布了我的旧代码at the end of their message here的一个版本。
所有这些方法都可能由于多种原因而失败。第三方方法有时会生成单个输出,然后在每个分节符时分割输出。这仅适用于某些合并类型,并且在邮件合并主文档中没有其他分节符的情况下。 “my”代码仅在合并一次消耗一条记录时才有效(显然,它可以适用于每个合并等2条记录,但如果邮件合并主文档包含NEXT,NEXTIF或SKIPIF字段,那么每个合并消耗的记录可能会有所不同,问题是AFAIK无法检测消耗了多少记录(除非您可以依赖于在邮件合并主文档中放置一个计数器。)
至于其他方面,我认为你需要改变这一部分:
Word.Application oWord = new Word.Application();
Word.Document oWrdDoc = new Word.Document();
// New Document Instance
Word.Application oNewWord = new Word.Application();
Word.Document oNewWrdDoc = new Word.Document();
因为(除非C#或其他东西正在做我不知道的事情),不能保证新的Word.Document对象将通过您刚刚创建的任何Word.Application实例创建。我认为你需要更像
的东西Word.Document oWrdDoc = oWord.Documents.Add(); // you may need to provide some parameters here in C#
同样适用于oNewWrdDoc
一旦你创建了这些,我认为rng.FormattedText将会消失或者更容易解决。