При настройке правил обмена в конфигурации «Конвертация данных 2.0» (КД 2) разработчики часто сталкиваются с необходимостью модифицировать реквизиты объектов при выгрузке — например, добавить префикс узла или организации к коду справочника или номеру документа. Однако попытка изменить значение напрямую через свойства выгружаемого объекта приводит к ошибке выполнения. Разберем по шагам, почему возникает эта ошибка, как правильно передавать новое значение и как корректно управлять длиной номера с учетом лидирующих нулей.
Рассмотрим типичную ошибку начинающих разработчиков. В обработчиках событий уровня объекта (например, ПередВыгрузкойОбъекта или ПередВыгрузкойОбъектаВыборки в ПВД/ПКО) часто пытаются написать код следующего вида:
// Ошибочный вариант
Объект.Код = "ПР" + Объект.Код;
При выполнении обмена обработка «Универсальный обмен данными в формате XML» аварийно прерывает выгрузку со следующим сообщением:
Ошибка в обработчике события ПередВыгрузкойОбъекта
ПВД = Контрагенты
ОписаниеОшибки = Поле объекта недоступно для записи (Код)
Выясним причину такого поведения платформы. В обработчиках выгрузки переменные Объект или Источник содержат ссылку на элемент (типы СправочникСсылка, ДокументСсылка) либо выборку из базы данных. Ссылочные типы в платформе 1С доступны исключительно для чтения. Прямое присвоение значения полям ссылки невозможно.
Важное предостережение: никогда не пытайтесь обойти эту ошибку через вызов метода Объект.ПолучитьОбъект() с последующей записью. Это грубейшая ошибка проектирования обмена, так как вы физически измените данные непосредственно в рабочей базе-источнике.
Проанализируем архитектуру правил конвертации. Чтобы изменить выгружаемое значение без модификации источника данных, платформе нужно передать результат вычисления в специальную переменную. Для этого правила конвертации свойств (ПККС) предоставляют предопределенный обработчик «Перед выгрузкой».
Разберем по шагам правильный алгоритм настройки:
Код (или Номер для документов).Значение.
Значение = "ПР" + Источник.Код;
В этом контексте платформа возьмет значение поля из исходной ссылки Источник.Код, добавит строку префикса и поместит итоговый результат в переменную Значение, которая и уйдет в исходящий XML-файл.
После добавления строкового префикса часто возникает сопутствующая проблема: длина реквизита Код ограничена метаданными приемника (например, ровно 9 символов). Если исходный код имел вид 000000154, то при простом сложении строк "ПР" + "000000154" мы получим 11 символов: ПР000000154.
При записи в приемнике платформа 1С автоматически обрежет строку справа под максимальную длину поля (9 символов). В итоге значащие цифры потеряются, и номер превратится в некорректный ПР0000001. Требуется сохранить значащие цифры, убрав лишние нули, чтобы получить, например, ПР0000154.
Рассмотрим простейший вариант решения, предложенный в обсуждении:
Значение = "ПР" + Сред(Источник.Код, 3);
Функция Сред(Источник.Код, 3) отсекает ровно 2 первых символа исходного кода, освобождая место под двухсимвольный префикс "ПР".
Опасность жесткого усечения: обратите внимание, что жесткое смещение с помощью Сред(..., 3) корректно сработает только в идеальной ситуации — когда все коды в базе строго заполнены лидирующими нулями до максимальной длины. Если в справочнике встретится элемент с коротким кодом, отрезание первых двух символов приведет к безвозвратной потере значащих данных.
Посмотрим на более надежный и профессиональный алгоритм. Чтобы гарантированно избежать ошибок усечения, значащую часть номера очищают от незначащих нулей, а затем дополняют нужным количеством нулей слева, исходя из длины реквизита в приемнике.
Разберем пример реализации для обработчика ПККС «Перед выгрузкой»:
Префикс = "ПР";
ДлинаПоляПриемника = 9; // Длина кода в конфигурации-приемнике
// Получаем исходный код без пробелов
ИсходныйКод = СокрЛП(Источник.Код);
// Вычисляем доступную длину под цифровую часть
ДлинаНомера = ДлинаПоляПриемника - СтрДлина(Префикс);
Если ДлинаНомера > 0 Тогда
// Удаляем лидирующие нули из исходного кода
Позиция = 1;
Пока Позиция <= СтрДлина(ИсходныйКод) И Сред(ИсходныйКод, Позиция, 1) = "0" Цикл
Позиция = Позиция + 1;
КонецЦикла;
ЗначащаяЧасть = Сред(ИсходныйКод, Позиция);
// Дополняем значащую часть нулями слева до нужной длины
ФорматированныйНомер = Прав("000000000000" + ЗначащаяЧасть, ДлинаНомера);
Значение = Префикс + ФорматированныйНомер;
Иначе
Значение = Префикс + ИсходныйКод;
КонецЕсли;
Проанализируем архитектурные риски, о которых важно помнить перед внедрением модификации кодов:
Код, изменение кода при выгрузке приведет к тому, что существующий в базе-приемнике объект не будет найден. В результате при каждом обмене создадутся дубли. Если вы модифицируете код, настройте поиск по уникальному идентификатору (GUID) или другим полям (например, по реквизитам ИНН и КПП).Не СсылкаНайденная. Если объект действительно новый, префикс присваивается только ему, что гарантирует сохранение кодов у ранее синхронизированных элементов.