Как сохранить тип документа в реквизите справочника и ограничить выбор на форме в 1С

Программист 1С v8.3 (Управляемые формы) 1С:Комплексная автоматизация IT и автоматизация бизнеса
← На главную

При проектировании учетных и сервисных механизмов разработчики часто сталкиваются с задачей сохранения типа конкретного документа или справочника в реквизите объекта. Рассмотрим, какие ограничения накладывает платформа 1С:Предприятие на работу с типами данных в базе, какими способами можно организовать хранение и как правильно настроить пользовательский интерфейс для ограничения списка доступных типов.

Ограничения платформы при хранении типов данных

Прежде чем переходить к программной реализации, проанализируем внутренние особенности платформы 1С:

  1. Отсутствие типа «Тип» в базе данных: объекты Тип и ОписаниеТипов существуют исключительно в оперативной памяти во время исполнения кода. Создать реквизит справочника или документа с таким типом на уровне метаданных невозможно.
  2. Особенности составного ссылочного типа: если назначить реквизиту составной тип, включающий множество видов документов, на уровне СУБД для каждого типа создается отдельная колонка. Избыточное расширение состава типов приводит к деградации производительности запросов и нерациональному расходу места в таблицах.
  3. Потеря ссылочной целостности при хранении строк: сохранение имени объекта метаданных в виде обычной строки лишает платформу контроля за переименованием или удалением объектов конфигурации. При изменении имени документа в конфигураторе строковые значения в базе останутся старыми.
  4. Ограничения ХранилищаЗначения: помещение сериализованного объекта типа в ХранилищеЗначения блокирует возможность фильтрации, сортировки и поиска по этому полю в запросах и динамических списках.

Способ 1. Использование справочника «ИдентификаторыОбъектовМетаданных» (БСП)

Если разработка ведется в типовой конфигурации (например, 1С:Комплексная автоматизация, 1С:ERP или 1С:Управление торговлей), наиболее правильным архитектурным решением является использование механизмов Библиотеки Стандартных Подсистем. В БСП включен служебный справочник ИдентификаторыОбъектовМетаданных.

Разберем преимущества этого подхода:

  1. Реквизит вашего справочника получает тип СправочникСсылка.ИдентификаторыОбъектовМетаданных. Это простой ссылочный тип, который не раздувает структуру таблиц СУБД.
  2. Подсистема БСП автоматически актуализирует соответствие между объектами конфигуратора и записями справочника при обновлении информационной базы.
  3. По реквизиту можно строить эффективные запросы, отборы и индексы.

Для получения типа документа по ссылке на идентификатор метаданных в коде используем метод БСП:


ИмяОбъекта = ОбщегоНазначения.ИмяОбъектаПоИдентификатору(СсылкаНаИдентификатор);
ТипДокумента = Тип("ДокументСсылка." + ИмяОбъекта);

Способ 2. Хранение пустой ссылки составного типа

Если конфигурация разрабатывается с нуля или БСП не используется, сохранять тип документа можно через значение пустой ссылки соответствующего типа. Для этого у реквизита справочника настраивается составной тип данных, куда включаются только те документы, которые могут быть выбраны.

В этом случае в реквизит записывается не конкретный документ, а результат вызова метода ПустаяСсылка() нужного менеджера, например: Документы.ПоступлениеТоваровУслуг.ПустаяСсылка().

Посмотрим на получение типа в коде:

ТипДокумента = ТипЗнч(ОбъектСправочника.РеквизитТипДокумента);

Способ 3. Хранение имени объекта метаданных строкой

Для служебных задач или простых настроек допустимо использовать строковый реквизит ограниченной длины (например, Строка(100)), куда записывается синоним или точное имя объекта метаданных из конфигуратора.

Рассмотрим, как восстановить рабочий тип данных по сохраненной строке:


// Предположим, в реквизите сохранено имя "РеализацияТоваровУслуг"
ИмяДокумента = ОбъектСправочника.ИмяДокументаСтрокой;
ТипДокумента = Тип("ДокументСсылка." + ИмяДокумента);

// Либо получение объекта метаданных напрямую:
ОбъектМетаданных = Метаданные.Документы.Найти(ИмяДокумента);

Ограничение выбора типов документов на управляемой форме

Выясним, как ограничить интерактивный выбор пользователя несколькими разрешенными типами документов при редактировании реквизита на форме.

Вариант А. Настройка свойства «ОграничениеТипа» для составного реквизита

Если реквизит имеет составной тип данных, платформа позволяет программно сузить список предлагаемых типов для конкретного элемента формы с помощью свойства ОграничениеТипа.

Разберем программную установку ограничения в событии формы ПриСозданииНаСервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    МассивРазрешенныхТипов = Новый Массив;
    МассивРазрешенныхТипов.Добавить(Тип("ДокументСсылка.ПоступлениеТоваровУслуг"));
    МассивРазрешенныхТипов.Добавить(Тип("ДокументСсылка.РеализацияТоваровУслуг"));
    
    // Применяем ограничение к полю ввода на форме
    Элементы.РеквизитТипДокумента.ОграничениеТипа = Новый ОписаниеТипов(МассивРазрешенныхТипов);

КонецПроцедуры

При нажатии на кнопку выбора платформа отобразит стандартное системное окно выбора типа, содержащее только типы из переданного массива.

Вариант Б. Перехват события «НачалоВыбора» и вызов «ПоказатьВыборИзСписка»

Если реквизит хранит строковое имя документа или ссылку на идентификатор метаданных, стандартный диалог выбора типа необходимо отключить и показать пользователю подготовленный список.

Посмотрим на клиентский обработчик события НачалоВыбора:


&НаКлиенте
Процедура РеквизитТипДокументаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

    СтандартнаяОбработка = Ложь;
    
    СписокТипов = Новый СписокЗначений;
    СписокТипов.Добавить("ПоступлениеТоваровУслуг", "Поступление товаров и услуг");
    СписокТипов.Добавить("РеализацияТоваровУслуг", "Реализация товаров и услуг");
    
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораТипаДокумента", ЭтотОбъект);
    ПоказатьВыборИзСписка(Оповещение, СписокТипов, Элемент);

КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораТипаДокумента(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт

    Если ВыбранныйЭлемент <> Неопределено Тогда
        Объект.РеквизитТипДокумента = ВыбранныйЭлемент.Значение;
    КонецЕсли;

КонецПроцедуры

Вариант В. Использование режима выбора из списка (выпадающий список)

Когда перечень разрешенных документов строго зафиксирован и невелик, удобнее всего включить у элемента формы свойство РежимВыбораИзСписка = Истина и заполнить выпадающий список значениями при инициализации формы.

Рассмотрим серверный код заполнения списка выбора с получением синонимов из метаданных:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    ЭлементФормы = Элементы.РеквизитТипДокумента;
    ЭлементФормы.РежимВыбораИзСписка = Истина;
    ЭлементФормы.СписокВыбора.Очистить();
    
    МассивИмен = Новый Массив;
    МассивИмен.Добавить("ПоступлениеТоваровУслуг");
    МассивИмен.Добавить("РеализацияТоваровУслуг");
    
    Для Каждого ИмяДокумента Из МассивИмен Цикл
        МдДокумент = Метаданные.Документы.Найти(ИмяДокумента);
        Если МдДокумент <> Неопределено Тогда
            ЭлементФормы.СписокВыбора.Добавить(МдДокумент.Имя, МдДокумент.Синоним);
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

Такой интерфейсный прием исключает появление лишних модальных окон и позволяет пользователю выбрать необходимый вид документа в один клик.

← На главную