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