При разработке универсальных механизмов, отчетов (особенно если применяется универсальная функция ПолучитьРезультатСКД) или обработок выгрузки данных программисты часто сталкиваются с ситуацией, когда обращение к коллекции Реквизиты объекта метаданных возвращает далеко не полный список полей. Например, там отсутствуют такие важные поля, как Номер, Дата, Ссылка или Проведен. Разберем подробно, опираясь на основы работы с объектами метаданных, почему так происходит, и какими способами можно получить действительно исчерпывающий перечень всех доступных реквизитов объекта.
В платформе 1С:Предприятие 8 все данные объекта разделены на несколько логических коллекций. Чтобы реализовать универсальное получение имен и синонимов всех полей объекта, необходимо проанализировать структуру объекта метаданных (например, документа):
Ссылка, Дата, Номер, ПометкаУдаления, Проведен.Рассмотрим ситуацию: если вы используете код Метаданные.Документы.РеализацияТоваровУслуг.Реквизиты, вы обращаетесь только к первой коллекции. Именно поэтому "стандартные" и "общие" поля в список не попадают.
Самый очевидный способ получить все поля — это последовательно перебрать все коллекции. Рассмотрим пример кода, который собирает имена всех доступных реквизитов документа в один массив. Такой подход часто применяется, когда требуется интерактивное формирование текста запроса на основе метаданных и анализ состава общих реквизитов (например, в универсальном переносе данных между конфигурациями 1С):
// Выбираем конкретный объект метаданных
ОбъектМетаданных = Метаданные.Документы.РеализацияТоваровУслуг;
СписокПолей = Новый Массив;
// 1. Добавляем стандартные реквизиты (Ссылка, Номер, Дата и др.)
Для Каждого Реквизит Из ОбъектМетаданных.СтандартныеРеквизиты Цикл
СписокПолей.Добавить(Реквизит.Имя);
КонецЦикла;
// 2. Добавляем обычные реквизиты
Для Каждого Реквизит Из ОбъектМетаданных.Реквизиты Цикл
СписокПолей.Добавить(Реквизит.Имя);
КонецЦикла;
// 3. Добавляем общие реквизиты, которые используются в данном документе
Для Каждого ОбщийРеквизит Из Метаданных.ОбщиеРеквизиты Цикл
ЭлементСостава = ОбщийРеквизит.Состав.Найти(ОбъектМетаданных);
Если ЭлементСостава <> Неопределено Тогда
Если ЭлементСостава.Использование = Метаданные.ВариантИспользованияОбщегоРеквизита.Использовать Тогда
СписокПолей.Добавить(ОбщийРеквизит.Имя);
КонецЕсли;
КонецЕсли;
КонецЦикла;
Этот метод хорош тем, что мы работаем напрямую с объектами метаданных и можем получить не только имена, но и синонимы, типы данных и подсказки. Это база для ситуаций, когда в дальнейшем может потребоваться получение значения реквизита по ссылке или глубокий анализ свойств.
Существует более изящный и быстрый способ, который часто применяют опытные разработчики (например, использующие консоль запросов для отладки) — для решения подобных задач есть набор инструментов разработчика 1С с консолью запросов. Мы можем заставить платформу саму собрать все доступные поля, обратившись к таблице базы данных через запрос. Проведем быстрый анализ данных с использованием пустых запросов для получения структуры таблиц и проанализируем этот прием:
// Используем запрос к таблице документа, но ограничиваем выборку 0 записей
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 0 * ИЗ Документ.РеализацияТоваровУслуг КАК Реализация";
// Выгружаем результат в пустую таблицу значений
ТаблицаПолей = Запрос.Выполнить().Выгрузить();
// Теперь в ТаблицаПолей.Колонки содержатся абсолютно все доступные поля
Для Каждого Колонка Из ТаблицаПолей.Колонки Цикл
Сообщить("Найдено поле: " + Колонка.Имя + " (Тип: " + Колонка.ТипЗначения + ")");
КонецЦикла;
Преимущества данного метода:
ОбщиеРеквизиты и проверять их состав.Важное замечание: При использовании символа * (звездочка) в запросе, платформа также может вернуть колонки, соответствующие табличным частям. Чтобы отличить их от обычных реквизитов, проверьте тип колонки: у табличных частей это будет РезультатЗапроса.
Чтобы избежать возможных неоднозначностей, когда имена таблиц могут пересекаться с именами полей, рекомендуется использовать псевдонимы. Рассмотрим улучшенную версию запроса:
ТекстЗапроса = "ВЫБРАТЬ ПЕРВЫЕ 0 Т.* ИЗ Документ.РеализацияТоваровУслуг КАК Т";
Запрос = Новый Запрос(ТекстЗапроса);
РеквизитыОбъекта = Запрос.Выполнить().Выгрузить().Колонки;
Использование конструкции Т.* гарантирует, что мы выбираем все поля именно из этой таблицы, что делает код более надежным в сложных конфигурациях.
Выясним причину, по которой свойства стандартных реквизитов (например, длина номера или дата) часто кажутся недоступными в конфигураторе. Стандартные реквизиты жестко определены логикой платформы. Однако, изучив нюансы использования стандартных реквизитов, можно увидеть, что современная платформа 8.3 позволяет изменять некоторые их параметры:
Код и Наименование.Проанализируем ситуации, когда даже запрос может вернуть "лишнее" или вести себя неожиданно:
Метаданные.Реквизиты может их не увидеть. В этом случае учитывайте особенности работы с метаданными (здесь полезен анализ конфигураций и расширений), где метод запроса к таблице является наиболее надежным.Период, Регистратор, НомерСтроки, которые также являются стандартными.Таким образом, если ваша цель — просто получить список имен полей для интерфейса или выгрузки, используйте запрос к пустой таблице. Если же вам нужно анализировать метаданные (например, искать реквизиты определенного типа или проверять настройки индексирования), используйте прямой перебор коллекций СтандартныеРеквизиты и Реквизиты.