Построение диалогов

См. также Экранные формы (Forms).

Диалоги

Диалоги являются абсолютно необходимым средством для повышения управляемости и гибкости макропрограмм.
Они представлены двумя командами: MsgBox (диалог с кнопками) и InputBox (для ввода значений).
Для начинающих программистов этого вполне достаточно.

Синтаксис команд:
MsgBox(prompt[, buttons] [, title] [, helpfile, context])
InputBox(prompt[, title] [, default] [, xpos] [, ypos] [, helpfile, context])

Можно заметить, что отдельные элементы весьма схожи и повторяются:
prompt — единственный обязательный элемент (он задает текст сообщения, выводимого внутри окна диалога);
title — заголовок окна, обобщающий вопрос диалога;
helpfile... — ваша подсказка, обсуждение (и создание) которой выходит за рамки изучаемого материала.

InputBox

Диалог предназначен для ввода единичного символьного (строкового) значения. Как видно из основного синтаксиса:

InputBox(prompt[, title] [, default] [, xpos] [, ypos]),

обязательным является только поясняющий текст (prompt).

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

Также можно указать в твипсах (1/20 часть пикселя, а не пункта, как принято в полиграфии) координаты окна (xpos, ypos). Если соответствующие координаты опущены, то диалог центрируется относи­тельно горизонтали и опускается примерно на треть экрана по вертикали.

Использовать команду следует в виде функции, так как введенное значение обязано быть присвоено переменной.

     Dim x As Single
     x = InputBox("Введите значение x для подстановки")

Результат будет выглядеть так:

Если внимательно посмотреть на текст программы, то закономерным будет вопрос: переменной x (числового типа Single) будет передаваться строковое значение, что является ошибочным?

Однако в VBA это будет обработано правильно, если пользователь введет любое число: преобразование пройдет само собой. Если же он введет буквы или нажмёт кнопку отмены (Cancel), то переменной будет присваиваться строковое значение, что породит ошибку:

Избежать подобной ситуации можно двумя способами, предоставляющими различные возможности.

Решение 1

     x = Val(InputBox("Введите значение x для подстановки"))

Здесь сразу происходит преобразование типа возвращаемого значения функцией Val(). В результате при вводе букв они будут:

  1. преобразованы в 0,
  2. если в начале строки введены числа ("125xyz"), то строка преобразуется в число (125).

При нажатии на кнопку Cancel будет возвращена пустая строка (""), преобразуемая в 0.

Если такой ввод допустим в принципе, то нет возможности прекратить выполнение программы без дополнительного запроса пользователю.

Решение 2

     Dim x As Single, xVal As String
     xVal = InputBox("Введите значение x для подстановки")
     If xVal = "" Then Exit Sub
     x = Val(xVal)

В данном случае создаётся дополнительная переменная (xVal), в которой хранится результат ввода. Что мы имеем в результате?

  1. В строке, выделенной красным, проведен анализ результата ввода и выход из программы при пустой строке. Такой подход вполне приемлем и для случая, когда пользователь забыл задать значение. Здесь ему может быть задан вопрос о необходимости прерывания программы.
  2. Значение, сохраненное в xVal, можно использовать и в дальнейшем. В том числе для детальной разборки или анализа, в том числе на предмет правильности ввода.
  3. Появляется возможность ввести несколько значений, например, через запятую, которые потом можно анализировать и использовать в соответствии с замыслом программиста.
  4. Занята дополнительная память, что является платой за функциональность.

InputBox в Excel VBA

К сожалению, объектная модель Word и Excel не совпадают, в связи с чем приходится говорить, что в Excel можно воспользоваться ещё одним способом:

     Dim x As Variant
     x = Application.InputBox(Prompt:="Введите значение x для подстановки", Type:=1)

В этой ситуации пользователь сможет ввести данные только указанного типа (числового). Если можно вводить несколько типов, то следует задать тип как сумму соответствующих типов: 1+2 (либо сразу 3) — можно вводить цифры и символы.

MsgBox

Вспомним синтаксис команды:

MsgBox(prompt[, buttons] [, title] [, helpfile, context])

Атрибут buttons представляет собой сумму трех (реже — более) целых чисел, означающих: набор кнопок, картинку, кнопку по умолчанию. Последняя довольно важна, так как многие пользователи невнимательно относятся к надписям в диалоге, и гораздо разумнее активизировать для него ту кнопку, нажатие на которую требуется чаще. Вместо чисел можно использовать системные переменные памяти. Подробная информация приведена в таблице.
Переменная WordЗначениеОписание
vbOKOnly0Вывести только кнопку OK
vbOKCancel1Вывести кнопки OK и Cancel
vbAbortRetryIgnore2Вывести кнопки Abort, Retry и Ignore
vbYesNoCancel3Вывести кнопки Yes, No и Cancel
vbYesNo4Вывести кнопки Yes и No
vbRetryCancel5Вывести кнопки Retry и Cancel
vbCritical16Вывести картинку Critical Message
vbQuestion32Вывести картинку Warning Query
vbExclamation48Вывести картинку Warning Message
vbInformation64Вывести картинку Information Message
vbDefaultButton10По умолчанию активна 1‑я кнопка
vbDefaultButton2256По умолчанию активна 2‑я кнопка
vbDefaultButton3512По умолчанию активна 3‑я кнопка
vbDefaultButton4768По умолчанию активна 4‑я кнопка
vbApplicationModal0Диалог модален для Word: для продолжения работы в приложении и самого макроса нужно нажать на одну из кнопок
vbSystemModal4096Диалог модален для Windows: все приложения прекращают работу до тех пор, пока пользователь не нажмет на одну из кнопок
vbMsgBoxHelpButton16384Добавляет в диалог кнопку Help (Справка)
VbMsgBoxSetForeground65536Переводит окно диалога на передний план (практическое применение неизвестно)
vbMsgBoxRight524288Надписи выравниваются вправо
vbMsgBoxRtlReading1048576Для языков, читаемых справа налево

Как видно, если не задавать для кнопок ничего, то получится диалог с кнопкой ОК и без пиктограммы. Кстати, он является одним из наиболее часто используемых вариантов для вывода информации о результатах работы программы как в процессе её отладки, так и при обычном режиме работы.

Пример: MsgBox "Значение х достигло " & x

Диалог будет выглядеть так:

Следует отметить, что кнопка ОК обладает интересным свойством: её можно нажать как мышкой, так и клавишами Enter, Space и Esc.

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

Ниже приведен список значений, возвращаемых функцией MsgBox() в зависимости от нажатой в диалоге кнопки.
ЗначениеКонстанта WordНадпись на кнопке
1vbOKOK
2vbCancelCancel
3vbAbortAbort
4vbRetryRetry
5vbIgnoreIgnore
6vbYesYes
7vbNoNo

Пример:

Dim RunMacro As Byte 'Задать целочисленную переменную минимального размера
RunMacro = MsgBox("Заменить дефисы в документе?", 4 + 48, "Замена дефисов")
	'Запустить диалог с кнопками Yes+No и картинкой "Внимание!"
	'Целое число, соответствующее нажатой кнопке, запомнить в RunMacro
If RunMacro = 6 Then 'Нажато Yes (вместо 6 можно записать vbYes)
	Selection.HomeKey Unit:=wdStory
	'Перейти на начало документа и продолжить программу после End If
Else 'Нажато не Yes (No для нашего примера)
	Exit Sub 'Выйти из программы, не делая ничего
End If
... Основная программа

Диалог будет выглядеть так:

Можно сказать, что в нем допущена интерфейсная ошибка, так как нажатие клавиши Esc не позволит закрыть диалог. Для комфортности лучше использовать одновременно кнопки Yes, No и Cancel. Для доработки понадобится только заменить в тексте программы 4 на 3: ведь нажатие на Cancel обработается также, как и No (выход из программы).

Обратите внимание! Вместо 4+48, можно было бы записать сразу результат сложения (52). Программа выполнилась бы чуточку быстрее, но редактирование человеком стало бы сложнее. Также можно заменить эту форму сложением программных констант: vbYesNo+vbExclamation, что легче понять при чтении.

Идеальным решением было бы добавление кнопки Cancel, как показано ниже.

   RunMacro = MsgBox("Заменить дефисы в документе?", 3 + 48, "Замена дефисов")

См. также Экранные формы (Forms).


Copyright © 1993–2020 Мацкявичюс Д.А. Все права защищены.
Никакая часть сайта не может быть воспроизведена никаким способом без письменного разрешения правообладателя и явной ссылки на данный ресурс.