Как реализовать переход на строку табличной части с ошибкой при использовании подписок на события?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке конфигураций на платформе 1С:Предприятие 8 часто возникает задача: не просто прервать запись документа при обнаружении некорректных данных в табличной части, но и максимально облегчить пользователю поиск этой ошибки. Идеальный вариант — когда система сама подсвечивает нужную ячейку и активизирует строку, в которой допущена оплошность. Рассмотрим, как добиться такого поведения, если проверка выполняется на стороне сервера, например, в подписке на события или в модуле объекта.

Анализ проблемы: почему стандартное сообщение не всегда «прыгает» на строку

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

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

Решение №1: Переход к использованию «ОбработкаПроверкиЗаполнения»

Как показывает практика и обсуждение экспертов, наиболее методологически верным решением является вынос проверок из события ПередЗаписью в специализированное событие ОбработкаПроверкиЗаполнения. Это событие специально спроектировано платформой для взаимодействия с интерфейсом. Рассмотрим, почему это лучше:

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

Посмотрим на пример реализации такой проверки в модуле объекта (или аналогично через подписку):


Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    
    Для Каждого ТекСтрока Из Товары Цикл
        Если ТекСтрока.Цена = 0 Тогда
            ТекстСообщения = НСтр("ru='Цена в строке %Номер% должна быть заполнена!'");
            ТекстСообщения = СтрЗаменить(ТекстСообщения, "%Номер%", ТекСтрока.НомерСтроки);
            
            Индекс = Товары.Индекс(ТекСтрока);
            Поле = "Объект.Товары[" + Формат(Индекс, "ЧГ=0") + "].Цена";
            
            Сообщение = Новый СообщениеПользователю;
            Сообщение.Текст = ТекстСообщения;
            Сообщение.Поле = Поле;
            Сообщение.УстановитьДанные(ЭтотОбъект);
            Сообщение.Сообщить();
            
            Отказ = Истина;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Решение №2: Использование БСП для формирования пути

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

Проанализируем ситуацию: в подписке на событие нам доступен Источник. Мы можем использовать функцию ПутьКТабличнойЧасти, чтобы не формировать строку пути вручную. Выясним причину, по которой это может не сработать: важно передать правильный индекс.


// В обработчике подписки на событие ПередЗаписью
Процедура ПроверитьДанныеПередЗаписью(Источник, Отказ, Замещение) Экспорт
    
    Для Каждого СтрокаТЧ Из Источник.Товары Цикл
        Если СтрокаТЧ.Количество <= 0 Тогда
            
            ИмяПути = ОбщегоНазначенияКлиентСервер.ПутьКТабличнойЧасти(
                "Объект.Товары", 
                СтрокаТЧ.НомерСтроки, 
                "Количество"
            );
            
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
                НСтр("ru='Количество должно быть больше нуля'"),
                Источник,
                ИмяПути,
                ,
                Отказ
            );
            
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Важный нюанс: В методе ПутьКТабличнойЧасти БСП самостоятельно вычитает единицу из НомерСтроки, преобразуя его в индекс 0-based. Это избавляет разработчика от лишних арифметических операций и снижает риск ошибки.

Решение №3: Передача информации через «ДополнительныеСвойства»

Бывают сложные случаи, когда проверка должна произойти на сервере в подписке, а фокус на строку нужно установить программно на клиенте после неудачной попытки записи. Рассмотрим алгоритм действий:

  1. В подписке на событие при обнаружении ошибки мы не только ставим Отказ = Истина, но и записываем индекс ошибочной строки в структуру Источник.ДополнительныеСвойства.
  2. На форме документа в событии ПослеЗаписиНаСервере (которое вызывается, даже если запись не состоялась из-за отказа на сервере в определенных сценариях или при использовании клиентских оберток) мы считываем этот индекс.
  3. Используем свойство формы ТекущаяСтрока для элемента управления таблицей.

Пример записи свойства на сервере:

Источник.ДополнительныеСвойства.Вставить("ОшибкаВСтрокеИндекс", ИндексСтроки);

Пример установки фокуса на форме (в процедуре, вызываемой после серверной проверки):


Если ПараметрыЗаписи.Свойство("ОшибкаВСтрокеИндекс") Тогда
    Элементы.Товары.ТекущаяСтрока = Объект.Товары[ПараметрыЗаписи.ОшибкаВСтрокеИндекс].ПолучитьИдентификатор();
КонецЕсли;

Оптимизация: запросы в подписках

Проанализируем еще один важный аспект, упомянутый в обсуждении — производительность. Выполнение запросов внутри подписки ПередЗаписью (внутри транзакции) — это ресурсозатратная операция. Если ваша проверка требует данных из базы (например, проверка остатков), постарайтесь:

Соблюдение этих правил позволит не только реализовать удобный переход к ошибкам для пользователя, но и сохранить высокую скорость работы системы при записи документов.

← На главную