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

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

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

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


Совет 246. Как сделать временную задержку

В версиях MS Basic для DOS имелся полезный оператор временной задержки

SLEEP Seconds

который приостанавливал выполнение программы на указанное число секунд. Такого оператора в VB не существует, но его нетрудно реализовать самостоятельно в виде следующей простой подпрограммы:

Sub SleepVB (Seconds)
  ' ожидание Seconds секунд
  Dim Start
  Start = Timer   ' текущее время в секундах
  Do While Timer < Start + Seconds
    ' обеспечивает параллельное выполнение других процессов
    DoEvents
  Loop
End Sub

Здесь нужно обратить внимание на использование функции DoEvents, которая позволяет производить другие процессы параллельно с выполнением текущего цикла. (DoEvents передает управление операционной системе, а сама функция возвращает число открытых форм в данном VB-приложении.)

Старый оператор SLEEP осуществлял задержку выполнения на заданное число секунд или до нажатия любой клавиши клавиатуры. (В Basic/DOS с ним были свои проблемы, так как код нажатой клавиши оставался в буфере клавиатуры и автоматически использовался в последующих операциях ввода. Для предотвращения подобной ситуации после оператора SLEEP нужно было очищать буфер.)

При желании такой режим можно реализовать и в нашей функции SleepVB. Один из ее вариантов, а также необходимость применения функции DoEvents мы покажем в следующем примере.

20.01.2008 напришло письмо из Самары от Юрия Гришина:

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

Совет 247. Как сделать заставку при старте VB-программы или VBA-документа

Как сделать, чтобы при запуске VB-программы появлялась некая заставка-форма, которая бы автоматически исчезала после завершения загрузки программы? Для этого лучше всего использовать вариант старта приложения с подпрограммы Main (устанавливается командой Project Properties|General|Strartup Object), которая может выглядеть примерно следующим образом:

Sub Main()
  '
  frmSplash.Show  ' открываем форму-заставку
  '
  Call AllStartOperations  ' этой процедурой
  ' мы обозначаем все необходимые подготовительные
  ' операции для запуска приложения, например,
  ' открываем базы данных, очищаем какие-то файлы и пр.
  '
  Load frmMain  ' загружаем основную форму приложения,
  ' с которой начнется его реальное выполнение
  Unload frmSplash  ' выгружаем форму-заставку
  'показываем основную форму и начинаем работать с ней
  frmMain.Show
End Sub

Обратите внимание, что форма-заставка появляется здесь только на очень короткое время (в данном случае, на время загрузки frmMain) и тут же исчезает. Как сделать временную задержку, мы покажем ниже.

А как создать заставку, которая бы появлялась при открытии офисного документа, например для Word 97/2000?

Откроем Word, создадим новый документ под названием Splash.doc и перейдем в среду VBA (Alt+F11). Затем создадим форму (Insert|UserForm), для которой установим свойства Name=frmSplash и Caption="Заставка нашей программы". На заставке можно показать разнообразную информацию о нашем приложении (название, логотип, имя автора и пр.). Мы же сейчас ограничимся только размещением небольшой GIF- картинки с помощью установки свойства Picture (рис. 247-1).

Рис. 247-1

Теперь в окне Project откроем узел Microsoft Word Objects и дважды щелкнем появившийся в нем стандартный элемент ThisDocument (в Excel это соответственно Microsoft Excel Objects|ThisWorkbook). В открывшемся окне кода в списке предопределенных событийных процедур (в правом верхнем углу) найдем подпрограмму Open. Именно ей передается управление в момент открытия документа и сюда можно поместить любой код для выполнения необходимых стартовых операций. Поместим в нее следующий программный код (рис. 247-2):

Private Sub Document_Open()
  ' эта процедура срабатывает при открытии документа
  '
  frmSplash.Show    ' открываем форму-заставку
  Unload frmSplash  ' выгружаем форму-заставку
  Msgbox "Hello!"   ' фиксируем начало реальной работы
End Sub

Рис. 247-2 Для проверки работы этой процедуры нужно сначала сохранить и закрыть документ, а затем заново открыть его.

Совет: Чтобы избежать постоянного закрытия-открытия документа для проведения отладки, измените в описателе Sub Document_Open ключевое слово Private на Public. В этом случае данная процедура автоматически попадет в список макрокоманд документа, и вы сможете обращаться к ней любой момент без перезагрузки документа.

Однако, запустив процедуру Document_Open, мы обнаружим, что характер ее работы отличается от того, как она функционирует в обычном Visual Basic: здесь форма- заставка не исчезает до тех пор, пока пользователь сам не закроет ее.

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

Различие в поведении формы-заставки в VB и VBA заключается в том, что благодаря используемому по умолчанию параметру метода Show в первом случае форма открывается в немодальном режиме, а во втором — в модальном.

Более того, в Office 97 был реализован только модальный режим работы форм. Поэтому для автоматического удаления формы-заставки нужно придумывать какой- нибудь программный трюк внутри ее модуля, который бы, например, отслеживал некую временную задержку и сам закрывал форму. В Office 2000 появилась возможность использования немодальных форм, но для этого нужно указать параметр Show в явном виде:

frmSplash.Show 0   ' открывает форму в немодальном режиме

Как нам сделать, чтобы форма-заставка не мелькала на экране, а оставалась некоторое минимальное время, например 5 секунд? Для этого можно воспользоваться подпрограммой временной задержки SleepVB, приведенной в Совете 246, и тогда код открытия документа будет выглядеть следующим образом:

frmSplash.Show 0   ' открываем форму-заставку
' Call AllStartOperations  необходимые дополнительные операции
Call SleepVB (5)  ' задержка на 5 секунд
Unload frmSplash  ' выгружаем форму-заставку
Msgbox "Hello!"   ' фиксируем начало реальной работы

В этом варианте видны два недостатка. Во-первых, если дополнительные операции будут занимать 20 секунд, то к ним все равно добавятся дополнительные 10 секунд, что будет уже лишним. Во-вторых, пользователь никак не сможет повлиять на сокращение этой временной задержки, например, самостоятельно закрыв форму-заставку.

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

frmSplash.Show 0   ' открываем форму-заставку
'
PauseTime = 10 ' задержка в 10 секунд
Start = Timer
' Call AllStartOperations ' необходимые дополнительные операции
Do While Timer < Start + PauseTime
  ' обеспечивает параллельное выполнение других процессов
  DoEvents 
Loop
'
Unload frmSplash  ' выгружаем форму-заставку
Msgbox "Hello!"   ' фиксируем начало реальной работы

Обратите внимание, что здесь мы вставили обращение к процедуре AllStartOperations после получения начального времени таймера. Таким образом, время появления заставки на экране будет оптимизировано с учетом длительности выполнения дополнительных операций, то есть мы устранили первый недочет начального варианта.

Для понимания смысла функции DoEvents (см. Совет 246) временно заблокируйте обращение к ней, поставив знак комментария. Запустите, процедуру на выполнение и вы увидите, что форма-заставка появляется без рисунка!

Объясняется это тем, что управление возвращается в вызывающую программу до полного завершения прорисовки формы, но этот процесс не может завершиться из-за выполнения цикла Do... Loop. Функция же DoEvents обеспечивает возможность выполнения других параллельных процессов, в том числе и завершения прорисовки заставки.

Как нам теперь дать возможность пользователю сократить время задержки, например, закрыв форму-заставку щелчком мыши? Тут могут быть два варианта в реализации цикла ожидания.

  1. Анализ числа открытых форм:

    Do
      OpenForms = DoEvents   ' число открытых форм в приложении
    Loop While Timer < Start + PauseTime And OpenForms > 0
    
    Но этот вариант не очень хорош, так как к этому моменту могут быть открыты еще какие-либо другие формы приложения (в процедуре StartAllOperations). Поэтому лучше воспользоваться другим способом.

  2. Анализ состояния формы-заставки:

    Do
      DoEvents
    Loop While Timer < Start + PauseTime And frmSplash.Visible
    

Вот, собственно, и все по поводу создания стартовых заставок. Обратите внимание, что реализация этих программных конструкций в VB и VBA практически одинакова.

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

Совет 248. Как изучать программирование в среде VBA

Парадокс заключается в том, что освоение программирования в среде MS Office представляет определенные трудности как для начинающих программистов, так и для опытных разработчиков. Первым нужно изучить незнакомый мир программирования, а вторым — овладеть функциональными возможностями офисных пакетов. И как выясняется на практике, для этого нужно читать не только книги по "программированию в Office", но и литературу (уже давно опубликованную) по собственно самому программированию и работе с офисными пакетами.

Не менее половины вопросов по "MS Office как средство разработки", поступающих в российский центр технической поддержки, связано с темой "как научиться программировать": как перекодировать данные, как работать со строковыми переменными, как использовать базы данных и пр.

Ответ на подобные вопросы довольно прост: изучайте материалы по программированию в среде обычного VB. Что касается собственно самого программирования, MS Office и VB пересекаются на 70-80 процентов. И не нужно удивляться, что в книгах по "Office/VBA" вопросы технологии написания кода зачастую освещаются довольно скупо. Просто эти темы рассматриваются более подробно в других книгах.

Информацию об информационных ресурсах по VB можно найти по адресу www.basic.visual2000.ru/develop/

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

Совет 249. Как обрабатывать строки на VBA и каковы преимущества для этого в MS Office 2000

Данный вопрос как раз относится к категории "как изучать программирование". Строки в VBA обрабатываются точно так же, как и в обычном VB. "Обработка строк" рассматривается во многих книгах, но, как правило, это делается довольно бегло, в рамках отдельной главы.

Современные авторы не уделяют особого внимания этому вопросу, считая, что данная тема была досконально описана еще во времена Basic/DOS. Поэтому советуем заглянуть в архив, находящийся по адресу www.basic.visual2000.ru/develop/basicdos. Из современных публикаций рекомендуем прочитать соответствующую главу в книге "Использование Visual Basic 6.0", а также статью "Особенности работы со строковыми переменными в Visual Basic", опубликованную в журнале "КомпьютерПресс" NN 10/99 и 01/2000.

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

Совет 250. Как перекодировать почтовые сообщения

Проблемы с двойной перекодировкой почтовых сообщений встречаются не часто, но они все же существуют.

В библиотеке Office Extensions имеется довольно большая группа решений этой проблемы. Дело в том, что включить макрос в Outlook 97/98 было не очень просто (там использовался механизм VBScript, а не VBA). Поэтому большинство решений основывалось на варианте, когда исходный текст копируется в среду Word, где и производится перекодирование. К счастью, Outlook 2000 содержит уже полнофункциональный VBA.

Если вы хотите написать собственный макрос перекодирования текста, то советуем посмотреть решение RusTextC в библиотеке Office Extensions, которое представлено в виде "открытого кода". А то, как интегрировать макрос в среду Word, можно прочитать в статье "Разработка приложений в среде Office 97".

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