При разработке и доработке документов на управляемых формах часто возникает задача перехватить или проанализировать момент, когда в табличную часть добавляются новые строки. Типичный сценарий — заполнение документа через специализированную форму подбора номенклатуры. Разработчик пытается установить точку останова в стандартных событиях таблицы или формы (таких как ОбработкаВыбора, ПередНачаломДобавления, ОбработкаОповещения), однако отладчик в них не останавливается. Рассмотрим подробнее архитектурные причины такого поведения платформы 1С:Предприятие 8 и разберем практические способы решения этой задачи.
Проанализируем механику работы управляемой формы. Коллекция строк таблицы на форме представляет собой объект ДанныеФормыКоллекция, а в модуле объекта — обычную табличную часть. Платформа строго разграничивает интерактивные действия пользователя и программные манипуляции с данными:
ПередНачаломДобавления, ПриОкончанииРедактирования, ОбработкаВыбора) вызываются платформой исключительно тогда, когда пользователь физически нажимает кнопку добавления строки на командной панели или выбирает значение непосредственно в поле ввода ячейки. Программные вызовы методов Добавить(), Вставить(), Загрузить() эти события не инициируют.ДанныеФормыКоллекция и у табличных частей прикладных объектов в платформе 1С отсутствуют события уровня «ПриДобавленииСтроки» или «ПриИзмененииСостава».ОткрытьФорму() с параметром ОписаниеОповещения. При завершении выбора форма подбора не генерирует оповещения общего назначения, а сразу передает результат в клиентскую процедуру обратного вызова (callback).Разберем по шагам, как найти точное место в коде формы, где происходит перенос строк из формы подбора в документ:
ПодборТоваров или ОбработкаКомандыПодбор).ОткрытьФорму() и смотрим, какой обработчик оповещения передан в параметрах.ПодборТоваровЗавершение) и вызываемую из нее серверную процедуру заполнения табличной части.Посмотрим на пример стандартной реализации обработки подбора:
&НаКлиенте
Процедура ПодборТоваров(Команда)
Оповещение = Новый ОписаниеОповещения("ПодборТоваровЗавершение", ЭтотОбъект);
ПараметрыФормы = Новый Структура("РежимВыбора", Истина);
ОткрытьФорму("Обработка.ПодборНоменклатуры.Форма.Форма", ПараметрыФормы, ЭтотОбъект,,,, Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПодборТоваровЗавершение(РезультатВыбора, ДополнительныеПараметры) Экспорт
Если РезультатВыбора = Неопределено Тогда
Возврат;
КонецЕсли;
// Именно здесь или в серверной процедуре ставится точка останова
ПеренестиДанныеПодбораНаСервере(РезультатВыбора);
КонецПроцедуры
&НаСервере
Процедура ПеренестиДанныеПодбораНаСервере(РезультатВыбора)
Для Каждого СтрокаВыбора Из РезультатВыбора Цикл
НоваяСтрока = Объект.Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаВыбора);
КонецЦикла;
КонецПроцедуры
Важно: для отладки программного добавления строк точку останова необходимо ставить непосредственно внутри процедуры ПодборТоваровЗавершение на клиенте или внутри цикла метода ПеренестиДанныеПодбораНаСервере на сервере.
Если необходимо добавить собственную логику обработки вновь добавленных строк без изменения типовой конфигурации, воспользуемся механизмом расширений:
&После или &Вместо.Посмотрим на пример перехвата заполнения через расширение:
&Вместо("ПеренестиДанныеПодбораНаСервере")
Процедура Расш_ПеренестиДанныеПодбораНаСервере(РезультатВыбора)
// Выполняем базовую логику заполнения
ПродолжитьВызов(РезультатВыбора);
// Логика постобработки добавленных строк
Для Каждого СтрокаВыбора Из РезультатВыбора Цикл
// Обработка и валидация добавленных позиций
КонецЦикла;
КонецПроцедуры
В ситуации, когда процесс заполнения полностью инкапсулирован внутри сложного типового механизма и прямого доступа к конкретным строкам нет, выясним факт появления новых строк с помощью уникальных идентификаторов элементов коллекции ДанныеФормыКоллекция. Метод ПолучитьИдентификатор() возвращает уникальный номер строки в текущем сеансе формы.
Разберем алгоритм выявления новых строк:
&НаКлиенте
Процедура ВыполнитьКонтрольДобавления()
// Запоминаем идентификаторы существующих строк перед операцией
МассивИдентификаторов = Новый Массив;
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
МассивИдентификаторов.Добавить(СтрокаТЧ.ПолучитьИдентификатор());
КонецЦикла;
// ... Вызов операции подбора или заполнения ...
// После возврата управления определяем, какие строки являются новыми
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
Если МассивИдентификаторов.Найти(СтрокаТЧ.ПолучитьИдентификатор()) = Неопределено Тогда
// Найдена программно добавленная строка
ИдентификаторНовойСтроки = СтрокаТЧ.ПолучитьИдентификатор();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Если цель перехвата заключается в проверке корректности заполнения реквизитов (например, контроль цен, остатков или заполненности аналитики), лучшей практикой является перенос контроля на уровень модуля объекта в обработчики ПередЗаписью или ОбработкаПроверкиЗаполнения. Это гарантирует, что данные будут проверены независимо от того, каким образом они попали в документ — интерактивным вводом, через форму подбора или внешней обработкой.