Разработка и Конфигурация · 12 мин
1С: как передать сообщение на клиент
Как в 1С передать сообщение на клиент: объект СообщениеПользователю, вывод из серверных процедур, привязка к полям формы, типичные ошибки и примеры кода.
Задача «передать сообщение на клиент» в 1С возникает постоянно: серверная проверка обнаружила ошибку, фоновая процедура завершила расчёт, обмен данными вернул предупреждение. Проблема в том, что старый метод Сообщить() в клиент-серверном режиме работает не так, как ожидают: вызванный в серверной процедуре, он может просто «потеряться» для пользователя или вывести текст без привязки к форме.
Правильный инструмент — объект СообщениеПользователю. Он создаётся на сервере, помещается в буфер сообщений и автоматически передаётся на клиент при возврате управления из серверного вызова. Дополнительно сообщение можно привязать к конкретному полю формы, чтобы платформа подсветила ошибочный реквизит.
Ниже разобраны рабочие механизмы: вывод сообщения из серверной процедуры, привязка к данным объекта и к полям формы, получение накопленных сообщений, а также ограничения, о которых нужно знать, чтобы не потерять важную информацию.
Как работает передача сообщений между сервером и клиентом
В клиент-серверной архитектуре 1С код выполняется в двух местах: на клиенте (форма, интерфейс) и на сервере (запросы к базе, проверки, проведение). Когда серверная процедура вызывает Сообщить() или создаёт СообщениеПользователю, текст не выводится мгновенно — он складывается в буфер сообщений сеанса.
При завершении серверного вызова платформа забирает накопленные сообщения и передаёт их на клиент, где они появляются в панели сообщений. Если серверный вызов завершился исключением, сообщения всё равно доходят — это удобно для диагностики. Но если серверный вызов вообще не происходит (код выполняется только на клиенте), то и механизм передачи не задействуется: сообщение выводится локально.
Важное следствие: из фонового задания сообщения пользователю напрямую не дойдут. Фоновое задание выполняется в отдельном сеансе, и его буфер сообщений не связан с сеансом пользователя. Для этого сценария используют другие механизмы — об этом ниже.
Вывод сообщения через СообщениеПользователю
Базовый шаблон выглядит так. Создаём объект, заполняем текст и вызываем метод Сообщить():
&НаСервере
Процедура ПроверитьДанныеНаСервере()
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = НСтр("ru = 'Не заполнен контрагент в документе'");
Сообщение.Сообщить();
КонецПроцедуры
После возврата из серверной процедуры пользователь увидит текст в панели сообщений формы. Если серверную процедуру вызвали из клиентской, сообщение появится автоматически — дополнительных действий не требуется.
Тот же объект работает и на клиенте: код идентичен, поэтому его удобно выносить в общие процедуры проверки, которые могут вызываться с обеих сторон.
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не заполнен контрагент";
Сообщение.Поле = "Контрагент";
Сообщение.КлючДанных = Объект.Ссылка;
Сообщение.УстановитьДанные(Объект);
Сообщение.Сообщить();Привязка сообщения к полю формы и данным объекта
Свойства Поле и ПутьКДанным
Свойство Поле задаёт имя реквизита, с которым связано сообщение. Когда пользователь щёлкает по сообщению в панели, платформа активирует соответствующее поле ввода и подсвечивает его. Для реквизитов табличных частей используется составной путь, например Товары[0].Количество, а индекс строки удобнее задавать через свойство Строка вместе с именем таблицы.
КлючДанных и УстановитьДанные
Свойство КлючДанных принимает ссылку на объект базы данных. Если сообщение привязано к объекту, который ещё не открыт в форме, двойной щелчок по сообщению откроет этот объект. Метод УстановитьДанные(ОбъектДанных) связывает сообщение с редактируемыми данными формы — тогда привязка к полю сработает даже для ещё не записанного объекта.
Типовой сценарий проверки заполнения в модуле объекта или форме:
&НаСервере
Процедура ПроверитьЗаполнениеТаблицы()
Для Каждого СтрокаТовары Из Объект.Товары Цикл
Если СтрокаТовары.Количество <= 0 Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = НСтр("ru = 'Количество должно быть больше нуля'");
Сообщение.Поле = "Товары[" + (СтрокаТовары.НомерСтроки - 1) + "].Количество";
Сообщение.УстановитьДанные(Объект);
Сообщение.Сообщить();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
- 1Создайте объект: Сообщение = Новый СообщениеПользователю
- 2Заполните свойство Текст понятным пользователю текстом
- 3Укажите Поле — путь к реквизиту формы или объекта
- 4Вызовите УстановитьДанные(Объект) для привязки к данным формы
- 5Вызовите Сообщить() и убедитесь, что сообщение появилось и подсвечивает поле
Сообщения при проверке заполнения и обработке проведения
В обработчиках ОбработкаПроверкиЗаполнения и ОбработкаПроведения модуля объекта сообщения выводятся тем же способом, но есть нюанс с отказом. Чтобы документ не записался при ошибке, нужно установить параметр Отказ = Истина. Само по себе сообщение запись не блокирует — оно лишь информирует.
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
Если Не ЗначениеЗаполнено(Склад) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = НСтр("ru = 'Укажите склад отгрузки'");
Сообщение.Поле = "Склад";
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Если проверяется типовой механизм, проще добавить имя реквизита в массив НепроверяемыеРеквизиты или использовать стандартную проверку заполнения — платформа сама сформирует сообщение с привязкой. Собственные сообщения оправданы для нестандартных условий: согласованность реквизитов между собой, остатки, лимиты.
Получение сообщений на клиенте и фоновые задания
ПолучитьСообщенияПользователю
На клиенте доступна функция ПолучитьСообщенияПользователю(), возвращающая массив сообщений, накопленных с момента последнего серверного вызова. Это полезно, когда нужно не просто показать сообщения, а обработать их программно: проанализировать, перенаправить в журнал, сгруппировать.
&НаКлиенте
Процедура ПослеЗаписиНаСервере()
Сообщения = ПолучитьСообщенияПользователю(Истина);
Для Каждого Сообщение Из Сообщения Цикл
// обработка текста сообщения
КонецЦикла;
КонецПроцедуры
Параметр Истина удаляет сообщения из буфера после получения, чтобы они не дублировались в панели.
Сообщения из фонового задания
Фоновое задание — отдельный сеанс, и его сообщения до пользователя не доходят автоматически. Решение: в коде фонового задания собирать сообщения через ПолучитьСообщенияПользователю(Истина) и передавать их наружу через ДлительныеОперации.СообщитьПрогресс() или помещать результат во временное хранилище, откуда клиент заберёт данные при ожидании завершения. В БСП для этого предусмотрен механизм длительных операций, который сам транспортирует сообщения пользователю.
Альтернативные способы уведомить пользователя
Не каждое уведомление должно быть сообщением в панели. В зависимости от сценария подходят разные механизмы:
ПоказатьПредупреждение()— модальное окно, требующее реакции; подходит для критичных ошибок на клиенте, но блокирует интерфейс и недоступно на сервере.ПоказатьОповещениеПользователя()— ненавязчивое всплывающее уведомление; хорошо для информационных событий («документ записан»).- Статусная строка и декорации формы — для постоянно отображаемого состояния.
- Журнал регистрации — для технической диагностики, невидимой пользователю.
Выбор простой: ошибка заполнения данных — СообщениеПользователю с привязкой к полю; информация о завершении — оповещение; критический сбой на клиенте — предупреждение.
Сравнение вариантов уведомления
Работает на сервере и клиенте, привязывается к полям, не блокирует интерфейс. Ограничение: требует серверного вызова для передачи с сервера.
Гарантирует, что пользователь увидел текст. Ограничение: только на клиенте, блокирует работу до нажатия кнопки.
Ненавязчивое уведомление о событии. Ограничение: только на клиенте, легко пропустить, нет привязки к полям.
Типичные ошибки и ограничения
Самая частая проблема — сообщение «не появляется». Причины обычно такие: серверная процедура вызвана, но сообщение создано в ветке кода, которая не выполнилась; сообщения перехвачены вызовом ПолучитьСообщенияПользователю(Истина) где-то выше по стеку; либо код выполняется в фоновом задании, откуда сообщения не транспортируются.
Вторая группа ошибок — неверная привязка. Если в свойстве Поле указать имя, которого нет в данных формы, подсветка просто не сработает, хотя текст отобразится. Для табличных частей часто путают индексацию: в пути используется индекс с нуля (Товары[0] — первая строка), а НомерСтроки начинается с единицы.
Третья типичная ситуация — потеря сообщений при исключении в транзакции. Сами сообщения доходят, но если после Сообщить() код выбрасывает исключение с собственным текстом, пользователь видит и сообщения, и текст исключения — получается дублирование. Решение: либо сообщения плюс Отказ = Истина, либо исключение, но не всё сразу без необходимости.
Как проверить результат
Текст виден в панели сообщений формы после серверного вызова
Панель пуста — проверьте, выполнилась ли ветка кода и не перехвачены ли сообщения
Щелчок по сообщению активирует и подсвечивает нужное поле
Поле не подсвечивается — проверьте путь в свойстве Поле и вызов УстановитьДанные
При ошибке документ не записывается, Отказ = Истина
Документ записался несмотря на сообщение — Отказ не установлен
Часто задаваемые вопросы
Почему сообщение из серверной процедуры не появляется у пользователя?
Чаще всего серверный вызов завершается, но сообщения перехватывает код выше по стеку через ПолучитьСообщенияПользователю с параметром Истина, либо процедура выполняется в фоновом задании. Проверьте отладчиком, что строка Сообщить() реально выполняется, и нет ли в цепочке вызовов очистки буфера сообщений.
Чем Сообщить() отличается от СообщениеПользователю?
Глобальный метод Сообщить() выводит простой текст без привязки к данным и полям. Объект СообщениеПользователю позволяет указать Поле, КлючДанных, привязаться к данным формы и управлять сообщением программно. Для прикладного кода с проверками рекомендуется именно объект.
Как привязать сообщение к строке табличной части?
В свойстве Поле укажите путь с индексом строки с нуля, например "Товары[2].Количество" для третьей строки. Индекс вычисляется как НомерСтроки - 1. Дополнительно вызовите УстановитьДанные(Объект), чтобы платформа связала сообщение с редактируемыми данными формы.
Как передать сообщение из фонового задания пользователю?
Напрямую — никак, фоновое задание имеет отдельный сеанс. Соберите сообщения внутри задания через ПолучитьСообщенияПользователю(Истина) и передайте их через ДлительныеОперации.СообщитьПрогресс() или поместите результат во временное хранилище, а клиент заберёт данные после завершения задания.
Можно ли заблокировать запись документа только сообщением?
Нет. Сообщение лишь информирует пользователя. Чтобы запретить запись или проведение, в обработчике ОбработкаПроверкиЗаполнения или ОбработкаПроведения установите параметр Отказ = Истина. Сообщение при этом объясняет причину отказа.
Как показать сообщение, не требующее реакции, об успешной операции?
Для информационных уведомлений лучше подходит ПоказатьОповещениеПользователя() на клиенте — оно появляется в углу экрана и исчезает само. СообщениеПользователю оставьте для ошибок и предупреждений, связанных с данными формы.
Что важно запомнить
Передача сообщений с сервера на клиент в 1С работает через буфер сообщений: создавайте СообщениеПользователю, заполняйте Текст, Поле и привязку через УстановитьДанные, вызывайте Сообщить(). Для блокировки действий используйте Отказ = Истина, для фоновых заданий — механизмы передачи прогресса, для информационных уведомлений — оповещения пользователя.