Макрос для замены текста в word

Обновлено: 06.07.2024

При использовании утилиты «Найти или заменить» в меню «Правка» текст будет найден или заменен независимо от того, где он находится в документе. Однако если вы запишете это действие, оно будет воздействовать только на текст в теле документа и не повлияет на текст, который находится в верхних или нижних колонтитулах документа, например, в текстовом поле, сносках или любая другая область, которая находится за пределами основной части документа.

Чтобы использовать макрос для поиска или замены текста, независимо от того, где он находится в документе, необходимо пройтись по каждому из StoryRanges в документе.

Существует 11 различных типов историй, которые могут быть частью документа, соответствующих следующим константам WdStoryType:

wdCommentsStory, wdEndnotesStory, wdEvenPagesFooterStory, wdEvenPagesHeaderStory, wdFirstPageFooterStory, wdFirstPageHeaderStory, wdFootnotesStory, wdMainTextStory, wdPrimaryFooterStory, wdPrimaryHeaderStory и wdTextFrameStory.

Следующий код будет перебирать первую статью для каждого типа материалов в документе, заменяя все экземпляры текста, который должен быть заменен в первой статье каждого типа:

Затемнить myStoryRange как диапазон

Для каждого myStoryRange в ActiveDocument.StoryRanges
С myStoryRange.Find
.Text = "findme"
.Replacement.Text = ""
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
Завершить
следующим myStoryRange

(Примечание для тех, кто уже знаком с VBA: в то время как при использовании Selection.Find необходимо указать все параметры поиска и замены, например .Forward = True, поскольку в противном случае настройки берутся из параметров поиска и замены. текущие настройки диалога, которые являются «липкими», в этом нет необходимости, если используется [Range].Find — где параметры используют свои значения по умолчанию, если вы не указываете их значения в своем коде).

Как упоминалось ранее, приведенный выше код будет действовать только для первой истории для каждого типа истории в документе. (Первый заголовок, первое текстовое поле и т. д.). Если ваш документ содержит разделы с несвязанными верхними и нижними колонтитулами или, например, содержит более одного текстового поля, код не будет действовать на второе и последующие вхождения каждого типа материала. Таким образом, чтобы убедиться, что код действует при каждом появлении текста, независимо от того, где он появляется, вы должны использовать метод NextStoryRange, как в следующем коде:

Затемнить myStoryRange как диапазон

Для каждого myStoryRange в ActiveDocument.StoryRanges
С myStoryRange.Find
.Text = "findme"
.Replacement.Text = ""
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
Завершить с помощью
Делать, пока нет (myStoryRange.NextStoryRange — ничто)
Установить myStoryRange = myStoryRange.NextStoryRange
С myStoryRange.Find
. Text = "findme"
.Replacement.Text = ""
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
Завершить
Цикл
Далее мой диапазон историй

Проблемы с циклическим переключением StoryRanges и некоторые обходные пути

Одним из способов решения этой проблемы является разработка всех ваших шаблонов таким образом, чтобы ни один из заголовков не был пустым — вставьте пробел во все пустые заголовки. Если это изменяет макет этого раздела, примените другой стиль в этом заголовке, чтобы он не менялся. Другого удовлетворительного обходного пути на самом деле не существует по причинам, которые вскоре будут обсуждаться в отдельной статье.

Скорость макроса
Еще одна проблема с приведенным выше кодом заключается в том, что он может быть очень медленным, если документ большой или если он содержит большое количество диапазонов статей. Это особенно проблема в Word 97. В Word 97 использование Selection.Find выполняется намного быстрее, чем использование [Range].Find. Таким образом, вы можете значительно ускорить приведенный выше код в Word 97, используя вместо этого следующее:

Затемнить myStoryRange как диапазон

'Сначала выполните поиск в основном документе, используя Выделение
С выделением.Найти
.Text = "findme"
.Replacement.Text = ""
.Forward = True < br />.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute Replace:=wdReplaceAll
End With

'Теперь ищите все остальные истории, используя диапазоны
Для каждого myStoryRange In ActiveDocument.StoryRanges
If myStoryRange.StoryType <> wdMainTextStory Then
With myStoryRange.Find
.Text = " findme"
.Replacement.Text = ""
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
Завершить
Делать, пока нет (myStoryRange.NextStoryRange Is Nothing )
Set myStoryRange = myStoryRange.NextStoryRange
With myStoryRange.Find
.Text = "findme"
.Replacement.Text = ""
.Wrap = wdFindContinue
/>.Execute Replace:=wdReplaceAll
Завершить
Цикл
Завершить, если
Следующий myStoryRange

И самый быстрый, но ненадежный обходной путь.

Если вы хотите, чтобы ваш код выполнялся так же быстро, как замена через пользовательский интерфейс, и/или если вы хотите, чтобы он был полностью невосприимчив к ошибке "заголовки пропускаются, если первый заголовок пуст", единственный решение состоит в том, чтобы вызвать диалог Word «Найти и заменить» напрямую, выполнив кнопку меню (использование коллекции диалогов Word не помогает); и используя команду SendKeys для ее выполнения. Вы можете установить настройки диалогового окна так, как вы хотите, используя With Selection.Find . Конец с конструкцией без команды .Execute, прежде чем вы нажмете кнопку меню. Вам нужно будет включить DoEvents в свой код, чтобы команда могла завершить поиск.

Но использование SendKeys, как известно, ненадежно, особенно в этом случае, потому что диалоговое окно «Найти и заменить» немодально; так что это, как правило, не очень хороший метод. Он упоминается здесь для полноты картины.

Найти и заменить можно с помощью объектов «Найти и заменить». Объект Find доступен из объекта Selection и объекта Range. Действие поиска немного отличается в зависимости от того, получаете ли вы доступ к объекту «Найти» из объекта «Выделение» или объекта «Диапазон».

Поиск текста и его выделение

Если доступ к объекту «Найти» осуществляется из объекта «Выбор», выбор изменяется при обнаружении критерия поиска. В следующем примере выбирается следующее вхождение слова «Hello». Если конец документа достигнут до того, как будет найдено слово "Hello", поиск останавливается.

Объект «Найти» содержит свойства, относящиеся к параметрам в диалоговом окне «Найти и заменить». Вы можете установить отдельные свойства объекта Find или использовать аргументы с методом Execute, как показано в следующем примере.

Поиск текста без изменения выделения

Если доступ к объекту «Найти» осуществляется из объекта «Диапазон», выбор не изменяется, но диапазон переопределяется при обнаружении критерия поиска. В следующем примере выполняется поиск первого вхождения слова «синий» в активном документе. Если операция поиска выполнена успешно, диапазон переопределяется и к слову "синий" применяется полужирное форматирование.

В следующем примере выполняется тот же результат, что и в предыдущем примере, с использованием аргументов метода Execute.

Использование объекта замены

Объект замены представляет критерии замены для операции поиска и замены. Свойства и методы объекта «Замена» соответствуют параметрам в диалоговом окне «Найти и заменить» (меню «Правка»).

Объект замены доступен из объекта «Найти». В следующем примере все вхождения слова «привет» заменены на «привет». Выбор изменяется, когда критерии поиска найдены, потому что доступ к объекту Find осуществляется из объекта Selection.

В следующем примере удаляется жирный шрифт в активном документе. Свойство Bold имеет значение True для объекта «Найти» и False для объекта «Замена». Чтобы найти и заменить форматирование, задайте для поиска и замены текст пустые строки ("") и установите для аргумента Format метода Execute значение True. Выбор остается неизменным, поскольку доступ к объекту Find осуществляется из объекта Range (свойство Content возвращает объект Range).

Поддержка и обратная связь

Есть вопросы или отзывы об Office VBA или этой документации? См. раздел Поддержка и отзывы об Office VBA, чтобы узнать, как получить поддержку и оставить отзыв.

Дэвид Пог

За прошедшие годы Microsoft превратилась из текстового процессора в базу данных, программу веб-дизайна и воск для пола. Среди тысяч функций макросы — это инструменты для опытных пользователей, которые могут пригодиться многим людям.

Они позволяют автоматизировать часто выполняемые задачи, обучая Word следовать вашему примеру. Вы нажимаете «Записать макрос», что-то делаете — скажем, выполняете поиск и замену — а затем можете воспроизвести этот макрос позже.

На самом деле поиск и замена — это плохой пример: Microsoft Word фактически не может записывать и воспроизводить поиск и замену. Он просто ничего не записывает.

Это облом. Вы знаете тех людей, которые ставят два пробела после точки? Когда мне попадется один из этих документов, я бы хотел иметь возможность искать два пробела и заменять их одним.

К счастью, такой макрос можно создать вручную.

Начните с выбора Инструменты -> Макрос -> Запись макроса. Назовите свой макрос «ReplaceSpaces» (или как хотите; имя макроса не может содержать пробелы). Нажмите "ОК".

Это та часть, где вы должны делать все, что вы хотите, чтобы макрос делал. Но в этом случае теперь выберите «Инструменты» -> «Макрос» -> «Остановить запись». Вы ничего не записываете.

Теперь выберите Инструменты -> Макрос -> Макросы. В диалоговом окне щелкните имя только что созданного макроса, а затем нажмите «Изменить».

Теперь замените этот пустой макрос —

Конец подписки

Подпрограмма ReplaceSpaces()

Макрос ReplaceSpaces

Конец подписки

— с этим, который вы можете скопировать прямо с этой веб-страницы:

Подпрограмма ReplaceSpaces()

С выделением.Найти

.ОчиститьФорматирование

.Replacement.ClearFormatting

.Текст = ” “

.Replacement.Text = ” “

.Вперед = Истина

.Wrap = wdFindContinue

.Формат = Ложь

.MatchCase = Ложь

.MatchWholeWord = False

.MatchWildcards = False

.MatchSoundsLike = False

.MatchAllWordForms = False

.Выполнить замену:=wdReplaceAll

Конец

Конец подписки

Кстати, вы можете воспользоваться этой возможностью, чтобы изменить этот макрос на любой поиск/замену, который вы хотите; не нужно заменять два пробела одним. Например, чтобы выполнить поиск по слову «рыба» и заменить каждое вхождение словом «чипсы», вы должны изменить показанные здесь строки следующим образом:

.Text = «рыба»

.Replacement.Text = «фишки»

Закройте редактор Visual Basic.

В следующий раз, когда вы захотите запустить этот макрос поиска/замены, выберите "Инструменты" -> "Макрос" -> "Макросы" и дважды щелкните имя того макроса, который вы хотите запустить.

Или, чтобы упростить задачу, вы можете назначить свой макрос сочетанию клавиш или превратить его в кнопку на панели инструментов.

Используя утилиту «Найти или заменить» в меню «Правка», вы можете найти или заменить текст «почти» в любом месте документа. Однако, если вы запишете это действие, область или «диапазон» результирующего записанного макроса будет действовать только на текст, содержащийся в теле документа (или, точнее, он будет действовать только на ту часть документа, которая содержит вставку). точка). Это означает, что если точка вставки находится в основной части документа, когда ваш макрос выполняется, он не повлияет на текст, который находится в верхних или нижних колонтитулах документа, например, или в текстовом поле, сносках или любая другая область, которая находится за пределами основной части документа.

Даже у утилиты «Найти и заменить» есть недостаток. Например, текст в текстовом поле, расположенном в верхнем или нижнем колонтитуле, выходит за рамки диапазона поиска утилиты «Найти и заменить».

Чтобы использовать макрос для поиска или замены текста в любом месте документа, необходимо просмотреть каждую отдельную часть документа. В VBA эти части называются StoryRanges. Каждый StoryRange идентифицируется уникальной константой wdStoryType.

wdCommentsStory, wdEndnotesStory, wdEvenPagesFooterStory, wdEvenPagesHeaderStory, wdFirstPageFooterStory, wdFirstPageHeaderStory, wdFootnotesStory, wdMainTextStory, wdPrimaryFooterStory, wdPrimaryHeaderStory и wdTextFrameStory.

Полный код для поиска или замены текста в любом месте немного сложен. Соответственно, давайте сделаем это шаг за шагом, чтобы лучше проиллюстрировать процесс. Во многих случаях для выполнения работы достаточно более простого кода.

Шаг 1

Следующий код перебирает каждый StoryRange в активном документе и заменяет указанный .Text на .Replacement.Text:

Затемнить rngStory как диапазон

Для каждой rngStory в ActiveDocument.StoryRanges

.Text = "найти текст"

.Replacement.Text = "Меня нашли"

(Примечание для тех, кто уже знаком с VBA: в то время как при использовании Selection.Find необходимо указать все параметры поиска и замены, например .Forward = True, поскольку в противном случае настройки берутся из параметров поиска и замены. текущие настройки диалога, которые являются «липкими», в этом нет необходимости, если используется [Range].Find — где параметры используют свои значения по умолчанию, если вы не указываете их значения в своем коде).

Простой макрос выше имеет недостатки. Он действует только на «первый» StoryRange каждого из одиннадцати StoryType (т. е. первый заголовок, первое текстовое поле и т. д.). Хотя документ имеет только один объект StoryRange wdMainTextStory, он может иметь несколько диапазонов StoryRange в некоторых других типах StoryType. Если, например, документ содержит разделы с несвязанными верхними и нижними колонтитулами или если он содержит несколько текстовых полей, для этих StoryTypes будет несколько StoryRanges, и код не будет воздействовать на второй и последующие StoryRanges. Еще больше усложняет ситуацию то, что если ваш документ содержит несвязанные верхние или нижние колонтитулы, а один из верхних или нижних колонтитулов пуст, у VBA могут возникнуть проблемы с "переходом" этого пустого верхнего или нижнего колонтитула и обработкой последующих верхних и нижних колонтитулов.

Шаг 2

Чтобы убедиться, что код работает с каждым StoryRange в каждом StoryType, вам необходимо:

  • Используйте метод NextStoryRange
  • Используйте «обманку» VBA, предложенную Питером Хьюеттом, чтобы соединить любые пустые несвязанные верхние и нижние колонтитулы.

Общедоступная подписка FindReplaceAlmostAnywhere()

Затемнить rngStory как Word.Range

Dim lngJunk As Long

'Исправить проблему с пропущенным пустым верхним/нижним колонтитулом, предоставленную Питером Хьюиттом

lngJunk = ActiveDocument.Sections( 1 ).Headers( 1 ).Range.Тип истории

'Перебрать все типы статей в текущем документе

Для каждой rngStory в ActiveDocument.StoryRanges

'Перебрать все связанные истории

.Text = "найти текст"

.Replacement.Text = "Меня нашли"

'Получить следующую связанную историю (если есть)

Установите rngStory = rngStory.NextStoryRange

Цикл до тех пор, пока rngStory не станет ничем

Осталась одна проблема. Как и в случае с утилитой «Найти и заменить», приведенный выше код может пропустить любой текст, содержащийся в одном StoryType/StoryRange, вложенном в другой StoryType/StoryRange. Хотя эта проблема не возникает с вложенным StoryType/StoryRange в wdMainTextStory StoryRange, она возникает в StoryRanges типа верхнего и нижнего колонтитула. Примером может служить текстовое поле, расположенное в верхнем или нижнем колонтитуле.

Шаг 3

К счастью, Джонатан Уэст предложил решение проблемы с такими вложенными объектами StoryRanges. Обходной путь использует тот факт, что текстовые поля и другие фигуры рисования содержатся в коллекции ShapeRange документа. Поэтому мы можем проверить ShapeRange в каждом из шести верхних и нижних колонтитулов StoryRange на наличие фигур. Если фигура найдена, мы затем проверяем каждую фигуру на наличие текста, и, наконец, если фигура содержит текст, мы устанавливаем диапазон поиска на .TextFrame.TextRange этой фигуры.

Этот последний макрос содержит весь код для поиска и замены текста «где угодно» в документе. Добавлено несколько улучшений, упрощающих применение нужного поиска и замены текстовых строк.

Примечание. Важно преобразовать текст кода в обычный текст перед вставкой: если вы вставляете непосредственно из веб-браузера, пробелы кодируются как неразрывные пробелы, которые не являются «пробелами» для VBA и вызовут компиляцию. - или ошибки времени выполнения. Также: будьте осторожны с длинными строками в этом коде. Когда вы вставляете этот код в редактор VBA, нигде в том, что вы вставили, не должно быть красного цвета. Если есть, попробуйте аккуратно соединить верхнюю красную линию с нижней (не удаляя видимые символы.

Общедоступная подписка FindReplaceAnywhere()

Затемнить rngStory как Word.Range

Затемнить pFindTxt как строку

Затемнить pReplaceTxt как строку

Dim lngJunk As Long

Тусклый экран как фигура

pFindTxt = InputBox("Введите текст, который вы хотите найти." _
, "НАЙТИ" )

Если pFindTxt = "" Тогда

MsgBox "Отменено пользователем"

pReplaceTxt = InputBox("Введите замену." , "REPLACE")

Если pReplaceTxt = "" Тогда

If MsgBox( "Вы просто хотите удалить найденный текст?", _
vbYesNoCancel) = vbNo Then

Читайте также: