Программное изменение кода.
Вызов 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