Каков правильный синтаксис для Find.Выполнить для Interop.Word?

#c# #ms-word #interop #office-interop #word-interop

#c# #ms-word #взаимодействие #office-взаимодействие #word-взаимодействие

Вопрос:

Я столкнулся с проблемой при использовании Microsoft.Office.Interop.Word — пытаюсь выполнить поиск и замену с изменением дизайна формата.
Самое неприятное здесь то, что я не получаю ошибку, просто приложение Word застревает.
Я проверял все, как использовать Find.Выполнить на Interop Word для этого нужно передать Object — и я не мог понять, каков правильный способ сделать это, и я нашел разные подходы при изучении этой проблемы.
Давайте предположим, что у меня есть такой код:

 using msWord = Microsoft.Office.Interop.Word;

msWord.Document doc = msWord.Application.ActiveDocument; // sets the document

Range range = doc.StoryRanges[WdStoryType.wdMainTextStory]; // sets the range as the main text

string textToFind = "ABC";    // the text to be found
string textToReplace = "123"; // the text to replace with
bool useWildCards = false;    // whether to use wildcards on search
bool makeBold = true;         // whether to change the font format to bold or non-bold
  

Теперь я выполняю функцию поиска и замены следующим образом:

 FindAndReplaceWithFormating(range ,textToFind ,textToReplace, useWildCards, makeBold)
  

Теперь мой вопрос заключается в том, как создать эту FindAndReplaceWithFormating функцию правильным и наиболее подходящим методом. Для этого у меня есть 3 разных подхода:

 private void FindAndReplaceWithFormating(Range range, string textToFind,
string textToReplace, bool useWildCards, bool makeBold)
{
range.Find.ClearFormatting();
range.Find.Replacement.ClearFormatting();
range.Find.Replacement.Font.Bold = makeBold; // the format design must come like this.

// here comes the rest of the code according to the chosen method...

}
  

Способ 1:

 range.Find.Text = textToFind;
range.Find.Replacement.Text = textToReplace;
range.Find.MatchWildcards = useWildCards;
range.Find.Forward = true;
range.Find.Format = true;
range.Find.Wrap = msWord.WdFindWrap.wdFindContinue;
object replaceAll = msWord.WdReplace.wdReplaceAll;
object missing = Missing.Value; // using System.Reflection;

// all ref are missing. only replaceAll ref is sent
range.Find.Execute(ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref replaceAll, ref missing, ref missing, ref missing, ref missing);
  

Способ 2:

 object missing = Missing.Value;
object FindText = textToFind;
object MatchCase = missing;
object MatchWholeWord = missing;
object MatchWildcards = useWildCards;
object MatchSoundsLike = missing;
object MatchAllWordForms = missing;
object Forward = true;
object Wrap = msWord.WdFindWrap.wdFindContinue;
object Format = true;
object ReplaceWith = textToReplace;
object Replace = msWord.WdReplace.wdReplaceAll;
object MatchKashida = missing;
object MatchDiacritics = missing;
object MatchAlefHamza = missing;
object MatchControl = missing;

// all are sent as object.
find.Execute(ref FindText, ref MatchCase, ref MatchWholeWord, ref MatchWildcards, ref MatchSoundsLike,
ref MatchAllWordForms, ref Forward, ref Wrap, ref Format, ref ReplaceWith, ref Replace,
ref MatchKashida, ref MatchDiacritics, ref MatchAlefHamza, ref MatchControl);
  

Метод 2b:

 // same as above just objects are sent without ref
// ...
find.Execute(FindText, MatchCase, MatchWholeWord, MatchWildcards, MatchSoundsLike,
MatchAllWordForms, Forward, Wrap, Format, ReplaceWith, Replace,
MatchKashida, MatchDiacritics, MatchAlefHamza, MatchControl);

  

Способ 3:

 range.Find.Execute(textToFind, false, false, useWildCards, false, false, true, 
msWord.WdFindWrap.wdFindContinue, true, textToReplace, msWord.WdReplace.wdReplaceAll,
false, false, false, false);
  

Комментарии:

1. Метод 3 кажется самым простым. Вы можете избежать передачи ненужных параметров, объявив их явно, как указано здесь

2. @YosefBernal — спасибо. Вы подразумеваете самый простой и правильный ? Несмотря на то, что в документации Microsoft похоже, что используется метод 2 .

3. Метод верен, если он выполняет свою работу, не так ли? Вы должны использовать то, что вам наиболее понятно. Подумайте о том, поймете ли вы код, когда посмотрите на него через 6 месяцев. Вы часто обнаружите, что документация Microsoft не всегда показывает наиболее краткий или часто используемый синтаксис. Я думаю, что это особенно верно для всей документации Office Interop.

4. Я начал свой вопрос с «Я столкнулся с проблемой …» — теперь я нашел проблему, и она не имеет ничего общего с синтаксисом find, поскольку все 3 метода работают просто отлично. Моя проблема была связана с отменой записи , и, безусловно, существует проблема с ошибкой при использовании StartCustomRecord amp; wdReplaceAll . Куда я должен сообщить об этой ошибке? [здесь в качестве ответа или где-то еще?], — это очень важно. Спасибо.

Ответ №1:

Благодаря @Yosef Bernal я проверил это снова и обнаружил, что все методы верны. Но, похоже, наиболее предпочтительным методом для его наглядности является объявление всех атрибутов и упорядочивание их «читаемым» способом следующим образом:

 range.Find.Execute(
FindText: "ABC",               // The text to be searched for.
ReplaceWith: "123",         // The replacment text.

MatchWildcards: false,       // Determines if the text to find contains wildcards.

Forward: true,                      // Determines if the find operation searches forward through the document.
Format: false,                       // Determine if formatting is included in the find operation.
Wrap: WdFindWrap.wdFindContinue,    // What happens if the search begins at a point other than the beginning of the document and the end of the document is reached (or vice versa if Forward is set to False) or if the search text isn't found in the specified selection or range.
Replace: WdReplace.wdReplaceAll,    // Specifies how many replacements to be made: one , none or all.

MatchCase: false,                   // Determines if the find operation is case-sensitive.
MatchWholeWord: false,              // Determines if the find operation locates only entire words and not text that's part of a larger word.
MatchSoundsLike: false,             // Determines if words that sound similar to the text to find are returned by the find operation.
MatchAllWordForms: false,           // Determines if all forms of the text to find are found by the find operation (for instance, if the text to find is "sit," "sat" and "sitting" are found as well).

MatchKashida: false,                // Match text with matching kashidas in an Arabic language document.
MatchDiacritics: false,             // Matching diacritics in a right-to-left language document.
MatchAlefHamza: false,              // Match text with matching alef hamzas in an Arabic language document.
MatchControl: false                 // Matching bidirectional control characters in a right-to-left language document.
);
  

Редактировать :
Просто имейте в виду Interop.Word ошибку при использовании UndoRecord с ReplaceAll — смотрите здесь и здесь