Word vba регулярное выражение

By default Regular Expression option is disabled in word 2007, to enable that plase do following steps,

1). Go to Tools > References as shown below.
enter image description here

2). Now put a tick on «Microsoft VBScript Regular Expressions 5.5» option and then press oh as shown below.
enter image description here

3). Now onward you can create a RegExp object in your VBA script. You can verify it be searching in object data base as explained below.
View > Object Browser ( Or press F2) , as shown below.

enter image description here

and search for RegExp object

enter image description here

4).
The RegExp object uses regular expressions to match a pattern. The following properties are provided by RegExp. These properties set the pattern to compare the strings that are passed to the RegExp instance:

a. Pattern: A string that defines the regular expression.

b. IgnoreCase: A Boolean property that indicates whether you must test the regular expression against all possible matches in a string.

c. Global: Sets a Boolean value or returns a Boolean value that indicates whether a pattern must match all the occurrences in a whole search string, or whether a pattern must match just the first occurrence.

RegExp provides the following methods to determine whether a string matches a particular pattern of a regular expression:

d. Test: Returns a Boolean value that indicates whether the regular expression can successfully be matched against the string.

e. Execute: Returns a MatchCollection object that contains a Match object for each successful match.

Please find a simile example for RexExp provided in Microsoft msdn forum.

Function TestRegExp(myPattern As String, myString As String)
   'Create objects.
   Dim objRegExp As RegExp
   Dim objMatch As Match
   Dim colMatches   As MatchCollection
   Dim RetStr As String

   ' Create a regular expression object.
   Set objRegExp = New RegExp

   'Set the pattern by using the Pattern property.
   objRegExp.Pattern = myPattern

   ' Set Case Insensitivity.
   objRegExp.IgnoreCase = True

   'Set global applicability.
   objRegExp.Global = True

   'Test whether the String can be compared.
   If (objRegExp.Test(myString) = True) Then

   'Get the matches.
    Set colMatches = objRegExp.Execute(myString)   ' Execute search.

    For Each objMatch In colMatches   ' Iterate Matches collection.
      RetStr = RetStr & "Match found at position "
      RetStr = RetStr & objMatch.FirstIndex & ". Match Value is '"
      RetStr = RetStr & objMatch.Value & "'." & vbCrLf
    Next
   Else
    RetStr = "String Matching Failed"
   End If
   TestRegExp = RetStr
End Function

I hope it might help full for some one, because i wasted almost half a day on it.

Thanks

Заметка написана Андреем Макаренко

Регулярные выражения (regular expressions) — очень мощный механизм для обработки строк. С его помощью можно найти нужные части текста, проверить, удовлетворяет ли строка определённой маске, заменить найденный текст. Такие выражения вcтроены во многие языки программирования, такие, как Perl, Php, JavaScript, и, конечно VBA.

Рассмотрим, как это работает на примере обработки счетов на доставку товаров. Исходные данные содержатся в отчете Excel в форме полного адреса (рис. 1). Наша задача — из строки вида «677000, Россия, Саха /Якутия/ Респ., г. Якутск, ул. Ойунского» выделить название города.

Рис. 1. Исходные данные

Скачать заметку в формате Word или pdf, примеры в архиве (политика провайдера не позволяет напрямую загружать на сайт файлы Excel, содержащие макросы)

Для использования регулярных выражений, необходимо подключить библиотеку MS Windows Script. Для подключения, запускаем VBA (меню Разработчик –> Visual Basic). В открывшемся окне VBA проходим по меню Tools –> References и в окне References — VBAProject ставим флажок в строке Microsoft VBScript Regular Expressions 5.5 (рис. 2).

Рис. 2. Подключение библиотеки MS Windows Script для работы с регулярными выражениями

Теперь в Visual Basic добавился объект RegExp, который содержит в себе всё, что нужно для работы с регулярными выражениями. Код, выполняющий поставленную задачу, выглядит так:

Sub RegExp()
Dim myRegExp As New RegExp ' создаем экземпляр RegExp
Dim aMatch As Match ' один из совпавших образцов
Dim colMatches As MatchCollection ' коллекция этих образцов
Dim strTest As String ' тестируемая строка

' устанавливаем свойства объекта RegExp
myRegExp.Global = False ' если Global = True, то поиск ведётся во всей строке, _
если False, то только до первого совпадения
myRegExp.IgnoreCase = True ' игнорировать регистр символов при поиске
myRegExp.Pattern = ", (г|c|п). .*?," ' шаблон для поиска

strTest = Sheets("Накладные").Range("E2").Text ' присваиваем переменной текст из текущей ячейки
Set colMatches = myRegExp.Execute(strTest) ' получаем коллекцию совпадений с образцом

'перебираем коллекцию и просматриваем результаты
For Each aMatch In colMatches ' проходим по всей коллекции
a = aMatch.FirstIndex ' порядковый номер первого символа найденного образца
b = aMatch.Length ' кол-во символов в найденном образце
c = aMatch.Value ' полный образец
Next aMatch

c = Mid(c, 6, Len(c) — 6)
MsgBox a & " | " & b & " | " & c ' смотрим, что получилось

' производим замену найденного выражения
d = myRegExp.Replace(strTest, " (здесь раньше был город)")

MsgBox d ' смотрим, что получилось
End Sub

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

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

Описание синтаксиса для создания шаблона можно найти в Интернете (см., например, msdn). Здесь я дам лишь краткое представление о возможностях (рис. 3) и прокомментирую шаблон, использованный в примере.

Рис. 3. Специальные символы

Разберем использованный нами в примере шаблон:

", (г|c|п). .*?,"

Сам шаблон берется в кавычки. Начинается шаблон с запятой и пробела, далее следует конструкция (г|c|п), которая позволят выбрать один из трех вариантов обозначения населенного пункта: г – город, с – село, п – поселок.

. — это просто точка. Обратная косая поставлена для того, чтобы отличить ее от спецсимвола

пробел — это и есть пробел

. — точка — любой символ

* — множитель, берет ни одного или множество символов, стоящих слева от него (а это точка – то есть, любой символ) между пробелом и запятой

? — ограничивает поиск первой встреченной запятой. Если его не использовать, то выражение вернет значение ", г. Якутск, ул. Ойунского,". Т.е., до последней запятой в тексте.

Итак, шаблон позволяет найти текст, который начинается с запятой, пробела, буквы («г», «с» или «п») с точкой и пробела, а заканчивается первой встреченной после этого запятой. В нашем случае шаблон извлекает следующий текст:

, г. Якутск,

Далее оператор c = Mid(c, 6, Len(c) — 6) оставляет от него лишь

Якутск

См. также Бен Форта. Регулярные выражения за 10 минут.

01

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

02 VBA

1
2
3
4
5
6
7
8
9
10
11

Dim objRegExp, matches, match

Set objRegExp = CreateObject(«VBScript.RegExp»)

With objRegExp
.Global = True
.IgnoreCase = False
.pattern = «pattern»
End With

03

Здесь, конечно, каждый кодер обрадуется — вызываем Replace и все ок!

04 VBA

1

Set matches = objRegExp.Replace(ActiveDocument.Content, «replacementstring»)

05

Но при запуске, конечно же, будет выдана ошибка. Это связано с тем, что метод Replace объекта VBScript.RegExp принимает на вход первым параметром строковую переменную, а не объект (в нашем случае ActiveDocument.Content), и возвращает этот метод также измененную строку, а не вносит изменение во входящую, отсюда и танцы с бубнами:

06 VBA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Set matches = objRegExp.Execute(ActiveDocument.Content)

For Each match In matches
Set matchRange = ActiveDocument.Content
With matchRange.Find
.Text = match.Value
.Replacement.Text = «replacementstring»
.MatchWholeWord = True
.MatchCase = True
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.Execute Replace:=wdReplaceOne
End With
Next

07

Ну хорошо, скажете вы, ну а если нам нужно переформатировать данные по аналогии с выражениями типа $1-$3-$2 (т. н. «обратные ссылки» в регулярных выражениях), т. е. как к примеру из 926-5562214 получить +7 (926) 556-22-14. Это тоже достаточно просто, здесь они тоже есть — единственное отличие — нумерация найденных групп начинается не с нуля, а единицы — $1. Давайте пока отвлечемся от нашего документа и посмотрим как это можно сделать с обычной строковой переменной:

08 VBA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

19

Dim objRegExp, matches, match

Set objRegExp = CreateObject(«VBScript.RegExp»)

Dim strSearch As String
Dim strResult As String
strSearch = «Пусть у нас есть несколько телефонов 8495-3584512, 8800-4852620 и, к примеру, 8950-5628585»

With objRegExp
.Global = True
.IgnoreCase = False

.pattern = «8(d{3})-(d{3})(d{2})(d{2})»

End With

strResult = objRegExp.Replace(strSearch, «+7 ($1) $2-$3-$4»)

Debug.Print strResult

09 На заметку:

12 строка выделена для того чтобы подчеркнуть каким образом было разделено указание на подгруппы ($2, $3 и $4), ведь выражение (d{3})(d{2})(d{2}) эквивалентно (d{7}). Но во втором случае, рекурсивный запрос содержал бы все 7 цифр.

Изучайте регулярные выражения!

10

Но поскольку, как уже говорилось выше, вместо входной строки у нас объект ActiveDocument.Content, такой метод не подойдет для работы. Придется пойти на хитрость — объединить два предыдущих кода:

11 VBA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Set objRegExp = CreateObject(«VBScript.RegExp»)

With objRegExp
.Global = True
.IgnoreCase = False
.pattern = «8(d{3})-(d{3})(d{2})(d{2})»
End With

Set matches = objRegExp.Execute(ActiveDocument.Content)

Dim strReplacement As String

For Each match In matches
Set matchRange = ActiveDocument.Content

strReplacement = objRegExp.Replace(match.Value, «+7 ($1) $2-$3-$4»)

With matchRange.Find
.Text = match.Value
.Replacement.Text = strReplacement
.MatchWholeWord = True
.MatchCase = True
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.Execute Replace:=wdReplaceOne
End With
Next

12

Оборачиваем в оболочку-функцию и, вуаля:

13 VBA

1

2
3
4

5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

Sub ВыполнитьГруппуПреобразований_RegExp()
Call Выполнить_RegExp(«8(d{3})-(d{3})(d{2})(d{2})», «+7 ($1) $2-$3-$4»)

End Sub

Sub ВыполнитьГруппуПреобразований_RegExp() …

Private Sub Выполнить_RegExp(pattern As String, patternExpr As String)
Set objRegExp = CreateObject(«VBScript.RegExp»)

With objRegExp
.Global = True
.IgnoreCase = False
.pattern = pattern
End With

Set matches = objRegExp.Execute(ActiveDocument.Content)

Dim strReplacement As String

For Each match In matches
Set matchRange = ActiveDocument.Content

strReplacement = objRegExp.Replace(match.Value, patternExpr)

With matchRange.Find
.Text = match.Value
.Replacement.Text = strReplacement
.MatchWholeWord = True
.MatchCase = True
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.Execute Replace:=wdReplaceOne
End With
Next
End Sub

Private Sub Выполнить_RegExp(pattern As String, patternExpr As String) …

14

Нельзя умолчать о существовании, к сожалению, некоторых ограничений в синтаксисе регулярных выражений при использовании объекта VBScript.RegExp в VBA. Эти ограничения провоцируют ошибку Run-time error ‘5017’ Application-defined or object-defined error. Вот некоторые из них:

15
  • отсутствуют указатели на начало и конец текста A и Z — вместо этих указателей можно использовать указатель конца текста $;
  • отсутствуют назад- (?<=…) и впередсмотрящие (?=…) указатели (утверждения, lookbehind assertions), равно как и их отрицательные реализации — (?!=…) и (?!…);
  • отсутствует ряд модификаторов.
17

Похожие запросы:

  • Регулярные выражения в MS-Word
  • VBA regular expression, replacing groups
  • Поиск и замена текста с помощью объекта VBScript.RegExp
  • Замена текста в документе при помощи регулярных выражений
  • Regex Capture Groups and Back-References
  • Разработка регулярного выражения для разбора строки с помощью обратных ссылок


August 20, 2018 — by Suat M. Ozgur

How to Use RegEx in Microsoft Word

Lissa asks:

Is there a way to change a number (always a random number) after the word fox? Example: fox 23, bear 1, fox 398, frog 12, fox 15. I want to change the number to the same color of the word fox.

We can find and replace by format in Microsoft Word. This is a great feature to quickly find the formatted text, and even replace the entire text format in the document.

Select Advanced Find on the ribbon.

Find and Replace Dialog

Find and Replace Dialog

Enter the text to find, then click More button to see advanced options, and click on Format button.

Advanced Find Options

Advanced Find Options

Select Font option in the settings, then you can set up the text color that you would like to find in the document. Click OK to close Find Font dialog window.


Select text color in Find Font dialog.

Select text color in Find Font dialog.

Click Find Next, and you’ll see the first occurance of the text being searched in certain color will be selected.

Find Next to find first occurance.

Find Next to find first occurance.

We can also make more complicated searches by using wildcards. However, Word’s native search module doesn’t let us make a search how Lissa asked.

That’s where we can call RegEx into the game!

VBSCript Regular Expressions Library

VBA doesn’t ship with any regular expression support. However Microsoft VBScript library contains powerful regular expression capabilities. This library is part of Internet Explorer 5.5 and later, so it is available on all computers running Windows XP, Vista, 7, 8, 8.1, or 10.

Mac Users

Since Internet Explorer is not a Mac application, this library doesn’t exist in Mac. Therefore, VBA samples below don’t work in Mac.

To use this library in VBA, switch to VBE, select Project and References in the VBE menu, then scroll down the list to find the item «Microsoft VBScript Regular Expressions 5.5», and tick it to include in the application.

VBScript Regular Expressions Library

VBScript Regular Expressions Library

Insert a new module, and copy and paste the following code into this module.

Sub doRegexFind()
Dim strSample As String
Dim objRegex As RegExp
Dim matches As MatchCollection
Dim fnd As Match

    strSample = "First product code is fox 12, second one is fox 22, and third product is fox 45."
    
    Set objRegex = New RegExp
    
    With objRegex
        .Pattern = "fox d+"
        .Global = True
        .IgnoreCase = True
        Set matches = .Execute(strSample)
        For Each fnd In matches
            Debug.Print fnd
        Next fnd
    End With
End Sub

This procedure takes the sample text, finds the product codes by the given pattern — which is starting with «fox», single space and a number, and prints the matched codes in the Immediate window (hit Ctrl + G in VBE if it is not visible already).

Matched product codes printed in Immediate window.

Matched product codes printed in the Immediate window.

d+ character class in the pattern defines one or more numeric characters, and pattern is basically «fox» prefix followed by a space followed by numbers.

Copy and paste following code to see RegEx in action to remove the spaces from product codes.

Sub doRegexFindReplace()
Dim objRegex As RegExp
Dim matches As MatchCollection
Dim fnd As Match
Dim strSample As String

    strSample = "First product code is fox 12, second one is fox 22, and third product is fox 45."
    
    Set objRegex = New RegExp
    
    With objRegex
        .Pattern = "(fox) (d+)"
        .Global = True
        .IgnoreCase = True
        strSample = .Replace(strSample, "$1$2")
    End With
    
    Debug.Print strSample
End Sub

This procedure replaces the sample text content by removing the spaces from the product codes matched with the given pattern, and prints the result text in the Immediate window.

Replaced text printed in the Immediate window.

Replaced text printed in the Immediate window.

Please note that pattern is slightly different than the first code. Terms in this pattern are enclosed with parentheses, and corresponding terms are used in the Replace method as $1 and $2 in order. This procedure simply joins the two terms without spaces.

Back to the Question

Let’s go back to the sample text we used at the beginning of this article.

Sample Text

Sample Text

We need to find «fox» followed by numeric characters, and change the match by using the color of the «fox» section in the matched text.

Although RegEx is very good matching by the given pattern, it cannot replace the color of text in Word document. So we will combine RegEx and Word VBA methods in the following procedure.

Here are the steps:

  1. Find the matches with RegEx.
  2. Search each matched text by using Word Find method.
  3. Find the color of the first word in the found range.
  4. Change the color of the found range with the color in the previous step.

Switch to VBE, and insert a new module. Make sure VBScript Regular Expressions library is added to the project, and copy and paste the following code into this new module.

Sub doRegexMagic()
Dim str As String
Dim objRegex As RegExp
Dim matches As MatchCollection
Dim fnd As Match
    Set objRegex = New RegExp
    
    str = "fox"
    
    With Selection
        .HomeKey wdStory
        .WholeStory
    End With
    
    With objRegex
        .Pattern = str & " d+"
        .Global = True
        .IgnoreCase = True
        Set matches = .Execute(Selection.Text)
    End With

    With Selection
        .HomeKey wdStory
        With .Find
            .ClearFormatting
            .Forward = True
            .Format = False
            .MatchCase = True
            For Each fnd In matches
                .Text = fnd
                .Execute
                With Selection
                    .Font.Fill.ForeColor = .Range.Words(1).Font.TextColor
                    .MoveRight wdCharacter
                End With
            Next fnd
        End With
        .HomeKey wdStory
    End With
End Sub

Run the code, and here is the result.

Result

Result

RegEx in Excel?

Regex is completely missing from Excel. However, we can still use VBScript Regular Expressions in Excel VBA.

Launch Excel, open a new workbook, and create the content as shown below.

Sample data in Excel

Sample data in Excel

Switch to VBE, and insert a new module. Make sure VBScript Regular Expressions library is added to the project just like you did in Word, and copy and paste the following code into this new module.

Sub doRegexMagicInExcel()
Dim str As String
Dim objRegex As RegExp
Dim matches As MatchCollection
Dim fnd As Match
Dim rng As Range
Dim cll As Range

    Set objRegex = New RegExp
    Set rng = Selection
    
    str = "fox"
        
    With objRegex
        .Pattern = "(" & str & ") (d+)"
        .Global = True
        .IgnoreCase = True
        For Each cll In rng.Cells
            Set matches = .Execute(cll.Value)
            For Each fnd In matches
                cll.Value = .Replace(cll.Value, "$1$2")
            Next fnd
        Next cll
    End With
End Sub

Return to worksheet, and select the range with sample text. Run the macro, and see the result.

Result in Excel

Result in Excel

This procedure loops through the cells in the selected range, replaces the text in the cells by removing the spaces from the product codes matched with the given RegEx pattern.

Title Photo: tito pixel / Unsplash

VBA RegExVBA or Visual Basic for Applications is a powerful programming tool in Microsoft Excel. Regular Expression class enables VBA programs to perform regular expression searches. The latter are text patterns that can help search for strings including email addresses, phone numbers and others with specific and defined criteria. In this intermediate level tutorial, we walk you through VBA RegEx. We assume that you have basic knowledge of VBA in Excel. If not we recommend that you go through our basic course on Excel VBA before proceeding further. You may also want to quickly read through this tutorial to get a feel of all the things you can accomplish with VBA.

What is VBA Regex (Regular Expression)?

A “regular expression” is an equation used to match a pattern. The most important uses include, string searching and replacement. Regex is available in many programming languages which include, VBA, VB, VBscript, JavaScript, C#, VB.Net, Java, PHP etc. You could hop over and check out how regular expressions are used in C, with this course.

  •  Quantifiers

Quantifiers are needed to match several characters. Here are a few of them.

Pattern

Meaning

Example

–  Stands for  a range a-z means all the letters a to z
[] Stands for any one of the characters quoted [abc] means either a, b or c.[A-Z] means either A, B, …, Z
() Used for grouping purposes
| Meaning is ‘or’ X|Y, means X or Y
+ Matches the character one or more times zo+ matches ‘zoo’, but not ‘z’
* Matches the character zero or more times “lo*” matches either “l” or “loo”
? Matches the character zero or once “b?ve?” matches the “ve” in “never”.
  • Special Characters

Regex covers a lot of special characters. We look at some of the commonly used ones.

Special Characters

Meaning

. Matches any single character
$ Matches the end of the input
n Matches the newline character
^ Matches the beginning of the input
t Matches the tab character
d Matches a digit in the range 0 to 9
D Matches a non-digital character
w Matches any alphanumeric character including “_”
W Matches any non-alphanumeric character
s Matches any white space characters including tab, space, newline, form feed
S Matches any non-white space character
r Matches a carriage return character; enter key
If you want to match special characters. For example “.”, “\”
v  To find the  vertical tab 
  • Character Classes

Characters can be grouped by putting them inside square brackets.

Pattern

Meaning

[xyz] Match the character x,y or z.
[a-z] Match any of the characters between a and z.
[^abc],[^0-9] A “^” caret at the beginning denotes “not.” Here the characters other than a,b,c is matched.
[+*?.]  For your information most special characters have no meaning inside the square brackets. This particular expression matches any of the special characters within the square brackets.

Are regex cases case sensitive? The answer is “yes” and “no”. It all depends on the way you write the regex code and call them in your programs.

The Limitations of Regular Expression

Certain patterns in a string cannot be matched by regular expressions. Here is an example that counts the number of occurrences of a pattern. The pattern is “anbn“. Here the characters “a” and “b” are both repeated n times. The reason being regular expressions cannot keep track of the number of occurrences.

Where is a large amount of data to process it’s wise to avoid RegEx. The reason is, if you do not use the RegEx pattern properly, it can lead to low efficiency of the program. To learn more about VBA regular expressions and how you can use them, check out this course.

Accessing VBA RegExp Object

Open your Microsoft Excel application. Click on Developer tab. From here you choose Visual Basic.From the visual Basic menu bar, choose Insert -> Module.

After the module opens a new sheet, go to Tool tab and select References. Here you get a list of items with check boxes. Search for VBscript Regular expressions. Check the corresponding checkboxes.

Regular expressions have three RegExp Methods and four RegExp Properties. Let’s take a look at each of them:

RegExp Methods

  1. Execute method– In this method, a match or matches of pattern from a string is extracted.
  2. Replace method– Here the character or string is searched, and once found it is replaced with a new character or string.
  3. Test- This method is used to find whether a Regex pattern is matched in a given string. The method returns either “True” or “False.” Test method is equivalent to testing whether the number of matches found is greater than 0.

Properties of RegExp Method

  1. Pattern– It can be a single character or a string of characters. You can go through the patterns mentioned in the above tables and use them in your programs as per your requirements.
  2. Global– The argument for this property is either “True” or “False.” It is “False” by default.If you set the parameter to “True” it finds all the matches in a string. However, if by default it will only check for the first match.
  3. IgnoreCase– This parameter accepts either “True” or “False.” By default it is set to “False” and it is case sensitive. If you want the search to ignore the case, then set the value to “True”.
  4. MultiLine- This parameter accepts either “True” or “False.” If the value is set to true, it will search each line of a multiline string. While the “False” searches only the current line.

Let’s use the  properties listed above in a sample program

Example 1: VBA program to test whether the string is a valid email address

Sub RegEx_Tester()
Set objRegExp_1 = CreateObject("vbscript.regexp")
objRegExp_1.Global = true
objRegExp_1.IgnoreCase=true
objRegExp_1.Pattern=[a-z,A-Z]*@[a-z,A-Z]*.com.
strToSearch="[email protected]"
Set regExp_Matches = objRegExp_1.Execute(strToSearch)
If regExp_Matches.Count = 1
MsgBox("This string is a valid email address.")
End if
End Sub

In this program, we declared sub SubroutineRegEx_Tester().

Set objRegExp_1 = CreateObject(“vbscript.regexp”), this statement creates the regular expression object from VBScript. The object has functions which perform regular expression searches. If you want the regular expression to match the string, just for the further occurrence of the string set, “objRegExp1.Global = true.” If you want to match for all occurrences of the string set “objRegExp.Global = false.” If you want your regular expression to ignore the case of string, set “objRegExp1.IgnoreCase=true” If case is important set this property to false.”objRegExp_1.Pattern=[a-z,A-Z]*@[a-z,A-Z]*.com” this pattern denotes the string with alphabetical characters before and after @ symbol. If the regular expression object match the text in your input string set “regExpMatches.Count=1”

Here is another VBA RegEx Method program which finds and replaces string. Let’s take a look.

Example 2: Excel VBA RegEx Replace function

Function RegExpReplace1(ByVal WhichString1 As String, _
ByVal Pattern1As String, _
ByVal ReplaceWith1As String, _
                        Optional ByVal IsGlobal1As Boolean = True, _
                        Optional ByVal IsCaseSensitive1As Boolean = True) As String
Dim objRegExp As Object
Set objRegExp = CreateObject("vbscript.regexp")
objRegExp.Global = IsGlobal1
objRegExp.Pattern = Pattern1
objRegExp.IgnoreCase = Not IsCaseSensitive1
RegExpReplace = objRegExp.Replace(WhichString, ReplaceWith)
End Function

In this program, the user can enter the values at the runtime because of the parameter “ByVal” is used.The function RegExpReplace1 is called with the value of the parameters. One parameter is the string to be searched; another parameter is the replacement string. Note that Global property is set to true. This means all the matches of a string are searched. This program searches for occurrences of a string and substitutes each of them with the replacement string.

You may also want to check out the the neat VBA examples in this course by MrExcel.

Example3: Function to extract only numbers in a string

 Function OnlyNumbers_1(ByValWhichString As String) As Variant
OnlyNumbers = CDbl(RegExpReplace(WhichString, _
                        "[^0-9]", vbNullString, True))
End Function

Note that CDBl() converts an expression into type double.

More on Regex.Replace Method

Regex.Replace Method in a designated input string replaces strings that match a regular expression pattern with a specified replacement string. This method is overloaded, i.e. the same function name is used with different numbers and types of arguments. What function is called is determined by the number and type of parameters passed.We look at a few of the overloadedReplace functions.

Replace(String, String, Int32) in a designated input string, replaces a specified maximum number of strings that match a regular expression pattern with a specified replacement string.

Replace(String, String, String) – In a designated input string, this function replaces all strings that match a specified regular expression with a specified replacement string.

Replace(String, String, Int32, Int32) – In  a in substring, the function replaces aspecified maximum number of strings that match a regular expression pattern with a specified replacement string.

More about the Replace() method is covered in our advanced VBA course here.

Programming is best learned by trying it out yourself. You have to play around with the code and see how to things work out. Do try out these examples for yourself and let us know your feedback. If you ever need a quick refresher course, feel free to take this awesome Excel VBA course by Infinite Skills.

Angry word helper

Возможно, у вас есть ощущение, что тема макросов в Ворде достаточно маргинальная. Кто ими может пользоваться-то вообще? Ну, малварь делают иногда… Да и пишутся они на давно забытом VBA (Visual Basic for Applications, он же несколько урезанный Visual Basic 6 в интерпретируемом виде), фу!

Но на самом деле у многих ведь возникает потребность то какой-нибудь отчётик в ворде написать, то курсовую оформить, то резюме перед отправкой в компанию вашей мечты подправить… А у некоторых работа напрямую связана с Word. Часто различные системы документации предлагают экспорт в форматы doc или docx, которые нужны вашим заказчикам. И бывает, что документы после экспорта выглядят фигово, приходится их исправлять.

Работа в ворде нередко подразумевает выполнение каких-то однообразных повторяющихся действий, которые иногда (но далеко не всегда!) решаются грамотной настройкой стилей и их применением, а также использованием шаблонов. Как же автоматизировать всё остальное? Тут-то нам на помощь приходят те самые макросы.

Что же в них такого хорошего? Ну, например, они автоматически и достаточно быстро выполняют за вас однообразные действия. Могут что-то подсчитать, переформатировать документ, пометить аннотациями подозрительные места, — словом, всё, что запрограммируете. Могут даже в режиме реального времени что-то исправлять и о чем-то предупреждать, пока вы пишете документ. VBA в Word позволяет автоматизировать практически все действия, которые вы можете выполнить с документом вручную.

Макросы можно прикрепить как к конкретному документу (в чём для нас мало пользы, а для писателей троянов это единственная опция), так и к самому ворду, что позволяет применять макросы к любому документу, с которым вы работаете.

Макросы работают в любой версии Word и требуют минимум правок при переносе с одной версии на другую (а чаще всего вообще не требуют). На макросах можно даже реализовать полноценный пользовательский интерфейс с формами!

Давайте же занырнём в Visual Basic и напишем что-нибудь полезное! В качестве первого примера я покажу, как сделать макрос, который заменит два и более последовательных перевода строки на единственный. Это часто требуется при исправлении документов после экспорта из систем документации, или если вы хотите удалить случайно проставленные лишние переводы строк в собственноручно написанном документе. Макрос сделаем добротный, с пользовательским интерфейсом и прогрессом выполнения операции.

Чтобы начать писать или использовать макросы, сначала требуется убедиться, что в Word’е отображается панель «Разработчик» («Developer»). Если она у вас не отображается, следует зайти после создания нового документа в меню «Файл» («File») -> «Параметры» («Options») -> «Настроить ленту» («Customize Ribbon»), после чего найти там и установить флажок «Разработчик» («Developer»).

Enable Word developer tab

После этого нужно зайти на вкладку «Разработчик» и выбрать меню «Visual Basic».

Word Visual Basic button

В открывшемся окне слева вы увидите два проекта: «Normal» и проект, относящийся к текущему открытому документу. Возможно, в проекте «Normal» у вас уже будет какой-то файл в каталоге «Modules». В любом случае, создайте новый модуль, кликнув правой кнопкой по проекту «Normal» и выбрав «Insert» -> «Module».

Word insert new module

Созданный модуль представляет из себя файл, куда мы и будем писать код макросов. Можно переименовать модуль (по умолчанию его имя будет «Module1») в окне «Properties» -> «Name». Я назову свой модуль «AllMacros». Теперь откроем код модуля, дважды кликнув по его имени, и приступим к созданию макроса. Напомню, что наша цель — заменить два и более последовательных перевода строки на единственный, произведя замены по всему документу. Очевидно, нам потребуется функция, которая осуществляет поиск по тексту, ведь мы хотим найти несколько последовательных переводов строки. В Word это эквивалентно началу нового параграфа. Вы могли бы осуществить поиск начала нового параграфа через обычное окно поиска, введя в поле поиска ^p, ^13 или ^013 (что соответствует ASCII-коду перевода строки). Функция поиска будет выглядеть так:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Private Function FindNextText(text As String, useWildcards As Boolean)

    Selection.Find.ClearFormatting

    Selection.Find.Replacement.ClearFormatting

    With Selection.Find

        .Text = text

        .Forward = True

        .Format = False

        .MatchCase = False

        .MatchWholeWord = False

        .MatchKashida = False

        .MatchDiacritics = False

        .MatchAlefHamza = False

        .MatchControl = False

        .MatchWildcards = useWildcards

        .MatchSoundsLike = False

        .MatchAllWordForms = False

        .Wrap = wdFindStop

    End With

    Selection.Find.Execute

    FindNextText = Selection.Find.Found

End Function

Давайте разберём, что тут происходит. Мы объявляем функцию с двумя параметрами. Первый имеет тип String — это текст для поиска, а второй Boolean говорит о том, нужно ли использовать символы подстановки (wildcards). Про них я поговорю позже. В следующих двух строках 2 и 3 мы очищаем форматирование для строки поиска и строки замены, если оно было задано пользователем. Word позволяет задать форматирование строки поиска/замены, а для нашей задачи это не требуется. Далее мы задаём набор параметров для объекта Selection.Find: выставляем неинтересные нам параметры в False, параметр Text — это текст, который мы хотим найти, а параметр MatchWildcards указывает на использование символов подстановки. Параметр Wrap говорит о том, следует ли продолжать поиск, когда мы дошли до той точки, с которой поиск начали, и у нас его значение установлено в wdFindStop, так как мы хотим остановиться, когда дойдём до конца документа, и не зацикливать поиск.

Вообще, всё это обилие свойств и объектов из объектной модели Word, Excel и PowerPoint (да, там тоже есть макросы) хорошо описано в MSDN. Например, вот тут перечислены свойства и методы объекта Find. Есть русская документация (скажем, эта страница), но она выполнена совершенно кринжовым машинным переводом, невозможно читать:

Есть совершенно смехотворные страницы:

В общем, лучше читайте на английском. :D

Кроме того, все доступные объекты, их свойства и методы можно посмотреть прямо в редакторе VBA в самом Word’е. Для этого нужно нажать F2 или выбрать меню «View» -> «Object browser», что приведет к открытию браузера объектов (Object browser), в котором можно пролистать или поискать то, что вам доступно.

Word object browser

Но вернёмся к нашей функции. На строке 19 мы непосредственно выполняем поиск заданного текста с указанными параметрами. Строка 20 — эта конструкция, аналогичная return в си-подобных языках, указывает возвращаемое значение функции. Мы возвращаем булевое значение Selection.Find.Found, которое говорит о том, было ли что-то найдено.

Хочу заметить, что использование объекта Selection.Find и изменение его свойств заменит их значения и для пользователя. Например, если вы в Word искали что-то хитроумное с конкретно заданными параметрами, то выполнение макроса заменит ваши параметры поиска на те, которые мы задали в макросе. В идеале, их можно запомнить, а потом вернуть, но мы не будем так сильно заморачиваться, а просто всё за собой подчистим. Сделаем функцию, которая сбрасывает параметры в значения по умолчанию:

Private Sub ClearFindAndReplaceParameters()

    With Selection.Find

       .ClearFormatting

       .Replacement.ClearFormatting

       .Text = «»

       .Replacement.Text = «»

       .Forward = True

       .Wrap = wdFindStop

       .Format = False

       .MatchCase = False

       .MatchWholeWord = False

       .MatchWildcards = False

       .MatchSoundsLike = False

       .MatchAllWordForms = False

    End With

End Sub

Обратите внимание, что это уже Sub, а не Function, потому что мы не хотим из этой процедуры возвращать никакое значение. Это аналог функции void в си-подобных языках.

Теперь нужно определить, как нам найти два или более последовательных перевода строки. Для этого нам и потребуются упомянутые ранее wildcards. Word поддерживает символы подстановки при поиске, и по своей функциональности они напоминают регулярные выражения. Кстати, вы можете ими пользоваться и без макросов из окна расширенного поиска:

Word wildcards

Хорошее описание символов подстановки я нашел здесь, правда, на английском языке. Составим регулярное выражение для поиска двух и более последовательных переводов строки: [^013]{2,}. Это очень похоже на классическое регулярное выражение Perl или PCRE, но в квадратных скобках в уникальном стиле Word мы задаем символ перевода строки. Фигурные скобки указывают, что символов перевода подряд должно быть два или более. Тут, кстати, есть нюанс: не во всех версиях/локализациях Word такая регулярка заработает. В некоторых случаях вместо запятой потребуется указать точку с запятой (да, в Microsoft иногда делают крайне странные вещи). Чтобы сделать наш макрос более универсальным, напишем функцию, которая вернёт регулярное выражение, пригодное для поиска в той версии Word, в которой эту функцию запустили:

Private Function GetLineBreakSearchRegExp()

    On Error GoTo Err

    FindNextText «[^013]{2,}», True

    GetLineBreakSearchRegExp = «[^013]{2,}»

    Exit Function

Err:

    GetLineBreakSearchRegExp = «[^013]{2;}»

End Function

Здесь мы сначала пытаемся осуществить поиск с помощью wildcard’а [^013]{2,}. Если всё окей, то вернём из функции этот самый wildcard как рабочий (строка 4). В противном случае произойдёт ошибка, но мы готовы её обработать: мы установили обработчик всех ошибок в строке 2. Нас перекинет на метку Err, и тут мы вернём wildcard, который пригоден для других ревизий Word (в котором запятая внутри фигурных скобок заменена на точку с запятой).

Далее напишем функцию, которая будет заменять несколько последовательных переводов строки на единственный:

Private Sub RemoveNextEnters()

    Selection.MoveStart wdWord, 1

    If Selection.Range.Start <> Selection.Range.End Then Selection.Delete

End Sub

Эта функция подразумевает, что вызывать её будут тогда, когда объект Selection указывает на найденные несколько переводов строки. В строке 2 перемещаем начало выделения (а в выделены у нас будут все найденные последовательные переводы строки) на один символ вперед, а затем в строке 3, если начало выделения не совпадает с его концом, удаляем его содержимое. Таким образом, если было выделено три перевода строки, мы отступаем вперед на 1 символ (оставляя один перевод строки нетронутым), а затем удаляем оставшиеся два.

Осталось написать последнюю функцию, которая будет всем управлять.

Sub RemoveExcessiveEnters()

    Dim lineBreakSearchRegExp As String

    lineBreakSearchRegExp = GetLineBreakSearchRegExp()

    Selection.HomeKey Unit:=wdStory

    While FindNextText(lineBreakSearchRegExp, True) = True

        RemoveNextEnters

    Wend

    ClearFindAndReplaceParameters

End Sub

Здесь мы оперируем ранее написанными функциями. Сначала получаем текст регулярного выражения (wildcard’а) для поиска нескольких переводов строки подряд, затем вызовом HomeKey в строке 5 переходим в самое начало документа (перемещаем туда курсор), а затем в цикле ищем все интересующие нас места и удаляем излишние переводы строки. В конце сбрасываем параметры поиска на значения по умолчанию.

Finished word macro

Вот и всё, макрос можно запускать! Обратите внимание, что все функции, кроме последней, мы пометили Private. Мы не хотим, чтобы их вызывали напрямую. Доступной для вызова снаружи будет только функция RemoveExcessiveEnters. Перед запуском макроса стоит убедиться, что макросы включены. Если вылазит такая панель, то нужно нажать «Включить содержимое» («Enable content»):

Word enable content

Если такой панели нет, то можно зайти в меню «Файл» («File») -> «Сведения» («Info») и включить макросы уже оттуда:

Word enable content from info menu

Вы можете включить макросы на время одного сеанса Word (это по умолчанию и происходит, если нажимаете «Включить содержимое»), так что после перезапуска Word макросы снова будут отключены. Для запуска макроса возвращаемся в Word на панель «Разработчик» и нажимаем кнопку «Макросы» («Macros»), выбираем наш макрос RemoveExcessiveEnters и нажимаем «Выполнить» («Run»). Разумеется, у вас должен быть открыт какой-нибудь подопытный документ, где имеются лишние переводы строк. В качестве бонуса наш макрос ещё и удалит пустые элементы списков, потому что они представляют из себя точно такие же несколько переводов строки подряд.

Word macro: before and after

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

Undo Word macro

Макросы можно отлаживать через окно VBA, в котором мы писали макрос. Кликнув слева от строки кода, можно, как и в других средах разработки, поставить точку останова, а потом запустить макрос кнопкой «Run». Запустится та функция, на которой у вас находится курсор. Если вы поставите курсор на функцию с параметрами, то появится обычный запрос на выбор макроса для запуска, как при нажатии на кнопку «Макросы» в Word.

Debug Word macros

Думаю, что материала для одной статьи уже вполне достаточно. Я, конечно, пообещал горы функционала в виде интерфейса пользователя, отслеживания прогресса выполнения, и всё это обязательно будет, но в следующей публикации.

Код макроса можно скачать тут. Вы сможете его импортировать к себе в Word, кликнув правой кнопкой на «Normal» -> «Import file…» и выбрав загруженный файл.

P.S. Кстати, рекомендую создавать бэкапы своих макросов, экспортируя их куда-нибудь на диск. Даже лицензионный Word имеет свойство их иногда по какой-то причине удалять из шаблона Normal, в котором мы их создавали.

Like this post? Please share to your friends:
  • Word vba показать форму
  • Word vba перенос строки
  • Word vba перенос строк
  • Word vba перекрестные ссылки
  • Word vba межстрочный интервал