При переходе с устаревшей процедуры Сообщить() на современный механизм управляемого интерфейса разработчики часто сталкиваются с вопросами: как правильно подставить переменные в текст СообщениеПользователю, почему сообщение выводится при интерактивной работе в форме документа, но пропадает при групповом перепроведении, и почему проверка табличных частей ведет себя по-разному. Разберем эти задачи по шагам и выясним причины типичных ошибок.
Объект СообщениеПользователю не имеет встроенного конструктора со списком параметров, поэтому итоговый текст формируется перед записью в свойство Текст. Рассмотрим два основных способа формирования строки с параметрами.
Способ 1. Простая конкатенация строк
Если требуется объединить несколько значений, приведем нестроковые переменные к строковому типу с помощью функции Строка():
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = Строка(Стр.Организация) + " " + Строка(Стр.ОрганизацияП) + " Текст сообщения";
Сообщение.Сообщить();
Способ 2. Использование функции СтрШаблон
Для повышения читаемости кода и удобства локализации рекомендуется применять функцию СтрШаблон(). Разберем пример:
ШаблонТекста = НСтр("ru = 'Организация: %1, Получатель: %2. Обнаружено расхождение сумм!'");
ТекстСообщения = СтрШаблон(ШаблонТекста, Стр.Организация, Стр.ОрганизацияП);
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ТекстСообщения;
Сообщение.Сообщить();
В конфигурациях, использующих Библиотеку стандартных подсистем (БСП), можно воспользоваться универсальной процедурой ОбщегоНазначенияКлиентСервер.СообщитьПользователю, которая сокращает объем шаблонного кода:
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
ТекстСообщения,
ЭтотОбъект.Ссылка,
"Количество",
"Товары"
);
Главное преимущество СообщениеПользователю перед Сообщить() — возможность связать предупреждение с конкретным полем на форме или со строкой табличной части. Посмотрим, как это настраивается:
КлючДанных указывает платформе, к какому объекту относится ошибка. Если передать ссылку на документ (ЭтотОбъект.Ссылка), платформа сможет открыть форму объекта прямо из панели сообщений при клике на ошибку.Поле позволяет подсветить конкретный элемент формы или ячейку табличной части (например, "Товары[0].Количество").
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не указано количество в строке 1!";
Сообщение.Поле = "Товары[0].Количество";
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
Проанализируем ситуацию: в интерактивном режиме при проведении открытого документа сообщение отображается корректно, а при запуске через групповое перепроведение или обработку сообщений нет. Выделим причины такого поведения:
Сообщить(), размещенные в обработчиках формы (например, ПередЗаписьюНаСервере или ОбработкаПроверкиЗаполненияНаСервере формы), при пакетной обработке просто не выполняются. Весь контроль данных и проведение должны находиться в модуле объекта (в обработчиках ПередЗаписью, ОбработкаПроверкиЗаполнения или ОбработкаПроведения).
МассивСообщений = ПолучитьСообщенияПользователю(Истина);
Для Каждого ТекСообщение Из МассивСообщений Цикл
// Обработка или вывод сообщения в лог
КонецЦикла;
Истина очищает стек сообщений после их извлечения.ЗаписьЖурналаРегистрации(), так как пользователь может не дождаться окончания работы интерфейса.Частая проблема при переносе кода из формы в модуль объекта — пропуск цикла обхода табличной части или получение пустой таблицы. Разберем основные причины:
Документ.РеализацияТоваровУслуг.Товары), запрос обращается к уже сохраненным данным в СУБД. Если объект еще не записан или изменяется в памяти, запрос может вернуть пустоту. Для проверки актуальных данных объекта в памяти в запрос передают выгруженную табличную часть:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВремТЗ.Организация КАК Организация,
| СУММА(ВремТЗ.Количество) КАК Количество
|ПОМЕСТИТЬ ВТ_Товары
|ИЗ
| &ТабличнаяЧасть КАК ВремТЗ
|СГРУППИРОВАТЬ ПО
| ВремТЗ.Организация";
Запрос.УстановитьПараметр("ТабличнаяЧасть", ЭтотОбъект.Товары.Выгрузить());
РезультатЗапроса = Запрос.Выполнить();
// ОШИБКА: метод Свернуть нельзя вызывать внутри цикла добавления строк!
Для Каждого СтрокаТЧ Из ТЧРез Цикл
ЗаполнитьЗначенияСвойств(ТЗВременная.Добавить(), СтрокаТЧ);
ТЗВременная.Свернуть("Организация", "Количество");
КонецЦикла;
Свернуть() вызвать один раз после завершения цикла, либо агрегировать данные сразу на уровне запроса через СГРУППИРОВАТЬ ПО.