В процессе разработки и интеграции систем на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда новый функционал выносится в расширение конфигурации для сохранения типовой конфигурации на поддержке. Однако при работе со специфическими объектами метаданных, такими как Планы обмена, в старых режимах совместимости (например, 8.3.11 или 8.3.12) могут возникать непредвиденные платформенные ограничения.
В этой статье мы подробно разберем одну из таких проблем: когда созданный в расширении план обмена отлично виден через меню «Все функции» (Функции для технического специалиста), но при этом его невозможно выбрать в поле ввода с типом ПланОбменаСсылка на форме. Мы выясним технические причины этого поведения платформы и рассмотрим практические методы решения.
Проанализируем ситуацию, разберемся в архитектурных причинах и пошагово внедрим надежные способы обхода этого ограничения.
Давайте разберем внутреннюю кухню работы платформы 1С:Предприятие с типами данных в расширениях. Основная сложность кроется в ограничении работы с составными типами данных в режимах совместимости до версии 8.3.18:
ПланОбменаСсылка (или составным типом, включающим ссылки на планы обмена), платформа генерирует список доступных типов и объектов на основе метаданных основной конфигурации. В режиме совместимости 8.3.11 динамическое расширение состава типов для стандартных элементов управления не поддерживается.Посмотрим, какими путями можно решить эту задачу, если поднять режим совместимости конфигурации (выше 8.3.11) в данный момент невозможно.
---
Этот способ является наиболее надежным и гарантирует стабильную работу интерфейса, системы компоновки данных (СКД), механизмов БСП и платформенных полей ввода. Мы минимально снимем основную конфигурацию с поддержки, создав в ней пустой объект-контейнер, а всю логику перенесем в расширение.
Разберем этот процесс по шагам:
План обмена в основной конфигурации. Назовите его, например, УдаленныйОбменДанными. Не добавляйте в него реквизиты, табличные части и не настраивайте состав. Этот объект будет служить исключительно «якорем» для типа данных в системе.Результат: Поскольку тип данных ПланОбменаСсылка.УдаленныйОбменДанными теперь физически объявлен в основной конфигурации, платформа без проблем отображает его во всех полях ввода, включает в составные типы и корректно обрабатывает при интерактивном выборе в режиме 1С:Предприятие.
---
Если вам категорически запрещено вносить любые изменения в основную конфигурацию (она должна оставаться на замке / на полной поддержке), мы можем решить проблему исключительно средствами расширения, переопределив логику работы поля ввода на форме.
Для этого мы заменим стандартный интерактивный выбор платформы на программное заполнение списка выбора элемента формы.
Рассмотрим пример реализации. Предположим, у нас есть форма (заимствованная или созданная в расширении), на которой расположено поле ввода ПолеВводаПланаОбмена. Мы настроим его так, чтобы при открытии формы оно заполнялось ссылками на узлы нашего расширенного плана обмена.
Разберем код, который необходимо разместить в модуле формы расширения:
&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Очищаем стандартный список выбора поля, если он был заполнен
Элементы.ПолеВводаПланаОбмена.СписокВыбора.Очистить();
// Устанавливаем режим выбора из списка для элемента формы
Элементы.ПолеВводаПланаОбмена.РежимВыбораИзСписка = Истина;
// Динамически выбираем узлы нашего плана обмена, созданного в расширении
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| НашПланОбменаИзРасширения.Ссылка КАК Ссылка,
| НашПланОбменаИзРасширения.Наименование КАК Наименование
|ИЗ
| ПланОбмена.НашПланОбменаИзРасширения КАК НашПланОбменаИзРасширения
|ГДЕ
| НЕ НашПланОбменаИзРасширения.ПометкаУдаления";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// Добавляем полученные ссылки в список выбора элемента формы
Элементы.ПолеВводаПланаОбмена.СписокВыбора.Добавить(
ВыборкаДетальныеЗаписи.Ссылка,
ВыборкаДетальныеЗаписи.Наименование
);
КонецЦикла;
КонецПроцедуры
При использовании этого метода важно учитывать, что тип реквизита формы, к которому привязано поле ввода, должен быть либо достаточно универсальным (например, Произвольный), либо на форме должно использоваться несвязанное поле ввода, значение которого при записи объекта мы будем программно транслировать в нужный реквизит.
---
Если задача интеграции носит служебный характер (например, разовая миграция данных, отладка или административное обслуживание), можно последовать примеру автора обсуждения на форуме:
Вместо размещения поля ввода типа ПланОбменаСсылка на стандартных формах документов или справочников, создается внешняя обработка. Внутри программного кода обработки вы можете свободно оперировать типом данных плана обмена из расширения, получать его узлы запросом или обращаться к менеджеру напрямую:
// Пример прямого программного обращения к плану обмена из расширения
УзелОбмена = ПланыОбмена["НашПланОбменаИзРасширения"].ЭтотУзел();
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, ВыгружаемыйОбъект);
Этот подход полностью снимает проблему интерфейсного выбора, перенося всю работу в плоскость чистого программного кода платформы.
---
Если вы приняли решение использовать собственные планы обмена в расширениях на старых версиях платформы (до 8.3.15 включительно), обязательно помните о следующих критических нюансах:
8.3.11 - 8.3.15 при попытке зарегистрировать изменения или прочитать таблицы регистрации изменений для объектов из расширений часто возникали критические ошибки ядра СУБД (например, «SDBL: Ожидается имя таблицы»). Платформа не всегда корректно генерирует SQL-структуру для таблиц изменений расширений.Резюме: Если перед вами стоит задача долгосрочной и стабильной поддержки обмена данными, лучшим архитектурным решением будет применение Способа №1 (создание пустого плана обмена в основной конфигурации с последующим заимствованием и наполнением в расширении). Это сэкономит время при сопровождении системы и убережет от платформенных багов отображения типов.