Как получить в табличной части одного справочника реквизиты другого и настроить динамический контроль заполнения?

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

В практике разработки на платформе 1С часто возникает задача создания гибких настроек. Например, когда для разных видов документов требуется разный набор обязательных полей. В этой статье мы подробно разберем, как реализовать механизм, при котором в одном справочнике (назовем его ВидыДокументов) выбираются реквизиты другого справочника (Файлы) и устанавливается признак их обязательности.

Шаг 1: Получение списка реквизитов через метаданные

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

Рассмотрим пример кода, который позволяет обойти коллекцию реквизитов:


Для Каждого Реквизит Из Метаданные.Справочники.Файлы.Реквизиты Цикл
    // Здесь мы получаем имя реквизита
    ИмяРеквизита = Реквизит.Имя;
    // Можно также получить синоним для отображения пользователю
    СинонимРеквизита = Реквизит.Синоним;
    
    // Далее логика добавления в табличную часть
    НоваяСтрока = Объект.РеквизитыДляКонтроля.Добавить();
    НоваяСтрока.ИмяРеквизита = ИмяРеквизита;
    НоваяСтрока.ПредставлениеРеквизита = СинонимРеквизита;
КонецЦикла;

Важный момент: если мы используем только коллекцию Реквизиты, в список не попадут стандартные поля, такие как Наименование, Код или Владелец. Если вам нужно контролировать и их, следует отдельно обработать коллекцию СтандартныеРеквизиты.

Шаг 2: Реализация визуального контроля на форме

Теперь разберем, как сделать так, чтобы при выборе определенного вида документа в справочнике Файлы нужные поля подсвечивались как обязательные. Самый простой способ — управлять свойствами элементов формы.

Выясним причину, по которой это удобно: пользователь сразу видит красный пунктир (отметку незаполненного), что повышает юзабилити. Проанализируем пример кода для процедуры ПриИзменении реквизита ВидДокумента на форме:


&НаКлиенте
Процедура ВидДокументаПриИзменении(Элемент)
    НастроитьПроверкуЗаполненияНаФорме();
КонецПроцедуры

&НаСервере
Процедура НастроитьПроверкуЗаполненияНаФорме()
    // Сначала сбрасываем проверку для всех элементов
    // (желательно иметь список управляемых реквизитов)
    
    Для каждого СтрокаНастройки Из Объект.ВидДокумента.РеквизитыДляКонтроля Цикл
        ИмяПоля = СтрокаНастройки.ИмяРеквизита;
        Если Элементы.Найти(ИмяПоля) <> Неопределено Тогда
            // Устанавливаем проверку заполнения
            Элементы[ИмяПоля].ПроверкаЗаполнения = ?(СтрокаНастройки.КонтрольЗаполнения, 
                                                    ПроверкаЗаполнения.ВыдаватьОшибку, 
                                                    ПроверкаЗаполнения.НеПроверять);
            
            // Включаем визуальную отметку (красный пунктир)
            Элементы[ИмяПоля].АвтоОтметкаНезаполненного = СтрокаНастройки.КонтрольЗаполнения;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Шаг 3: Программная проверка в модуле объекта

Управление элементами формы — это только половина решения. Если объект будет записываться программно (например, через загрузку данных), проверка на форме не сработает. Чтобы обеспечить целостность данных, мы должны использовать обработчик ОбработкаПроверкиЗаполнения в модуле объекта справочника Файлы.

Рассмотрим, как это реализовать структурно:

  1. Система вызывает событие ОбработкаПроверкиЗаполнения перед записью.
  2. Мы получаем ссылку на настройки из реквизита ВидДокумента.
  3. Обходим табличную часть настроек.
  4. Добавляем имена реквизитов, у которых стоит галочка, в массив ПроверяемыеРеквизиты.

Посмотрим на пример реализации в модуле объекта:


Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    
    Если ЗначениеЗаполнено(ВидДокумента) Тогда
        // Получаем настройки из справочника ВидыДокументов
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |   ВидыДокументовРеквизитыДляКонтроля.ИмяРеквизита
            |ИЗ
            |   Справочник.ВидыДокументов.РеквизитыДляКонтроля КАК ВидыДокументовРеквизитыДляКонтроля
            |ГДЕ
            |   ВидыДокументовРеквизитыДляКонтроля.Ссылка = &Ссылка
            |   И ВидыДокументовРеквизитыДляКонтроля.КонтрольЗаполнения = ИСТИНА";
        
        Запрос.УстановитьПараметр("Ссылка", ВидДокумента);
        Выборка = Запрос.Выполнить().Выбрать();
        
        Пока Выборка.Следующий() Цикл
            // Добавляем реквизит в список проверяемых платформой
            Если ПроверяемыеРеквизиты.Найти(Выборка.ИмяРеквизита) = Неопределено Тогда
                ПроверяемыеРеквизиты.Добавить(Выборка.ИмяРеквизита);
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
КонецПроцедуры

Нюансы и рекомендации

Разберем несколько важных моментов, которые помогут сделать решение более профессиональным:

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

2. Работа с типами данных. При заполнении табличной части в справочнике ВидыДокументов, лучше не давать пользователю вводить имена реквизитов вручную. Реализуйте выпадающий список или форму выбора на основе метаданных, чтобы исключить опечатки в именах ИмяРеквизита.

3. Использование БСП. Если ваша конфигурация основана на "1С:Библиотека стандартных подсистем", проанализируйте подсистему ДополнительныеРеквизитыИСведения. В ней уже заложен механизм динамического добавления реквизитов и настройки их обязательности без изменения структуры метаданных в конфигураторе.

4. Обработка стандартных реквизитов. Как мы уже упоминали, Наименование или Дата (для документов) проверяются отдельно. В коде ОбработкаПроверкиЗаполнения платформа может уже содержать их в массиве ПроверяемыеРеквизиты, поэтому всегда проверяйте наличие элемента в массиве перед добавлением через метод Найти().

Таким образом, мы создали гибкую систему, которая позволяет администратору системы без привлечения программиста определять, какие поля обязательны для заполнения в зависимости от контекста (вида документа). Это значительно снижает количество ошибок ввода данных и делает систему более отказоустойчивой.

← На главную