Creating a nested field with Word.Interop

僤鯓⒐⒋嵵緔 提交于 2019-12-12 09:55:17

问题


I'm playing around with VSTO, more precisely with C# and a "Microsoft Word" application add-in, at the moment. I do want to programmatically create nested fields. I've come up with the following source code (for testing purposes):

public partial class ThisAddIn
{
    private void ThisAddIn_Startup(object sender, EventArgs e)
    {
        // TODO This is just a test.
        this.AddDocPropertyFieldWithinInsertTextField("Author", ".\\\\FileName.docx");
    }

    private void AddDocPropertyFieldWithinInsertTextField(string propertyName, string filePath)
    {
        // TODO Horrible, since we rely on the UI state.
        this.Application.ActiveWindow.View.ShowFieldCodes = true;

        Word.Selection currentSelection = this.Application.ActiveWindow.Selection;

        // Add a new DocProperty field at the current selection.
        currentSelection.Fields.Add(
            Range: currentSelection.Range,
            Type: Word.WdFieldType.wdFieldDocProperty,
            Text: propertyName,
            PreserveFormatting: false
        );

        // TODO The following fails if a DocProperty with the specified name does not exist.

        // Select the previously inserted field.
        // TODO This is horrible!
        currentSelection.MoveLeft(
            Unit: Word.WdUnits.wdWord,
            Count: 1,
            Extend: Word.WdMovementType.wdExtend
        );

        // Create a new (empty) field AROUND the DocProperty field.
        // After that, the DocProperty field is nested INSIDE the empty field.
        // TODO Horrible again!
        currentSelection.Fields.Add(
            currentSelection.Range,
            Word.WdFieldType.wdFieldEmpty,
            PreserveFormatting: false
        );

        // Insert text BEFORE the inner field.
        // TODO Horror continues.
        currentSelection.InsertAfter("INCLUDETEXT \"");

        // Move the selection AFTER the inner field.
        // TODO See above.
        currentSelection.MoveRight(
            Unit: Word.WdUnits.wdWord,
            Count: 1,
            Extend: Word.WdMovementType.wdExtend
        );

        // Insert text AFTER the nested field.
        // TODO See above.
        currentSelection.InsertAfter("\\\\" + filePath + "\"");

        // TODO See above.
        this.Application.ActiveWindow.View.ShowFieldCodes = false;

        // Update the fields.
        currentSelection.Fields.Update();
    }

Although the provided code covers the requirements, it has some major problems (as you can see if reading some of the code comments), e.g.:

  1. It isn't robust, since it relies on the UI state of the application.
  2. Is is verbose. The task isn't that complex, imo.
  3. It isn't easy to understand (Refactoring could help, but by solving problems 1. and 2., this drawback should disappear).

I did some research on the WWW, but haven't been able to find a clean solution, yet.

So, my question is:

  • Can someone provide (alternative) C# source code, that is more robust than mine and that allows me to add nested fields to a "Microsoft Word" document?

回答1:


I've created a generic implementation to create both non-nested and nested fields with VSTO for Microsoft Word. You can see the relevant source code in this Gist. I've ported the VBA source code from the article Nested Fields in VBA to C# and applied some improvements.

Still not perfect (needs some additional error handling), but far better than a solution with a Selection object, which relies on the state of the user interface!



来源:https://stackoverflow.com/questions/16774411/creating-a-nested-field-with-word-interop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!