C# Word Interop:如何根据Find命令的结果设置插入点?
注:代码基于中记录的方法 我的目标是使用C# Word Interop:如何根据Find命令的结果设置插入点?,c#,ms-word,vsto,find-replace,word-interop,C#,Ms Word,Vsto,Find Replace,Word Interop,注:代码基于中记录的方法 我的目标是使用wordinterop Find.Execute在第一页页眉中找到的单词后立即插入一个新段落。为此,我需要在找到的单词的开头或结尾插入点(type==wdSelectionIP) 我的假设是,由于使用word Interop Find.Execute在第一页页眉中查找单词,word将在找到的单词的开头或结尾设置插入点(type==wdSelectionIP)。你可以在我的SomeEventMethod\u单击method中看到这一点,也就是说,在这个假设下
wordinterop Find.Execute
在第一页页眉中找到的单词后立即插入一个新段落。为此,我需要在找到的单词的开头或结尾插入点(type==wdSelectionIP
)
我的假设是,由于使用word Interop Find.Execute
在第一页页眉中查找单词,word将在找到的单词的开头或结尾设置插入点(type==wdSelectionIP
)。你可以在我的SomeEventMethod\u单击method中看到这一点,也就是说,在这个假设下,在找到单词后,我导航到行尾,创建一个新的空段落,设置一些属性,然后键入一些文本
文本已键入,但未在第一页页眉中找到的单词后面。而是在最后一页底部的主文本区域(即文档正文)中键入文本
如何根据“查找”命令的结果设置插入点
类用于报告查找和替换结果
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; }
}
调用FindReplaceAwhere方法的事件方法
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'");
}
}
FindReplaceAwhere方法
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);
}
问题中的代码正在搜索范围
对象,因此选择不会更改。只需使用范围
作为新内容的“目标”
问题中的代码非常复杂,很难准确地理解到底发生了什么。。。但简单来说:
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;
}
注意:为这种格式创建样式更为正确。然后,可以根据需要在一个步骤中应用格式设置。样式具有以下优点
- 如果以后需要更改格式,只需在一个位置、一个操作中更改样式定义,而无需查找和更改文档中的每个格式实例
- 使用样式应用格式可以减少内存管理量,尤其是Word用于维护“撤消列表”的“临时文件”。相关性:撤消列表较短
如果您想修改具有Find.Execute(在我的例子中是myFindReplaceAnywhere
方法)的方法中的范围,这种方法非常有效。但是,我希望调用代码(在我的例子中,我的SomeEventMethod\u Click
method)修改范围,因此我将返回workingStoryRange作为返回值并在那里修改范围。谢谢@好的。关于WordRange
对象(这只适用于Range
对象,在Word API中没有其他内容),需要记住一件非常重要的事情:这些是指向对象的直接“指针”。如果您执行Word.Range rngTwo=rngOne代码>两者完全相同-对其中一个所做的任何事情都会影响另一个。rngOne.Find.Execute还将更改rngTwo在文档中的位置。通常,在Office API中,我们已经学会了期待“浅拷贝”——这是一个例外。所以如果你得到奇怪的结果,请记住:-)谢谢你的提示。还有一个:作为Word.Range rngFound=workingStoryRange.Duplicate的替代方案
,执行workingStoryRange.Select()
,然后执行,例如,workingStoryRange.Selection.collapsedirection(Word.wdCollapseEnd)代码>,等等,等等。是可以接受的,是吗?@NovaSysEng嗯,我不确定我会称之为“可以接受”,不知道为什么使用这种方法。。。但在我之前的评论中,这不会导致特别的问题。根据我所知道的(您的评论),我倾向于返回一个范围
对象-独立于搜索范围
(这是一个故事范围
,意味着它不能被缩小)。我只会使用选择
,如果它是应该呈现给用户进行进一步编辑的内容。