Сообщение пользователю из кода 1С: какой метод выбрать в управляемых формах

· 9 мин

Содержание

Чтобы написать сообщение в 1С, чаще всего хватает одной строки: Сообщить("Документ проведён");. Текст появится в окне сообщений внизу формы. Если же сообщение должно быть привязано к полю формы, используйте объект СообщениеПользователю, для окна с кнопкой «ОК» — ПоказатьПредупреждение(), для остановки операции с ошибкой — ВызватьИсключение, а для следа, который увидит администратор, — ЗаписьЖурналаРегистрации().

Выбор зависит от трёх вещей: где выполняется код (клиент или сервер), должен ли пользователь отреагировать и нужно ли прервать операцию. Всё ниже относится к платформе 8.3 и управляемым формам. Методы общие для любой конфигурации: БП 3.0, ЗУП 3.1, УТ 11 и своих разработок.

Какие способы вывести сообщение есть в 1С и чем они отличаются

Сначала сводная таблица. Она закрывает 90% вопросов «как вывести сообщение».

МетодГде работаетЧто видит пользовательОстанавливает код
Сообщить()клиент и серверстрока в окне сообщенийнет
СообщениеПользователюклиент и серверстрока с переходом к полюнет
ПоказатьПредупреждение()только клиентокно с кнопкой «ОК»нет (асинхронно)
ПоказатьВопрос()только клиентокно с кнопками ответанет (асинхронно)
ПоказатьОповещениеПользователя()только клиентвсплывающее оповещениенет
Состояние()только клиенттекст и прогресс в строке состояниянет
ВызватьИсключениеклиент и серверокно ошибкида
ЗаписьЖурналаРегистрации()клиент и серверничего, запись видит админнет

Главное правило: всё, что рисует окно, живёт только на клиенте. На сервере доступны Сообщить, СообщениеПользователю, исключения и журнал.

Сообщить — самый быстрый вариант

Сообщить("Обработано строк: " + Формат(КоличествоСтрок, "ЧГ=0"));

Число склеивайте со строкой через Формат() с параметром ЧГ=0. Без него 12500 превратится в «12 500» с неразрывным пробелом, а это мешает при копировании в Excel.

Второй параметр Сообщить — статус (СтатусСообщения.Важное, СтатусСообщения.Внимание и другие). В управляемом интерфейсе он почти не влияет на вид строки, поэтому на него не рассчитывайте.

СообщениеПользователю — сообщение, привязанное к полю

Когда пользователь не заполнил реквизит, полезно не просто написать «Заполните контрагента», а подсветить поле. Для этого нужен объект СообщениеПользователю:

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

Щелчок по сообщению переводит курсор в поле «Контрагент», а само поле выделяется рамкой. Для строки табличной части путь пишется с индексом: "Товары[2].Количество". Индекс начинается с нуля, так что Товары[2] — это третья строка.

В модуле формы вместо УстановитьДанные указывают путь к данным формы:

Сообщение.Поле = "Объект.Контрагент";

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

Окна предупреждений и вопросов в управляемых формах

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

Поэтому в управляемых формах пишут асинхронные варианты.

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

&НаКлиенте
Процедура Проверить(Команда)
    ПоказатьПредупреждение(, "Выгрузка завершена", 10, "Готово");
КонецПроцедуры

Параметры по порядку: описание оповещения (можно пропустить), текст, таймаут в секундах (0 — без автозакрытия), заголовок окна.

ПоказатьВопрос с обработкой ответа

Ответ пользователя приходит не в следующую строку кода, а в отдельную процедуру. Её указывают через ОписаниеОповещения:

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

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

Процедура-обработчик обязательно должна быть Экспорт, иначе платформа её не найдёт. Кнопка по умолчанию здесь «Нет»: для удаления данных это безопаснее, чем случайный Enter на «Да».

Асинх и Ждать — короче, но с оговоркой

С платформы 8.3.18 появились асинхронные функции. Тот же вопрос пишется линейно:

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

Читать проще, но у конфигурации должен стоять режим совместимости не ниже 8.3.18. В доработках типовых с более старым режимом остаётся ОписаниеОповещения.

Ненавязчивые сообщения

  • 🔔 ПоказатьОповещениеПользователя("Файл сохранён", , ПутьКФайлу) — всплывашка в углу экрана. Не мешает работе и сама исчезает.
  • ⏳ Состояние("Загрузка", Процент) — текст и полоска прогресса для долгих циклов на клиенте.

Как сообщить об ошибке: исключения и Отказ

Ошибка — это не просто сообщение. Операцию нужно остановить, а транзакцию откатить. Здесь два инструмента.

ВызватьИсключение

Если НЕ ЗначениеЗаполнено(Склад) Тогда
    ВызватьИсключение НСтр("ru = 'Не задан склад по умолчанию в настройках'");
КонецЕсли;

Выполнение обрывается, транзакция откатывается, пользователь видит окно ошибки с вашим текстом. Используйте это для ситуаций, когда дальше идти бессмысленно: нет настройки, недоступен файл, сломаны данные.

Отказ в обработчиках событий

В ПередЗаписью, ОбработкаПроверкиЗаполнения, ОбработкаПроведения есть параметр Отказ. Для ошибок заполнения правильнее его, а не исключение:

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    Если Товары.Количество() = 0 Тогда
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Добавьте хотя бы одну строку в табличную часть «Товары»";
        Сообщение.Поле = "Товары";
        Сообщение.УстановитьДанные(ЭтотОбъект);
        Сообщение.Сообщить();
        Отказ = Истина;
    КонецЕсли;
КонецПроцедуры

Разница ощутима. С Отказ пользователь получает все замечания разом и переходит к каждому полю. С исключением — одно окно, первая же ошибка, без привязки к полю.

Попытка … Исключение: перехват и текст ошибки

Попытка
    Файл.Записать(ИмяФайла);
Исключение
    Инфо = ИнформацияОбОшибке();
    Сообщить("Не удалось сохранить файл: " + ОбработкаОшибок.КраткоеПредставлениеОшибки(Инфо));
    ЗаписьЖурналаРегистрации("Выгрузка.Ошибка", УровеньЖурналаРегистрации.Ошибка, , ,
        ОбработкаОшибок.ПодробноеПредставлениеОшибки(Инфо));
КонецПопытки;

Краткий текст — пользователю, подробный со стеком вызовов — в журнал. Менеджер ОбработкаОшибок есть в платформе 8.3.17 и новее. В старом коде встречается ОписаниеОшибки() — она тоже работает, но даёт только текст без деталей.

Не глотайте исключения пустым блоком Исключение КонецПопытки. Ошибка исчезнет без следа, и через месяц никто не поймёт, почему документы не выгружаются.

Если ошибку нужно передать выше, внутри блока Исключение напишите просто ВызватьИсключение; без текста. Исходное исключение пробросится дальше со всеми деталями.

Сообщения с сервера и из фоновых заданий

Тут больше всего сюрпризов.

Серверный вызов

Сообщить на сервере не показывает строку сразу. Сообщения копятся и приходят на клиент, когда серверная процедура закончилась. Если сервер считает 5 минут, пользователь всё это время видит пустое окно сообщений.

Для прогресса долгой операции на сервере сообщения не годятся. Выносите расчёт в фоновое задание.

Фоновое задание

В фоне окна сообщений нет вообще. Тексты Сообщить и СообщениеПользователю сохраняются в самом задании. Забирают их так:

// внутри фонового задания: забрать накопленное и очистить
Сообщения = ПолучитьСообщенияПользователю(Истина);

// снаружи, по объекту задания
Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Идентификатор);
Сообщения = Задание.ПолучитьСообщенияПользователю(Истина);
Для Каждого Сообщение Из Сообщения Цикл
    Сообщение.Сообщить();
КонецЦикла;

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

💡 Регламентное задание запускается без пользователя. Его Сообщить никто не прочитает. Для регламентных заданий единственный надёжный способ что-то сообщить — журнал регистрации.

Как вывести таблицу или отчёт вместо сотни строк Сообщить

Выводить таблицу значений построчно через Сообщить можно для отладки на 10–20 строках. На тысяче окно сообщений становится нечитаемым.

Варианты получше:

ЗадачаСпособ
Посмотреть данные при разработкеточка останова, затем «Вычислить выражение» (Shift+F9) или табло отладчика
Показать таблицу пользователюреквизит формы типа ТаблицаЗначений и элемент «Таблица» на форме
Красивый вывод с итогамиТабличныйДокумент и макет или СКД
Длинный текстовый логТекстовыйДокумент, затем Показать() или запись в файл

Быстрый вывод в табличный документ без макета:

ТабДок = Новый ТабличныйДокумент;
Для НомерСтроки = 1 По Таблица.Количество() Цикл
    Строка = Таблица[НомерСтроки - 1];
    ТабДок.Область(НомерСтроки, 1).Текст = Строка.Номенклатура;
    ТабДок.Область(НомерСтроки, 2).Текст = Формат(Строка.Количество, "ЧГ=0");
КонецЦикла;
ТабДок.Показать("Результат");

Табличный документ формируют на сервере, а Показать() вызывают на клиенте. Если код серверный, верните ТабДок на клиент через реквизит формы или результат функции.

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

Журнал регистрации и поиск по записям

Журнал регистрации — это сообщения не для пользователя, а для администратора и разработчика. Пишут в него так:

ЗаписьЖурналаРегистрации(
    "ОбменСБанком.Загрузка",
    УровеньЖурналаРегистрации.Предупреждение,
    Метаданные.Документы.СписаниеСРасчетногоСчета,
    Документ,
    "Не найден контрагент по ИНН " + ИНН);

Параметры: имя события, уровень (Ошибка, Предупреждение, Информация, Примечание), объект метаданных, данные (ссылка), комментарий.

Как назвать событие:

  • 📌 через точку, от общего к частному: Подсистема.Действие;
  • 📌 одинаково во всём модуле — по имени потом фильтруют;
  • 📌 без дат и сумм в имени — изменчивое пишите в комментарий.

Где смотреть: в БП 3.0, ЗУП 3.1 и УТ 11 журнал открывается через Администрирование → Поддержка и обслуживание → Журнал регистрации, в Конфигураторе — Администрирование → Журнал регистрации. В отборе указывают событие, уровень, пользователя, период. По тексту комментария журнал фильтрует тоже, поэтому пишите туда ИНН, номер документа, имя файла — по ним вы потом найдёте нужную запись.

Полнотекстовый поиск и логирование

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

Ошибки при выводе сообщений и диалогов

Ниже — то, на чём спотыкаются чаще всего, с причиной.

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

Ещё три мелочи, которые портят сообщения:

  • ❌ Строка вместо НСтр. Если конфигурация многоязычная, текст в НСтр("ru = '…'") переведётся, а обычная строка — нет.
  • ❌ Склейка через плюс вместо шаблона. СтрШаблон("Документ %1 от %2 не проведён", Номер, Формат(Дата, "ДЛФ=D")) читается лучше цепочки из пяти плюсов, и порядок слов в переводе легко поменять.
  • ❌ Сообщения в цикле без остановки. 3000 строк «Не найдено» никто не прочитает. Соберите ошибки в массив и покажите итог: «Не найдено 3000 позиций, список — в журнале регистрации».

Перед сдачей доработки пройдитесь по короткому списку:

Проверка сообщений перед выпуском
Выполнено: 0 / 5

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

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