К статье
Практический материал

Разработка и Конфигурация · 12 мин

1С: как передать сообщение на клиент

Как в 1С передать сообщение на клиент: объект СообщениеПользователю, вывод из серверных процедур, привязка к полям формы, типичные ошибки и примеры кода.

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

Правильный инструмент — объект СообщениеПользователю. Он создаётся на сервере, помещается в буфер сообщений и автоматически передаётся на клиент при возврате управления из серверного вызова. Дополнительно сообщение можно привязать к конкретному полю формы, чтобы платформа подсветила ошибочный реквизит.

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

Как работает передача сообщений между сервером и клиентом

В клиент-серверной архитектуре 1С код выполняется в двух местах: на клиенте (форма, интерфейс) и на сервере (запросы к базе, проверки, проведение). Когда серверная процедура вызывает Сообщить() или создаёт СообщениеПользователю, текст не выводится мгновенно — он складывается в буфер сообщений сеанса.

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

Важное следствие: из фонового задания сообщения пользователю напрямую не дойдут. Фоновое задание выполняется в отдельном сеансе, и его буфер сообщений не связан с сеансом пользователя. Для этого сценария используют другие механизмы — об этом ниже.

Вывод сообщения через СообщениеПользователю

Базовый шаблон выглядит так. Создаём объект, заполняем текст и вызываем метод Сообщить():

&НаСервере

Процедура ПроверитьДанныеНаСервере()

Сообщение = Новый СообщениеПользователю;

Сообщение.Текст = НСтр("ru = 'Не заполнен контрагент в документе'");

Сообщение.Сообщить();

КонецПроцедуры

После возврата из серверной процедуры пользователь увидит текст в панели сообщений формы. Если серверную процедуру вызвали из клиентской, сообщение появится автоматически — дополнительных действий не требуется.

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

bsl
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не заполнен контрагент";
Сообщение.Поле = "Контрагент";
Сообщение.КлючДанных = Объект.Ссылка;
Сообщение.УстановитьДанные(Объект);
Сообщение.Сообщить();

Привязка сообщения к полю формы и данным объекта

Свойства Поле и ПутьКДанным

Свойство Поле задаёт имя реквизита, с которым связано сообщение. Когда пользователь щёлкает по сообщению в панели, платформа активирует соответствующее поле ввода и подсвечивает его. Для реквизитов табличных частей используется составной путь, например Товары[0].Количество, а индекс строки удобнее задавать через свойство Строка вместе с именем таблицы.

КлючДанных и УстановитьДанные

Свойство КлючДанных принимает ссылку на объект базы данных. Если сообщение привязано к объекту, который ещё не открыт в форме, двойной щелчок по сообщению откроет этот объект. Метод УстановитьДанные(ОбъектДанных) связывает сообщение с редактируемыми данными формы — тогда привязка к полю сработает даже для ещё не записанного объекта.

Типовой сценарий проверки заполнения в модуле объекта или форме:

&НаСервере

Процедура ПроверитьЗаполнениеТаблицы()

Для Каждого СтрокаТовары Из Объект.Товары Цикл

Если СтрокаТовары.Количество <= 0 Тогда

Сообщение = Новый СообщениеПользователю;

Сообщение.Текст = НСтр("ru = 'Количество должно быть больше нуля'");

Сообщение.Поле = "Товары[" + (СтрокаТовары.НомерСтроки - 1) + "].Количество";

Сообщение.УстановитьДанные(Объект);

Сообщение.Сообщить();

КонецЕсли;

КонецЦикла;

КонецПроцедуры

Порядок действий при выводе сообщения с привязкой
  1. 1
    Создайте объект: Сообщение = Новый СообщениеПользователю
  2. 2
    Заполните свойство Текст понятным пользователю текстом
  3. 3
    Укажите Поле — путь к реквизиту формы или объекта
  4. 4
    Вызовите УстановитьДанные(Объект) для привязки к данным формы
  5. 5
    Вызовите Сообщить() и убедитесь, что сообщение появилось и подсвечивает поле

Сообщения при проверке заполнения и обработке проведения

В обработчиках ОбработкаПроверкиЗаполнения и ОбработкаПроведения модуля объекта сообщения выводятся тем же способом, но есть нюанс с отказом. Чтобы документ не записался при ошибке, нужно установить параметр Отказ = Истина. Само по себе сообщение запись не блокирует — оно лишь информирует.

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

Если Не ЗначениеЗаполнено(Склад) Тогда

Сообщение = Новый СообщениеПользователю;

Сообщение.Текст = НСтр("ru = 'Укажите склад отгрузки'");

Сообщение.Поле = "Склад";

Сообщение.УстановитьДанные(ЭтотОбъект);

Сообщение.Сообщить();

Отказ = Истина;

КонецЕсли;

КонецПроцедуры

Если проверяется типовой механизм, проще добавить имя реквизита в массив НепроверяемыеРеквизиты или использовать стандартную проверку заполнения — платформа сама сформирует сообщение с привязкой. Собственные сообщения оправданы для нестандартных условий: согласованность реквизитов между собой, остатки, лимиты.

Получение сообщений на клиенте и фоновые задания

ПолучитьСообщенияПользователю

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

&НаКлиенте

Процедура ПослеЗаписиНаСервере()

Сообщения = ПолучитьСообщенияПользователю(Истина);

Для Каждого Сообщение Из Сообщения Цикл

// обработка текста сообщения

КонецЦикла;

КонецПроцедуры

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

Сообщения из фонового задания

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

Альтернативные способы уведомить пользователя

Не каждое уведомление должно быть сообщением в панели. В зависимости от сценария подходят разные механизмы:

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

Выбор простой: ошибка заполнения данных — СообщениеПользователю с привязкой к полю; информация о завершении — оповещение; критический сбой на клиенте — предупреждение.

Сравнение вариантов уведомления

СообщениеПользователю

Работает на сервере и клиенте, привязывается к полям, не блокирует интерфейс. Ограничение: требует серверного вызова для передачи с сервера.

ПоказатьПредупреждение

Гарантирует, что пользователь увидел текст. Ограничение: только на клиенте, блокирует работу до нажатия кнопки.

ПоказатьОповещениеПользователя

Ненавязчивое уведомление о событии. Ограничение: только на клиенте, легко пропустить, нет привязки к полям.

Типичные ошибки и ограничения

Самая частая проблема — сообщение «не появляется». Причины обычно такие: серверная процедура вызвана, но сообщение создано в ветке кода, которая не выполнилась; сообщения перехвачены вызовом ПолучитьСообщенияПользователю(Истина) где-то выше по стеку; либо код выполняется в фоновом задании, откуда сообщения не транспортируются.

Вторая группа ошибок — неверная привязка. Если в свойстве Поле указать имя, которого нет в данных формы, подсветка просто не сработает, хотя текст отобразится. Для табличных частей часто путают индексацию: в пути используется индекс с нуля (Товары[0] — первая строка), а НомерСтроки начинается с единицы.

Третья типичная ситуация — потеря сообщений при исключении в транзакции. Сами сообщения доходят, но если после Сообщить() код выбрасывает исключение с собственным текстом, пользователь видит и сообщения, и текст исключения — получается дублирование. Решение: либо сообщения плюс Отказ = Истина, либо исключение, но не всё сразу без необходимости.

Типичные ошибки
01
Использование глобального метода Сообщить() в серверном коде без привязки — сообщение не подсвечивает поле и плохо управляется
02
Индекс строки табличной части с единицы вместо нуля в свойстве Поле — привязка указывает не на ту строку
03
Ожидание сообщений из фонового задания без механизма передачи — пользователь ничего не видит
04
Сообщение без Отказ = Истина в проверке заполнения — документ записывается несмотря на ошибку
Контрольные точки

Как проверить результат

Появление сообщения
Норма

Текст виден в панели сообщений формы после серверного вызова

Тревожный признак

Панель пуста — проверьте, выполнилась ли ветка кода и не перехвачены ли сообщения

Привязка к полю
Норма

Щелчок по сообщению активирует и подсвечивает нужное поле

Тревожный признак

Поле не подсвечивается — проверьте путь в свойстве Поле и вызов УстановитьДанные

Блокировка записи
Норма

При ошибке документ не записывается, Отказ = Истина

Тревожный признак

Документ записался несмотря на сообщение — Отказ не установлен

Часто задаваемые вопросы

Почему сообщение из серверной процедуры не появляется у пользователя?

Чаще всего серверный вызов завершается, но сообщения перехватывает код выше по стеку через ПолучитьСообщенияПользователю с параметром Истина, либо процедура выполняется в фоновом задании. Проверьте отладчиком, что строка Сообщить() реально выполняется, и нет ли в цепочке вызовов очистки буфера сообщений.

Чем Сообщить() отличается от СообщениеПользователю?

Глобальный метод Сообщить() выводит простой текст без привязки к данным и полям. Объект СообщениеПользователю позволяет указать Поле, КлючДанных, привязаться к данным формы и управлять сообщением программно. Для прикладного кода с проверками рекомендуется именно объект.

Как привязать сообщение к строке табличной части?

В свойстве Поле укажите путь с индексом строки с нуля, например "Товары[2].Количество" для третьей строки. Индекс вычисляется как НомерСтроки - 1. Дополнительно вызовите УстановитьДанные(Объект), чтобы платформа связала сообщение с редактируемыми данными формы.

Как передать сообщение из фонового задания пользователю?

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

Можно ли заблокировать запись документа только сообщением?

Нет. Сообщение лишь информирует пользователя. Чтобы запретить запись или проведение, в обработчике ОбработкаПроверкиЗаполнения или ОбработкаПроведения установите параметр Отказ = Истина. Сообщение при этом объясняет причину отказа.

Как показать сообщение, не требующее реакции, об успешной операции?

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

Итог

Что важно запомнить

Передача сообщений с сервера на клиент в 1С работает через буфер сообщений: создавайте СообщениеПользователю, заполняйте Текст, Поле и привязку через УстановитьДанные, вызывайте Сообщить(). Для блокировки действий используйте Отказ = Истина, для фоновых заданий — механизмы передачи прогресса, для информационных уведомлений — оповещения пользователя.