[英]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
样式具有以下优点
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.