选择 Word 互操作标题范围会导致 Word 切换到草稿视图

Posted

技术标签:

【中文标题】选择 Word 互操作标题范围会导致 Word 切换到草稿视图【英文标题】:Selecting a Word Interop Header Range causes Word to switch to Draft View 【发布时间】:2012-12-05 19:53:42 【问题描述】:

使用.Select() 选择标题范围时,Microsoft Word 会自动从我当前的视图类型(打印布局)切换到草稿视图。如何阻止 Word 切换到草稿视图?

以下代码示例演示了我在做什么:

 // this.Document is a Microsoft.Office.Interop.Word.Document
 Section section = this.Document.Sections.First;
 foreach (HeaderFooter header in section.Headers)
 
   if (header.Exists) 
   
     header.Range.Select(); // When I call this, Word switches to Draft View.
     break;
   
 

编辑(3):

显然保存视图类型并重置它确实有效。但是,当 Word 切换到草稿视图然后返回到打印布局时,这会导致令人讨厌的闪烁。此外,当我双击主文档空间以退出页眉部分时,Word 切换回草稿视图。

 WdViewType viewType = this.Document.ActiveWindow.View.Type;
 range.Select();
 this.Document.ActiveWindow.View.Type = viewType;

【问题讨论】:

发现了一个抛出异常的场景 - 请参阅我的修复答案 【参考方案1】:

在选择范围之前,必须为除 wdNormalView(草稿视图)之外的所有视图类型设置 View.SeekView 属性。

var window = this.Document.ActiveWindow;
// wdNormalView == Draft View, where SeekView can't be used and isn't needed.
if (window.View.Type != WdViewType.wdNormalView)

  // -1 Not Header/Footer, 0 Even page header, 1 Odd page header, 4 First page header
  // 2 Even page footer, 3 Odd page footer, 5 First page footer
  int rangeType = range.Information[WdInformation.wdHeaderFooterType];
  if (rangeType == 0 || rangeType == 1 || rangeType == 4)
    window.View.SeekView = WdSeekView.wdSeekCurrentPageHeader;
  if (rangeType == 2 || rangeType == 3 || rangeType == 5)
    window.View.SeekView = WdSeekView.wdSeekCurrentPageFooter;

header.Range.Select();

【讨论】:

发现了一个抛出异常的场景 - 请参阅我的修复答案【参考方案2】:

7 年后,但在我的 Word VSTO Addin 中使用 Joe W 的答案时,我遇到了一个问题并决定在此处发布修复:

View.SeekView 设置为WdSeekView.wdSeekCurrentPageHeaderWdSeekView.wdSeekCurrentPageFooter 之前,检查View.SeekView 是否已设置为页眉或页脚值。如果是,则抛出异常,因为如果View.SeekView 已设置为标头值,则当前View.SeekView 无法更改为wdSeekCurrentPageHeader,并且当前View.SeekView 无法更改为wdSeekCurrentPageFooter,如果View.SeekView 已设置为页脚值。如果在执行代码以调整视图设置(例如,在 Word VSTO 插件中)时用户正在编辑页眉或页脚,则可能会出现这种情况。

此代码有效。它包含在调用SetView 之前保存View.SeekView 设置并在调用SetView 之后将其重置的代码。这考虑到用户在调用 SetView 时正在编辑页眉或页脚的场景,就像在 Word VSTO Addin 中可能出现的情况一样。

// ... some Word VSTO Addin code that calls SetView 

Word.WdSeekView enumSavedSeekView = Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.SeekView;

bool viewResetNeeded = SetView(workingStoryRange);

if (viewResetNeeded)

    Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.SeekView = enumSavedSeekView;


// ... end of some Word VSTO Addin code that calls SetView 

private bool SetView(Word.Range range)

    bool viewResetNeeded = false;

    // wdNormalView == Draft View, where SeekView can't be used and isn't needed.
    if (Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.Type != Word.WdViewType.wdNormalView)
    
        // -1 Not Header/Footer, 0 Even page header, 1 Odd page header, 4 First page header
        // 2 Even page footer, 3 Odd page footer, 5 First page footer

        switch (range.Information[Word.WdInformation.wdHeaderFooterType])
        
            case 0:
            case 1:
            case 4:

                if ((Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.SeekView != Word.WdSeekView.wdSeekEvenPagesHeader) && (Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.SeekView != Word.WdSeekView.wdSeekFirstPageHeader) && (Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.SeekView != Word.WdSeekView.wdSeekPrimaryHeader))
                
                    Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.SeekView = Word.WdSeekView.wdSeekCurrentPageHeader;
                    viewResetNeeded = true;
                

                break;

            case 2:
            case 3:
            case 5:

                if ((Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.SeekView != Word.WdSeekView.wdSeekEvenPagesFooter) && (Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.SeekView != Word.WdSeekView.wdSeekFirstPageFooter) && (Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.SeekView != Word.WdSeekView.wdSeekPrimaryFooter))
                
                    Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.View.SeekView = Word.WdSeekView.wdSeekCurrentPageFooter;
                    viewResetNeeded = true;
                

                break;

            default:
                break;
        
    

    return viewResetNeeded;

【讨论】:

【参考方案3】:

您可以利用范围对象中的 Words 集合来选择标题

 Section section = this.Document.Sections.First;
 foreach (HeaderFooter header in section.Headers)
 
   if (header.Exists) 
   
     header.Range.Words.First.Select()
     break;
   
 

【讨论】:

我在选择标题时没有任何问题......这就是header.Range.Select(); 正在做的事情。当我选择标题时,Word 切换到草稿视图时遇到问题。 @Joe W 我知道为什么我提供了代码。它选择标题并且不切换到草稿视图。 除非我做错了什么,否则我尝试了您的确切代码,但它不起作用。它仍然切换到草稿视图,但现在它只选择标题中的第一个单词而不是整个范围。

以上是关于选择 Word 互操作标题范围会导致 Word 切换到草稿视图的主要内容,如果未能解决你的问题,请参考以下文章

在 VB.NET 中使用 Word 和 Outlook 2007 的 Office 互操作

System.UnauthorizedAccessException:检索 Word 互操作的 COM 类工厂失败并出现错误 80070005

无法嵌入互操作类型“ApplicationClass”。请改用适用的接口 - Microsoft.Office.Interop.Word.ApplicationClass

从 Javascript 插件控制 Word 文档中的选择范围

Java + OpenOffice,互操作自动化真的这么难吗?

如何在word中指定范围,在指定位置自动生成目录?