Visual2000 · Архив статей А.Колесова & О.Павловой

Советы тем, кто программирует на Visual Basic и MS Office/VBA

Андрей Колесов, Ольга Павлова

© 1996, Андрей Колесов, Ольга Павлова
Авторский вариант. Статья была опубликована c незначительной литературной правкой в журнале "КомпьютерПресс" N 11/96, с. 85-89.


Совет 57. Используйте функцию Len для проверки пустой строковой переменной

Как уже подчеркивалось ранее, все операции над строковыми переменными, в том числе сравнения, выполняются существенно медленнее операций с числовыми данными и даже часто уступают по времени обращения к числовым функциям. В частности, при проверке пустой строки конструкция:

If Len(sName) Then ...

выглядит предпочтительнее, чем:

If sName <> "" Then ...

В начало статьи

Совет 58. Как сделать невидимыми на форме все ее элементы управления

Для этого следует просмотреть весь список элементов управления и присвоить значение False каждому свойству Enabled с помощью такого кода:

Sub cmdArray_Click ()
  Dim iLoop As Integer
  For iLoop = 0 To Me.Controls.Count - 1
    Me.Controls(iLoop).Enabled = False
  Next iLoop
End Sub

Так же просто сделать невидимой всю форму:

Me.Enabled = False

Однако следует помнить, что в последнем случае, сделав невидимым управляющее меню формы, вы сможете закрыть эту форму, лишь выгрузив ее из другой формы.

В начало статьи

Совет 59. Быстрый поиск строки в Combo Box

Для быстрого поиска нужной строки в списке, в частности в элементе управления Combo Box, можно использовать функцию API SendMessage() (вариант для 16-разрядных приложений), обеспечивающую более эффективное выполнение программы, чем аналогичный код на VB. Для этого можно, например, прибегнуть к процедуре CBFindString:

Declare Function SendMessage Lib "User" _
  (ByVal hWnd As Integer, ByVal wMsg As Integer, _
  ByVal wParam As Integer, lParam As Any) As Long

Sub CBFindString(ctlEdit As Control, sSearch As String)
  Dim lPos As Long
  Const CB_FINDSTRING = &H40C
  lPos = SendMessage(ctlEdit.hWnd, CB_FINDSTRING, 0, ByVal sSearch)
  If lPos >=0 Then ctlEdit.ListIndex = lPos
End Sub

В начало статьи

Совет 60. Как выгрузить все формы

Это можно сделать с помощью такой процедуры:

Public Sub UnLoadAll ()
  Dim i As Integer
  i = Forms.Count   ' количество загруженных форм
  Do While i > 0
    Unload Forms(i - 1)
    ' если форма не выгрузилась - завершить выполнение функции
    If i = Forms.Count Then Exit Do i = i - 1
  Loop
End Sub

В начало статьи

Совет 61. Используйте для ожидания функцию API Sleep

При работе в Windows 95/NT для ожидания истечения некоторого отрезка времени (реализации задержки) вместо оператора DoEvent удобнее использовать функцию API (Win32) Sleep, которая должна быть описана следующим образом:

Public Declare Sub Sleep Lib "kernel32" _
  Alias "Sleep" (ByVal lMilliseconds As Long)

Обращение к ней может выглядеть так:

Sleep 15*1000&  'миллисекунды, в данном случае - 15 секунд

В начало статьи

Совет 62. Программное определение режимов "Run Time" и "Design Mode"

При разработке VB-приложения иногда бывает полезно на уровне программного кода определить, в каком режиме это приложение работает: "Design Mode" (работа в среде VB) или "Run Time" (выполнение автономного модуля). Для этого, в частности, можно анализировать имена каталогов, где хранятся VB-проект и законченное приложение, примерно в таком виде:

If InStr (App.Path, "VB") Then Stop

В начало статьи

Совет 63. Как загрузить форму VB 4.0 в среде VB 3.0

Форму, сделанную в VB4, нельзя напрямую использовать в среде VB3. Если это все же необходимо, следует вручную отредактировать файл с определением формы, который выглядит примерно так:

VERSION 4.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 5940
...
End
Attribute VB_Name = "Form1"
Attribute VB_Creatable = False
Attribute VB_Exposed = False
Option Explicit

Чтобы загрузить эту форму в VB3, нужно заменить VERSION 4.00 на VERSION 2.00, удалить все префиксы "VB.", которые имеются в конструкции Begin VB.Form Form1, а также удалить все объявления Attribute. Запомните этот файл и загрузите его в VB3.

В начало статьи

Совет 64. Проверка существования файла

Для этого проще всего использовать команду Dir$:

FileName$ = "C:\WINDOWS\WIN.INI"  'имя проверяемого файла
  If Dir$ (FileName$) <> "" Then
	' данный файл существует
  Else
	' данный файл не существует
  End If

В начало статьи

Совет 65. Создание многоуровневых каталогов

Иногда приходится анализировать наличие указанного каталога (к примеру, при установке вашей программы на жесткий диск) и создавать новый при его отсутствия. Для этого можно использовать, например, такую процедуру:

Sub CreateLongDir(sDir As String)
  Dim sBuild As String, sDirTmp As String, i As Integer
  '
  sDirTmp = sDir & "\"
  i = InStr (sDirTmp, ":")
  If i > 0 Then    ' задано имя диска
    sBuild = Left$(sDirTmp, i)      ' имя текущего каталога
    sDirTmp = Mid$(sDirTmp, i + 1)
  Else
    sBuild = ""    ' имя текущего каталога
  End If
  Do ' проверка-создание вложенных каталогов
    i = InStr (2, sDirTmp, "\")
    If i = 0 Then Exit Do
    sBuild = sBuild & Left$(sDir, i - 1)
    sDirTmp = Mid$(sDirTmp, i)
    If Dir$(sBuild, 16) = "" Then   'нет такого каталога
      MkDir sBuild    ' создание каталога
    End If
  Loop
End Sub

Sub Test () ' примеры обращения
  ' полное имя каталога с именем диска
  Call CreateLongDir("C:\Tests\TestDir\NewDir")
  ' полное имя каталога в текущем диске
  Call CreateLongDir("\Current\TestDir\NewDir")
  ' имя нового каталога относительно текущего каталога
  Call CreateLongDir("Current\TestDir\NewDir")
End Sub

Здесь крайне важно дать правильное описание имени каталога при обращении к CreateLongDir (в соответствии с правилами обращения к функциям VB: MkDir, ChDir, RmDir, Dir):

В начало статьи

Совет 66. Редактирование ячеек Grid

Содержимое ячеек элемента управления Grid, поставляемого с VB, нельзя редактировать напрямую. Но проблема легко решается с помощью следующей конструкции:

Private Sub Grid1_KeyPress(KeyAscii As Integer)
  Grid1.Text = Grid1.Text & Chr(KeyAscii)
End Sub

Эта операция выполняется для текущей выбранной ячейки таблицы.

В начало статьи

Совет 67. Как сделать Beep в VB4

Переход из VB3 в VB4 сопровождается некоторыми не очень приятные моментами, связанными с тем, что вроде бы очевидные программные конструкции работают в нем по-другому. Например, могут возникнуть проблемы с тривиальным гудком. Сколько раз "бибикнет" такая конструкция?

Beep: Beep

Ответ: в Basic/DOS, VB3 - два раза, а в VB4 - один.

Если на слух эта разница не очень убедительна, попробуйте другую конструкцию:

Beep:
Beep: A = 1

В этом случае при работе в VB4 вы вообще ничего не услышите. Почему-то зарезервированное слово Beep (так же, как и Cls), написанное первым в строке с разделителем ":", в VB4 воспринимается как метка.

В начало статьи

Совет 68. Простой способ очистки выбранных элементов списка

В VB3 отменить выделение всех элементов списка можно таким образом:

List1.Selected (-1) = False

К сожалению, в VB4 эта конструкция не работает.

В начало статьи

Совет 69. Перемещение элементов списка

Изменить расположение элементов списка можно, перетаскивая их мышью с помощью такой конструкции:

Sub List1_MouseDown (Button As Integer, Shift As Integer, _
  X As Single, Y As Single)
  ' Эта процедура запоминает номер текущего
  ' элемента списка и его содержимое
  ' при нажатии клавиши мыши
  Old_Index = List1.ListIndex
  TmpText = List1.Text
End Sub

Sub List1_MouseUp (Button As Integer, Shift As Integer, _
  X As Single, Y As Single)
  ' Когда вы отпустите клавишу мыши,
  ' указанный ранее элемент переместится
  ' в текущую позицию списка
  New_Index = List1.ListIndex
  If New_Index <> Old_Index Then
    List1.RemoveItem Old_Index   ' удалить старый
    List1.AddItem TmpText, New_Index ' вставить новый
  End If
End Sub

В общем модуле программы нужно зарезервировать глобальные переменные:

Dim TmpText As String
Dim Old_Index As Integer
Dim New_Index As Integer

В начало статьи

Совет 70. Как посмотреть методы и свойства объекта

Чтобы подробнее познакомиться с составом и описанием методов и свойств различных объектов (например, элементов управления OCX), имеющихся на вашем компьютере, в VB 4.0 можно воспользоваться командой Object Browser:

  1. Запустите VB. Нажмите F7, чтобы перейти в режим просмотра кода, а затем F2 - для запуска команды просмотра объектов.

  2. На появившемся окне Object Browser в раскрывающемся меню Libraries/Projects выберите нужный файл (библиотеку или приложение). В списке Classes/Modules выделите интересующий вас объект, при этом в списке Methods/Properties появится описание его свойств и методов.

  3. Чтобы познакомиться с каким-то свойством или методом, выделите его в списке - краткое описание будет выведено в нижней части окна. Для получения более подробной информации нужно щелкнуть кнопку помощи "?" на этом же окне.

В начало статьи

Совет 71. Определение типа элемента управления

Если для продолжения процедуры необходимо определить, с каким типом элемента управления она в данный момент работает, можно применить следующую конструкцию, использующую функцию TypeOf:

Function myFunc (ctl As Control)
  ' Эта процедура работает для VB3 и VB4
  If TypeOf ctl Is TextBox Then
     ' Текстовое поле
  Else If TypeOf ctl Is CommandButton Then
     ' Кнопка
  End If
End Function

В VB4 это можно сделать с помощью новой функции TypeName, при этом код будет выглядеть примерно так:

Function myFunc (ctl As Control)
  Dim sCtlType As String
  sCtlType = TypeName(ctl)
  Select Case sCtlType
    Case "TextBox"
            ...
    Case "CommandButton"
            ...
  End Select
End Function

Узнать точное имя типа или класса конкретного элемента управления можно, посмотрев его в окне Properties в среде VB.

В начало статьи

Совет 72. Как преобразовать приложения для Access 2.0 в приложения для Access 7.0

Приложение А в руководстве "Building Applications with Microsoft Access for Windows 95" содержит основные инструкции по преобразованию 16-разрядных приложений для Access 2.0 в 32-разрядные приложения для Access 7.0. Ниже приводится пошаговая инструкция преобразования для незащищенных баз данных, основанных на последней бета-версии Access 7.0. Она немного дополняет информацию, содержащуюся в руководстве:

1. Если ваше приложение для Access 2.0 вызывает дополнительные 16-разрядные DLL-библиотеки или использует 16-разрядные элементы управления OLE, убедитесь, что у вас есть соответствующие 32-разрядные версии.

2. Преобразуйте библиотеки или дополнительные средства, необходимые для Access 7.0. Вам, вероятно, потребуется обновить библиотеки или дополнительные средства третьих фирм на 32-разрядные версии.

3. Если вы еще не разделили свое приложение для Access 2.0 на отдельное приложение и файлы данных data.mdb, то сделайте это сейчас. Вы можете связать таблицы Access 2.0 с приложениями как для Access 2.0, так и Access 7.0, а не наоборот. Access 7.0 имеет ограничение на 32 индекса плюс связи для одной таблицы, выйдя за которое, то вы потеряете индексы и/или связи.

4. Удалите ненужные объявления функций Windows API, а также вызовы функций. Например, библиотека CTL3DV2.DLL не нужна в приложениях, выполняемых только в Windows 95.

5. Откройте модуль кода, затем из меню Run выберите команду Compile Loaded Modules, чтобы скомпилировать весь код, содержащийся в приложении. Если вы не сделаете этого, переход к Access 7.0 может не удасться.

6. Временно отключите макрокоманду AutoExec для своего приложения, предварительно переименовав ее.

7. Сожмите MDB-файл, используемый в вашем приложении.

8. Попытайтесь преобразовать свой MDB-файл. Если преобразование не получится, создайте новую базу данных в Access 7.0 и вручную импортируйте туда объекты из MDB-файлов Access 2.0, используя в меню File команду Get External Data, а затем Import.

9. Используйте Add-in Manager для подключения необходимых дополнительных средств к своему приложению.

10. Если ваше приложение обращается к библиотечному коду, выберите команду References из меню Tools для того, чтобы открыть диалоговое окно References. Затем установите тип .MDA в поле Files of Types, выберите необходимый библиотечный MDA-файл и создайте ссылку на него.

11. Если ваше приложение содержит элементы управления OLE, проверьте, что необходимые ссылки установлены для 32-разрядных, а не для 16-разрядных версий.

12. Откройте преобразованный модуль и выберите команду Compile All Modules из меню Run. Исправьте ошибки в программе таким образом, чтобы все модули компилировались без ошибок. Приложение А руководства описывает наиболее часто требуемые изменения, которые следует внести в код.

13. После того как вы скомпилировали все свои модули, выберите команду Save All Modules из меню File.

14. В окне Module Options установите параметр Break On All Errors, если ваш опыт обработки ошибок на уровне строки с помощью операторов On Error Resume Next и If Err Then недостаточен.

15. Теперь попробуйте запустить свое приложение. Вероятно, появятся некоторые ошибки выполнения, но они обычно легко исправляются в Debug Window (Окне Отладки).

В начало статьи

Совет 73. Используйте параметр Optional при вызове процедур

В VB4 как процедуры-функции, так и подпрограммы могут использовать ключевое слово Optional (Необязательный) в объявлении процедур для указания необязательного параметра. Например:

Function mfbCheckDBStatus(Optional vroTest As Variant) As Boolean

В этом случае функция может вызываться без указания параметра:

MfbCheckDBStatus

Если необходимо проверить наличие необязательного параметра, используйте функцию IsMissing для его тестирования.

В начало статьи

Совет 74. Как узнать разрешающую способность монитора

Для этого можно воспользоваться функцией WinAPI:

Declare Function GetsystemMetrics Lib "User" (ByVal _
  iIndex As Integer) As Integer

Sub Form_Load()
  Dim iXres As Integer, iYres As Integer
  ' разрешающая способность экрана монитора:
  iXres = GetsystemMetrics(0)  ' по оси X
  iYres = GetsystemMetrics(1)  ' по оси Y
End Sub

В начало статьи

Совет 75. Анализ имени файла

Довольно часто бывает необходимо по полному имени файла определить имя его каталога или/и само имя файла внутри каталога. Для этого можно воспользоваться следующими процедурами (они будут работать в любой версии MS Basic, здесь используется формат представления текста модуля для QB):

DECLARE FUNCTION InstrReverse% (Text$, Key$)
DEFINT I-N

SUB FileNameTest (PathFile$, Path$, File$)
  '
  ' Вход:  PathFile$ - полное имя файла
  ' Выход: Path$ - имя каталога
  ' File$ - имя файла
  ' Например:
  ' Вход:  PathFile$ = "d:\Test1\Test2\File.txt"
  ' Выход: Path$ = "d:\Test1\Test2\"
  ' File$ = "File.txt"
  ''''''''''''''''''''''''''''''''''''''''''''''
  in = InstrReverse(PathFile$, "\")
  IF in <= 0 THEN
    Path$ = "": File$ = PathFile$
  ELSE
    Path$ = LEFT$(PathFile$, in): File$ = MID$(PathFile$, in + 1)
  END IF
END SUB

FUNCTION InstrReverse (Text$, Key$)
  '
  '  поиск ПОСЛЕДНЕГО (а не первого, как в INSTR)
  '  контекста в строке
  '  Text$ - исходная строка
  '  Key$  - разделитель в строке
  ' Например:
  ' Вход:  Text$ = "d:\Test1\Test2\Test3"
  ' Key$ = "\"
  ' Выход: InstrReverse = 15
  ''''''''''''''''''''''''''''''''''''''
  in = INSTR(Text$, Key$)
  IF in > 0 THEN
    DO WHILE in < LEN(Text$)
      in1 = INSTR(in + 1, Text$, Key$)
      IF in1 <= 0 THEN EXIT DO ELSE in = in1
    LOOP
  END IF
  InstrReverse = in
END FUNCTION

В начало статьи