Сообщения, вопросы и окна ввода во встроенном языке 1С 8.3
Содержание
Чтобы вывести диалоговое окно в 1С 8.3, на клиенте вызывают ПоказатьПредупреждение() для простого окна с кнопкой «ОК», ПоказатьВопрос() для выбора «Да/Нет» и ПоказатьВводСтроки(), ПоказатьВводЧисла(), ПоказатьВводДаты() для ввода значения. Старые модальные Предупреждение(), Вопрос(), ВводСтроки() работают только там, где в свойствах конфигурации разрешена модальность. Текст без окна выводят через Сообщить() или объект СообщениеПользователю.
Типичная ситуация: программист дописывает обработку, нажимает «Выполнить» в веб-клиенте, и вместо окна с вопросом получает исключение. Код писался под модальный Вопрос(), а конфигурация собрана в режиме без модальности. Ниже каждый способ показан с рабочим кодом и с оговоркой, где он не сработает.
Какой способ показа окна выбрать
Методы делятся на три поколения. Модальные пришли из 8.2 и обычных форм. Немодальные с ОписаниеОповещения появились в 8.3 вместе с режимом без модальности. Асинхронные …Асинх добавлены в платформе 8.3.18 и позволяют писать тот же диалог без отдельной процедуры-обработчика.
| Задача | Модальный метод | Немодальный метод | Асинхронный (8.3.18+) |
|---|---|---|---|
| Окно с кнопкой «ОК» | Предупреждение() | ПоказатьПредупреждение() | ПредупреждениеАсинх() |
| Вопрос с кнопками | Вопрос() | ПоказатьВопрос() | ВопросАсинх() |
| Ввод строки | ВводСтроки() | ПоказатьВводСтроки() | ВводСтрокиАсинх() |
| Ввод числа | ВводЧисла() | ПоказатьВводЧисла() | ВводЧислаАсинх() |
| Ввод даты | ВводДаты() | ПоказатьВводДаты() | ВводДатыАсинх() |
| Выбор значения по типу | ВводЗначения() | ПоказатьВводЗначения() | ВводЗначенияАсинх() |
| Выбор из списка | Список.ВыбратьЭлемент() | Список.ПоказатьВыборЭлемента() | — |
Правило простое:
- ✅ новая разработка или доработка типовой конфигурации — немодальные методы или
Асинх; - ✅ старая конфигурация на обычных формах, где модальность включена, — можно оставить модальные;
- ❌ серверный код — никакие окна не вызываются, только сообщения.
Все методы этой группы, кроме Сообщить(), доступны только на клиенте. В модуле формы процедуру помечают директивой &НаКлиенте, в общем модуле включают флажок «Клиент (управляемое приложение)».
Сообщить и СообщениеПользователю: текст без отдельного окна
Сообщить() — самый короткий способ показать пользователю строку. Текст попадает в панель сообщений внизу формы, окно не открывается, код выполняется дальше без паузы.
Сообщить("Обработано документов: " + Формат(Счетчик, "ЧГ=0"));
Метод работает и на клиенте, и на сервере. Сообщения, отправленные с сервера, пользователь увидит, когда управление вернётся на клиент. Число склеивают со строкой через Формат(), иначе 1500 превратится в «1 500» с неразрывным пробелом.
Для управляемых форм фирма-разработчик рекомендует объект СообщениеПользователю. Его главное отличие — привязка к полю формы: по щелчку на сообщении курсор встаёт в нужный реквизит, а само поле подсвечивается.
&НаСервере
Процедура ПроверитьЗаполнениеНаСервере()
Если Не ЗначениеЗаполнено(Объект.Контрагент) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не указан контрагент";
Сообщение.Поле = "Контрагент";
Сообщение.ПутьКДанным = "Объект";
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры
В типовых конфигурациях на БСП то же самое делают одной строкой: ОбщегоНазначения.СообщитьПользователю(Текст, , "Контрагент", "Объект") на сервере или ОбщегоНазначенияКлиент.СообщитьПользователю(...) на клиенте.
Ещё два способа «сказать» что-то без диалога:
- 📌
ПоказатьОповещениеПользователя("Выгрузка завершена")— всплывающее уведомление в углу экрана, исчезает само; - ⏳
Состояние("Загрузка строк...", 40)— текст и полоса прогресса в строке состояния во время долгой операции.
Перед новой серией сообщений панель очищают процедурой ОчиститьСообщения().
Предупреждение: окно, которое нужно закрыть
Когда пользователь обязан увидеть текст, а не пропустить его в панели внизу, нужен диалог с кнопкой «ОК». Немодальный вариант:
&НаКлиенте
Процедура Выгрузить(Команда)
ПоказатьПредупреждение(, "Файл сохранён в каталог выгрузки.", 10, "Выгрузка");
КонецПроцедуры
Параметры по порядку:
ОписаниеОповещенияОЗавершении— что выполнить после закрытия окна. Если продолжать ничего не нужно, параметр пропускают, оставляя запятую.ТекстПредупреждения— строка или форматированная строка.Таймаут— через сколько секунд окно закроется само. 0 — не закрывать.Заголовок— текст в шапке окна.
Если после закрытия нужно что-то сделать, создают описание оповещения и выносят продолжение в отдельную экспортную процедуру:
&НаКлиенте
Процедура Закрыть(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеПредупреждения", ЭтотОбъект);
ПоказатьПредупреждение(Оповещение, "Документ будет закрыт без записи.");
КонецПроцедуры
&НаКлиенте
Процедура ПослеПредупреждения(ДополнительныеПараметры) Экспорт
Закрыть();
КонецПроцедуры
Модальная Предупреждение("Текст", 10, "Заголовок") останавливает выполнение до нажатия «ОК». Код короче, но в конфигурации без модальности вызов закончится исключением.
Вопрос пользователю: Да, Нет и свои кнопки
Диалог с вопросом нужен, когда от ответа зависит дальнейшая работа: удалить строки, перезаполнить табличную часть, провести документ задним числом.
Немодальный ПоказатьВопрос
&НаКлиенте
Процедура Перезаполнить(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Табличная часть будет очищена. Продолжить?",
РежимДиалогаВопрос.ДаНет, 0, КодВозвратаДиалога.Нет, "Перезаполнение");
КонецПроцедуры
&НаКлиенте
Процедура ПослеОтветаНаВопрос(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
ПерезаполнитьНаСервере();
КонецЕсли;
КонецПроцедуры
Параметры после текста: набор кнопок, таймаут в секундах, кнопка по умолчанию, заголовок и кнопка, которая сработает по таймауту. Готовые наборы кнопок в РежимДиалогаВопрос: ДаНет, ДаНетОтмена, ОК, ОКОтмена, ПовторитьОтмена, ПрерватьПовторитьПропустить.
Код после ПоказатьВопрос() выполняется сразу, не дожидаясь ответа. Всё, что зависит от ответа пользователя, пишите только в процедуре-обработчике. Это главная ошибка при переходе с модального Вопрос().
Свои надписи на кнопках
Вместо перечисления передают СписокЗначений. Значение элемента вернётся в обработчик, представление станет текстом кнопки:
Кнопки = Новый СписокЗначений;
Кнопки.Добавить("Все", "Перезаполнить всё");
Кнопки.Добавить("Цены", "Только цены");
Кнопки.Добавить(КодВозвратаДиалога.Отмена, "Отмена");
ПоказатьВопрос(Оповещение, "Что обновить в документе?", Кнопки, , "Цены");
В обработчике Результат будет равен «Все», «Цены» или КодВозвратаДиалога.Отмена. Если окно закрыли по таймауту, придёт КодВозвратаДиалога.Таймаут.
Асинхронный ВопросАсинх
С платформы 8.3.18 тот же диалог пишут линейно, без отдельной процедуры. Процедуру помечают словом Асинх, результат получают оператором Ждать:
&НаКлиенте
Асинх Процедура Удалить(Команда)
Ответ = Ждать ВопросАсинх("Удалить выделенные строки?", РежимДиалогаВопрос.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
УдалитьСтрокиНаСервере();
КонецЕсли;
КонецПроцедуры
Окно при этом немодальное, поэтому код работает в веб-клиенте и в конфигурациях без модальности. Нужен режим совместимости конфигурации не ниже 8.3.18.
Окна ввода строки и числа
Когда от пользователя нужно одно значение, отдельную форму рисовать не обязательно. Платформа покажет стандартное окно с полем и кнопками «ОК» и «Отмена».
ВводСтроки и ПоказатьВводСтроки
&НаКлиенте
Процедура ЗадатьКомментарий(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВводаКомментария", ЭтотОбъект);
ПоказатьВводСтроки(Оповещение, Объект.Комментарий, "Комментарий к документу", 200, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаКомментария(Строка, ДополнительныеПараметры) Экспорт
Если Строка <> Неопределено Тогда
Объект.Комментарий = Строка;
Модифицированность = Истина;
КонецЕсли;
КонецПроцедуры
Параметры: начальное значение, подсказка (заголовок окна), максимальная длина (0 — без ограничения) и многострочность. При нажатии «Отмена» в обработчик приходит Неопределено, это надо проверять всегда.
Модальная форма возвращает Булево, а введённое значение кладёт в переменную, переданную первым параметром:
Код = "";
Если ВводСтроки(Код, "Введите код подтверждения", 6) Тогда
Сообщить("Введён код: " + Код);
КонецЕсли;
ВводЧисла и ПоказатьВводЧисла
Отличие от строки — два параметра формата: длина и точность. Для суммы до 9 999 999,99 указывают длину 10 и точность 2.
&НаКлиенте
Процедура ЗадатьСкидку(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВводаСкидки", ЭтотОбъект);
ПоказатьВводЧисла(Оповещение, 0, "Скидка, %", 5, 2);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаСкидки(Число, ДополнительныеПараметры) Экспорт
Если Число = Неопределено Тогда
Возврат;
КонецЕсли;
Если Число < 0 Или Число > 100 Тогда
ПоказатьПредупреждение(, "Скидка должна быть от 0 до 100%");
Возврат;
КонецЕсли;
ПрименитьСкидкуНаСервере(Число);
КонецПроцедуры
Окно ввода числа не проверяет диапазон, только формат. Границы допустимых значений проверяют в обработчике, как в примере.
Ввод даты, значения и выбор из списка
Дата и время
ПоказатьВводДаты(Оповещение, ТекущаяДата(), "Дата отгрузки", ЧастьДаты.Дата) откроет поле с календарём. Третий параметр управляет составом: ЧастьДаты.Дата, ЧастьДаты.Время или ЧастьДаты.ДатаВремя. Как и в других окнах, отмена возвращает Неопределено.
Значение произвольного типа
ПоказатьВводЗначения() открывает поле нужного типа, в том числе ссылочного. Для справочника пользователь получит привычную кнопку выбора:
Тип = Новый ОписаниеТипов("СправочникСсылка.Контрагенты");
Оповещение = Новый ОписаниеОповещения("ПослеВыбораКонтрагента", ЭтотОбъект);
ПоказатьВводЗначения(Оповещение, Неопределено, "Выберите контрагента", Тип);
Удобно в обработках, где нужно спросить один параметр перед запуском, а заводить реквизит формы ради этого не хочется.
Выбор из списка и отметка нескольких пунктов
У СписокЗначений есть свои диалоги:
- 📋
ПоказатьВыборЭлемента(Оповещение, "Заголовок")— выбрать один пункт. В обработчик придётЭлементСпискаЗначенийилиНеопределено, значение берут из свойства.Значение; - ☑️
ПоказатьОтметкуЭлементов(Оповещение, "Заголовок")— поставить флажки у нескольких пунктов. После закрытия проверяют свойствоПометкау элементов списка.
&НаКлиенте
Процедура ВыбратьФормат(Команда)
Список = Новый СписокЗначений;
Список.Добавить("xlsx", "Excel");
Список.Добавить("pdf", "PDF");
Список.Добавить("mxl", "Табличный документ 1С");
Список.ПоказатьВыборЭлемента(Новый ОписаниеОповещения("ПослеВыбораФормата", ЭтотОбъект), "Формат файла");
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФормата(Элемент, ДополнительныеПараметры) Экспорт
Если Элемент <> Неопределено Тогда
СохранитьВФормате(Элемент.Значение);
КонецЕсли;
КонецПроцедуры
Когда параметров больше двух-трёх, цепочка стандартных окон утомляет пользователя. Тогда честнее нарисовать свою форму и открыть её через ОткрытьФорму() с описанием оповещения о закрытии и режимом РежимОткрытияОкна.БлокироватьОкноВладельца. Окно-владелец заблокируется, но код будет немодальным.
Модальность, веб-клиент и сервер: где окно не откроется
За поведение отвечает свойство конфигурации «Режим использования модальности». Его меняют в конфигураторе: правой кнопкой по корню дерева конфигурации → «Свойства». Вариантов три:
| Значение | Модальные методы | Что увидит пользователь |
|---|---|---|
| Использовать | Работают | Обычное окно, код ждёт ответа |
| Использовать с предупреждениями | Работают | Окно открывается, а проверка модулей отмечает модальные вызовы |
| Не использовать | Вызывают исключение | Ошибку вместо окна |
Новые конфигурации и актуальные типовые релизы собираются в режиме «Не использовать». Поэтому код с Вопрос() или ВводСтроки(), перенесённый из старой обработки, в них падает. Решение одно — переписать вызовы на Показать… или …Асинх.
В веб-клиенте модальные окна ещё и конфликтуют с браузером: им мешают блокировщики всплывающих окон, а в мобильном клиенте модальности нет совсем. Немодальные методы работают одинаково в тонком, веб- и мобильном клиенте.
Особенности, о которых часто забывают:
- 🖥️ на сервере окна недоступны вообще. Если решение принимается в серверной процедуре, сначала задайте вопрос на клиенте, потом передайте ответ параметром;
- ⚙️ в фоновом задании
Сообщить()не показывает текст сразу. Сообщения накапливаются, клиент забирает их черезПолучитьСообщенияПользователю()у фонового задания; - 🧩 во внешней обработке те же правила: режим модальности берётся из конфигурации, в которой обработку открыли.
Вопрос перед записью документа
Самый частый случай, который ломается при переходе на немодальные окна, — подтверждение в обработчике ПередЗаписью формы. Обработчик не может ждать ответа, поэтому запись сначала отменяют, а после ответа «Да» запускают заново. Флаг в переменной модуля не даёт задать вопрос второй раз:
&НаКлиенте
Перем ЗаписьПодтверждена;
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
Если ЗаписьПодтверждена = Истина Тогда
ЗаписьПодтверждена = Ложь;
Возврат;
КонецЕсли;
Отказ = Истина;
Оповещение = Новый ОписаниеОповещения("ПослеВопросаОЗаписи", ЭтотОбъект, ПараметрыЗаписи);
ПоказатьВопрос(Оповещение, "Документ уже попал в отчётность. Записать изменения?",
РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВопросаОЗаписи(Результат, ПараметрыЗаписи) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
ЗаписьПодтверждена = Истина;
Записать(ПараметрыЗаписи);
КонецЕсли;
КонецПроцедуры
Параметры записи передаются третьим параметром описания оповещения. Так повторная запись пройдёт с тем же режимом: просто запись, проведение или отмена проведения.
Если окно не появляется, а код не падает, проверьте по шагам:
Частые вопросы
Можно ли вывести вопрос из модуля объекта или менеджера?
Как сделать перенос строки в тексте окна?
Символы.ПС или многострочный литерал с символом | в начале продолжения строки. Для жирного шрифта и цвета передайте вместо строки форматированную строку Новый ФорматированнаяСтрока(...).Как передать данные в процедуру-обработчик ответа?
ОписаниеОповещения. Туда кладут структуру, например со ссылкой на строку таблицы, и в обработчике читают её из ДополнительныеПараметры.Почему обработчик ответа не вызывается и ошибки нет?
ОписаниеОповещения написано с опечаткой или вторым параметром передан не тот модуль. Проблема проявляется только после закрытия окна, поэтому её легко пропустить при беглой проверке.Окно с таймаутом закрылось само. Что придёт в обработчик?
КодВозвратаДиалога.Таймаут, если не задана кнопка таймаута. Для окон ввода — Неопределено, как при отмене.