我的Word C#VSTO加载项有助于为邮件合并生成专用标签。将在文档中创建邮件标签,并以编程方式填充标签“表”中的第一个标签:
Word.Field myField = myCell.Range.Fields.Add(range, missing, missing, missing);
myField.Code.Text = " MERGEFIELD MyField ";
现在,当Word为邮件合并创建邮件标签时,它将字段代码放在下一条记录的位置:它们在Word中看起来像{ NEXT }
或«Next Record»
。
在Word的“邮件”标签中,有一个名为Update Labels的内置按钮。其Office控件ID为MailMergeUpdateLabels
。如果您打开了邮件标签表,它将将第一个标签中的所有内容复制到每个有效标签空间中。它还可以确保«Next Record»
字段在第一个标签之后开始于每个标签,以便邮件合并可以插入下一个记录。
Before Update Labels / After Update Labels
我需要通过C#以编程方式触发此操作。如果我告诉用户“请转到邮件选项卡并按更新标签按钮”,那将非常厚颜无耻。我可以想到三种解决方法:
通过Word Interop触发“更新标签”按钮所使用的相同方法。
myObject.Range.Fields.Update()
并没有做到这一点。)。引用按钮并模拟点击。
updateButton.PerformClick();
,但我不知道如何通过Interop公开内置按钮,以便可以在我的代码中引用它。编写一种实现相同结果的方法。毕竟,我可能正在追逐XY Problem。
作为参考,这是我用来填充单个标签单元格的方法:
private void InsertIntoCell(Word.Cell cell, bool insertNextField)
{
string[] fieldCodes = { @" NEXT ",
@" MERGEFIELD Name ",
@" MERGEFIELD SerialNumber \b "": "" ",
"\v",
@" MERGEBARCODE Barcode CODE128 " };
cell.Range.Delete();
Word.Range range = cell.Range;
range.Collapse(WdCollapseDirection.wdCollapseStart);
foreach(string fieldCode in fieldCodes)
{
//the NEXT field is the first one in the fieldcodes array
//skip it if the program asks not to insert it
if (!insertNextField)
{
insertNextField = true;
continue;
}
//if the field codes demand a Vertical Tab character
//write it, because word reads it as a newline character
if(fieldCode.Equals("\v"))
{
range.Text = fieldCode;
range.Move(WdUnits.wdCharacter, 1);
continue;
}
Word.Field field = cell.Range.Fields.Add(range, missing, missing, missing);
field.Code.Text = fieldCode;
//move the range to the end of the most recent field
range = field.Result;
range.Collapse(WdCollapseDirection.wdCollapseEnd);
}
//set font, update the fields to make them visible
cell.Range.Font.Size = FIELD_FONT_SIZE;
cell.Range.Fields.Update();
}
同样,这种方式非常慢。我可以使用选择并以编程方式复制粘贴(是的,使用用户的剪贴板),但这似乎很脏。即使这样,“更新标签”仍然具有优越性,因为它“知道” «Next Record»
在用户删除的地方。
我最想知道选项2 的实现方式。如果向我展示了如何将“更新标签”按钮展示给点击,那么我可以学习将任何按钮展示给模拟点击。
答案 0 :(得分:2)
是的,可以同时执行选项1和选项2。这两种方法都有些晦涩,因此没有遇到它们就不足为奇了。
选项1 :由于某种奇怪的原因,该命令未包含在标准对象模型中。但是可以通过 late bound WordBasic
对象模型进行访问。 (实际上,Word中的所有命令都有相应的WordBasic
实现,因为在幕后仍然可以运行所有内容。但是它们没有文档说明。)
VB语言可以直接使用它。但是,C#无法直接与后期绑定的对象一起使用,因此需要PInvoke:
object wordBasic = wdApp.GetType().InvokeMember("WordBasic", BindingFlags.GetProperty, null, wdApp, null);
wordBasic.GetType().InvokeMember("MailMergePropagateLabel", BindingFlags.InvokeMethod, null, wordBasic, null);
选项2 :所有Office应用程序都可以访问共享对象模型的CommandBars
部分。最初,它负责菜单和工具栏用户界面(Office 2007之前的版本)。在Office 2007中,此功能已由Ribbon UI取代,保留了该对象是为了实现向后兼容性,进行了扩展,以便与Ribbon UI进行有限的交互。
ExecuteMso
是这些“新”方法之一,它执行按钮命令就像被单击一样:
wdApp.CommandBars.ExecuteMso("MailMergeUpdateLabels");