Программное изменение кода.

Вызов API-функций и других библиотечных функций

В программе на VBA можно обратиться к встроенным в Windows функциям API. Эти функции размещаются во многочисленных динамически подключаемых библиотеках, т.е. в DLL. Библиотеки располагаются чаще всего в каталоге windows\system32.

Для внешней функции необходимо в общей области дать предварительное описание. Описание API функций Вы можете найти в специальной литературе, в SDK-справочнике, MSDN - справочнике.

А узнать о том, в какой библиотеке, что лежит, можно, например, следующим образом: открыть файл с расширением dll блокнотом и поискать (Ctrl+F) имя нужной вам функции.

В приведенном примере объявляется функция Sleep – «засыпание». Важно, что несмотря на то, что почти всюду в Windows регистр букв не важен, здесь, если вы укажите имя функции с маленькой буквы (sleep), то будет выдано сообщение об ошибке «Can’t find DLL entry point sleep in kernel32.dll».

Declare Sub Sleep Lib "kernel32.dll" (ByVal dwM As Long)

Sub try()

Sleep 2000

MsgBox "111"

End Sub

Обратите внимание на это, в VBA нет функции eval(), которая есть в JavaScript, поэтому программно сформировать, а потом выполнить произвольный программный код несколько сложнее, не ясно, как перейти от имени объекта к самому объекту.

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

Рассмотрим пример. Пусть в проекте описан класс с именем fragm:

Public name As String, val As Integer

Private Sub Class_Initialize()

name = "f" & Int(Rnd * 10000) 'формирование случайного имени вида f567

val = Rnd * 20 + 10 ' случайное значение от 10 до 30

End Sub

В форме заводим список имен формируемых экземпляров

Dim cl_f As New Collection

Private Sub UserForm_Initialize()

Dim f As fragm, i As Integer

Randomize

For i = 1 To 10

Set f = New fragm

cl_f.Add f, f.name

ListBox1.AddItem f.name

Next

End Sub

По щелчку пользователя на пункт списка выдается сообщение – значение элемента коллекции с выбранным именем.

Private Sub ListBox1_Click()

MsgBox cl_f(ListBox1.List(ListBox1.ListIndex)).val

End Sub

Объект VBE предоставляет возможности для программного изменения операторов. В коллекции проектов содержатся проекты всех открытых документов. Компоненты – это ThisDocument, формы, модули, модули классов в том порядке, в каком они указаны в окне проекта. К любому из них можно обратиться по номеру или по имени. Свойство CodeModule предоставляет объект, с помощью которого можно работать с программными инструкциями. Можно изменять строки, можно удалять и добавлять строки, можно добавлять текст из строки или из текстового файла.

В примере текст программы содержится в модуле1 (никаких форм нет). В программе сначала удаляется строка из макроса changecode, затем вставляется другая строка и вызывается измененный макрос. Комбинация Chr(34) возвращает знак «кавычки».

Sub try()

j = 2: ns = 11

With VBE.VBProjects(1).VBComponents(j).CodeModule

.DeleteLines ns, 1

.InsertLines ns, "MsgBox " & Chr(34) & "22222" & Chr(34)

End With

changcode

End Sub

 

Sub changcode()

MsgBox "11111"

End Sub