При настройке правил обмена в конфигурации «Конвертация данных 2.0» (КД 2) разработчики часто сталкиваются с ситуацией, когда необходимо заполнить табличную часть документа или справочника-приемника фиксированными (статическими) значениями или рассчитать их программно, но при этом у объекта-источника соответствующая табличная часть отсутствует или не заполнена.
Попытка просто прописать жесткое значение (например, Значение = 5) в Правилах конвертации свойств (ПКС) для колонок табличной части ни к чему не приведет, если у самой группы свойств (ПКГС) не указан источник. Конвертатор просто проигнорирует эти правила, поскольку он не знает, сколько строк нужно создать в приемнике. В этой статье мы подробно разберем, почему так происходит, и рассмотрим два надежных способа решения этой проблемы, а также затронем важнейшие аспекты отладки и особенности поиска документов.
Для понимания сути проблемы проанализируем внутренний алгоритм работы КД 2. Когда система обрабатывает Правило конвертации свойств (ПКГС) для табличной части, она ожидает получить коллекцию строк. Если поле «Источник» у табличной части не заполнено, конвертатор считает, что данных для выгрузки нет, и полностью пропускает обработку вложенных ПКС (колонок табличной части). Ему попросту не к чему применить ваше правило Значение = 5, так как не создано ни одной строки-контейнера.
Чтобы заставить КД 2 зайти внутрь табличной части и обработать правила конвертации ее колонок, нам необходимо принудительно инициализировать и передать коллекцию строк для выгрузки. Сделать это можно двумя основными способами.
Этот способ является наиболее простым и лаконичным, если вам требуется заполнить табличную часть фиксированным набором строк или программно сформировать таблицу значений непосредственно в правиле этой табличной части.
Для реализации этого метода выполним следующие шаги:
КоллекцияОбъектов является предопределенной в КД 2 — именно в нее мы должны передать подготовленные данные.Рассмотрим пример кода для инициализации КоллекцияОбъектов:
// Создаем таблицу значений с колонками, соответствующими реквизитам ТЧ приемника
ТаблицаСтрок = Новый ТаблицаЗначений;
ТаблицаСтрок.Колонки.Добавить("Номенклатура");
ТаблицаСтрок.Колонки.Добавить("Количество");
ТаблицаСтрок.Колонки.Добавить("Цена");
ТаблицаСтрок.Колонки.Добавить("Сумма");
// Добавляем новую строку и заполняем ее данными
НоваяСтрока = ТаблицаСтрок.Добавить();
// Для поиска номенклатуры можно передать ссылку, код или структуру поиска
НоваяСтрока.Номенклатура = "000000001";
НоваяСтрока.Количество = 1;
НоваяСтрока.Цена = 5;
НоваяСтрока.Сумма = 5; // Наше числовое значение
// Передаем подготовленную таблицу в предопределенную переменную КД 2
КоллекцияОбъектов = ТаблицаСтрок;
При таком подходе КД 2 увидит, что КоллекцияОбъектов заполнена, обойдет каждую ее строку и применит к ней правила конвертации свойств, настроенные внутри ПКГС табличной части.
Если данные для табличной части зависят от реквизитов шапки источника или должны собираться сложным запросом на уровне конвертации всего документа, правильнее использовать механизм «Входящие данные».
Разберем этот алгоритм по шагам:
ИсходящиеДанные.
// Формируем таблицу на уровне документа-источника
ТЗ_Товары = Новый ТаблицаЗначений;
ТЗ_Товары.Колонки.Добавить("Номенклатура");
ТЗ_Товары.Колонки.Добавить("Количество");
ТЗ_Товары.Колонки.Добавить("Сумма");
// Заполняем данными (например, из запроса или программно)
СтрокаТЗ = ТЗ_Товары.Добавить();
СтрокаТЗ.Номенклатура = Источник.ОсновнаяНоменклатура; // пример заполнения из шапки
СтрокаТЗ.Количество = 10;
СтрокаТЗ.Сумма = 50;
// Передаем таблицу в структуру ИсходящиеДанные под уникальным ключом
Если ТипЗнч(ИсходящиеДанные) <> Тип("Структура") Тогда
ИсходящиеДанные = Новый Структура;
КонецЕсли;
ИсходящиеДанные.Вставить("ТаблицаТовары", ТЗ_Товары);
// Получаем переданную таблицу из структуры ВходящиеДанные
Если ТипЗнч(ВходящиеДанные) = Тип("Структура") Тогда
КоллекцияОбъектов = ВходящиеДанные.ТаблицаТовары;
КонецЕсли;
Этот способ более гибкий и позволяет разделять логику формирования данных и логику их непосредственного сопоставления.
Вы успешно настроили заполнение табличной части, данные выгружаются, но при просмотре загруженного документа в приемнике числовые реквизиты (особенно Сумма) оказываются незаполненными или равными нулю. Выясним основные причины этой проблемы:
1. Автоматический пересчет строк в конфигурации-приемнике. Во многих типовых и кастомных конфигурациях 1С на уровне модулей документов жестко прописаны алгоритмы пересчета строк. Например, при записи документа или при изменении реквизитов строки срабатывает обработчик, вычисляющий: Сумма = Количество * Цена. Если при загрузке вы передали только Сумма = 5, а Количество и Цена остались пустыми (или равными 0), алгоритм пересчета отработает при записи документа в приемнике и перезапишет вашу сумму на результат вычисления: 0 * 0 = 0.
Решение: Всегда выгружайте полный набор взаимосвязанных реквизитов (Количество, Цена, Сумма), даже если их приходится заполнять фиктивными или статическими значениями.
2. Обход режима загрузки. По умолчанию при загрузке данных через КД 2 свойство объекта ОбменДанными.Загрузка устанавливается в значение Истина. Это должно отключать принудительные проверки и пересчеты в модулях объектов. Однако, если программисты при доработке базы-приемника не добавили в начало процедур ПередЗаписью или ПриЗаписи проверку вида:
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
то все алгоритмы пересчета сработают и исказят загружаемые данные. Обязательно проверьте наличие этой строчки в модуле загружаемого документа в приемнике.
Разработчики часто пытаются поставить точку останова в конфигураторе приемника в стандартном обработчике ПриЗагрузке, но сталкиваются с тем, что контекст переменных внутри выполнения не виден или вычисляется некорректно. Это происходит потому, что КД 2 выполняет код обработчиков динамически с помощью конструкции Выполнить().
Проанализируем правильную и удобную методику интерактивной отладки обработчиков загрузки:
v8_ExchangeDebug.epf). Сохраните его.Объект, Параметры, ОбъектМодифицирован и другие.В процессе обмена часто возникает сопутствующая проблема: документ в базе-приемнике уже существует, но его время было изменено вручную пользователями (например, в источнике документ проведен в 12:00:00, а в приемнике — в 12:05:15). Стандартный поиск КД 2 по полям Номер и Дата не сопоставит эти объекты, так как сравнение дат по умолчанию идет с точностью до секунды. В результате в приемнике создастся дублирующий документ.
Чтобы решить эту задачу, настроим гибкий поиск по дате в пределах суток с помощью обработчика «Поля поиска» в ПКО документа:
Номер и Дата установите флаг «Использовать при поиске».
// Проверяем, что первый вариант поиска (по УИД) не дал результатов
Если НомерВариантаПоиска = 1 Тогда
// Получаем переданные для поиска дату и номер из свойств
ДатаИсточника = СвойстваПоиска["Дата"];
НомерИсточника = СвойстваПоиска["Номер"];
Если ЗначениеЗаполнено(ДатаИсточника) И ЗначениеЗаполнено(НомерИсточника) Тогда
// Строим запрос для поиска документа по номеру в пределах суток
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг // Замените на имя вашего документа
|ГДЕ
| Номер = &Номер
| И Дата МЕЖДУ &НачалоПериода И &КонецПериода";
Запрос.УстановитьПараметр("Номер", НомерИсточника);
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаИсточника));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаИсточника));
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
// Передаем найденную ссылку системе КД 2
СсылкаНаОбъект = Выборка.Ссылка;
// Прекращаем дальнейший стандартный поиск, чтобы не затереть результат
ПрекратитьПоиск = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Используя этот подход, вы гарантируете корректное сопоставление документов даже при изменении времени их проведения внутри операционных суток, что значительно повысит стабильность работы ваших интеграционных механизмов.