При разработке конфигураций на платформе 1С:Предприятие 8.3 с использованием управляемых форм, часто возникает необходимость информировать пользователя о результатах выполнения операций, особенно тех, которые выполняются на сервере. Например, процедура проведения документа, вызываемая с директивой НаСервере, должна не только выполнить проверку остатков, но и сообщить пользователю, если чего-то не хватает, или если документ успешно проведен — для этого подойдёт автоматизация контроля данных и шаблонов сообщений без программирования. Нам предстоит разобраться, какие инструменты для этого существуют, какие из них предпочтительны, и как правильно их использовать, чтобы обеспечить наилучший пользовательский опыт.
Традиционно для вывода сообщений используется метод Сообщить(), но в последнее время фирма "1С" активно продвигает объект СообщениеПользователю и соответствующие обертки из Библиотеки стандартных подсистем (БСП). Давайте рассмотрим эти подходы, их преимущества, недостатки и особенности применения.
Прежде чем углубляться в конкретные методы, важно понять, как вообще сообщения, генерируемые на сервере, доходят до клиента. Когда мы вызываем серверную процедуру (например, из модуля формы или общего модуля с директивой НаСервере), все вызовы Сообщить() или СообщениеПользователю.Сообщить() не выводят информацию немедленно — для анализа серверного контекста есть инструмент для отладки серверного кода 1С в режиме Предприятие. Вместо этого, платформа помещает эти сообщения в специальный буфер. Когда выполнение серверного вызова завершается и управление возвращается на клиент, платформа автоматически считывает все накопленные сообщения из этого буфера и отображает их в окне сообщений активной формы. Это очень важный аспект, поскольку он объясняет, почему сообщения из серверной процедуры появляются только после ее завершения, а не по ходу выполнения.
Сообщить()Метод Сообщить() является самым простым и старым способом вывода текстовых сообщений (поможет консоль кода и запросов для разработчика 1С). Он действительно прекрасно работает как на клиенте, так и на сервере, и сообщения, выведенные с его помощью на сервере, аккумулируются и показываются на клиенте.
Пример использования на сервере:
// В процедуре с директивой НаСервере
Процедура ПроверитьОстаткиНаСервере(ТабличнаяЧастьДокумента) НаСервере
// Допустим, здесь происходит проверка остатков
Если НеДостаточноТовара Тогда
Сообщить("Не хватает товара на складе! Проведение невозможно.");
Возврат;
Иначе
Сообщить("Остатки проверены, все в порядке.");
КонецЕсли;
КонецПроцедуры
Сообщить():Сообщить():Сообщить() считается устаревшим и не рекомендуется для использования в продакшн-коде. Инструменты вроде BSL Language Server даже диагностируют его использование как потенциальную проблему — поможет инструмент разработки и проверки синтаксиса кода через BSL. Многие разработчики используют его только для временных отладочных сообщений, чтобы потом легко их находить и удалять.Сообщить(Неопределено)) или в определенных контекстах метод может не привести к ожидаемому результату, хотя это скорее исключение.Итак, хотя Сообщить() и функционален, для серьезных прикладных решений нам следует рассмотреть более продвинутые инструменты.
СообщениеПользователюОбъект СообщениеПользователю является современным и рекомендуемым инструментом для вывода сообщений. Он предоставляет гораздо более гибкие возможности, чем простой метод Сообщить().
СообщениеПользователю:СообщениеПользователю:Для создания и вывода сообщения с помощью объекта СообщениеПользователю, мы обычно выполняем следующие шаги:
НовоеСообщение = Новый СообщениеПользователю;НовоеСообщение.Текст = "Текст вашего сообщения";НовоеСообщение.Поле = "Объект.ТабличнаяЧасть.Количество";НовоеСообщение.КлючДанных = СсылкаНаОбъект;ИдентификаторНазначения: НовоеСообщение.ИдентификаторНазначения = GUIDЦелевойФормы;НовоеСообщение.Сообщить();Пример использования СообщениеПользователю в серверной процедуре проверки остатков:
// В процедуре с директивой НаСервере
Процедура ПроверитьОстаткиНаСервере(ТабличнаяЧастьДокумента, ИдентификаторФормыДокумента) НаСервере
// Имитация проверки остатков для каждой строки табличной части
Для Каждого СтрокаТЧ Из ТабличнаяЧастьДокумента Цикл
Если СтрокаТЧ.Количество > 10 Тогда // Условие нехватки для примера
НовоеСообщение = Новый СообщениеПользователю;
НовоеСообщение.Текст = "Не хватает товара '" + СтрокаТЧ.Номенклатура.Наименование + "' в количестве " + (СтрокаТЧ.Количество - 10) + " шт.";
НовоеСообщение.Поле = "Объект.Товары[" + (СтрокаТЧ.НомерСтроки - 1) + "].Количество"; // Привязка к конкретной ячейке
НовоеСообщение.КлючДанных = ТабличнаяЧастьДокумента.Владелец.Ссылка; // Привязка к объекту документа
Если ЗначениеЗаполнено(ИдентификаторФормыДокумента) Тогда
НовоеСообщение.ИдентификаторНазначения = ИдентификаторФормыДокумента; // Выводим в форму, откуда был вызов
КонецЕсли;
НовоеСообщение.Сообщить();
КонецЕсли;
КонецЦикла;
// Если нет сообщений о нехватке, можно вывести общее информационное сообщение
Если ПрочитатьСообщенияПользователю().Количество() = 0 Тогда
НовоеСообщение = Новый СообщениеПользователю;
НовоеСообщение.Текст = "Проверка остатков завершена. Все товары в наличии.";
Если ЗначениеЗаполнено(ИдентификаторФормыДокумента) Тогда
НовоеСообщение.ИдентификаторНазначения = ИдентификаторФормыДокумента;
КонецЕсли;
НовоеСообщение.Сообщить();
КонецЕсли;
КонецПроцедуры
Обратите внимание, что для использования ИдентификаторНазначения, нам нужно передать идентификатор формы с клиента на сервер. Мы можем получить его с помощью метода формы УникальныйИдентификатор.
В конфигурациях, использующих БСП, настоятельно рекомендуется применять специализированные процедуры для вывода сообщений, которые инкапсулируют работу с объектом СообщениеПользователю. Это обеспечивает единообразие и упрощает поддержку кода. Обычно используются процедуры ОбщегоНазначения.СообщитьПользователю() (для серверного контекста) и ОбщегоНазначенияКлиент.СообщитьПользователю() (для клиентского контекста).
Пример (псевдокод, точная сигнатура может отличаться в разных версиях БСП):
// В процедуре с директивой НаСервере
Процедура ПроверитьОстаткиНаСервереСБСП(ТабличнаяЧастьДокумента) НаСервере
// ... логика проверки ...
Если НеДостаточноТовара Тогда
// Пример вызова из БСП
ОбщегоНазначения.СообщитьПользователю("Не хватает товара на складе!",
ОбъектДокумента.Ссылка,
"ТабличнаяЧасть.РеквизитКоличества");
КонецЕсли;
КонецПроцедуры
Функции БСП часто позволяют также указывать поле, данные и могут иметь дополнительные параметры для тонкой настройки вывода. Мы рекомендуем ознакомиться с актуальной документацией по БСП и исходным кодом этих процедур в вашей конфигурации.
Одна из распространенных проблем, с которой мы можем столкнуться при использовании СообщениеПользователю, заключается в том, что сообщения, привязанные к форме, могут исчезнуть, если эта форма закрывается. Это особенно актуально при проведении документа из формы списка (например, по ПКМ -> "Провести"), когда форма самого документа может быть успешно закрыта после проведения, а важные информационные сообщения или предупреждения, которые не привели к отказу проведения, остаются не увиденными пользователем.
Для решения этой проблемы мы можем использовать следующий подход:
ПослеЗаписиНаСервере или ПослеЗаписи модуля формы документа, мы можем прочитать все накопленные сообщения с помощью функции ПрочитатьСообщенияПользователю().ИдентификаторНазначения родительской формы (формы списка).Давайте рассмотрим, как это может выглядеть:
// В модуле формы документа
// Предположим, что мы передали идентификатор формы списка при открытии документа
// как параметр формы, например, "ИдентификаторФормыСписка".
// Или получили его из контекста.
ПеременнаяДляИдентификатораФормыСписка = Неопределено;
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// ...
// Сохраняем идентификатор формы списка, если он был передан
Если Параметры.Свойство("ИдентификаторФормыСписка") Тогда
ПеременнаяДляИдентификатораФормыСписка = Параметры.ИдентификаторФормыСписка;
КонецЕсли;
// ...
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПрочитатьИПеренаправитьСообщения(ИдентификаторЦелевойФормы)
Сообщения = ПрочитатьСообщенияПользователю();
Для Каждого Сообщение Из Сообщения Цикл
// Изменяем идентификатор назначения на идентификатор родительской формы
Сообщение.ИдентификаторНазначения = ИдентификаторЦелевойФормы;
Сообщение.Сообщить();
КонецЦикла;
КонецФункции
&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
// ... Ваша логика после записи ...
// Проверяем, если форма должна закрыться после записи и есть куда перенаправить
Если ПараметрыЗаписи.ЗакрыватьФормуИлиПриЗакрытииФормы = Истина
И ЗначениеЗаполнено(ПеременнаяДляИдентификатораФормыСписка) Тогда
ПрочитатьИПеренаправитьСообщения(ПеременнаяДляИдентификатораФормыСписка);
КонецЕсли;
КонецПроцедуры
Этот подход позволяет нам обеспечить видимость всех сообщений, даже если форма-источник была закрыта. Он особенно полезен для информационных сообщений или предупреждений, которые не блокируют проведение, но важны для пользователя.
ПоказатьОповещениеПользователя()Для вывода некритичных информационных сообщений, которые не являются ошибками и не требуют привязки к конкретному полю, существует отдельный метод ПоказатьОповещениеПользователя(). Он используется для уведомлений о фоновых операциях, завершении длительных процессов или просто для предоставления дополнительной информации, которая не требует немедленного внимания пользователя и отображается в виде всплывающего уведомления, обычно в правом нижнем углу экрана.
Этот метод подходит для информирования пользователя о ходе выполнения длительных серверных операций, не перегружая окно сообщений и не требуя активных действий.
Пример:
&НаСервере
Процедура ВыполнитьДлительнуюОперациюНаСервере()
// ... Длительные вычисления ...
ПоказатьОповещениеПользователя("Операция завершена", "Ваша длительная операция успешно выполнена.", , , "Информационная", 10);
КонецПроцедуры
Важно отметить, что ПоказатьОповещениеПользователя() является клиентским методом, поэтому его прямое использование с сервера невозможно. Если вам нужно показать такое оповещение после серверной процедуры, необходимо вызвать его с клиента, передав нужные параметры с сервера.
// В серверной процедуре:
&НаСервере
Функция ВыполнитьДлительнуюОперациюНаСервереИСообщить()
// ... Длительные вычисления ...
Возврат "Ваша длительная операция успешно выполнена.";
КонецФункции
// В клиентской процедуре, которая вызывает серверную:
&НаКлиенте
Процедура ЗапуститьДлительнуюОперацию()
ТекстОповещения = ВыполнитьДлительнуюОперациюНаСервереИСообщить();
ПоказатьОповещениеПользователя("Операция завершена", ТекстОповещения);
КонецПроцедуры
Независимо от выбранного метода, мы должны всегда помнить о качестве самих сообщений. Хорошо сформулированные сообщения значительно улучшают пользовательский опыт. Фирма "1С" рекомендует следующие принципы:
Следуя этим рекомендациям, мы можем сделать наши приложения более удобными и интуитивно понятными для пользователей.
Мы выяснили, что в контексте управляемых форм и серверных вызовов в 1С:Предприятии 8.3:
Сообщить() все еще может быть использован, но его следует избегать в продакшн-коде.СообщениеПользователю. Он предоставляет гибкость в привязке к элементам формы, данным объекта и указании целевой формы.ОбщегоНазначения.СообщитьПользователю(), для стандартизации и упрощения кода.ИдентификаторНазначения родительской формы.ПоказатьОповещениеПользователя(), вызывая его с клиента.Применяя эти знания на практике, мы сможем создавать более robustные и удобные пользовательские интерфейсы в наших решениях на платформе 1С:Предприятие.