При разработке интерфейсов в управляемом приложении «1С:Предприятие 8.3» одной из частых задач является проверка (валидация) данных, введенных пользователем в табличную часть. Нам, как разработчикам, крайне важно не просто выбросить абстрактный текст ошибки внизу экрана, а четко указать пользователю, в какой строке и в каком именно поле допущена ошибка. Однако при попытке связать объект СообщениеПользователю с конкретной ячейкой таблицы на форме разработчики регулярно сталкиваются с неочевидными техническими трудностями. В этой статье мы подробно разберем, как правильно реализовать эту привязку, почему возникают популярные системные ошибки и как сделать интерфейс максимально дружелюбным.
Прежде всего проанализируем базовое поведение платформы «1С:Предприятие». Многие начинающие разработчики ожидают, что при заполнении свойств Поле и ПутьКДанным красное «облачко» с предупреждением мгновенно раскроется прямо над ошибочной ячейкой в таблице. Но это не так.
Запомните важное правило: любое системное сообщение в управляемых формах первоначально всегда попадает в общую панель сообщений (внизу экрана или в виде всплывающего списка уведомлений в правом углу). Привязка работает интерактивно. Только когда пользователь производит клик по тексту сообщения в панели, платформа автоматически:
Сделать так, чтобы это облачко открылось у ячейки автоматически при выполнении серверного кода без клика пользователя, стандартными средствами платформы невозможно. Это базовое ограничение UX-системы 1С, созданное для того, чтобы не захламлять экран множеством всплывающих окон одновременно.
Рассмотрим частую ошибку, возникающую при попытке использовать стандартные методы Библиотеки Стандартных Подсистем (БСП) для вывода сообщений:
{ОбщийМодуль.ОбщегоНазначенияКлиентСервер.Модуль}: Ошибка при установке значения атрибута контекста (КлючДанных)
Сообщение.КлючДанных = КлючДанных;
по причине: Несоответствие типов
Выясним причину этой ошибки. Она происходит, когда в процедуру БСП СообщитьПользователю в качестве второго параметра (который отвечает за источник данных) передается ключевое слово ЭтотОбъект внутри модуля управляемой формы.
Дело в том, что в контексте модуля формы слово ЭтотОбъект возвращает тип УправляемаяФорма. В то же время свойство КлючДанных объекта СообщениеПользователю ожидает уникальный идентификатор строки БД, ключ записи регистра или ссылку на объект базы данных (например, ДокументСсылка.РеализацияТоваровУслуг). Передача типа УправляемаяФорма в свойство КлючДанных и вызывает системный сбой из-за несоответствия типов.
Решение проблемы: если валидация данных происходит интерактивно в форме и документ еще не записан, привязывать сообщение к конкретной ссылке в базе данных через КлючДанных не требуется. Достаточно указать путь к данным формы. Во второй параметр функции БСП следует передавать либо Неопределено, либо, если объект уже сохранен в базе данных, ссылку на него: Объект.Ссылка.
Еще одна неочевидная проблема связана с адресацией строки табличной части. Посмотрим на некорректный пример формирования пути:
Индекс = ЭлементСтрокаНаУдаление.Значение.НомерСтроки;
Поле = "Объект.интФайлыПоНарушениям[" + Индекс + "].ФайлНарушения";
Здесь кроется критическая логическая ошибка:
НомерСтроки возвращает порядковый номер, нумерация которого для пользователя начинается с 1 (например, первая строка имеет номер 1).СообщениеПользователю платформа ожидает индекс элемента коллекции, нумерация которого в коде начинается с 0 (первая строка имеет индекс 0).Если в путь данных подставить НомерСтроки напрямую, адресная привязка сломается. Платформа попытается обратиться к несуществующей строке, не сможет сопоставить путь с элементом на форме и «уронит» сообщение в самый низ экрана без возможности интерактивного перехода.
Более того, если вы используете функции БСП, например, ОбщегоНазначенияКлиентСервер.ПутьКТабличнойЧасти, помните, что эта функция на входе ожидает именно реальный НомерСтроки (начиная с 1). Внутри себя она автоматически вычитает единицу для получения верного индекса. Если вы по ошибке передадите туда готовый индекс (начиная с 0), функция попытается вычесть единицу еще раз. В результате вы получите отрицательный индекс (например, -1), что приведет к некорректной работе интерфейса.
Рассмотрим, как правильно написать код для вывода сообщений у табличной части формы. Разберем два варианта реализации: с использованием встроенного языка 1С и с применением механизмов БСП.
Если мы работаем на сервере в контексте управляемой формы, мы можем вручную рассчитать индекс строки табличной части и сформировать правильный путь к данным:
&НаСервере
Процедура ПроверитьТабличнуюЧастьНаСервере()
Для Каждого СтрокаТЧ Из Объект.интФайлыПоНарушениям Цикл
// Проверяем условие ошибки (например, файл не выбран)
Если Не ЗначениеЗаполнено(СтрокаТЧ.ФайлНарушения) Тогда
// Вычисляем правильный индекс строки (начиная с 0)
ИндексСтроки = Объект.интФайлыПоНарушениям.Индекс(СтрокаТЧ);
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Поле ""Файл нарушения"" обязательно для заполнения!";
// Указываем путь к табличной части и конкретной колонке
Сообщение.Поле = "Объект.интФайлыПоНарушениям[" + Формат(ИндексСтроки, "ЧГ=0") + "].ФайлНарушения";
Сообщение.ПутьКДанным = "Объект";
Сообщение.Сообщить();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В типовых конфигурациях правильнее использовать стандартизированные методы БСП. Это гарантирует корректную работу платформы во всех режимах (включая веб-клиент) и упрощает поддержку кода:
&НаСервере
Процедура ПроверитьТабличнуюЧастьБСПНаСервере()
Для Каждого СтрокаТЧ Из Объект.интФайлыПоНарушениям Цикл
Если Не ЗначениеЗаполнено(СтрокаТЧ.ФайлНарушения) Тогда
ТекстСообщения = "Необходимо прикрепить корректный файл в строке " + СтрокаТЧ.НомерСтроки;
// Формируем путь к полю через стандартную функцию (передаем НомерСтроки)
ПолеОшибки = ОбщегоНазначенияКлиентСервер.ПутьКТабличнойЧасти(
"интФайлыПоНарушениям",
СтрокаТЧ.НомерСтроки,
"ФайлНарушения"
);
// Выводим сообщение. Обратите внимание: второй параметр - Неопределено
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
ТекстСообщения,
Неопределено,
ПолеОшибки,
"Объект"
);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Что делать, если заказчик категорически требует, чтобы пользователь мгновенно замечал ошибочные строки без необходимости совершать клики по панели сообщений внизу экрана? В этом случае опытные разработчики используют альтернативные паттерны проектирования интерфейсов.
Этот способ позволяет визуально выделить ошибочные строки цветом фона или текста. Посмотрим, как это реализовать:
интФайлыПоНарушениям служебный реквизит ОшибочнаяСтрока с типом данных Булево (на форму выносить эту колонку не нужно).
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Программное добавление условного оформления
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
// Указываем оформляемые поля (всю строку или конкретные колонки)
ОформляемоеПоле = ЭлементОформления.Поля.Элементы.Добавить();
ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("интФайлыПоНарушениямФайлНарушения");
// Задаем условие: ОшибочнаяСтрока Равно Истина
ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.интФайлыПоНарушениям.ОшибочнаяСтрока");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Истина;
// Устанавливаем цвет оформления (например, светло-красный фон)
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", WebЦвета.СветлоРозовый);
КонецПроцедуры
Теперь при валидации данных на сервере достаточно установить для ошибочной строки СтрокаТЧ.ОшибочнаяСтрока = Истина. Платформа мгновенно окрасит ячейку в розовый цвет, и пользователь сразу поймет, где допущена ошибка.
Отличным решением является добавление в табличную часть специальной текстовой колонки ИнформацияОбОшибке. При проведении проверки вы можете записывать текст ошибки прямо в эту ячейку текущей строки. Пользователю не придется гадать или нажимать на сообщения внизу экрана — расшифровка проблемы будет всегда находиться прямо перед его глазами в таблице.
Если проверка выполняется в контексте клиентских процедур (например, перед записью или при изменении значения), мы можем программно перенести фокус ввода на проблемное место. Разберем этот сценарий:
&НаКлиенте
Процедура ПослеПроверкиДанныхНаКлиенте(ИндексОшибочнойСтроки)
Если ИндексОшибочнойСтроки <> Неопределено Тогда
// Получаем идентификатор строки по индексу
СтрокаТЧ = Объект.интФайлыПоНарушениям[ИндексОшибочнойСтроки];
ИдентификаторСтроки = СтрокаТЧ.ПолучитьИдентификатор();
// Переносим фокус на нужную строку табличной части
Элементы.интФайлыПоНарушениям.ТекущаяСтрока = ИдентификаторСтроки;
// Активизируем конкретную колонку
Элементы.ТекущийЭлемент = Элементы.интФайлыПоНарушениямФайлНарушения;
// Показываем стандартное всплывающее оповещение в углу экрана
ПоказатьОповещениеПользователя(
"Внимание!",
,
"В табличной части найдены некорректные файлы. Проверьте выделенную строку!",
КартинкаОсобоеУведомление
);
КонецЕсли;
КонецПроцедуры
Сочетание программного фокуса на клиенте, условного оформления строк цветом и аккуратного использования СообщениеПользователю позволяет создавать профессиональные, интуитивно понятные и надежные интерфейсы, которые высоко оценят конечные пользователи вашей конфигурации.