Предупреждение, вопрос и оповещение в 1С 8.3: какой метод вызвать и где
Содержание
Чтобы вывести предупреждение в 1С 8.3, на клиенте вызовите ПоказатьПредупреждение(, "Текст предупреждения") — это немодальное окно с кнопкой «ОК». Старый оператор Предупреждение("Текст") тоже существует, но в конфигурациях без модальных окон он вызывает ошибку. В платформе с поддержкой Асинх/Ждать удобнее всего Ждать ПредупреждениеАсинх("Текст").
Типичная ситуация: разработчик дорабатывает форму документа, пишет одну строку Предупреждение("Не заполнен склад!"), а пользователь получает вместо подсказки окно Использование модальных окон в данном режиме запрещено. Ниже — какой метод выводит предупреждение в каждом случае, как он работает в управляемых формах и чем окно отличается от сообщения и всплывающего оповещения.
Синтаксис оператора Предупреждение и его немодальной версии
Все три варианта показывают одно и то же окно: текст, кнопка «ОК», необязательный заголовок и таймаут. Разница — в том, как код ждёт закрытия окна.
| Метод | Модальность | Что делает код после вызова |
|---|---|---|
Предупреждение(Текст, Таймаут, Заголовок) | модальный | останавливается, пока окно не закрыто |
ПоказатьПредупреждение(Оповещение, Текст, Таймаут, Заголовок) | немодальный | идёт дальше сразу; реакция на закрытие — в процедуре-обработчике |
ПредупреждениеАсинх(Текст, Таймаут, Заголовок) | немодальный | в асинхронной процедуре ждёт закрытия через Ждать |
Параметры:
- 📝 Текст — строка, которую увидит пользователь. Перенос строки — через
Символы.ПС. - ⏱ Таймаут — число секунд, через которое окно закроется само.
0или пропуск — ждать нажатия «ОК». - 🏷 Заголовок — текст в шапке окна. Если не задан, платформа подставит заголовок по умолчанию.
- 🔔 Оповещение (только у
ПоказатьПредупреждение) — объектОписаниеОповещения, который вызовется после закрытия. Если реакция не нужна, параметр пропускают, оставляя запятую.
Простейший вызов:
&НаКлиенте
Процедура ПроверитьСклад(Команда)
Если Не ЗначениеЗаполнено(Объект.Склад) Тогда
ПоказатьПредупреждение(, "Не заполнен склад." + Символы.ПС + "Укажите склад и повторите.", 10, "Проверка документа");
Возврат;
КонецЕсли;
// дальнейшая обработка
КонецПроцедуры
Окно закроется само через 10 секунд, если пользователь не нажмёт «ОК».
Почему Предупреждение() выдаёт ошибку о модальных окнах
Начиная с 8.3.3 в свойствах конфигурации появился параметр Режим использования модальности. Новые и типовые конфигурации создаются со значением «Не использовать». В таком режиме любой модальный вызов — Предупреждение(), Вопрос(), ОткрытьФормуМодально() — падает с ошибкой.
У параметра три значения:
| Значение | Что происходит с Предупреждение() |
|---|---|
| Использовать | работает как раньше, код ждёт закрытия окна |
| Использовать с предупреждениями | работает, при проверке модуля платформа выдаёт предупреждения |
| Не использовать | ошибка Использование модальных окон в данном режиме запрещено |
Где посмотреть: в Конфигураторе откройте свойства корня дерева конфигурации (Конфигурация → Открыть конфигурацию, правый щелчок по корню → Свойства), группа «Совместимость».
Не переключайте типовую конфигурацию на «Использовать» ради одной строки кода. Это меняет поведение всей базы, ломает работу в веб-клиенте на планшетах и создаёт расхождения при обновлении. Правильный путь — переписать вызов на немодальный.
Как переписать модальный вызов
Код, который стоял после Предупреждение(), переносится в процедуру-обработчик:
&НаКлиенте
Процедура Провести(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеПредупреждения", ЭтотОбъект);
ПоказатьПредупреждение(Оповещение, "Документ будет проведён задним числом.");
КонецПроцедуры
&НаКлиенте
Процедура ПослеПредупреждения(ДополнительныеПараметры) Экспорт
ЗаписатьНаСервере();
КонецПроцедуры
Три правила, без которых обработчик не сработает:
- Процедура-обработчик объявлена с ключевым словом
Экспорт. - Она находится в том же модуле, что указан вторым параметром
ОписаниеОповещения(ЭтотОбъект— модуль формы). - У обработчика предупреждения один параметр —
ДополнительныеПараметры. Через него передают данные из основной процедуры: третий параметр конструктораОписаниеОповещения, например структура.
Как передать данные в обработчик
Локальные переменные основной процедуры в обработчике не видны: к моменту закрытия окна она уже завершилась. Нужные значения кладут в структуру и передают третьим параметром ОписаниеОповещения:
&НаКлиенте
Процедура ПроверитьСумму(Команда)
Параметры = Новый Структура("Сумма, Лимит", Объект.СуммаДокумента, 100000);
Если Параметры.Сумма > Параметры.Лимит Тогда
Оповещение = Новый ОписаниеОповещения("ПослеПредупрежденияОЛимите", ЭтотОбъект, Параметры);
ПоказатьПредупреждение(Оповещение, СтрШаблон("Сумма %1 превышает лимит %2.",
Формат(Параметры.Сумма, "ЧГ=0"), Формат(Параметры.Лимит, "ЧГ=0")));
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПослеПредупрежденияОЛимите(ДополнительныеПараметры) Экспорт
Объект.Комментарий = "Превышен лимит на " + Формат(ДополнительныеПараметры.Сумма - ДополнительныеПараметры.Лимит, "ЧГ=0");
КонецПроцедуры
При сумме 125 000 и лимите 100 000 пользователь увидит «Сумма 125000 превышает лимит 100000.», а в комментарий попадёт «Превышен лимит на 25000».
💡 Чтобы найти все модальные вызовы разом, в Конфигураторе есть команда Конфигурация → Рефакторинг → Анализ модальных вызовов конфигурации. Она выводит список мест, которые нужно переписать.
Асинхронный вариант: ПредупреждениеАсинх и Ждать
В платформе 8.3.18 и новее появились ключевые слова Асинх и Ждать. С ними немодальный код читается как старый модальный — без отдельной процедуры-обработчика.
&НаКлиенте
Асинх Процедура Провести(Команда)
Ждать ПредупреждениеАсинх("Документ будет проведён задним числом.", , "Внимание");
ЗаписатьНаСервере();
КонецПроцедуры
Пока пользователь читает предупреждение, интерфейс не блокируется, а строка ЗаписатьНаСервере() выполнится только после закрытия окна.
Ограничения:
- ✅ Работает, только если режим совместимости конфигурации разрешает возможности 8.3.18 и выше.
- ✅
Ждатьдопустимо только внутри процедуры или функции, помеченнойАсинх. - ❌ Обработчики событий формы, где платформа ждёт решения сразу (
ПередЗакрытием,ПередЗаписьюс параметромОтказ), так не переписать: платформа не будет ждать окончания асинхронной процедуры,Отказнадо выставить до первогоЖдать.
Предупреждение, вопрос или сообщение: что выбрать
Предупреждение — не единственный способ сказать пользователю «стоп». Выбор зависит от того, нужен ли ответ и должен ли пользователь прерваться.
| Задача | Метод | Где работает |
|---|---|---|
| Сообщить и дождаться, пока прочтут | ПоказатьПредупреждение, ПредупреждениеАсинх | клиент |
| Получить ответ «Да/Нет» | ПоказатьВопрос, ВопросАсинх | клиент |
| Указать на ошибку в конкретном поле | СообщениеПользователю | клиент и сервер |
| Отметить, что операция завершилась | ПоказатьОповещениеПользователя | клиент |
| Показать ход длительной обработки | Состояние | клиент |
Вопрос с выбором ответа
Если после предупреждения пользователь должен решить, продолжать ли, нужен вопрос, а не предупреждение:
&НаКлиенте
Процедура Очистить(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВопросаОчистки", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Очистить табличную часть?", РежимДиалогаВопрос.ДаНет, 0, КодВозвратаДиалога.Нет);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВопросаОчистки(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
Объект.Товары.Очистить();
КонецЕсли;
КонецПроцедуры
У обработчика вопроса два параметра: Результат и ДополнительныеПараметры. Если задан таймаут и пользователь не ответил, Результат равен КодВозвратаДиалога.Таймаут.
Асинхронный вариант того же вопроса короче: Ответ = Ждать ВопросАсинх("Очистить табличную часть?", РежимДиалогаВопрос.ДаНет); — дальше обычное Если Ответ = КодВозвратаДиалога.Да Тогда. Процедура при этом объявляется с Асинх.
Для вопроса с таймаутом есть ещё параметр «Кнопка таймаута»: на ней идёт обратный отсчёт секунд. Так пользователь видит, какой вариант выберется сам, если он отойдёт от компьютера.
Сообщение вместо окна
Окно прерывает работу. Если ошибок несколько — например, пять незаполненных строк в табличной части, — пять окон подряд раздражают. Здесь нужно сообщение:
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не указана цена в строке 3";
Сообщение.Поле = "Объект.Товары[2].Цена";
Сообщение.Сообщить();
Сообщение появится в панели сообщений формы, а щелчок по нему поставит курсор в нужную ячейку. Индекс строки в поле начинается с нуля, поэтому третья строка — [2].
Старый метод Сообщить("Текст") по-прежнему работает, но не умеет привязываться к полю.
Предупреждения в управляемых формах и при вызове сервера
В управляемом приложении код формы делится на клиентский (&НаКлиенте) и серверный (&НаСервере). Окна показывает только клиент. На сервере нет интерфейса, поэтому ПоказатьПредупреждение и Вопрос в серверных процедурах недоступны — модуль не пройдёт синтаксический контроль.
Как быть, если проверка выполняется на сервере:
- Вернуть результат на клиент. Серверная функция возвращает текст ошибки или
Истина/Ложь, клиентская процедура показывает окно. - Использовать
СообщениеПользователю. Оно работает на сервере: сообщения копятся и доходят до клиента после возврата из серверного вызова. - В модуле объекта (
ОбработкаПроверкиЗаполнения,ПередЗаписью) — только сообщения иОтказ = Истина. Окно оттуда не показать в принципе.
Пример первого способа:
&НаКлиенте
Процедура Проверить(Команда)
ТекстОшибки = ПроверитьОстаткиНаСервере();
Если ЗначениеЗаполнено(ТекстОшибки) Тогда
ПоказатьПредупреждение(, ТекстОшибки);
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция ПроверитьОстаткиНаСервере()
// запрос к остаткам
Если НедостаточноТовара() Тогда
Возврат "Недостаточно товара на складе.";
КонецЕсли;
Возврат "";
КонецФункции
В типовых конфигурациях на БСП
В конфигурациях на Библиотеке стандартных подсистем (БП 3.0, ЗУП 3.1, УТ 11 и другие) для сообщений принято вызывать ОбщегоНазначения.СообщитьПользователю(Текст, , Поле, ПутьКДанным, Отказ) на сервере и ОбщегоНазначенияКлиент.СообщитьПользователю на клиенте. Эти процедуры оборачивают СообщениеПользователю и сразу выставляют Отказ.
Предупреждение при закрытии формы
Классическая задача: «Данные изменены. Закрыть без сохранения?» В ПередЗакрытием модальный вопрос запрещён, поэтому закрытие сначала отменяют, а потом закрывают форму из обработчика:
&НаКлиенте
Перем ЗакрытиеПодтверждено;
&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
Если ЗакрытиеПодтверждено = Истина Тогда
Возврат;
КонецЕсли;
Если ЗавершениеРаботы Тогда
Отказ = Истина;
ТекстПредупреждения = "Есть несохранённые изменения.";
Возврат;
КонецЕсли;
Отказ = Истина;
ПоказатьВопрос(Новый ОписаниеОповещения("ПослеВопросаЗакрытия", ЭтотОбъект),
"Закрыть без сохранения?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВопросаЗакрытия(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
ЗакрытиеПодтверждено = Истина;
Закрыть();
КонецЕсли;
КонецПроцедуры
При завершении работы всей программы (ЗавершениеРаботы = Истина) окна показывать нельзя. Вместо этого заполняют параметр ТекстПредупреждения — платформа сама выведет его в общем списке перед выходом.
Всплывающие оповещения и строка состояния
Не каждое предупреждение должно блокировать работу. Когда операция прошла и пользователю достаточно узнать об этом, подходит всплывающее оповещение в углу экрана:
ПоказатьОповещениеПользователя("Выгрузка завершена", , "Файл сохранён в каталог обмена", БиблиотекаКартинок.Информация32);
Параметры по порядку: текст, действие при нажатии (навигационная ссылка или ОписаниеОповещения), пояснение, картинка. В новых версиях платформы добавлены статус оповещения и ключ уникальности: оповещение со статусом «Важное» остаётся в центре оповещений, пока пользователь его не просмотрит, а одинаковый ключ не даёт плодить дубли.
Для длительных операций — Состояние:
Для Сч = 1 По 100 Цикл
Состояние("Обработка документов", Сч, "Обработано " + Формат(Сч, "ЧГ=0") + " из 100");
// обработка
КонецЦикла;
Второй параметр — процент выполнения от 0 до 100. Числа склеиваются со строкой через Формат, иначе при больших значениях в тексте появится пробел-разделитель тысяч.
Как изменить внешний вид окна предупреждения
Стандартное окно настраивается слабо: текст, заголовок, таймаут. Шрифт, цвет, свои кнопки и картинку через ПоказатьПредупреждение не задать. Варианты:
- 🔘 Свои кнопки — через
ПоказатьВопрос: вместоРежимДиалогаВопроспередайтеСписокЗначений. Значения вернутся вРезультат, представления станут надписями кнопок. - 🖼 Своя форма — создайте общую форму с декорациями, нужным шрифтом и цветом и откройте её через
ОткрытьФормус параметром оповещения о закрытии. Режим открытия окна формы — «Блокировать окно владельца»: так она ведёт себя как предупреждение, но остаётся немодальной для платформы. - ✍️ Многострочный текст —
Символы.ПСмежду строками иСтрШаблондля подстановки значений:СтрШаблон("Не хватает %1 шт. товара %2", Нехватка, Товар).
Пример вопроса со своими кнопками:
Кнопки = Новый СписокЗначений;
Кнопки.Добавить("Провести", "Провести и закрыть");
Кнопки.Добавить("Записать", "Только записать");
Кнопки.Добавить("Отмена", "Отмена");
ПоказатьВопрос(Новый ОписаниеОповещения("ПослеВыбораДействия", ЭтотОбъект),
"Документ не проведён. Что сделать?", Кнопки, , "Провести");
Ошибки при выводе предупреждений
Ещё одна частая ошибка — вызвать предупреждение внутри цикла. Если строк 200, пользователь получит 200 окон подряд. Соберите ошибки в массив и выведите одним сообщением или через СообщениеПользователю построчно.