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