Текст книги "Excel. Трюки и эффекты"
Автор книги: Алексей Гладкий
Жанр: Программы, Компьютеры
сообщить о неприемлемом содержимом
Текущая страница: 5 (всего у книги 22 страниц)
После того как с открытым с помощью инструкции Open файлом выполнены необходимые действия, его нужно закрыть. Операция закрытия (или освобождения) является обязательной для всех объектов операционной системы, а не только для файлов. При закрытии файла освобождается его дескриптор, а другие приложения получают возможность работать с этим файлом, если он был заблокирован при открытии.
В VBA для закрытия файлов предусмотрены две инструкции: Reset и Close. Формат этих инструкций следующий:
Reset
Close [[#]Десктиптор [, [#]Дескриптор]...]
Инструкция Reset закрывает все файлы, открытые ранее с помощью инструкции Open. Инструкция Close закрывает только файлы с указанными дескрипторами, например:
Close 1, #3, hFile
Если при использовании инструкции Close дескрипторы закрываемых файлов не указаны, то она закрывает все открытые ранее файлы.
Чтение из файлов и запись в файлыВ VBA программисту предоставляется множество инструкций для чтения и записи данных при работе с файлами. Эти инструкции разделяются на три группы в соответствии с тем, при каком типе доступа к файлу они используются: последовательном, произвольном или бинарном.
Инструкции последовательного доступа
Описание инструкций последовательного доступа, используемых для работы с файлами, приведено в табл. 1.11.
Таблица 1.11. Инструкции последовательного доступа к файлу
Ниже приведен пример использования данной функции для считывания из файла первых 10 символов:
Sub WriteToFile()
Open «D:MyTextFile.txt» For Output As 1
' Запись данных в файл
Write #1, «Значение», «Value», 154.32
Print #1, «Слово1», «Слово2», 14.28464
Close 1
End Sub
Далее целесообразно привести пример процедуры, в которой осуществляется чтение записанных данных из файла:
Sub ReadFromFile()
Dim strVal1, strVal2, dblNumber
Dim strString
Open «D:MyTextFile.txt» For Input As 1
' Чтение данных из файла
Input #1, strVal1, strVal2, dblNumber
Line Input #1, strString
Close 1
End Sub
Кроме приведенных в табл. 1.11 инструкций, в VBA имеется встроенная функция Input, позволяющая считывать из файла заданное количество символов:
Input(Количество_символов, [#]Дескриптор)
Ниже приведен пример использования данной функции для считывания из файла первых 10 символов:
Sub TestInput()
Dim strText As String
Open «D:MyTextFile.txt» For Input As 1
" Чтение из файла первых 10 символов
strText = input(10, 1)
Close 1
End Sub
Инструкции произвольного доступа
При произвольном (Random) доступе файл представляется как совокупность записей, имеющих постоянную длину. Именно запись при данном типе доступа является элементарной единицей информации, которую можно считывать из файла или записывать в файл. Каждая запись имеет свой номер (нумерация начинается с единицы). Для работы с файлами при использовании произвольного доступа в VBA реализованы инструкции Put и Get для записи и чтения информации:
Put [#]Дескриптор, [Номер_записи], Переменная
Get [#]Дескриптор, [Номер_записи], Переменная
При выполнении инструкции Put значение переменной Переменная помещается в файл на место записи с номером Номерзаписи. Если номер записи не указывается, то данные помещаются в текущую запись файла.
Инструкция Get позволяет считать значение записи с номером Номерзаписи в переменную Переменная. Если номер записи не указан, то считывается текущая запись файла.
Рассмотрим пример, в котором две структуры сначала записываются в файл с помощью инструкции Put, а потом считываются из того же файла, но в обратном порядке:
Type Record
intVal As Integer
strName As String * 100
End Type
Sub TestRandomAccess()
Dim rec1 As Record, rec2 As Record
' Заполнение rec1 и rec2 значениями ...
Open «D:MyRandomAccessFile.txt» For Random Access Read Write _
As 1 Len = Len(rec1)
' Запись данных в файл
Put 1, , rec1
Put 1, , rec2
' Теперь считывание данных из файла
Get 1, 2, rec2
Get 1, 1, rec1
Close 1
End Sub
Инструкции бинарного доступа
Бинарный (Binary) доступ к файлу по своей сути идентичен произвольному доступу с тем лишь различием, что запись в файле имеет длину 1 байт. При бинарном доступе к файлу используются те же инструкции Put и Get, что и при произвольном доступе. Также при бинарном доступе для чтения определенного количества байт может быть использована функция Input, о которой было рассказано выше.
Определение конца файлаНа практике часто приходится сталкиваться с необходимостью чтения данных из файла, размер которого заведомо неизвестен. Если достигается конец файла, а после этого производится попытка прочитать из него данные, то генерируется ошибка. Для предотвращения подобных ситуаций можно использовать функции EOF и LOF:
EOF(Дескриптор)
LOF(Дескриптор)
Функция EOF возвращает значение True, если достигнут конец файла, заданного параметром Дескриптор, и False – в противном случае. Если функция EOF возвратила значение False, то читать из файла больше нельзя. Для файлов, открытых в режиме Output, функция EOF всегда возвращает значение True.
Функция LOF позволяет узнать длину файла, заданного параметром Дескриптор. Эта функция возвращает значение типа Long, отражающее длину открытого файла в байтах.
Определение текущей позиции файлаДля определения текущей позиции файла в VBA предусмотрены функции Loc и Seek, имеющие следующий формат:
Loc(Дескриптор)
Seek(Дескриптор)
Обе функции возвращают значение текущей позиции файла, заданного параметром Дескриптор. Однако каждая из этих функций имеет свои особенности.
Функция Loc для файлов, открытых в режиме Random, возвращает номер последней считанной или записанной записи. Для файлов, открытых в режиме Binary, – номер последнего считанного или записанного байта. Для файлов, открытых в режиме последовательного доступа, – текущую позицию в байтах, деленную на 128.
Функция Seek для файлов, открытых в режиме Random, возвращает номер записи, которая будет считана из файла или записана в файл при следующей операции чтения/записи. Для остальных файлов эта функция возвращает номер байта, с которого будет начинаться следующая операция чтения или записи.
Стандартные окна сообщений
Для вывода информации пользователю в арсенале VBA есть очень удобная функция MsgBox. Она позволяет отображать стандартное окно с сообщением (например, об ошибке). Функция MsgBox имеет следующий формат:
MsgBox(Текст_сообщения[, Стиль] [, Заголовок] [, Файл_справки, Индекс_темы])
Здесь Текстсообщения задает строку с текстом сообщения, Заголовок – строку с текстом, который отображается в строке заголовка окна, Файлсправки – имя справочного файла. Если задан аргумент Файлсправки, то должен быть задан аргумент Индекстемы, который идентифицирует тему из заданного файла справки, посвященную выводимому диалоговому окну.
Особого рассмотрения заслуживает аргумент Стиль – он задает значок окна сообщения, отображаемые в этом окне кнопки и другие полезные параметры стиля окна. В табл. 1.12 приведено описание значений, которые объединяются при задании аргумента Стиль с помощью оператора Or.
Таблица 1.12. Значения, используемые для формирования стиля окна
После того как пользователь закроет окно, функция возвратит значение, соответствующее нажатой в нем кнопке. Возможные значения, возвращаемые функцией MsgBox, и их объяснения приведены в табл. 1.13.
Таблица 1.13. Значения, возвращаемые функцией MsgBox
Обработка ошибок времени выполнения
Иногда в процессе работы программы возникают ситуации, когда та или иная инструкция не может быть выполнена, например при попытке расчета значения выражения, в котором происходит деление на ноль, или при обращении к приводу компакт-дисков, когда диска в нем нет. В таких случаях генерируется ошибка времени выполнения. Если в программе не предусмотрен перехват ошибок, то будет выдано соответствующее сообщение об ошибке, а выполнение программы прекратится. Согласитесь, такое поведение программы является отнюдь не самым лучшим и дружественным по отношению к пользователю.
В VBA имеются возможности, позволяющие программе отслеживать возникновение ошибочных ситуаций и адекватно, с точки зрения программиста, на них реагировать.
Перехват ошибокДля перехвата ошибок времени выполнения в VBA используется специальная инструкция On Error, вставляемая перед тем местом программы, в котором возможно возникновение ошибки. В распоряжение программиста предоставляются три разновидности этой инструкции:
On Error GoTo Метка
On Error Resume Next
On Error GoTo 0
Первый вариант инструкции On Error активизирует обработчик ошибок (см. подраздел об обработке перехваченных ошибок). При возникновении ошибки после этой инструкции выполнение программы продолжается с метки Метка.
Использование второго варианта позволяет игнорировать все ошибки: при возникновении любой ошибки инструкция, вызвавшая ошибку, пропускается, а выполнение программы продолжается со следующей инструкции.
Третий вариант инструкции On Error отключает перехват ошибок обработчиком, находящимся в выполняемой процедуре или функции.
Обработка перехваченных ошибокЕсли в программе используется инструкция вида On Error GoTo Метка, то при возникновении ошибки после этой инструкции выполнение программы продолжается с метки Метка. Программный код, который начинается с данной метки и заканчивается (обычно, но не всегда и не обязательно) инструкцией Resume, называется обработчиком ошибок. В обработчике ошибок программист помещает действия, которые либо исправляют ошибку, либо информируют о ней пользователя. В конец обработчика ошибок обычно помещается один из вариантов инструкции Resume:
Resume [0]
Resume Next
Resume Метка
При использовании Resume [0] выполнение программы продолжается с той инструкции, в которой произошла ошибка. Если использовать вариант Resume Next, то выполнение программы продолжается со следующей инструкции после той, в которой произошла ошибка. Использование же варианта Resume Метка позволяет продолжить выполнение программы с указанной после Resume метки.
При обработке ошибок важно знать, что в распоряжении программиста всегда имеется глобальная ссылка с именем Err на объект ErrObject. Этот объект хранит подробную информацию о возникшей ошибке (номер ошибки, текст сообщения об ошибке и т. д.). В обработчике эту ссылку можно использовать для уточнения типа, источника ошибки, а также для получения других сведений.
Ниже приведен пример функции с обработчиком ошибок (она пытается записать текст в файл на гибком диске А:):
Function dhWriteToFloppy(strText As String) As Boolean
' Включение обработчика ошибок
On Error GoTo ErrHandler
' Выполнение операций с дискетой
Open «A:Text.txt» For Output As 1
Write #1, strText
Close 1
' Действия выполнены успешно
dhWriteToFloppy = True
ExitFunc:
' Выход из функции до обработчика ошибок
Exit Function
ErrHandler:
' Закрытие файла, если его все-таки удалось открыть
Close 1
Dim strErrMessage As String
' Идентификация ошибки и формирование текста сообщения
Select Case Err.Number
Case 71
strErrMessage = «Нет диска в дисководе»
Case 70
strErrMessage = «Диск защищен от записи»
Case 61
strErrMessage = «Нет места на диске»
Case Else
strErrMessage = Err.Description
End Select
' Отображение сообщения об ошибке
MsgBox strErrMessage, vbExclamation, «Ошибка»
' Продолжение выполнения программы
dhWriteToFloppy = False
Resume ExitFunc
End Function
Если запись удается, то функция возвращает значение True. Если возникает ошибка, то выдается соответствующее сообщение, после чего функция возвращает значение False. На примере функции dhWriteToFloppy следует заметить, что при нормальном выполнении программы (без возникновения ошибок) обработчик ошибок выполняться не должен, что достигается выходом из функции до обработчика с помощью инструкции Exit Function.
Классы в VBA
Язык программирования VBA является объектно-ориентированным, хотя и не поддерживает наследование и полиморфизм. VBA-программист может работать с встроенными классами, а также создавать и использовать свои собственные классы.
Создание класса на VBAСоздание класса на VBA отличается от других языков программирования (таких как C++), в которых описание классов во многом аналогично описанию структур.
В VBA для каждого класса в проект должен быть добавлен отдельный модуль, в который помещается код, реализующий работу класса, – модуль класса. Добавление нового модуля класса осуществляется с помощью команды меню Insert → Class Module (Вставить → Модуль класса) редактора Visual Basic. Имя модулю класса присваивается с помощью окна Properties (Свойства), которое показано на рис. 1.3.
Имя, которое присвоено добавленному модулю, и будет являться именем нового класса. В данном случае имя созданного класса – Class1. В качестве примера с помощью этого класса будет реализовано хранение ссылки на объект, а также хранение некоторой информации об объекте.
Рис. 1.3. Назначение имени классу
Свойства классаСвойства для классов в VBA могут быть реализованы двумя способами. Первый способ – это использование в модуле класса общих переменных-членов (объявленных с атрибутом Public). Добавим таким способом свойство в созданный ранее класс Class1, в котором будет храниться строка с описанием данных, содержащихся в объекте-экземпляре этого класса:
Public strTag As String
Такой способ реализации свойств является самым простым, однако в нем не предусмотрена возможность контролировать правильность задания параметра и осуществлять какие-либо действия при изменении его значения. Для решения этой проблемы можно использовать второй способ – создание процедур и функций, которые выполняются при установке и получении значений свойств соответственно. Для этих целей в модуле класса применяются обычные объявления процедур и функций, в которых используется ключевое слово Property.
Для получения значения свойства предназначена функция, объявленная с использованием Property Get:
[Public | Private] [Static] Property Get Имя_свойства ([Аргументы]) _
[As Имя_типа]
[Инструкции]
[Имя_свойства = Выражение]
[Exit Property]
[Инструкции]
[Имя_свойства = Выражение]
End Property
Для присвоения значения свойству, не являющемуся ссылкой на объект, предназначена процедура, объявленная с использованием Property Let:
[Public | Private] [Static] Property Let Имя_свойства ([Аргументы,]Значение)
[Инструкции]
[Exit Property]
[Инструкции]
End Property
Для присвоения значения свойству, являющемуся ссылкой на объект, предназначена процедура, объявленная с использованием Property Set:
[Public | Private] [Static] Property Set Имя_свойства ([Аргументы,]Значение)
[Инструкции]
[Exit Property]
[Инструкции]
End Property
Использование процедур и функций с ключевым словом Property очень удобно для создания свойств только для чтения (для этого свойства не реализуются Property Let и Property Set) и свойств только для записи (не реализуется Property Get).
Разберем реализацию свойств ObjectRef и ObjectType для рассматриваемого класса Class1 (частная переменная-член objRef используется для хранения установленной ссылки на объект):
Методы классаPrivate objRef As Object
Property Set ObjectRef(objNewRef As Object)
' Задание ссылки хранимого объекта
Set objRef = objNewRef
End Property
Property Get ObjectRef() As Object
' Возврат ссылки на хранимый объект
Set ObjectRef = objRef
End Property
Property Get ObjectType() As String
' Возврат имени типа хранимого объекта
ObjectType = TypeName(objRef)
End Property
Любая функция или процедура, описанная в модуле класса, является методом этого класса. Методы делятся на общие (описаны с использованием Public) и частные (описаны с использованием Private).
Ниже приведена реализация метода для созданного нами класса Class1, при обращении к которому на экран выводится сообщение со значениями атрибутов класса:
Использование класса в программеSub ShowInfo()
' Отображение окна со значением свойства strTag и именем типа _
объекта, на который хранится ссылка
MsgBox "strTag = " & strTag & vbCrLf & _
"Object type = " & ObjectType
End Sub
Как было сказано в начале главы, операции со всеми объектами VBA осуществляет только с использованием ссылок. Объявление ссылок на объекты было рассмотрено в разделе, посвященном переменным в VBA. Здесь будет рассмотрено лишь применение объекта созданного ранее класса Class1. Для создания ссылки на объект можно использовать следующее объявление:
Dim obj As Class1
После создания ссылки сам объект создается с помощью инструкции Set:
Set obj = New Class1
Объявление переменной ссылки и создание объекта можно также совместить:
Dim obj As New Class1
Для доступа к свойствам и методам объекта используется точка, например:
obj.strTag = «Некоторый текст»
Set obj.ObjectRef = Nothing
MsgBox obj.ObjectType
obj.ShowInfo
Ниже приведен пример процедуры, которая использует реализованный класс
Class1:
Sub TestClass()
' Создание объекта
Dim obj As New Class1
' Установка свойств
Set obj.ObjectRef = New Collection
obj.strTag = "В этом объекте хранится ссылка на объект
Collection"
' Вызов метода
obj.ShowInfo
End Sub
В результате работы данной процедуры на экран будет выведено окно сообщения, показанное на рис. 1.4.
Рис. 1.4. Окно с информацией о свойствах объекта
Как можно заметить, в процедуре TestClass не происходит явного уничтожения ссылки на объект класса Class1. Дело в том, что ссылка obj – локальная переменная процедуры. А при выходе из процедуры данные всех локальных (не статических) переменных уничтожаются, в том числе удаляются и локальные ссылки на объекты.
Использование API-функций в VBA
Иногда даже при программировании на таком языке, как VBA, возникает необходимость использовать API-функции Windows. Эти стандартные функции действительно предоставляют программисту поистине огромные возможности – от управления отображением окон и кнопок до организации сетевого взаимодействия. Всего Windows API (Application Programming Interface) насчитывает около 1000 различных функций.
Объявление API-функцийЧтобы API-функцию можно было вызывать из программы на VBA, ее нужно объявить с использованием инструкции Declare:
[Public | Private] Declare Function Имя Lib «Библиотека» _
[Alias «Псевдоним»] [([Аргументы])] [As Имя_типа]
или, если API-функция не возвращает значения:
[Public | Private] Declare Sub Имя Lib «Библиотека» [Alias «Псевдоним»] _
[([Аргументы])]
Данная инструкция помещается в блоке объявлений модуля. Ключевые слова Public и Private задают область видимости объявляемой API-функции аналогично обычной процедуре или функции. Единственной особенностью является то, что при объявлении API-функции в модуле класса нужно использовать Private. Назначение остальных элементов инструкции Declare поясняется в табл. 1.14.
Таблица 1.14. Элементы инструкции Declare
Ниже приведен пример объявления API-функции получения имени текущего пользователя без использования псевдонима:
Declare Function GetUserNameA Lib «advapi32.dll» _
(ByVal lpBuffer As String, nSize As Long) As Long
а также с использованием псевдонима:
Declare Function GetUserName Lib «advapi32.dll» Alias
«GetUserNameA» _
(ByVal lpBuffer As String, nSize As Long) As Long
При использовании первой из приведенных инструкций для вызова функции нужно использовать имя GetUserNameA. При использовании второй – имя GetUserName.
Вызов API-функцийВызов API-функций, объявленных с помощью инструкции Declare Function, ничем не отличается от вызова других функций: программист волен использовать инструкцию Call или употреблять функцию в выражениях. Если API-функция объявлена с использованием Declare Sub, то для вызова может применяться только инструкция Call (аналогично процедуре).
Для закрепления изложенного выше рассмотрим пример использования API-функции GetUserName для получения имени текущего пользователя компьютера:
' Объявление API-функции с использованием псевдонима
Declare Function GetUserName Lib «advapi32.dll» Alias
«GetUserNameA» _
(ByVal lpBuffer As String, nSize As Long) As Long
Sub UserName()
Dim strBuffer As String
' Создание строкового буфера для возврата значения функцией
strBuffer = Space(100)
' Получение имени пользователя (ВЫЗОВ API-ФУНКЦИИ). _
Функция возвращает ненулевое значение, если имя пользователя _
записано в strBuffer
If GetUserName(strBuffer, 100) Then
' Вывод имени пользователя
MsgBox RTrim(strBuffer)
Else
MsgBox «Не удалось получить имя пользователя»
End If
End Sub
Использование объектов Excel
Программирование на VBA в Microsoft Office чаще всего представляет собой управление объектами соответствующего приложения. Не является исключением и программирование в Excel. Данный раздел ознакомит читателя с основными объектами, встроенными в Excel. Эти объекты используются в подавляющем большинстве примеров (трюков), приведенных в дальнейших главах книги.
Правообладателям!
Это произведение, предположительно, находится в статусе 'public domain'. Если это не так и размещение материала нарушает чьи-либо права, то сообщите нам об этом.