Предупреждение, вопрос и оповещение в 1С 8.3: какой метод вызвать и где

· 9 мин

Содержание

Чтобы вывести предупреждение в 1С 8.3, на клиенте вызовите ПоказатьПредупреждение(, "Текст предупреждения") — это немодальное окно с кнопкой «ОК». Старый оператор Предупреждение("Текст") тоже существует, но в конфигурациях без модальных окон он вызывает ошибку. В платформе с поддержкой Асинх/Ждать удобнее всего Ждать ПредупреждениеАсинх("Текст").

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

Синтаксис оператора Предупреждение и его немодальной версии

Все три варианта показывают одно и то же окно: текст, кнопка «ОК», необязательный заголовок и таймаут. Разница — в том, как код ждёт закрытия окна.

МетодМодальностьЧто делает код после вызова
Предупреждение(Текст, Таймаут, Заголовок)модальныйостанавливается, пока окно не закрыто
ПоказатьПредупреждение(Оповещение, Текст, Таймаут, Заголовок)немодальныйидёт дальше сразу; реакция на закрытие — в процедуре-обработчике
ПредупреждениеАсинх(Текст, Таймаут, Заголовок)немодальныйв асинхронной процедуре ждёт закрытия через Ждать

Параметры:

  • 📝 Текст — строка, которую увидит пользователь. Перенос строки — через Символы.ПС.
  • ⏱ Таймаут — число секунд, через которое окно закроется само. 0 или пропуск — ждать нажатия «ОК».
  • 🏷 Заголовок — текст в шапке окна. Если не задан, платформа подставит заголовок по умолчанию.
  • 🔔 Оповещение (только у ПоказатьПредупреждение) — объект ОписаниеОповещения, который вызовется после закрытия. Если реакция не нужна, параметр пропускают, оставляя запятую.

Простейший вызов:

&НаКлиенте
Процедура ПроверитьСклад(Команда)
	Если Не ЗначениеЗаполнено(Объект.Склад) Тогда
		ПоказатьПредупреждение(, "Не заполнен склад." + Символы.ПС + "Укажите склад и повторите.", 10, "Проверка документа");
		Возврат;
	КонецЕсли;
	// дальнейшая обработка
КонецПроцедуры

Окно закроется само через 10 секунд, если пользователь не нажмёт «ОК».

Почему Предупреждение() выдаёт ошибку о модальных окнах

Начиная с 8.3.3 в свойствах конфигурации появился параметр Режим использования модальности. Новые и типовые конфигурации создаются со значением «Не использовать». В таком режиме любой модальный вызов — Предупреждение(), Вопрос(), ОткрытьФормуМодально() — падает с ошибкой.

У параметра три значения:

ЗначениеЧто происходит с Предупреждение()
Использоватьработает как раньше, код ждёт закрытия окна
Использовать с предупреждениямиработает, при проверке модуля платформа выдаёт предупреждения
Не использоватьошибка Использование модальных окон в данном режиме запрещено

Где посмотреть: в Конфигураторе откройте свойства корня дерева конфигурации (Конфигурация → Открыть конфигурацию, правый щелчок по корню → Свойства), группа «Совместимость».

Не переключайте типовую конфигурацию на «Использовать» ради одной строки кода. Это меняет поведение всей базы, ломает работу в веб-клиенте на планшетах и создаёт расхождения при обновлении. Правильный путь — переписать вызов на немодальный.

Как переписать модальный вызов

Код, который стоял после Предупреждение(), переносится в процедуру-обработчик:

&НаКлиенте
Процедура Провести(Команда)
	Оповещение = Новый ОписаниеОповещения("ПослеПредупреждения", ЭтотОбъект);
	ПоказатьПредупреждение(Оповещение, "Документ будет проведён задним числом.");
КонецПроцедуры

&НаКлиенте
Процедура ПослеПредупреждения(ДополнительныеПараметры) Экспорт
	ЗаписатьНаСервере();
КонецПроцедуры

Три правила, без которых обработчик не сработает:

  1. Процедура-обработчик объявлена с ключевым словом Экспорт.
  2. Она находится в том же модуле, что указан вторым параметром ОписаниеОповещения (ЭтотОбъект — модуль формы).
  3. У обработчика предупреждения один параметр — ДополнительныеПараметры. Через него передают данные из основной процедуры: третий параметр конструктора ОписаниеОповещения, например структура.

Как передать данные в обработчик

Локальные переменные основной процедуры в обработчике не видны: к моменту закрытия окна она уже завершилась. Нужные значения кладут в структуру и передают третьим параметром ОписаниеОповещения:

&НаКлиенте
Процедура ПроверитьСумму(Команда)
	Параметры = Новый Структура("Сумма, Лимит", Объект.СуммаДокумента, 100000);
	Если Параметры.Сумма > Параметры.Лимит Тогда
		Оповещение = Новый ОписаниеОповещения("ПослеПредупрежденияОЛимите", ЭтотОбъект, Параметры);
		ПоказатьПредупреждение(Оповещение, СтрШаблон("Сумма %1 превышает лимит %2.",
			Формат(Параметры.Сумма, "ЧГ=0"), Формат(Параметры.Лимит, "ЧГ=0")));
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПослеПредупрежденияОЛимите(ДополнительныеПараметры) Экспорт
	Объект.Комментарий = "Превышен лимит на " + Формат(ДополнительныеПараметры.Сумма - ДополнительныеПараметры.Лимит, "ЧГ=0");
КонецПроцедуры

При сумме 125 000 и лимите 100 000 пользователь увидит «Сумма 125000 превышает лимит 100000.», а в комментарий попадёт «Превышен лимит на 25000».

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

Асинхронный вариант: ПредупреждениеАсинх и Ждать

В платформе 8.3.18 и новее появились ключевые слова Асинх и Ждать. С ними немодальный код читается как старый модальный — без отдельной процедуры-обработчика.

&НаКлиенте
Асинх Процедура Провести(Команда)
	Ждать ПредупреждениеАсинх("Документ будет проведён задним числом.", , "Внимание");
	ЗаписатьНаСервере();
КонецПроцедуры

Пока пользователь читает предупреждение, интерфейс не блокируется, а строка ЗаписатьНаСервере() выполнится только после закрытия окна.

Ограничения:

  • ✅ Работает, только если режим совместимости конфигурации разрешает возможности 8.3.18 и выше.
  • ✅ Ждать допустимо только внутри процедуры или функции, помеченной Асинх.
  • ❌ Обработчики событий формы, где платформа ждёт решения сразу (ПередЗакрытием, ПередЗаписью с параметром Отказ), так не переписать: платформа не будет ждать окончания асинхронной процедуры, Отказ надо выставить до первого Ждать.

Предупреждение, вопрос или сообщение: что выбрать

Предупреждение — не единственный способ сказать пользователю «стоп». Выбор зависит от того, нужен ли ответ и должен ли пользователь прерваться.

ЗадачаМетодГде работает
Сообщить и дождаться, пока прочтутПоказатьПредупреждение, ПредупреждениеАсинхклиент
Получить ответ «Да/Нет»ПоказатьВопрос, ВопросАсинхклиент
Указать на ошибку в конкретном полеСообщениеПользователюклиент и сервер
Отметить, что операция завершиласьПоказатьОповещениеПользователяклиент
Показать ход длительной обработкиСостояниеклиент

Вопрос с выбором ответа

Если после предупреждения пользователь должен решить, продолжать ли, нужен вопрос, а не предупреждение:

&НаКлиенте
Процедура Очистить(Команда)
	Оповещение = Новый ОписаниеОповещения("ПослеВопросаОчистки", ЭтотОбъект);
	ПоказатьВопрос(Оповещение, "Очистить табличную часть?", РежимДиалогаВопрос.ДаНет, 0, КодВозвратаДиалога.Нет);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВопросаОчистки(Результат, ДополнительныеПараметры) Экспорт
	Если Результат = КодВозвратаДиалога.Да Тогда
		Объект.Товары.Очистить();
	КонецЕсли;
КонецПроцедуры

У обработчика вопроса два параметра: Результат и ДополнительныеПараметры. Если задан таймаут и пользователь не ответил, Результат равен КодВозвратаДиалога.Таймаут.

Асинхронный вариант того же вопроса короче: Ответ = Ждать ВопросАсинх("Очистить табличную часть?", РежимДиалогаВопрос.ДаНет); — дальше обычное Если Ответ = КодВозвратаДиалога.Да Тогда. Процедура при этом объявляется с Асинх.

Для вопроса с таймаутом есть ещё параметр «Кнопка таймаута»: на ней идёт обратный отсчёт секунд. Так пользователь видит, какой вариант выберется сам, если он отойдёт от компьютера.

Сообщение вместо окна

Окно прерывает работу. Если ошибок несколько — например, пять незаполненных строк в табличной части, — пять окон подряд раздражают. Здесь нужно сообщение:

Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не указана цена в строке 3";
Сообщение.Поле = "Объект.Товары[2].Цена";
Сообщение.Сообщить();

Сообщение появится в панели сообщений формы, а щелчок по нему поставит курсор в нужную ячейку. Индекс строки в поле начинается с нуля, поэтому третья строка — [2].

Старый метод Сообщить("Текст") по-прежнему работает, но не умеет привязываться к полю.

Предупреждения в управляемых формах и при вызове сервера

В управляемом приложении код формы делится на клиентский (&НаКлиенте) и серверный (&НаСервере). Окна показывает только клиент. На сервере нет интерфейса, поэтому ПоказатьПредупреждение и Вопрос в серверных процедурах недоступны — модуль не пройдёт синтаксический контроль.

Как быть, если проверка выполняется на сервере:

  1. Вернуть результат на клиент. Серверная функция возвращает текст ошибки или Истина/Ложь, клиентская процедура показывает окно.
  2. Использовать СообщениеПользователю. Оно работает на сервере: сообщения копятся и доходят до клиента после возврата из серверного вызова.
  3. В модуле объекта (ОбработкаПроверкиЗаполнения, ПередЗаписью) — только сообщения и Отказ = Истина. Окно оттуда не показать в принципе.

Пример первого способа:

&НаКлиенте
Процедура Проверить(Команда)
	ТекстОшибки = ПроверитьОстаткиНаСервере();
	Если ЗначениеЗаполнено(ТекстОшибки) Тогда
		ПоказатьПредупреждение(, ТекстОшибки);
	КонецЕсли;
КонецПроцедуры

&НаСервере
Функция ПроверитьОстаткиНаСервере()
	// запрос к остаткам
	Если НедостаточноТовара() Тогда
		Возврат "Недостаточно товара на складе.";
	КонецЕсли;
	Возврат "";
КонецФункции

В типовых конфигурациях на БСП

В конфигурациях на Библиотеке стандартных подсистем (БП 3.0, ЗУП 3.1, УТ 11 и другие) для сообщений принято вызывать ОбщегоНазначения.СообщитьПользователю(Текст, , Поле, ПутьКДанным, Отказ) на сервере и ОбщегоНазначенияКлиент.СообщитьПользователю на клиенте. Эти процедуры оборачивают СообщениеПользователю и сразу выставляют Отказ.

Предупреждение при закрытии формы

Классическая задача: «Данные изменены. Закрыть без сохранения?» В ПередЗакрытием модальный вопрос запрещён, поэтому закрытие сначала отменяют, а потом закрывают форму из обработчика:

&НаКлиенте
Перем ЗакрытиеПодтверждено;

&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
	Если ЗакрытиеПодтверждено = Истина Тогда
		Возврат;
	КонецЕсли;
	Если ЗавершениеРаботы Тогда
		Отказ = Истина;
		ТекстПредупреждения = "Есть несохранённые изменения.";
		Возврат;
	КонецЕсли;
	Отказ = Истина;
	ПоказатьВопрос(Новый ОписаниеОповещения("ПослеВопросаЗакрытия", ЭтотОбъект),
		"Закрыть без сохранения?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВопросаЗакрытия(Результат, ДополнительныеПараметры) Экспорт
	Если Результат = КодВозвратаДиалога.Да Тогда
		ЗакрытиеПодтверждено = Истина;
		Закрыть();
	КонецЕсли;
КонецПроцедуры

При завершении работы всей программы (ЗавершениеРаботы = Истина) окна показывать нельзя. Вместо этого заполняют параметр ТекстПредупреждения — платформа сама выведет его в общем списке перед выходом.

Всплывающие оповещения и строка состояния

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

ПоказатьОповещениеПользователя("Выгрузка завершена", , "Файл сохранён в каталог обмена", БиблиотекаКартинок.Информация32);

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

Для длительных операций — Состояние:

Для Сч = 1 По 100 Цикл
	Состояние("Обработка документов", Сч, "Обработано " + Формат(Сч, "ЧГ=0") + " из 100");
	// обработка
КонецЦикла;

Второй параметр — процент выполнения от 0 до 100. Числа склеиваются со строкой через Формат, иначе при больших значениях в тексте появится пробел-разделитель тысяч.

Как изменить внешний вид окна предупреждения

Стандартное окно настраивается слабо: текст, заголовок, таймаут. Шрифт, цвет, свои кнопки и картинку через ПоказатьПредупреждение не задать. Варианты:

  • 🔘 Свои кнопки — через ПоказатьВопрос: вместо РежимДиалогаВопрос передайте СписокЗначений. Значения вернутся в Результат, представления станут надписями кнопок.
  • 🖼 Своя форма — создайте общую форму с декорациями, нужным шрифтом и цветом и откройте её через ОткрытьФорму с параметром оповещения о закрытии. Режим открытия окна формы — «Блокировать окно владельца»: так она ведёт себя как предупреждение, но остаётся немодальной для платформы.
  • ✍️ Многострочный текст — Символы.ПС между строками и СтрШаблон для подстановки значений: СтрШаблон("Не хватает %1 шт. товара %2", Нехватка, Товар).

Пример вопроса со своими кнопками:

Кнопки = Новый СписокЗначений;
Кнопки.Добавить("Провести", "Провести и закрыть");
Кнопки.Добавить("Записать", "Только записать");
Кнопки.Добавить("Отмена", "Отмена");
ПоказатьВопрос(Новый ОписаниеОповещения("ПослеВыбораДействия", ЭтотОбъект),
	"Документ не проведён. Что сделать?", Кнопки, , "Провести");

Ошибки при выводе предупреждений

Диагностика: выберите симптом

Ещё одна частая ошибка — вызвать предупреждение внутри цикла. Если строк 200, пользователь получит 200 окон подряд. Соберите ошибки в массив и выведите одним сообщением или через СообщениеПользователю построчно.

Частые вопросы

Можно ли вывести предупреждение из фонового задания?
Нет. У фонового задания нет клиента. Используйте СообщениеПользователю: основной сеанс забирает такие сообщения методом ПолучитьСообщенияПользователю() объекта фонового задания и показывает их пользователю.
Как вывести предупреждение из внешней обработки?
Так же, как из формы: в клиентской процедуре формы обработки вызовите ПоказатьПредупреждение. Режим модальности берётся из конфигурации базы, в которой открыта обработка.
Чем Сообщить() отличается от СообщениеПользователю?
Сообщить() выводит только текст. СообщениеПользователю умеет привязаться к полю формы и объекту данных, поэтому щелчок по сообщению ведёт к ошибке.
Работает ли ПоказатьПредупреждение в веб-клиенте?
Да. Немодальные методы работают в тонком, веб- и мобильном клиенте одинаково, поэтому их и рекомендуют вместо модальных.
Как очистить панель сообщений перед новой проверкой?
Вызовите ОчиститьСообщения() на клиенте до начала проверки — старые сообщения исчезнут, останутся только новые.