- •Создание динамических структур данных
- •Встроенный динамический класс Collection
- •Создание собственных динамических классов
- •Обертывание коллекции vba
- •Несколько слов об api, Win32, dll
- •Вызов функций и оператор Declare
- •Две кодировки ansi и Unicode
- •Два языка: c и vb. Различия при вызове функций
- •Соответствие между простыми типами данных
- •Структуры языка c и тип, определенный пользователем, в языке vba
- •Об описателях языка c и объектах Windows
- •Void функции языка c
- •Вызов аргументов по ссылке ByRef и по значению ByVal
- •Строковые аргументы при вызове функций Win32 api
- •Примеры работы с Win32 api функциями
- •Работа с окнами
- •Характеристики окружения
- •Вызов функций Win32 api, работающих в Unicode кодировке
- •Обработка ошибок, возникающих при вызове функций Win32 api
- •Функции api и вызов Callback функций
- •Функции высших порядков и конструкция AddressOf
- •Функции перечисления Win32 api
- •Функция EnumWindows
- •Еще один пример работы с функцией EnumWindows
- •Функции Win32 api для работы с таймером
- •Функция SetTimer
- •Функция обратного вызова TimerProc
- •Функция KillTimer
- •Пример создания, работы и удаления таймера
- •Классы как обертка вызовов функций Win32 api
- •Построение класса "ВашТаймер"
- •Использование класса ВашТаймер
- •Операторы
- •Операторы и строки
- •Оператор комментария
- •Присваивание
- •Оператор Let
- •Оператор lSet
- •Оператор rSet
- •Оператор Set
- •Управляющие операторы
- •Условный оператор If Then Else End If
- •Оператор выбора Select Case
- •Цикл For Next
- •Цикл Do...Loop
- •Цикл While...Wend
- •Цикл For Each...Next
- •Работа с каталогами, папками и файлами
- •Изменение текущего диска: оператор ChDrive
- •Изменение текущего каталога (папки): оператор ChDir
- •Создание каталога (папки): оператор MkDir
- •Переименование каталогов (папок) и файлов: оператор Name
- •Удаление каталога (папки): оператор RmDir
- •Установка атрибутов файла: оператор SetAttr
- •Копирование файлов: оператор FileCopy
- •Удаление файлов: оператор Kill
- •Прочие операторы
- •Операции с одним объектом. Оператор With
- •Операции
- •Работа с числовыми данными
- •Математические функции
- •Работа со строками
- •Сравнение строк
- •Сравнение с образцом
- •Основные операции над строками
- •Новые функции для работы со строками
- •Функция InStrRev - поиск последнего вхождения подстроки
- •Функция Replace - замена всех вхождений подстроки
- •Удаление подстроки
- •Разбор строки. Функции Split, Join и Filter
- •Преобразование строки в массив. Функция Split
- •Сборка элементов массива в строку. Функция Join
- •Фильтрация элементов массива. Функция Filter
- •Несколько модификаций встроенных функций
- •Замена, основанная на шаблоне. Функция WildReplace
- •Замена разных символов строки. Функция CharSetReplace
- •Фильтрация, основанная на шаблоне. Функция WildFilter
- •Разбор строки, допускающей разные разделители ее элементов. Функция WildSplit
- •Работа с датами и временем
- •Присваивание значений
- •Встроенные функции для работы с датами
- •Определение текущей даты или времени.
- •Вычисления над датами
- •Функция Timer и хронометраж вычислений
- •Некоторые встроенные функции
- •Функции проверки типов данных
- •Преобразование типов данных
- •Форматирование данных. Функции группы Format
- •Функция Format.
- •Другие функции форматирования
- •Описание и создание процедур
- •Классификация процедур
- •Синтаксис процедур и функций
- •Функции с побочным эффектом
- •Создание процедуры
- •Создание процедур обработки событий
- •Вызовы процедур и функций Вызовы процедур Sub
- •Вызовы функций
- •Использование именованных аргументов
- •Аргументы, являющиеся массивами
- •Конструкция ParamArray
- •Задача о медиане
- •Пользовательские функции, принимающие сложный объект Range
- •Рекурсивные процедуры
- •Деревья поиска
- •Класс TreeNode
- •Класс BinTree
- •Работа со словарем
- •Отладка
- •Написание надежных программ
- •Искусство отладки
- •Средства отладки
- •Панель отладки и команды меню
- •Окна наблюдения
- •Окно локальных переменных - Locals
- •Окно проверки - Immediate
- •Окно контрольных выражений - Watch
Void функции языка c
В языке С формально нет процедур, есть только функции. В тех случаях, когда по существу речь идет о процедурах, вычисляющих не один скалярный результат, а имеющих несколько выходных параметров, как правило, используется функция, результат которой говорит об успешности выполнения процедуры. Если результат функции имеет значение True, то все выходные параметры благополучно вычислены, в противном случае следует проанализировать причину неуспеха. Типично для языка C то, что вызов функций является условием оператора If, - оператор If задает упаковку вызова функции, позволяя не только вызвать функцию, но и проверить корректность завершения ее работы. При трансляции заголовков таких функций в язык VBA, они естественно транслируются в функции VBA и для работы с ними можно сохранить стиль языка C.
Однако в языке C используются и функции, не возвращающие результата. Результат таких функций задается описателем Void, по существу, они являются процедурами. И при трансляции их в VBA их и следует задавать в виде процедур.
Вызов аргументов по ссылке ByRef и по значению ByVal
В языке C++ основным способом передачи параметров является передача их по значению, в VBA - по ссылке. Конечно, в обоих языках применяются оба способа. Тем не менее, нужно понимать, что описатель ByVal очень часто будет встречаться при вызове Win32 API функций, значительно чаще, чем при вызове обычных VBA функций. Если используется API Viewer, то этот описатель автоматически будет появляться для тех параметров, где необходима подобная форма вызова. Следует обратить внимание на одно обстоятельство. Несмотря на то, что такой описатель может появляться и для строковых аргументов, строки всегда передаются в функции Win32 API по ссылке. Последнее обстоятельство также связано со спецификой работы со строками в функциях языка C, на которых следует остановиться подробнее.
Строковые аргументы при вызове функций Win32 api
Как мы уже говорили, строки передаются по ссылке, даже если у параметра указан описатель ByVal. Не возникает никаких проблем при передаче строки в функцию Win32 API. Передаваемый аргумент может быть произвольным строковым выражением, в том числе переменной типа String или строковой константой. Сложнее дело обстоит, если функция должна вернуть строку, в качестве результата. Прежде всего, напомним, что в функциях Win32 API тип возвращаемого значения никогда не является строкой, - это всегда целочисленное значение, чаще всего булево значение, указывающее на то, удачно ли завершилось выполнение функции. Поэтому, если нужно получить строку в качестве результата, то функции передается два параметра - строка и ее длина, описанные чаще всего следующим образом:
ByVal lpResultStr As String, ByVal LenResultString As Long
Поскольку результат будет формироваться непосредственно в области памяти, отведенной строке lpResultStr, то перед вызовом эта строка должна удовлетворять следующим условиям:
-
она должна быть строкой, завершаемой нулем. Чаще всего она вся состоит из нулевых символов.
-
Ее длина должна быть достаточной для того, чтобы вместить результирующую строку.
-
Параметр LenResultString должен указывать максимально допустимое число символов результирующей строки.
С учетом этих требований перед вызовом функций, возвращающих строковые значения, как правило, передаваемая функции строка инициализируется и набивается подходящим количеством нулевых символов. Напомним, нулевой символ задается константой vbNullChar. Обычно, это делается следующим образом:
Const MaxSize = 255 As Long
lpResultString = String$(MaxSize, vbNullChar)
LenResultString = Len(lpResultString)
После того, как функция благополучно завершит работу, приходится выделять из строки возвращенное значение. Если строка до вызова состояла сплошь из нулевых символов, то результат после вызова представляет ее префикс, заканчивающийся первым нулевым значением. В этом случае результат легко выделяется и это причина того, почему целесообразно строку инициализировать нулевыми символами.
Тип Any
Иногда, параметр функции API может принимать значения различных типов. В этом случае в операторе Declare нельзя указать один конкретный тип этого параметра. Для решения подобной проблемы и был введен специальный тип Any. Если параметр имеет этот тип, то в период трансляции не проверяется правильность соответствия типов и аргумент может принимать значения любых типов. Конечно, нужно иметь в виду, что функция может принимать значения хоть и нескольких, но совершенно определенных типов. Поэтому при работе с типом Any на программиста возлагается вся ответственность за корректную передачу значения функции API. Альтернативой применения типа Any является задание для одной функции нескольких операторов Declare, - по одному на каждый возможный тип параметра. Тогда в каждой конкретной ситуации будет вызываться соответствующая функция с нужным типом параметра.