简体   繁体   English

Word Interop:如何根据Find命令的结果设置插入点?

[英]Word Interop: How do I set an insertion point based on the results of a Find command?

Note: Code is based on the approach documented in Using a macro to replace text where ever it appears in a document 注意:代码基于使用宏替换文档中出现的文本中所述的方法。

My goal is to insert a new paragraph immediately after a word found in the first page header using Word Interop Find.Execute . 我的目标是使用Word Interop Find.Execute在第一页标题中找到的单词之后立即插入一个新段落。 To do this, I need an insertion point (type == wdSelectionIP ) at either the beginning or the end of the found word. 为此,我需要在找到的单词的开头或结尾插入一个插入点(类型== wdSelectionIP )。

My assumption is/was that as a result of finding the word in the first page header using Word Interop Find.Execute , Word will set an insertion point (type == wdSelectionIP ) at either the beginning or at the end of the found word. 我的假设是/由于使用Word Interop Find.Execute在首页标题中找到单词,因此Word将在找到的单词的开头或结尾设置一个插入点(类型== wdSelectionIP )。 You can see this in my SomeEventMethod_Click method, ie, under this assumption, after I find the word, I navigate to the end of the line, create a new, empty paragraph, set some attributes, then type in some text. 您可以在SomeEventMethod_Click方法中看到这一点,即,在这种假设下,找到单词后,我导航到行尾,创建一个新的空段落,设置一些属性,然后键入一些文本。

The text is typed in, but it's not following the word found in the first page header. 键入了文本,但没有在首页标题中找到该单词。 Rather, the text is typed in the main text area (ie, the body of the document) at the bottom of the last page. 而是在最后一页底部的主文本区域(即文档的正文)中键入文本。

How do I set an insertion point based on the results of a Find command? 如何根据“查找”命令的结果设置插入点?

Class use to report find and replace results 类使用来报告查找和替换结果

private class ClsFindReplaceResults
{
    bool isFound = false;
    Microsoft.Office.Interop.Word.Selection selection = null;

    public ClsFindReplaceResults(bool isFound, Selection selection)
    {
        this.IsFound = isFound;
        this.Selection = selection;
    }

    public bool IsFound { get => isFound; set => isFound = value; }
    public Selection Selection { get => selection; set => selection = value; }
}

Event method from which FindReplaceAnywhere method is called 从中调用FindReplaceAnywhere方法的事件方法

private void SomeEventMethod_Click(object sender, RibbonControlEventArgs e)
{
    //Find the text 'foo\r'. No replacement. I just want the insertion point
    ClsFindReplaceResults objFindReplaceResults = FindReplaceAnywhere(findText: "foo^p", replaceWithText: null, enumWdStoryType: WdStoryType.wdFirstPageHeaderStory);

    if (objFindReplaceResults.IsFound)
    {
        objFindReplaceResults.Selection.EndKey(WdUnits.wdStory);
        objFindReplaceResults.Selection.TypeParagraph();
        objFindReplaceResults.Selection.Font.Size = 9;
        objFindReplaceResults.Selection.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphJustify;
        objFindReplaceResults.Selection.ParagraphFormat.SpaceAfter = 6f;
        objFindReplaceResults.Selection.TypeText("new paragraph that should appear after 'foo^p'");
    }
}

FindReplaceAnywhere method FindReplaceAnywhere方法

private ClsFindReplaceResults FindReplaceAnywhere(string findText, string replaceWithText, WdStoryType enumWdStoryType)
{
    bool found = false;
    object wfrFindText = findText;
    object wfrMatchCase = true;
    object wfrMatchWholeWord = true;
    object wfrMatchWildCards = false;
    object wfrMatchSoundsLike = false;
    object wfrMatchAllWordForms = false;
    object wfrForward = true;
    object wfrWrap = WdFindWrap.wdFindContinue;
    object wfrFormat = false;
    object wfrReplaceWith = replaceWithText;
    object wfrReplace = null;

    if (wfrReplaceWith == null)
    {
        wfrReplace = WdReplace.wdReplaceNone;
    }
    else
    {
        wfrReplace = WdReplace.wdReplaceOne;
    }

    object wfrMatchKashida = false;
    object wfrMatchDiacritics = false;
    object wfrMatchAlefHamza = false;
    object wfrMatchControl = false;

    Globals.ThisAddIn.Application.Selection.Find.ClearFormatting();
    Globals.ThisAddIn.Application.Selection.Find.Replacement.ClearFormatting();

    //Fix the skipped blank Header/Footer problem as provided by Peter Hewett. Don't know what the heck this does
    WdStoryType junk = Globals.ThisAddIn.Application.ActiveDocument.Sections[1].Headers[Microsoft.Office.Interop.Word.WdHeaderFooterIndex.wdHeaderFooterPrimary].Range.StoryType;

    Microsoft.Office.Interop.Word.Range workingStoryRange = null;

    foreach (Microsoft.Office.Interop.Word.Range storyRange in Globals.ThisAddIn.Application.ActiveDocument.StoryRanges)
    {
        if (storyRange.StoryType != enumWdStoryType)
        {
            continue;
        }

        workingStoryRange = storyRange;

        do
        {
            // Find and replace text in the current story
            found = workingStoryRange.Find.Execute(FindText: ref wfrFindText, MatchCase: ref wfrMatchCase, MatchWholeWord: ref wfrMatchWholeWord, MatchWildcards: ref wfrMatchWildCards, MatchSoundsLike: ref wfrMatchSoundsLike, MatchAllWordForms: ref wfrMatchAllWordForms, Forward: ref wfrForward, Wrap: ref wfrWrap, Format: ref wfrFormat, ReplaceWith: ref wfrReplaceWith, Replace: ref wfrReplace, MatchKashida: ref wfrMatchKashida, MatchDiacritics: ref wfrMatchDiacritics, MatchAlefHamza: ref wfrMatchAlefHamza, MatchControl: ref wfrMatchControl);

            // The call to SearchAndReplaceInStory above misses text that is contained in a StoryType/StoryRange nested in a different 
            // StoryType /StoryRange. While this won't occur with a nested StoryType/StoryRange in the wdMainTextStory StoryRange, it 
            // will occur in header and footer type StoryRanges. An example is textbox that is located in a header or footer. The fix 
            // makes use of the fact that Textboxes and other Drawing Shapes are contained in a document’s ShapeRange collection. 
            // Check the ShapeRange in each of the six header and footer StoryRanges for the presence of Shapes. If a Shape is found, 
            // check each Shape for the presence of the text, and finally, if the Shape contains text we set our search range to that 
            // Shape's .TextFrame.TextRange. 
            switch (workingStoryRange.StoryType)
            {
                // Case 6 , 7 , 8 , 9 , 10 , 11
                case Microsoft.Office.Interop.Word.WdStoryType.wdEvenPagesHeaderStory:
                case Microsoft.Office.Interop.Word.WdStoryType.wdPrimaryHeaderStory:
                case Microsoft.Office.Interop.Word.WdStoryType.wdFirstPageHeaderStory:
                case Microsoft.Office.Interop.Word.WdStoryType.wdEvenPagesFooterStory:
                case Microsoft.Office.Interop.Word.WdStoryType.wdPrimaryFooterStory:
                case Microsoft.Office.Interop.Word.WdStoryType.wdFirstPageFooterStory:

                    if (workingStoryRange.ShapeRange.Count > 0)
                    {
                        foreach (Microsoft.Office.Interop.Word.Shape shape in workingStoryRange.ShapeRange)
                        {
                            if (shape.TextFrame.HasText != 0)
                            {
                                found = shape.TextFrame.TextRange.Find.Execute(FindText: ref wfrFindText, MatchCase: ref wfrMatchCase, MatchWholeWord: ref wfrMatchWholeWord, MatchWildcards: ref wfrMatchWildCards, MatchSoundsLike: ref wfrMatchSoundsLike, MatchAllWordForms: ref wfrMatchAllWordForms, Forward: ref wfrForward, Wrap: ref wfrWrap, Format: ref wfrFormat, ReplaceWith: ref wfrReplaceWith, Replace: ref wfrReplace, MatchKashida: ref wfrMatchKashida, MatchDiacritics: ref wfrMatchDiacritics, MatchAlefHamza: ref wfrMatchAlefHamza, MatchControl: ref wfrMatchControl);
                            }
                        }
                    }

                    break;

                default:
                    break;
            }

            workingStoryRange = workingStoryRange.NextStoryRange;

        } while (workingStoryRange != null);
    }

    return new ClsFindReplaceResults(found, Globals.ThisAddIn.Application.Selection);
}

The code in the question is searching on a Range object, so the Selection won't change. 问题中的代码正在搜索Range对象,因此Selection不会更改。 Simply use the Range as the "target" for the new content. 只需将Range用作新内容的“目标”。

The code in the quesiton is so complex it's hard to follow exactly what's going on... But in simple terms: 问题中的代码是如此复杂,以至于很难确切地了解正在发生的事情...但是简单来说:

bool found = workingStoryRange.Find.Execute(FindText: ref wfrFindText, MatchCase: ref wfrMatchCase, 
  MatchWholeWord: ref wfrMatchWholeWord, MatchWildcards: ref wfrMatchWildCards, MatchSoundsLike: ref wfrMatchSoundsLike, 
  MatchAllWordForms: ref wfrMatchAllWordForms, Forward: ref wfrForward, Wrap: ref wfrWrap, Format: ref wfrFormat, 
  ReplaceWith: ref wfrReplaceWith, Replace: ref wfrReplace, MatchKashida: ref wfrMatchKashida, 
  MatchDiacritics: ref wfrMatchDiacritics, MatchAlefHamza: ref wfrMatchAlefHamza, MatchControl: ref wfrMatchControl);

if (found)
{
  //Work with a duplicate of the original range so as not to "destroy" it
  //may not be needed, but included for "in case"
  Word.Range rngFound = workingStoryRange.Duplicate;
  //go to the end - the point just after the found content
  rngFound.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
  rngFound = "\nText in new paragraph.";
  rngFound.Font.Size = 9
  rngFound.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphJustify;
  rngFound.ParagraphFormat.SpaceAfter = 6f;
}

Note: it would be more correct to create a style for this formatting. 注意:为此格式创建样式会更正确。 The formatting can then be applied in one step, as often as required. 然后可以根据需要在一个步骤中应用格式化。 A style has the following advantages 样式具有以下优点

  • If the formatting should change at a later time, it's a simple matter to change the style definition - in one place, one action - rather than needing to find and change each formatting instance in the document 如果格式应在以后更改,则只需更改样式定义-只需一次操作即可-无需查找和更改文档中的每个格式实例,这很简单
  • Applying formatting using a style reduces the amount of memory management, most especially the "scratch files" Word uses to maintain the "Undo list". 使用样式应用格式会减少内存管理量,尤其是Word用于维护“撤消列表”的“暂存文件”。 A corralary: the Undo list is shorter. 一个畜栏:“撤消”列表较短。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM