首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C# Word Interop:在邮件中使用内置的“更新标签”功能

C# Word Interop:在邮件中使用内置的“更新标签”功能
EN

Stack Overflow用户
提问于 2018-08-26 00:23:30
回答 1查看 712关注 0票数 2

我的C# VSTO外接程序帮助生成邮件合并的专用标签.邮件标签是在文档中创建的,标签“表”中的第一个标签是以编程方式填充的:

代码语言:javascript
复制
Word.Field myField = myCell.Range.Fields.Add(range, missing, missing, missing);
myField.Code.Text = " MERGEFIELD MyField ";

现在,当Word为邮件合并创建邮件标签时,它会将字段代码放在下一个记录所在的位置:它们在Word中看起来像{ NEXT }«Next Record»

在Word的"Mailings“选项卡中,有一个名为更新标签的内置按钮。其Office为MailMergeUpdateLabels。如果打开了邮件标签表,它将将第一个标签中的所有内容复制到每个有效的标签空间中。它还确保«Next Record»字段在第一个标签之后开始每个标签,以便邮件合并可以插入下一个记录。

更新标签之前 / 更新标签后

我需要通过C#以编程方式触发此操作。如果我告诉用户“请转到mailings选项卡并按”更新标签“按钮”,那将是非常厚颜无耻的。我可以想出三种方法来解决这个问题:

  1. 触发与“更新标签”按钮通过Word Interop.使用的相同方法
代码语言:javascript
复制
- I've done a deep dive through the MSDN reference for Word Interop in C#. I have found no such method (and no, `myObject.Range.Fields.Update()` does not accomplish this.).

  1. 引用按钮并模拟单击.
代码语言:javascript
复制
- Something like `updateButton.PerformClick();`, but I have no idea how to expose the built-in button through Interop so that I could reference it in my code.

  1. 编写了一个实现相同结果的方法。毕竟,我可能是在追XY问题.
代码语言:javascript
复制
- I already wrote one. Unfortunately, it's very slow (~7 seconds for a page of 30 labels). The most time-consuming operation seems to be adding the fields to the ranges. The "Update Labels" button's effect is very flexible and near-instantaneous.

作为参考,下面是我用来填充单个标签单元格的方法:

代码语言:javascript
复制
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的实现方式很好奇。如果向我展示了如何将“更新标签”按钮公开给单击,我可以学习向模拟单击公开任何按钮。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-26 06:23:55

是的,可以同时使用选项1和选项2,这两种方法都有点模糊,所以您没有遇到它们也就不足为奇了。

选项1:由于一些奇怪的原因,该命令没有包含在标准对象模型中。但是它可以通过后期绑定的WordBasic对象模型访问。(实际上,Word中的所有命令都有相应的WordBasic实现,因为幕后仍然运行着所有的东西。但它们没有记录.)

VB语言可以直接使用。但是,C#不能直接处理绑定晚的对象,因此需要PInvoke:

代码语言:javascript
复制
object wordBasic = wdApp.GetType().InvokeMember("WordBasic", BindingFlags.GetProperty, null, wdApp, null);
wordBasic.GetType().InvokeMember("MailMergePropagateLabel", BindingFlags.InvokeMethod, null, wordBasic, null);

选项2:所有应用程序都可以访问共享对象模型的CommandBars部分。最初,这是负责菜单和工具栏的用户界面(预Office 2007).在Office 2007中,该对象被Ribbon取代,该对象被保留为向后兼容性,并扩展为与Ribbon的有限交互。

这些“新”方法之一是ExecuteMso,它执行按钮命令,就像单击了按钮一样:

代码语言:javascript
复制
wdApp.CommandBars.ExecuteMso("MailMergeUpdateLabels");
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52022278

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档