В процессе разработки на платформе 1С часто возникает задача создания универсальных механизмов настройки. Например, когда нужно создать справочник, в котором пользователь сам выбирает, какие поля документа будут заполняться автоматически. Для реализации такой функциональности нам необходимо научиться программно считывать структуру метаданных документов, получать список их реквизитов и корректно определять типы данных этих реквизитов.
В этой статье мы подробно разберем, как реализовать подобную задачу, проанализируем работу с объектом Метаданные и выясним, как обрабатывать сложные случаи, такие как составные типы данных и табличные части.
Для начала рассмотрим базовый способ получения всех реквизитов конкретного документа. В 1С вся информация о структуре базы данных хранится в объекте Метаданные. Доступ к реквизитам осуществляется через коллекцию документов. Разберем ситуацию, когда нам нужно программно заполнить таблицу значений именами реквизитов документа.
Предположим, у нас есть переменная ИмяДокумента, содержащая строковое название (например, "РеализацияТоваровУслуг"). Мы можем получить список его реквизитов следующим образом:
// Получаем объект метаданных конкретного документа
ДокументМетаданные = Метаданные.Документы[ИмяДокумента];
// Обходим коллекцию обычных реквизитов
Для Каждого ТекущийРеквизит Из ДокументМетаданные.Реквизиты Цикл
НоваяСтрока = ТаблицаРеквизитов.Добавить();
НоваяСтрока.Имя = ТекущийРеквизит.Имя;
НоваяСтрока.Синоним = ТекущийРеквизит.Синоним;
НоваяСтрока.Тип = ТекущийРеквизит.Тип;
КонецЦикла;
Важный нюанс: коллекция Реквизиты содержит только те поля, которые были созданы разработчиком вручную. Однако у любого документа есть также стандартные реквизиты, такие как Дата, Номер, Проведен, Ссылка. Если ваша логика предполагает работу и с этими полями, их нужно обходить отдельно через коллекцию СтандартныеРеквизиты.
Зачастую задача усложняется необходимостью получить не только "шапку" документа, но и данные из его табличных частей. Структура метаданных в 1С иерархична, поэтому для получения реквизитов табличной части нам потребуется вложенный цикл. Проанализируем пример кода, который выводит в сообщение названия всех табличных частей и их колонок:
Для Каждого ТабличнаяЧасть Из Метаданные.Документы[ИмяДокумента].ТабличныеЧасти Цикл
Сообщить("Табличная часть: " + ТабличнаяЧасть.Имя);
Для Каждого РеквизитТЧ Из ТабличнаяЧасть.Реквизиты Цикл
Сообщить(" - Реквизит ТЧ: " + РеквизитТЧ.Имя + " (Тип: " + РеквизитТЧ.Тип + ")");
КонецЦикла;
КонецЦикла;
Такой подход позволяет полностью "просканировать" состав документа. При заполнении вашей настроечной таблицы в справочнике рекомендуется сохранять именно Имя реквизита (строкой), так как оно является уникальным идентификатором поля в метаданных, в то время как Синоним может измениться или повторяться.
Одной из подзадач, озвученных пользователями, является автоматическое определение типа реквизита для того, чтобы во второй колонке таблицы (значение по умолчанию) можно было выбрать значение именно этого типа. Каждый объект метаданных реквизита имеет свойство Тип, которое имеет тип ОписаниеТипов.
Когда вы выбрали конкретный реквизит документа в первой колонке, вы можете программно ограничить тип значения во второй колонке. Рассмотрим, как это сделать:
ОписаниеТипов.Если мы работаем с обычными формами, код будет выглядеть примерно так:
// Допустим, пользователь выбрал реквизит в колонке "ИмяРеквизита"
МетаданныеДокумента = Метаданные.Документы[ВыбранныйДокумент];
РеквизитМетаданные = МетаданныеДокумента.Реквизиты.Найти(ТекущаяСтрока.ИмяРеквизита);
Если РеквизитМетаданные <> Неопределено Тогда
// Получаем ОписаниеТипов реквизита
НужныйТип = РеквизитМетаданные.Тип;
// Устанавливаем ограничение типа для ячейки "ЗначениеПоУмолчанию"
// В обычных формах это часто делается через приведение значения
ТекущаяСтрока.ЗначениеПоУмолчанию = НужныйТип.ПривестиЗначение(ТекущаяСтрока.ЗначениеПоУмолчанию);
КонецЕсли;
Ситуация становится интереснее, если реквизит документа имеет составной тип (например, поле "Владелец" может быть и "СправочникСсылка.Контрагенты", и "СправочникСсылка.ФизическиеЛица").
Чтобы проверить, является ли тип составным, проанализируем количество типов в объекте ОписаниеТипов:
ТипРеквизита = РеквизитМетаданные.Тип;
МассивТипов = ТипРеквизита.Типы();
Если МассивТипов.Количество() > 1 Тогда
Сообщить("Это составной тип данных!");
КонецЕсли;
Для корректной работы интерфейса при выборе значения по умолчанию для такого реквизита 1С автоматически предложит сначала выбрать тип из списка разрешенных, а затем само значение. Главное — правильно назначить ОписаниеТипов колонке табличной части.
Выясним еще один важный момент: в современных конфигурациях часто используются Общие реквизиты. Они не входят в коллекцию Документы[Имя].Реквизиты. Чтобы их получить, нужно обратиться к Метаданные.ОбщиеРеквизиты и проверить, входит ли ваш документ в состав этого общего реквизита.
Также стоит помнить о производительности. Обращение к метаданным — операция относительно "дорогая". Если в вашем справочнике много строк и вы постоянно вызываете поиск в метаданных при каждом изменении, форма может "подтормаживать".
Рекомендация: при открытии формы настройки один раз соберите дерево или соответствие всех реквизитов выбранного документа в кэш (например, в структуру или таблицу значений в памяти). При редактировании строк обращайтесь к этому кэшу вместо постоянного обращения к глобальному объекту Метаданные.
Подведем итог. Для реализации функционала настройки реквизитов документа нам необходимо:
Метаданные для получения списка полей.Тип (объект ОписаниеТипов) для динамической настройки полей ввода значений по умолчанию.Рассмотренные методы позволяют создавать гибкие и масштабируемые решения, которые избавляют пользователя от необходимости вносить изменения в код при обновлении структуры документов.