Programming: Visual Basic
Советы тем, кто программирует на VB & VBA
Авторы: Алексей Малинин, Ольга Павлова
Совет 1.
Настройка интерфейса VB/VBA
Совет 2.
Добавьте команды управления комментариями к среде разработки
Совет 3.
Как прочитать адреса отправленных писем
Совет 4.
Использование пробелов в именах таблиц баз данных ADO
Совет 5.
Как передать Null в API-функцию
Совет 6.
Как вставить колонки в VB MSFlexGrid
Совет 7.
Динамическое увеличение динамического массива
Совет 8.
Как работать с адресной книгой MS Exchange
Совет 9.
Как отключить ADO Recordset, созданный с помощью объекта Command
Совет 10.
Как использовать символ @ в именах параметров SQL Server
Совет 11.
Генерация строк соединения для OLE DB
Совет 12.
Как создавать ISAM-файлы
Совет 13.
Защита от макросов при использовании глобальных шаблонов
Совет 14. Управление подключением макросов в приложениях
Office
Совет 15. Использование цифровой подписи в Office 2000/XP
Замечание для Office 2000
Совет 16. Идентификация элементов управления
Совет 17. Предотвращение многократного запуска VB-программы
на одном компьютере
Совет 18. Удостоверьтесь, что используете нужный провайдер
при создании структурированных наборов данных ADO
Совет 19. Программная реализация копирования экрана
Совет 20. Как открыть ниспадающее меню программным образом
Совет 21. Формирование кода цвета для HTML
Совет 22. Модернизация объекта Err
Далеко
не все VB/VBA-разработчики знают о возможности выполнять настройку интерфейса
среды разработки с помощью окна Customize, которое открывается командой
View|Toolbars|Customize (рис. 1).
Рис. 1
Как и в офисных приложениях, вы можете делать видимыми или невидимыми панели
инструментов (многие программисты думают, что существует только одна —
Стандартная), создавать собственные панели, перемещать команды между разными
панелями и меню, то есть создавать такую систему меню и панелей инструментов,
какая вам кажется наиболее подходящей.
Советуем также открыть вкладку Customize|Commands (рис. 2). В списке
Categories вы обнаружите перечень категорий команд, которые представлены в среде
в виде меню. Но если внимательно посмотреть на состав команд отдельных категорий
(список Commands), то можно заметить, что на самом деле их гораздо больше, чем
видны в меню по умолчанию.
Рис. 2
К сожалению, справка окна Customize работает не самым лучшим образом, поэтому
разобраться в смысле незнакомых команд непросто. Пользователи офисных приложений
находятся в лучшем положении: в справке имеется раздел VB Use Interface Help с
описаниями всех встроенных команд. Они также могут воспользоваться кнопкой
Description для вывода подсказки (в VB эта кнопка почему-то не работает).
Продемонстрируем,
как применить предыдущий совет на практике. Так, при разработке приложений
довольно часто бывает нужно закомментировать целые блоки программного кода. Это
приходится делать в тех случаях, когда нужно на некоторое время удалить код или
даже удалить совсем, но оставить его в виде комментария. Обычно вы это делаете,
пробегая курсором по всем строкам и нажимая клавишу апострофа. Но все это можно
гораздо проще совершить с помощью малоизвестных для вас команд среды разработки
VB.
Командой View|Toolbars|Customize откройте окно Customize|Commands. Далее в
списке Categories выделите строку Edit. Потом в списке Commands найдите команды
Comment Block и Uncomment Block, а затем перетащите их мышью на панель
управления Standard. Теперь, если вы выделите некоторый фрагмент кода, то одним
щелчком мыши по соответствующей команде сможете устанавливать или убирать
апострофы в первой позиции выделенных строк.
Кстати, среди таких малоизвестных команд имеются также Indent и Outdent,
которые позволяют сдвигать фрагменты текста на один отступ вправо или влево.
Допустим,
вам нужно получить список адресов, по которым вы отправили письма. Если они
лежат в папке отправленных писем Outlook, то это можно сделать с помощью такого
кода:
Dim myItems As Items
Dim mailmsg As MailItem
' выборка писем из папки
Set myItems = _
Application.Session.GetDefaultFolder(olFolderOutbox).Items
If myItems.Count > 0 Then ' есть письма
For Each mailmsg In myItems
MsgBox "Куда отправлено - " & mailmsg.To
Next
Else
MsgBox "нет отправленных писем"
End If
Если же вам нужно обратиться к некоторой произвольной пользовательской папке,
то выборка писем будет выглядеть примерно так: Set myItems = Application.GetNamespace("MAPI"). _
Folders.Item("Personal Folders").Folders.Item("Outbox").Items
Наверняка
вам известно, что в именах таблиц и полей баз данных ADO нельзя использовать ни
пробелы, ни идентификаторы типа «Большая деревня». Но на самом деле подобные
имена вполне допустимы, просто для их обозначения нужно применять квадратные
скобки. Соответственно метод Open будет выглядеть примерно следующим образом:
rst.Open "[Большая деревня]", conn,,,adCmdTable
А SQL-запрос может выглядеть так:
rst.Open "SELECT [Малыш Дик] FROM [Большая деревня]"
Довольно
часто бывает необходимо передать в API-функцию значение Null (0&) в качестве
одного из аргументов. Но сделать это порой не так-то просто, поскольку вы можете
столкнуться с ограничением объявления функции: VB выдаст в этом случае сообщение
об ошибке. Например, рассмотрим такое объявление функции, которое получено
копированием соответствующего кода из файла Win32api.txt с помощью API Viewer:
Public Declare Function ScrollWindowEx Lib _
"user32" (ByVal hwnd As Long, ByVal dx As Long, _
ByVal dy As Long, lprcScroll As RECT, _
lprcClip As RECT, ByVal hrgnUpdate As Long, _
lprcUpdate As RECT, ByVal fuScroll As Long) As Long
Здесь видно, что эта функция использует несколько структур RECT, в которых
задается область прокрутки Windows. Но если передать вместо адресов блоков
данных нуль, то Windows самостоятельно будет определять эти области. С этих
позиций следующее обращение к функции является вполне допустимым: ScrollWindowEx m_hWnd, 0, 5, ByVal 0&, ByVal 0&, 0&, ByVal 0&, _
SW_SCROLLCHILDREN Or SW_INVALIDATE
Однако в данном случае VB выдаст сообщение о том, что такое обращение
(передача аргумента по значению) противоречит сделанному выше объявлению
(передача по ссылке).
Чтобы решить указанную проблему, можно использовать два варианта. В первом
нужно заменить в объявлении типы данных RECT на Any: Public Declare Function ScrollWindowEx Lib _
"user32" (ByVal hwnd As Long, ByVal dx As Long, _
ByVal dy As Long, lprcScroll As Any, _
lprcClip As Any, ByVal hrgnUpdate As Long, _
lprcUpdate As Any, ByVal fuScroll As Long) As Long
С таким объявлением будет допустима передача как адреса структуры, так и
числовой величины.
Однако, как мы уже неоднократно упоминали, использование типа Any повышает
риск ошибки (фактически в данном случае отключается синтаксический контроль,
вследствие чего вся ответственность за правильность обращения возлагается на
программиста). Поэтому мы советуем воспользоваться возможностью альтернативного
объявления функции, например следующим образом: Public Declare Function ScrollWindowExLong Lib _
"user32" Alias ScrollWindowEx
(ByVal hwnd As Long, ByVal dx As Long, _
ByVal dy As Long, ByVal lprcScroll As Long, _
ByVal lprcClip As Long, ByVal hrgnUpdate As Long, _
ByVal lprcUpdate As Long, ByVal fuScroll As Long) As Long
Соответственно при необходимости передачи нулевых параметров нужно
использовать обращение именно к этой функции: ScrollWindowExLong _
m_hWnd, 0, 5, ByVal 0&, ByVal 0&, 0&, ByVal 0&, _
SW_SCROLLCHILDREN Or SW_INVALIDATE
Совет 6. Как вставить колонки в VB MSFlexGrid
Елемент
управления MSFlexGrid предоставляет отличные возможности для визуализации данных
в виде таблицы. Однако иногда необходимо, чтобы сам пользователь мог вставлять
колонки в определенных точках таблицы, в то время как VB по умолчанию добавляет
новые колонки в конец таблицы. Эта проблема легко решается с помощью
обновленного свойства ColPosition, для чего достаточно написать такой код: Private Sub Command1_Click()
With MSFlexGrid1
' добавить новую колонку
.Cols = .Cols + 1
' переместить в нужную позицию
.ColPosition(.Cols - 1) = .Col
End With
Call SetHeaders ' переписать заголовки
End Sub
Private Sub SetHeaders()
' формирование заголовков
Dim i As Integer
With MSFlexGrid1
For i = 0 To .Cols - 1
.Col = i
.Row = 0
.Text = "Колонка " & i
Next i
End With
End Function
Если
вам нужно динамически увеличить верхнюю границу массива, то можно
воспользоваться такой конструкцией: Dim upper As Long ...
upper = UBound(myArray) ' текущее значение верхней границы
ReDim myArray(upper + 1) 'увеличение
Но если к моменту обращения к функции Ubound массив не был еще
инициализирован (то есть был определен в виде Dim myArray()), то приведенный
выше код вызовет ошибку. Чтобы избежать этого, используйте такой код: Dim myArray() As String
Private Sub cmdAdd_Click()
Dim upper As Long
On Error Resume Next ' включаем обработку ошибок
upper = UBound(myArray)
If Err.Number Then
upper = 0
ReDim myArray(0)
Else
upper = upper + 1
ReDim Preserve myArray(upper)
End If
On Error GoTo 0 ' отключаем обработку ошибок
myArray(upper) = CStr(txtName) ' ввод нового значения
End Sub
Наш
читатель Виктор Крюков поделился своим опытом работы с адресной книгой MS
Exchange. В организации, где он работает, почтой управляет MS Exchange 2000,
поэтому результат обращения к свойству ContactItem.Email1Address выглядит
примерно так: "/o=UFG/ou=UFG/cn=Recipients/cn=VKryukov".
Как же получить реальный адрес? Виктор
предлагает такой рецепт. Объект, который хранит информацию о пользователе, —
это AddressEntry, находящийся в коллекции AddressEntries, которая, в свою
очередь, находится в объекте AddressList коллекции AddressLists данной сессии. У
этого объекта есть семейство Fields, которое и хранит нужные свойства. Видимо,
для доступа эти свойства проиндексированы какими-нибудь именованными константами
типа PR_ADDRESS_EMAIL и т.п., но мы их не
нашли.
Вот возможные варианты решения этой задачи:
- делать цикл по всем полям и искать значение, содержащее '@' в качестве
подстроки;
- найти значение, которое является массивом, — оно всего одно, представляет
собой массив строк и содержит строчки примерно такого вида (этот вариант
кажется более надежным):
SMTP:_servrice@ufg.com
MS:UFG/UFG/Service
CCMAIL: Service at UFG
X400:c=RU;a= ;p=UFG;o=UFG;s=?service;
то есть это адреса в разных форматах. Из данного массива выбирается строчка,
начинающаяся с 'SMTP', и обрезается начало, которое и является правильным
ответом.
Вот код для примера (мы добавляем в коллекцию Result все имена и адреса), для
выполнения которого требуется в References подключить Microsoft CDO 1.21
Library. Private Sub Form_Load()
Dim oSession As MAPI.Session
Dim oAList As MAPI.AddressList
Dim oAEntry As MAPI.AddressEntry
Dim oValue As Variant
Dim i As Integer, v As Variant, j As Integer
Dim Result As New Collection
' Logon to the MAPI session
Set oSession = New MAPI.Session
oSession.Logon
' Get the Global Address List
Set oFolder = oSession.AddressLists("Global Address List")
For Each oEntry In oFolder.AddressEntries
For i = 1 To oEntry.Fields.Count
v = oEntry.Fields(i).Value
If IsArray(v) Then
For j = LBound(v) To UBound(v)
If Mid(v(j), 1, 5) = "SMTP:" Then
Result.Add Mid(v(j), 6) & " : " & oEntry.Name
GoTo continue
End If
Next j
End If
Next i
continue:
Next oEntry
For i = 1 To Result.Count
MsgBox Result(i)
Next i
End Sub
Когда
вы создаете распределенное приложение, крайне важно, чтобы ваш код занимал как
можно меньше ресурсов сервера. В этом случае узким местом является поддержка
соединения с сервером баз данных. Конечно, выполнить отключение набора данных из
стандартного объекта Recordset очень просто. А вот сделать это с набором данных,
который был сгенерирован с помощью объекта Command, не так легко, хотя и
возможно.
В этих целях создайте объект Command и установите его свойства, как вы это
обычно делаете, но вместо обращения к свойству Execute используйте метод Open
объекта Recordset с аргументом Source. Тогда вы отключите соединение обычным
образом и удалите объект Command. Все это можно проиллюстрировать с помощью
такого кода: Dim cmd As ADODB.Command
Dim rst As ADODB.Recordset
Dim param As ADODB.Parameter
Set cmd = CreateObject("ADODB.Command")
With cmd
.CommandText = "sp_myStoredProc"
.CommandType = adCmdStoredProc
.ActiveConnection = STR_CONN 'Какая-то строка соединения
Set param = .CreateParameter("Param1", _
adVarChar, adParamInput, 2, "foo")
.Parameters.Append param
End With
Set rst = CreateObject("ADODB.Recordset")
With rst
.CursorLocation = adUseClient
.Open cmd, CursorType:=adOpenStatic, _
Options:=adCmdStoredProc
Set .ActiveConnection = Nothing
End With
Set DataGrid1.DataSource = rst
Set cmd = Nothing
End Sub
Как
известно, ADO предлагает два варианта поддержки хранимых процедур со значениями
параметров: в первом случае нужно сослаться на имя параметра напрямую и просто
присвоить значение, а во втором следует построить объект Parameter и добавить
его к коллекции Parameters объекта Command. Однако нужно иметь в виду, что,
когда вы используете именованные параметры, следует применять символ @ перед
именем каждого параметра SQL, например вот так: cmd.Parameters("@someParam") = 250
Если же вы создаете объект Parameter, этот символ не используется: Set param = cmd.CreateParameter _
("someParam", adBigInt, adParamInput, 2, 250)
cmd.Parameters.Append param
Совет 11. Генерация строк соединения для OLE DB
Создать
строку соединения OLE DB без использования элемента управления DataEnvironment в
VB-проекте не так-то просто: нужно в контекстном меню объекта Connection1
выделить команду Properies, а затем установить значение в диалоговом окне Data
Link Properties, которое потом переписать в свойство ConnectionSource. Однако
существует довольно легкое решение этой проблемы.
Создайте текстовый файл с расширением VBS (VBScript) с таким кодом: Dim oDataLinks, sRetVal
Set oDataLinks = CreateObject("DataLinks")
On Error Resume Next 'отслеживание кнопки Cancel
sRetVal = oDataLinks.PromptNew
On Error Goto 0 ' отключение обработки ошибок
If Not IsEmpty (sRetVal) Then ' не была нажата Cancel
InputBox "Строка соединения OLE DB = ", sRetVal
End If
Set oDataLinks = Nothing
После двойного щелчка по имени этого файла начнет выполняться этот код, и вы
сможете скопировать строку соединения из поля ввода.
Если же вы работаете с VB, то можно добавить ссылку на Microsoft OLE DB
Service Component 1.0 Type Library (OLEDB32.DLL) и использовать Object Browser
для обращения к объекту DataLinks.
помощью библиотеки ADOX 2.1 (Microsoft ADO Extensions for DLL and Security)
можно легко создать новый ISAM-файл в самых различных форматах (Excel, dBase,
Paradox, HTML и Lotus) без обращения к соответствующим объектным моделям и даже
при отсутствии приложений, для которых эти форматы являются родными.
Приведем пример того, как можно создать XLS-файл с двумя рабочими листами:
Public Sub Main()
Dim cn As Connection
Dim cat As Catalog
Dim tbl As Table
Dim fld As Column
Set cn = New Connection
With cn ' установка соединения
.ConnectionString = _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Extended Properties=Excel 8.0;" & _
"Data Source=" & App.Path & "\newfile.xls"
.Open
End With
Set cat = New Catalog
With cat ' формирование таблиц
.ActiveConnection = cn
' первая таблица (рабочий лист)
Set tbl = New Table
tbl.Name = "NewSheet1"
Set fld = New Column
fld.Name = "MyCol1"
fld.Type = adWChar
fld.DefinedSize = 30
tbl.Columns.Append fld
' вторая колонка
tbl.Columns.Append "Column2", adInteger
.Tables.Append tbl ' добавляем первую таблицу
' вторая таблица (рабочий лист)
Set tbl = New Table
tbl.Name = "NewSheet2"
' вторая колонка
tbl.Columns.Append "МояКолонка1", adWChar, 20
.Tables.Append tbl ' добавляем вторую таблицу
cat.Tables.Refresh ' запись
End With
' очистка
Set fld = Nothing
Set tbl = Nothing
Set cat = Nothing
cn.Close
Set cn = Nothing
End Sub
Запустите эту процедуры, а потом с помощью Excel убедитесь, что вы получили
рабочую книгу с двумя листами, в которых заданы соответственно две и одна
колонки. Вы можете создавать файлы и других типов, просто установив в Extended
Properties нужное значение: dBase IV, Paradox 4.x и пр.
Совет 13. Защита от макросов при использовании
глобальных шаблонов
нам поступил вопрос: «Почему при работе в Word 2000 при использовании глобальных
шаблонов, а также при загрузке шаблонов в виде автономных документов или
присоединенного файла из каталога «Шаблоны пользователя» не производится
проверка на наличие макрокода, хотя такой режим контроля у меня установлен?»
Отвечаем на это следующим образом. Управление режимом контроля за наличием
макрокода при загрузке документов производится в диалогом окне
Security[Безопасность] (команда меню Tools|Macro|Securiry
[Сервис/Макрос/Безопасность]). На его вкладке Trusted Sources [Надежные
источники] имеется флажок Trust all installed Add-ins and templates [Доверять
всем установленным надстройкам и шаблонам]. Под установленными здесь
подразумеваются дополнения и шаблоны, помещенные в каталог «Шаблоны
пользователя» (конкретное имя этого каталога указывается в поле User Templates
[Шаблоны пользователя] во вкладке File Locations [Расположение] диалогового окна
Tools|Options [Сервис|Параметры]).
По умолчанию данный флажок установлен, поэтому все шаблоны из этого каталога
не проверяются на наличие макрокода (предполагается, что вы помещаете туда
файлы, в которых точно уверены). Если вы все же хотите выполнять такую проверку,
то очистите флажок.
В Word 97 специального режима для загрузки шаблонов не было. Но в начальной
версии программы иногда имела место ошибка, когда шаблоны загружались без
проверки на макрокод. Этот дефект уже давно устранен — заплатку, которая решает
данную проблему, можно скачать по адресу .
Совет 14. Управление подключением макросов в приложениях
Office
В одной из Web-дискуссий был задан такой вопрос: «При загрузке Outlook у меня
постоянно выдается окно предупреждения о наличии макросов в загружаемом проекте.
Как мне добиться того, чтобы загрузка выполнялась автоматически без требования
подтверждения в диалоговом окне?»
В целом решение
этого вопроса одинаково для всех
приложений Office. Но в отношении Outlook (версии
2000 и 2002) стоит напомнить, что эта программа
использует для хранения макросов только
один фиксированный файл с именем VbaProject.OTM,
который хранится в каталоге C:\Windows\Application
Data\Microsoft\Outlook\. Сам программный проект может
иметь еще и собственное произвольное имя (оно
видно только в среде VBA).
Для ответа на
поставленный вопрос нужно иметь в виду, что
приложения Office (начиная с 2000) имеют три
уровня безопасности для управления
загрузкой макросов, а также возможность
использования цифровой подписи. С помощью
этих механизмов можно более гибко
управлять режимами загрузки.
Рассмотрим возможности управления безопасностью. Режим защиты устанавливается
в диалоговом окне «Безопасность» (Security), которое открывается командой «Сервис|Макро|Безопасность», где видно описание трех возможных уровней безопасности.
рис. 3
- Высокий. Разрешается запуск только подписанных макросов из надежных источников.
Неподписанные макросы удаляются автоматически. При наличии макросов с неизвестными
подписями выдается окно предупреждения, однако такие макросы можно подключить,
только признав подлинность подписи.
- Средний. Подписанные макросы загружаются автоматически. О наличии неподписанных
макросов выдается предупреждение, и решение об их загрузке принимается пользователем.
- Низкий. Защита отсутствует, все макросы загружаются автоматически.
В приложениях Office
по умолчанию установлен средний уровень
безопасности, что и вызывает появление окна
предупреждения о наличии макросов.
Соответственно существует два варианта
ответа на приведенный выше вопрос:
- Установите низкий уровень безопасности — и никаких предупреждений вообще
не будет. Но мы не рекомендуем этот вариант, так как проверка на наличие макросов
при загрузке неизвестных файлов (например, полученных из Интернета или по
электронной почте) необходима. Но для Outlook такой вариант является вполне
подходящим — ведь мы имеем дело только с фиксированным файлом локального компьютера,
который создается исключительно его хозяином.
- Лучший способ (наиболее универсальный) — использовать цифровую подпись проекта
(в том числе и для Outlook). Этот способ немного подробнее мы рассмотрим в
совете 16.
Для тех, кто
работает с Word и Excel, есть еще один вариант,
который позволяет отменить проверку
наличия макросов в глобальных шаблонах и
Add-ins. Для подобных приложений во вкладке
Trusted Sources [Надежные источники] окна Security [Безопасность]
имеется флажок Trust all installed Add-ins and templates [Доверять
всем установленным надстройкам и шаблонам].
Под «установленными»
подразумеваются дополнения и шаблоны,
помещенные в каталог «Шаблоны пользователя».
(Конкретное имя этого каталога указывается
в поле User Templates [Шаблоны пользователя] во
вкладке File Locations [Расположение] диалогового
окна Tools|Options [Сервис|Параметры].)
По умолчанию
данный флажок установлен, поэтому все
шаблоны из этого каталога не проверяются на
наличие макрокода (подразумевается, что вы
помещаете туда файлы, в которых абсолютно
уверены). Если вы все же хотите выполнять
такую проверку, то снимите флажок.
В Word 97 такого специального режима для загрузки шаблонов не было. Но в начальной
версии программы иногда имела место ошибка, когда шаблоны загружались без проверки
на макрокод. Этот дефект уже давно устранен — заплатку, которая решает данную
проблему, можно скачать по адресу .
Совет 15. Использование цифровой подписи в Office 2000/XP
Здесь
есть три элемента: создание и удаление сертификата, подключение цифровой подписи
к документу, признание подписи в качестве «надежной». Рассмотрим их последовательно.
- Создание и удаление сертификата. Каждый пользователь может создать один
или несколько сертификатов. Это делается тремя способами: создать собственный
сертификат, получить сертификат у администратора сети (если на предприятии
разработаны собственные стандарты) и получить фирменный сертификат в специализированном
центре (например, у той же компании Microsoft).
Собственный сертификат создается утилитой SelfCert.exe, которая входит
в состав пакета
рис. 4
В первом варианте русской
версии MS Office 2000 в этой программе была ошибка (не раскрывалось диалоговое
окно), но уже в первом сервисном наборе обновления дефект был исправлен.
-
-
Удаление же сертификата выполняется довольно хитрым способом, с помощью
(кто бы мог ожидать?) Internet Explorer. Для этого в IE нужно выбрать команду
«Сервис|Свойства обозревателя», затем выделить вкладку «Содержание», нажать
кнопку «Сертификатов...», открыть вкладку «Личные» в окне «Диспетчер Сертификатов»
и уже там проводить операции с сертификатами
рис. 5
- Подключение цифровой подписи. Электронная подпись подключается к VBA-проекту
в среде VBA с помощью команды Tools|Digital Signature, которая выводит соответствующее
окно «Цифровая подпись»
рис. 6
Для выбора нужного сертификата нужно нажать кнопку «Выбрать», после чего
выдается окно Select Certificate со списком имеющихся сертификатов
рис. 7
Нажав кнопку, можно ознакомиться с более детальной информацией о сертификате
в окне Certificate с тремя вкладками
рис. 8
К этой же информации можно получить доступ из других диалоговых окон при
работе с сертификатами (обычно они называются «Подробности»). При желании
можно в любой момент поменять подпись проекта или удалить ее совсем.
- Признание подписи в качестве надежной. Эта операция выполняется только в
момент загрузки проекта с наличием макросов, имеющих подписи, в режиме среднего
и высокого уровней безопасности.
В этом случае выдается окно предупреждения
рис. 9
В этот момент можно посмотреть более детальную информацию о данном сертификате
(кнопка Details). Если вы считаете данный источник надежным, то нужно установить
флажок Always trust macros from this source [Всегда доверять макросам этого
источника] — и данный сертификат автоматически попадет в список надежных.
Эти можно увидеть во вкладке Trusted Source окна Security
рис.
10
Здесь же можно удалить ненужные подписи.
Обратите внимание, что при использовании среднего уровня безопасности вы
можете разрешить использование макросов проекта даже без занесения подписей
в список доверенных (в том числе загружать проекты без подписей, например
созданных в Office 97). При работе с высоким уровнем это можно сделать,
только признав подпись (установив флажок «Всегда доверять»), то есть макросы
проектов без подписей вообще нельзя использовать.
Замечание для Office 2000
Следует обратить
внимание еще на один важный момент, который
имел место в приложениях Office 2000.
Порой здесь
возникает ситуация, когда пользователь не
может сохранить проект (документ с
макрокодом) с электронной подписью —
запись документа возможна только без
подписи. При этом выдается неверная
диагностика о нехватке места на диске.
Причина такого
поведения — наличие внутренних
синтаксических ошибок в коде проекта.
Поэтому при обнаружении подобного
сообщения о невозможности сохранения
документа с электронной подписью, прежде
чем отменять подпись, рекомендуем вам
проверить работоспособность вашего кода.
Довольно часто ошибка связана с
отсутствием описания переменной или ссылки
на внешний объект. Чтобы лучше понять суть
ситуации, сделайте следующий простой
пример в Word: создайте новый документ,
перейдите в среду VBA и там создайте
макрокоманду Test1:
Sub Test1 ()
Avar = 1
End If
Разумеется,
сначала должен быть задан режим Option Explicit (обязательное
объявление переменных).
Теперь установите
электронную подпись и попробуйте сохранить
документ. Скорее всего, у вас появится
сообщение о нехватке места на диске для
записи файла. Запустите
макрокоманду Test1 на выполнение —
транслятор выдаст сообщение о
синтаксической ошибке (не определена
переменная Avar). Добавьте в процедуру
описание:
Dim Avar As Integer
Теперь
макрокоманда станет выполняться (правда, не
делая ничего полезного), и документ тоже без
проблем сохранится с электронной подписью.
Судя по всему,
такое поведение Word 2000 является ошибкой (об
этом говорит хотя
бы выдача неверной диагностики). В Word 2002 эта
ситуация исправлена — сохранение проекта с
подписью выполняется независимо от ошибок
кода.
Совет 16. Идентификация элементов управления
Порой
бывает необходимо узнать внутри программного кода тип элемента управления, с
которым выполняется в данный момент работа. Например, вы хотите изменить текст
на всех командных кнопках формы или изменить какие-то свойства элементов управления
определенного типа. Для подобной идентификации лучше всего подходит оператор
TypeOf, который может использоваться в операторе If...Then:
If TypeOf ctl Is CommandButton Then
' Выполнить что-то
End If
Для идентификации типа произвольного элемента управления
можно использовать, например, такую процедуру:
Private Sub Command1_Click()
Dim ctl As Control
Dim str As String
For Each ctl In Me.Controls
If TypeOf ctl Is CommandButton Then _
str = "CommandButton"
If TypeOf ctl Is TextBox Then str = "TextBox"
If TypeOf ctl Is OptionButton Then str = _
"OptionButton"
If TypeOf ctl Is DriveListBox Then str = _
"DriveListBox"
If TypeOf ctl Is DataCombo Then str = _
"DataCombo"
MsgBox "Элемент управления типа " & str
Next ctl
End Sub
Совет 17. Предотвращение многократного запуска VB-программы
на одном компьютере
Возможно,
вам необходимо предотвратить возможность повторного запуска вашего приложения
(если оно уже запущено). Для этого можно воспользоваться свойством PrevInstance
объекта App, например таким образом:
Private Sub Main()
If App.PrevInstance Then
' приложение уже запущено
Exit Sub ' завершить процедуру (а значит и приложение)
End If
' продолжение работы программы
End Sub
Совет 18. Удостоверьтесь, что используете нужный провайдер
при создании структурированных наборов данных ADO
Как
вы, возможно, знаете, технология ADO позволяет включать иерархические структуры
данных в один объект Recordset. Однако при создании такого объекта нужно правильно
указать опции провайдера. Например, типичный вариант формирования стандартного
набора данных может использовать такую строку соединения:
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\MyData\SomeDB.mdb"
Но для создания
структурированного объекта Recordset вам нужно
в качестве провайдера использовать SDataShape. К
тому же вы должны указать, какой механизм
OLEDB будет обеспечивать поддержку данных:
"Provider=MSDataShape;Data Provider=Microsoft.Jet.OLEDB.4.0;
Data Source=C:\MyData\SomeDB.mdb"
или в случае SQL Server users:
"Provider=MSDataShape;Data Provider=SQLOLEDB;
Data Source=MyServerName;Initial Catalog=SomeSQLDB"
Кроме того, можно
указать подобную строку в свойстве Provider
объекта ADO Connection.
Совет 19. Программная реализация копирования экрана
Наш
читатель Евгений спрашивает, как программным образом реализовать режим PrintScreen.
А спустя пару дней сам же прислал свое решение этой задачи:
Private Declare Function BitBlt Lib "gdi32" _
(ByVal hDestDC As Long, ByVal x As Long, _
ByVal y As Long, ByVal nWidth As Long, _
ByVal nHeight As Long, ByVal hSrcDC As Long, _
ByVal xSrc As Long, ByVal ySrc As Long, _
ByVal dwRop As Long) As Long
Private Declare Function GetDesktopWindow _
Lib "user32" () As Long
Private Declare Function GetDC _
Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" _
(ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Const SRCCOPY = &HCC0020
'--------------------------------------------------------------------------
Private Sub Command1_Click()
Dim hwndScreen As Long
Dim hScreenDC As Long
Dim Res As Long
hwndScreen = GetDesktopWindow()
hScreenDC = GetDC(hwndScreen)
Res = BitBlt(hdc, 0, 0, ScaleWidth, ScaleHeight, hScreenDC, 0, 0, SRCCOPY)
Res = ReleaseDC(hwndScreen, hScreenDC)
Form1.WindowState = vbMaximized 'распахиваем окно на полный экран
End Sub
Но только для
формы нужно установить свойство AutoRedraw=True.
Совет 20. Как открыть ниспадающее меню программным образом
Как
известно, VB 6 включает возможность задания Style=5 (tbrDropDown) для объекта
Button элемента управления Toolbar. В этом случае можно добавить кнопке несколько
объектов ButtonMenu. Но открыть меню можно только с помощью щелчка стрелки.
То есть нельзя выполнить такую операцию из программного кода. Эта задача может
быть решена с помощью следующего кода:
Private Type POINTAPI
x As Long
y As Long
End Type
Private Declare Function GetCursorPos Lib "user32" _
(lpPoint as POINTAPI) As Long
Private Declare Function ClientToScreen Lib "user32" _
(ByVal hWnd As Long, _
lpPoint as POINTAPI) As Long
Private Declare Function SetCursorPos Lib "user32" _
(ByVal x As Long, ByVal y As Long) As Long
Private Declare Function ShowCursor Lib "user32" _
(ByVal bShow As Long) As Long
Private Declare Sub mouse_event Lib "user32" _
(ByVal dwFlags As Long, ByVal dx As Long, _
ByVal dy As Long, ByVal cButtons As Long, _
ByVal dwExtraInfo As Long)
Private Sub ShowPopUpMenu _
(TB As Toolbar, IndexOfButton%)
' раскрываем меню
CONST MOUSEEVENTF_LEFTDOWN = &H2
Const MOUSEEVENTF_LEFTDOWN = &H2
Const MOUSEEVENTF_LEFTUP = &H4
Dim Pt As POINTAPI, oldPt As POINTAPI
With TB.Buttons(IndexOfButton)
If Not (.Style = tbrDropdown Then Exit Sub
' режим разрешен
Call GetCursorPos(oldPt) ' запоминаем позицию курсора
Call ClientToScreen(TB.hWnd, Pt)
Call ShowCursor(False)
' устанавливаем курсор на стрелку
Call SetCursorPos(Pt.x + ((.Left + .Width) / _
Screen.TwipsPerPixelX) - 1, _
Pt.y + ((.Top + .Height)\ 2 /_
Screen.TwipsPerPixelY))
End With
' имитируем щелчок мышью
Call mouse_event(MOUSEEVENTF_LEFTDOWN, _
0, 0, 0, 0)
Call mouse_event(MOUSEEVENTF_LEFTUP, _
0, 0, 0, 0)
' восстанавливаем позицию курсора мыши
Call SetCursor(oldPt.x, oldPt.y)
Call ShowCursor (True)
End Sub
Используя эту
подпрограмму, можно, например, открыть меню,
когда пользователь щелкнет саму кнопку:
Sub ToolBar1_ButtonClick _
(ByVal Button As MSComctllib.Button)
Call ShowPopUpMenu (Toolbar1.Button.Index)
End Sub
Совет 21. Формирование кода цвета для HTML
Эта
функция преобразует числовое значение цвета в строковую переменную для использования
в HTML:
Public Function HtmlHexColor _
(ByVal ColorValue As Long) As String
Dim r As Byte
Dim g As Byte
Dim b As Byte
' преобразование цвета (если это нужно)
Call OleTranslateColor _
(ColorValue, 0&, ColorValue)
r = ColorValue Mod &H10
g = (ColorValue \ &h100) Mod &H100
b = (ColorValue \ &h10000) Mod &H100
HtmlHexColor = "#" & _
Right$("0" & Hex$(r),2) & _
Right$("0" & Hex$(g),2) & _
Right$("0" & Hex$(b),2)
End Function
Совет 22. Модернизация объекта Err
Как
это ни странно, но вы можете расширить функциональность встроенного объекта
Err. Создайте класс с именем Cerror и включите в него такую процедуру свойства:
Public Property Get Number() As Long
Number = VBA.Err.Number
End Property
Далее создайте BAS-модуль со следующим кодом:
Public Function Err() As Cerror
Static oErr As Cerror
If oErr Is Nothing Then
Set oErr = New Cerror
End If
Set Err = oErr
End Function
Теперь вы можете
обращаться к созданному объекту Cеrror
для которого можно создать любой набор
свойств и методов.
При перепечатке любого материала
с сайта, видимая ссылка на источник www.warayg.narod.ru
и все имена, ссылки авторов обязательны.
© 2005
|