VBasic, краткий справочник |
![]() |
Добавил(а) microsin | |||||||||||||||||||||||||||||||||||||||||||
1. Перенос строки кода VBasic на следующую делается с помощью символа '_' в конце строки (можно применять не более 10 разделителей, и суммарная длина строки не должна превышать 1023 символа). В одной строке можно использовать два и более различных оператора, разделённых символом ':'. Комментарий указывается с помощью символа ' (можно использовать в любом месте строки) или оператора REM (только в начале строки). 2. Можно задавать переменные неявно, просто присваивая им значение. Переменные задаются явно с помощью оператора DIM: DIM имя_переменной [AS тип_переменной] Внимание! Через запятую можно указать несколько переменных, но для каждой ОБЯЗАТЕЛЬНО нужно отдельно указать тип (не так, как в C, с непривычки получается попадалово!). Как обычно, имя переменной должно начинаться с буквы и не может быть зарезервированным словом. Длина имени не может превышать 255 символов. Указывать тип данных при объявлении не обязательно, имеется возможность указать тип добавлением к имени переменной в конце специального символа (используется для совместимости со старыми версиями Basic, и Microsoft не рекомендует использовать эти символы):
Если ни символ в конце, ни тип переменной явно не указан, то тип переменной становится Variant. VBasic всегда по умолчанию использует тип Variant. Тип хранимой величины по ходу выполнения может меняться. Использование такого типа чревато логическими ошибками в программе, которые трудно выявить, поскольку в ходе чтения кода тип данных не виден. Кроме того, для поддержки Variant расходуется больше памяти. 3. Видимость переменных - существует 3 вида: - локальная (переменная доступна только в процедуре. Для этого она должна быть определена внутри неё). 4. Время жизни переменных - локальные переменные при каждом выходе из процедуры удаляются из памяти, а при новом вызове инициализируются заново. Если это не нужно, то надо либо определить переменную в начале модуля (т. е. сделать её переменной контейнера или глобальной). Но при этом существует опасность (при совпадении имён) случайного изменения содержимого переменной в другом месте программы. Поэтому есть возможность сделать переменную в процедуре статической. Такая переменная сохраняет значение при выходе из процедуры, пока существует в памяти форма или модуль. Для этого вместо оператора Dim применяют оператор Static. Чтобы сделать все переменные процедуры статическими, процедура объявляется с оператором Static: Static Sub AllVarsTheseSubAutoDeclaredAsStatic (...) ... End Sub 5. Массивы в VBasic. - Элементы массива всегда индексируются с нуля (стартовый элемент массива имеет индекс 0), но с помощью оператора Option Base 1, указанного в начале модуля, можно задать начало индексации с 1. Для установки других границ массива используют другой синтаксис: [Static|Piblic|Dim] Имя_массива([Нижний_предел To] Верхний_предел) Например: Dim aBirthDate (1980 To 2050) - Многомерный массив задаётся так: Dim Название_массива (Измерение1, Измерение2, ..., ИзмерениеN) Например: Dim aStudent (5, 10, 30) ' 5-номер школы, 10-номер класса, 30-номер ученика aStudent(3, 5, 17) = "Иванов" Для отдельных размеров (измерений) тоже могут задаваться пределы индекса. - Массивы бывают статические и динамические. Ключевое слово Static тут ни при чём! Статические массивы - это совсем не то, что имелось в виду, когда описывалось время жизни переменной (ключевое слово Static). Здесь подразумевается то, что размер (количество элементов) массива фиксированный (статический). Статический массив определяется так: Dim SampleArray(150) As String 'статический массив из 150 строк Теперь немного про динамические массивы. Динамические массивы создаются в 2 этапа. Сначала в начале контейнера - модуля, формы, класса - (по-другому эта область называется General Declarations) определяют массив без указания размера: Dim aArray() As Variant Затем внутри процедур с помощью оператора ReDim устанавливают фактический размер массива: ... ReDim aArray (50,10) ... Синтаксис оператора ReDim: ReDim [Preserve] Имя_массива(Границы) [As Тип_данных] В отличие от оператора Dim, оператор ReDim используется только в процедурах. При этом тип данных указывать не обязательно, особенно если он уже определён оператором Dim. Вы не можете переопределять тип данных массива, если он был заранее определён оператором Dim, за исключением того случая, когда был указан тип Variant (который, как мы знаем, является типом по умолчанию, т. е. если мы не указали тип, или указали тип Variant, эффект одинаковый). Мы можем при необходимости менять размер массива, но! Нужно помнить, что записанные в массив данные мы при этом потеряем (они инициализируются значением по умолчанию. Каким? Молчит наука...). И тут опять но... Сохранить размерность массива позволяет ключевое слово Preserve: Dim aArray() As Variant ... Private Sub Subroutine1() ... ReDim Preserve aArray (50,15) ... End Sub Теперь при изменении размера массива его содержимое сохраняется. Но (которое по счёту?!) следует учитывать, что для многомерных массивов можно менять только последнее измерение. Область видимости динамического массива бывает либо глобальной (если он был определён с помощью оператора Public), либо контейнерной (если с помощью Dim). 'создаем пользовательский тип данных Private Type tSklad Name As String Summa As Double Kol As Long End Type Dim Store() As tSklad ... 'инициализируем массив Erase Store ReDim Store(0) 'получаем массив с одним элементом ... 'пример сканирования всего массива для доступа к его данным Dim U As Long Dim L As Long L = LBound(Store) U = UBound(Store) For i = L To U If (Store(i).Name = sname) Then ... Exit For End If Next i ... 'пример добавления в массив одного элемента с сохранением ' данных существующих элементов массива U = UBound(Store) ReDim Preserve Store(U + 1) Store(U).Name = sname Store(U).Summa = 0 Store(U).Kol = 0 ... Массивы можно присваивать друг другу (с копированием содержимого), как обычные переменные. Это, безусловно, удобно, однако (опять...) если массивы имеют разные типы данных, размерность, а также если один статический, а другой динамический, то возникает куча тонкостей, цитировать и помнить которые нет сил. Любителей отсылаю к спецлитературе. 6. Типы, задаваемые пользователем (собственные). Определение общего (Public) собственного типа данных возможно только в секции General Declarations модуля (по-русски - в начале исходного файла, где задаём глобальные переменные). В этом случае этот тип будет доступен во всех процедурах всех форм, модулей и модулей классов. Для определения пользовательского типа в форме или модуле класса следует использовать ключевое слово Private, поскольку объявление общего типа в данной ситуации не допускается. При этом область видимости такого типа будет ограничена тем контейнером, где он был объявлен. Определив собственный тип данных, вы можете использовать его для объявления переменных этого типа (они могут быть, как обычно, локальными, глобальными или переменными контейнера). [Private|Public] Type Имя_типа Элем1 [([Размерность])] As Тип Элем2 [([Размерность])] As Тип ... End Type Пример: (General)(Declarations)(Module) Type usrType Num As Long Name As String Price As Currency End Type ... (General)(Declarations)(Form) Dim usrTools As usrType Private Sub Command1_Click() usrTools.Name = "Отвёртка" usrTools.Price = 2.95 End Sub ... 7. Константы. Область видимости может быть та же, что и у переменных (они могут быть локальными, глобальными или контейнера). Глобальная константа определяется с Public и её можно определить только в модуле. [Public|Private] Const Имя_константы [As Тип] = Значение 8. Замечания по поводу процедур обработки событий: - имя процедуры обработки событий составляется как "имяэлементауправления_имясобытия". 9. Процедуры бывают общего назначения (глобальные Public), их можно вызвать из процедур другого контейнера и закрытые (Private, то есть принадлежащие определённому контейнеру - форме, модулю, классу). Закрытые процедуры доступны только изнутри контейнера. Начиная с VBasic 4.0, все процедуры обработки событий формы являются по умолчанию Private, то есть их можно вызвать только изнутри этой формы. Общие процедуры формы или модуля также являются закрытыми, причём они останутся закрытыми даже после того, как вы их объявите как Public. Тем не менее, из процедуры одной формы есть возможность вызвать процедуру другой формы - надо делать вызов в виде имя_формы.имя_процедуры_этой_формы. Внутри модуля полностью работают директивы Public и Private, причём Public указывать не обязательно, то есть все глобальные процедуры и переменные модуля являются по умолчанию общими (доступными из других модулей). Для того, чтобы сделать модуль закрытым для других приложений и проектов, есть выражение Option Private Module Это выражение делает составные элементы модуля (переменные, процедуры, функции, пользовательские типы данных и проч.), не объявленные как Private, доступными только для модулей проекта, но не для других проектов и приложений. В модуле выражение Option Private Module должно находиться перед самой первой процедурой (в начале модуля). 10. Аргументы. Могут передаваться по ссылке (ключевое слово ByRef, которое можно опустить, поскольку такой тип передачи используется по умолчанию - не так, как в C и Pascal. Внимание! Не испортите случайно передаваемые переменные, при необходимости применяйте ByVal) или по значению (ключевое слово ByVal). При вызове можно использовать именованные аргументы, например: Sub S(arg1, arg2, arg3) ... End Sub ... S 1, 2, 3 'обычный вызов с неименованными параметрами Call S (1, 2, 3) ' то же самое S arg2:=2, arg1:=1, arg3:3 'использование именованных параметров При использовании именованных аргументов их можно передавать в любом порядке. Если при вызове использовать не все аргументы, то возникает сообщение об ошибке. Однако есть возможность объявить некоторые аргументы как необязательные, для этого перед именем аргумента ставится ключевое слово Optional. После первого необязательного аргумента все остальные тоже должны быть необязательными. Внутри функции можно проверить, был ли передан аргумент с помощью специальной функции IsMissing (см. help). 11. Циклы. Вроде ничего особенного, за исключением того, что цикл while условие wend считается в VBasic "нестандартным", и для него нет оператора досрочного выхода из цикла Exit. 12. Существует такое понятие, как массив элементов управления (ЭУ), например, кнопок. Чтобы создать массив ЭУ, достаточно скопировать в буфер обмена элемент и потом снова вставить его в форму, оставив его имя тем же. ЭУ в массиве имеют одно и то же имя и обработчики событий, но разное значение свойства Index. Значение этого свойства передаётся в обработчик события, что бывает очень удобно. С помощью операторов Load и Unload во время выполнения можно создавать на форме новые ЭУ. Более широкие возможности по созданию ЭУ runtime предоставляет оператор Add. 13. Для работы с реестром есть функции (установки программ на VBasic сохраняются в HKEY_CURRENT_USER\Software\VB and VBA Program Settings и дублируется в HKEY_USERS\S-1-5-21-1864085942-2410699049-2459454283-1003\Software\VB and VBA Program Settings): SaveSetting Имя_приложения, Секция, Ключ, Установка GetSetting Имя_приложения, Секция, Ключ[, Значение_по_умолчанию] GetAllSettings Имя_приложения, Секция DeleteSetting Имя_приложения, Секция[, Ключ] Значение Имя_приложения не имеет значения, но для пользователя было бы удобнее, чтобы оно носило осмысленный характер (для облегчения поиска по реестру). 14. Кроме обычных, очевидных свойств, элементы управления имеют свойства Parent (которое позволяет считывать свойства родительского элемента-контейнера, например, формы) и Container (позволяет менять контейнер для ЭУ). Следующие ЭУ могут служить контейнером для других ЭУ - Form, Frame, Picture, Toolbar. 15. События клавиатуры - Keypress, KeyUp, KeyDown. Обычно событие вызывается для активного элемента управления. Если свойство KeyPreview установлено в true, то событие, связанное с клавиатурой, передаётся сначала форме, а затем текущему элементу управления. Оператор SendKeys позволяет записывать коды нажатий в буфер клавиатуры, тем самым имитируя клавиатурные нажатия. 16. Интересные свойства формы: ControlBox определяет, отражается или нет системное меню, с помощью которого пользователь может выйти из программы (Alt+F4). Если системное меню удаляется, следует обеспечить пользователю другой способ выхода из программы. 17. Для передачи фокуса приложению существует оператор AppActivate. Его первый параметр должен в точности совпадать с заголовком активируемой программы. Следующий пример запускает калькулятор Windows, складывает числа 1 и 2, передаёт результат в буфер обмена и закрывает калькулятор: Private Sub Command1_Click() ret = Shell ("calc.exe", vbNormalFocus) AppActivate "Калькулятор", False SendKeys "1+2=^C%(F4)", True Text1.Text = Clipboard.CetText() End Sub 18. Принцип работы с файлами в VBasic несколько необычен. Он осуществляется в такой последовательности: - получение свободного дескриптора файла - handle (с помощью FreeFile) 19. Для печати используют 2 способа: - оператор PrintForm (выводит всё содержимое формы без заголовка и рамки) 20. Перехват ошибок времени выполнения (runtime). Все ошибки периода выполнения разделяются на 2 вида - ожидаемые и неожиданные. Подготовка обработки ожидаемых ошибок осуществляется в 3 этапа: - подготовка перехвата; Подготовка перехвата осуществляется оператором On Error {Goto label|Resume Next|Goto 0} При возникновении ошибки внутри блока On Error выполнение программы не прерывается и стандартное сообщение об ошибке не выдаётся, управление при ошибке передаётся на метку label, которая должна находиться в той же процедуре, что и оператор On Error. Обычно блок, начинающийся с метки label, находится в конце процедуры, и перед меткой label стоит оператор Exit (при безошибочном выполнении код после label не выполняется). Если в качестве метки указан 0, то снова включается стандартный режим обработки ошибок. Второй этап заключается в выявлении типа ошибки. Для этого в VBasic существует объект Err, у которого свойство Number содержит код последней ошибки, а Description - текст её системного описания. Завершив обработку ошибки, на третьем этапе следует продолжить нормальное выполнение программы. Оператор Resume позволяет продолжить выполнение со строки, вызвавшей ошибку, а Resume Next - со строки, следующей за строкой с ошибкой. Оператор Resume Next можно использовать вместе с оператором On Error, и тогда каждая строка, вызвавшая ошибку, игнорируется: On Error Resume Next Однако такая простейшая обработка ошибок не позволяет определить источники ошибки и исправить её. Типичным примером использования обработчика ошибок может быть обработка нажатия кнопки Cancel элемента диалога CommonDialog. Если установить свойство CommonDialog.CancelError=true, то при щелчке на кнопке Cancel возникает ошибка. Если значение CancelError==false, то различить, какая из кнопок была нажата - Ok или Cancel - будет затруднительно. Пример: Function OpenFile As String On Error Goto Cancel CommonDialog.CancelError = true CommonDialog.Filter = "Все файлы (*.*)|*.*" CommonDialog.ShowOpen OpenFile = CommonDialog.Filename Exit Function Cancel: If Err.Number=cdlCancel Then OpenFile = "" MsgBox Err.Description Exit Function Else MsgBox Err.Description Stop End If End Function Можно генерировать ошибки искусственно, вызвав Err.Raise код_ошибки. Например, Err.Raise 11
генерирует ошибку деления на ноль. 21. Строки можно объединять (склеивать) оператором + или &. 22. Внимание! Если изменить имя объекта (например, кнопки), то все обработчики событий этого объекта перестают работать, поскольку они привязаны к старому имени. Поправить можно, поменяв соответственно новому имени все названия обработчиков событий объекта. 23. Интересные (необычные) отличия функций от процедур в VBasic: - у функции аргументы всегда передаются в скобках. 24. Кое что из "горячих клавиш".
25. Если вы по недосмотру не установили для Visual Basic 6.0 сервис-пак 3, то не удивляйтесь, что всё глючит не по-детски (например, при попытке скомпилировать простейший проект и получить exe-файл среда разработки неприлично рушилась). 26. OCX означает "OLE Custom Control". 27. В других проектах можно использовать некоторую составную часть другого проекта, например - модуль, форму и т. д. Для этого их просто копируют в рабочую папку проекта и добавляют в проект командой Project\Add... . 28. Очень полезна опция, запрещающая неявное определение переменных. Махом избавляемся от кучи ошибок. Для активизации надо: - либо указать в начале модуля (это так называемая область General Declarations) строку Option Explicit 29. Exit применяют в следующих контекстах: Exit Do Для выхода из процедуры нельзя использовать GoSub, GoTo, или Return. 30. Для преобразования числа в строку применяют Str, Hex (хорошо подходят для целых чисел) и Format (для чисел с плавающей запятой и многих других типов). Format довольно гибко позволяет форматировать выходные данные. Вот пример обработки функцией Format даты и времени: ' ' Автоматическое генерирование имени файла из текущих даты и времени. ' Function FileName() As String Dim currentTimeDate As Variant Dim iYear, iMonth, iDay As Integer Dim iHour, iMinute, iSec As Integer currentTimeDate = Now() iYear = Year(currentTimeDate) iMonth = Month(currentTimeDate) iDay = Day(currentTimeDate) iHour = Hour(currentTimeDate) iMinute = Minute(currentTimeDate) iSec = Second(currentTimeDate) FileName = Format(currentTimeDate, "yymmdd") _ + Format(currentTimeDate, "hhmmss") + ".bmp" End Function 31. Для преобразования строки в число применяют Val, (хорошо подходят для целых чисел) или, в зависимости от типа данных, одну из следующих функций: CBool(expression) CByte(expression) CCur(expression) CDate(expression) CDbl(expression) CDec(expression) CInt(expression) CLng(expression) CSng(expression) CStr(expression) CVar(expression) 32. Для чтения текстового файла в VBA (Visual Basic for Application) есть, по крайней мере, 3 способа - использование CreateObject("Scripting.FileSystemObject"), object.OpenAsTextStream([iomode, [format]]) и импорт в таблицу Excel. Пример использования CreateObject("Scripting.FileSystemObject") для считывания файла exclude.txt в динамический массив: Dim ExceptionsFN As String Dim Exclusions() As String 'считываем файл исключаемых магазинов Path = ActiveWorkbook.FullName Path = Mid(Path, 1, Len(Path) - Len(Dir(Path))) ExceptionsFN = Path + "exclude.txt" Dim FS As Object Dim tf As Object Dim LineCnt As Integer Set FS = CreateObject("Scripting.FileSystemObject") Set tf = FS.OpenTextFile(ExceptionsFN) LineCnt = 0 Do If tf.AtEndOfStream Then Exit Do End If ReDim Preserve Exclusions(LineCnt) Exclusions(LineCnt) = tf.ReadLine LineCnt = LineCnt + 1 Loop tf.Close 33. VBA Excel: как обработать в цикле по столбцам и строкам все ячейки выделенной области? Для доступа к выделению служит объект Selection. Для доступа к столбцам выделения служит дочерний объект Selection.Columns, а к строкам Selection.Rows. И Columns, и Rows имеют свойство Count, которое дает количество столбцов и строк соответственно. Пример заполнения выделенной области символом "A": Dim xCount, yCount xCount = Selection.Columns.Count yCount = Selection.Rows.Count For x = 1 To xCount For y = 1 To yCount Selection.Cells(y, x).Value = "A" Next Next 34. VBA Excel: почему при попытке присвоить цвет через Interior.ColorIndex происходит ошибка выполнения 1004 (невозможно установить свойство ColorIndex класса Interior)? Run-time error '1004': Пример кода, который дает такую ошибку: Dim clYellow As Long clYellow = RGB(&HFF, &HFF, &H0) 'На этой строке ошибка Run-time error '1004': MyRange.Cells(1, 2).Interior.ColorIndex = clYellow Этот код может нормально работать в Excel 2010, и давать ошибку в Excel 2003, причем нерегулярно. Причина в том, что Microsift поменяло реализацию основного поведения методов VBA, так что это может повлиять на то, как работает код в разных версиях Excel. Если у Вас нет возможности в данной ситуации обновить версию Office, то используйте вместо присвоения свойства ColorIndex свойство Color. 'Теперь проблемы с установкой цвета нет: MyRange.Cells(1, 2).Interior.Color = clYellow 35. VBA: как открыть диалог выбора файла? Dim lngCount As Long With Application.FileDialog(msoFileDialogOpen) ' В свойство InitialFileName можно записать путь, от которого ' стартует диалог, например "c:\temp". В этом примере берется ' путь текущего каталога, где находится файл документа Office.
.InitialFileName = Application.ActiveWorkbook.Path ' Разрешить выбрать несколько файлов сразу: .AllowMultiSelect = True ' Если это надо, добавим фильтр по расширению файла: .Filters.Add "Bitmap", "*.bmp; *.gif; *.jpg; *.jpeg", 1 ' Отобразить диалог: .Show ' Отобразить полный путь до каждого выбранного файла For lngCount = 1 To .SelectedItems.Count MsgBox .SelectedItems(lngCount) Next lngCount End With [Ссылки] |