При активной разработке в среде 1С:Предприятие 8.3 (особенно на актуальных версиях платформы 8.3.24 и 8.3.25) программисты часто сталкиваются с коллизиями метаданных при попытке заимствования объектов в расширение. Одной из наиболее специфических проблем является конфликт свойств предопределенных элементов справочников, когда в основной конфигурации справочник имеет нулевую длину кода, но сам элемент содержит некое значение в поле Код. Это приводит к тому, что при применении расширения система выдает ошибку о различии свойств элемента в расширении и основной конфигурации.
В данной статье мы подробно разберем, почему возникает эта ситуация, проанализируем причины поведения платформы и рассмотрим несколько методов решения проблемы: от «быстрых исправлений» до архитектурно правильных подходов.
Давайте выясним, почему возникает этот парадокс: длина кода в свойствах справочника установлена в значение 0, но у предопределенного элемента код физически существует (например, «000000001»). Чаще всего это происходит в типовых конфигурациях, таких как УНФ 3.0, при переходе с одной модели хранения данных на другую. Разработчики могли изменить тип справочника на бескодовый, но для обеспечения обратной совместимости или из-за особенностей реструктуризации базы данных у старых предопределенных элементов коды сохранились в таблицах SQL.
Когда мы заимствуем такой справочник и его предопределенные данные в расширение, платформа пытается выполнить синхронизацию. Поскольку в расширении для справочника с нулевой длиной кода поле Код недоступно для редактирования и по умолчанию пусто, возникает конфликт: в конфигурации код есть, а в расширении его нет. Платформа блокирует обновление, указывая на несоответствие метаданных.
Рассмотрим алгоритм действий, который позволяет «обмануть» проверку платформы и заполнить скрытый код в расширении. Этот метод предложил автор темы, и он является рабочим инструментом, если вам критически важно иметь предопределенный элемент именно в метаданных расширения.
000000001).Важный момент: Несмотря на то что после возврата длины кода в 0 поле снова станет невидимым, записанное значение сохранится во внутренней структуре расширения, и проверка на идентичность свойств будет пройдена успешно.
Проанализируем ситуацию: зачем нам вообще понадобилось добавлять предопределенный элемент в расширение? Чаще всего это нужно для изменения динамического списка в форме или написания запроса в конструкторе. Однако заимствование объектов в расширение всегда несет риски при будущих обновлениях основной конфигурации.
Мы можем обойтись без добавления предопределенного элемента в метаданные расширения, если будем редактировать текст запроса вручную (без использования визуального конструктора). В 1С существует возможность обращаться к предопределенным данным через литерал ЗНАЧЕНИЕ().
Рассмотрим пример кода запроса, который будет работать в расширении без заимствования конкретного элемента:
ВЫБРАТЬ
СправочникНоменклатура.Ссылка КАК Ссылка,
СправочникНоменклатура.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК СправочникНоменклатура
ГДЕ
СправочникНоменклатура.ТипНоменклатуры = ЗНАЧЕНИЕ(Справочник.ТипыНоменклатуры.Товар)
Если вы вставите такой текст непосредственно в поле «Текст запроса» динамического списка или в программный код, платформа отработает корректно. Главное — не открывать конструктор запроса после этого, так как он может потребовать заимствования объекта Справочник.ТипыНоменклатуры.Товар в расширение.
Наиболее безопасным и «чистым» с точки зрения архитектуры решением является программная работа с данными. Вместо того чтобы менять запрос в метаданных расширения (что часто ведет к конфликтам при обновлении), мы можем установить нужный фильтр при создании формы.
Рассмотрим, как это реализовать в процедуре ПриСозданииНаСервере. В этом случае нам вообще не нужно заимствовать предопределенные элементы в расширение, так как программный код имеет доступ ко всем данным основной конфигурации.
&НаСервере
Процедура ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Устанавливаем отбор по предопределенному элементу программно
// Нам не нужно добавлять этот элемент в расширение!
НовыйОтбор = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ТипНоменклатуры");
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
НовыйОтбор.ПравоеЗначение = Справочники.ТипыНоменклатуры.Товар; // Обращение напрямую
НовыйОтбор.Использование = Истина;
НовыйОтбор.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
КонецПроцедуры
Преимущества данного метода: мы минимизируем количество заимствованных объектов в расширении, что существенно упрощает дальнейшую поддержку и обновление информационной системы.
Если визуальные средства конфигуратора не позволяют добиться результата, мы можем прибегнуть к редактированию файлов выгрузки. Этот метод позволяет обойти ограничения интерфейса 1С.
Code) для конкретного элемента.Этот путь позволяет жестко прописать нужные свойства, которые конфигуратор скрывает при установленной нулевой длине кода.
Подводя итоги, можно сказать, что проблема «невидимых» кодов в бескодовых справочниках — это известная особенность платформы. Рассмотрим основные выводы:
ЗНАЧЕНИЕ() в тексте запроса.Мы рекомендуем всегда начинать с программных способов решения (Способ 3), так как это гарантирует отсутствие проблем при обновлении типовой конфигурации. Использование расширений должно быть максимально «легким», чтобы не превращать поддержку системы в бесконечную борьбу с конфликтами метаданных.