Как найти реквизиты объекта по типу значения в 1С с помощью БСП

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

При разработке универсальных обработок, особенно для конфигураций со сложной структурой данных (таких как Управление торговлей 10.3 или ERP), мы часто сталкиваемся с необходимостью найти все поля, содержащие определенный тип данных. Например, при построении отчета или фильтрации данных по конкретной организации, нам нужно знать, в каких измерениях или реквизитах регистров хранится ссылка на СправочникСсылка.Организации (в сложных случаях поможет Analyzer 1C — инструмент для анализа зависимостей).

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

Использование стандартной функции БСП ИменаРеквизитовПоТипу

В составе БСП существует готовый инструмент для решения нашей задачи. Чаще всего эта функция расположена в общем модуле ОбщегоНазначения. Однако важно учитывать, что реализация этой функции может отличаться в зависимости от версии БСП, установленной в вашей конфигурации.

Рассмотрим классический вариант реализации, который встречается в большинстве современных систем на базе 1С:Предприятие 8.3:


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

Проанализируем этот код. Функция принимает объект метаданных (визуализировать дерево которых поможет информер по метаданным) и искомый тип. Метод СодержитТип() позволяет корректно обрабатывать даже составные типы данных, что критически важно для универсальных механизмов.

Проблема совместимости версий: Строка против Массива

При работе с разными конфигурациями (например, при переносе кода из УТ 10.3 в ERP) мы можем столкнуться с тем, что одна и та же функция возвращает разные типы данных. В старых версиях БСП функция могла возвращать строку с именами реквизитов, разделенными запятыми, а в новых — массив строк.

Чтобы наш код был по-настоящему универсальным, проанализируем ситуацию и внедрим проверку возвращаемого значения:


РезультатФункции = ОбщегоНазначения.ИменаРеквизитовПоТипу(МетаданныеОбъекта, ТипЗнч(НужнаяОрганизация));

Если ТипЗнч(РезультатФункции) = Тип("Массив") Тогда
    МассивИмен = РезультатФункции;
ИначеЕсли ТипЗнч(РезультатФункции) = Тип("Строка") Тогда
    МассивИмен = СтрРазделить(РезультатФункции, ", ", Ложь);
КонецЕсли;

Для Каждого ИмяПоля Из МассивИмен Цикл
    // Обработка найденного поля
КонецЦикла;

Такой подход гарантирует, что ваша обработка не "упадет" после обновления конфигурации или при использовании в другой среде.

Расширение поиска: работа с регистрами и измерениями

Важно помнить, что стандартная функция БСП часто ограничивается только коллекцией Реквизиты. Однако в регистрах накопления, сведений и бухгалтерии ключевая информация (такая как Организация или Склад) почти всегда хранится в Измерениях.

Разберем, как модифицировать алгоритм, чтобы он охватывал все возможные места хранения данных. Мы должны перебрать не только реквизиты, но и измерения, а также общие реквизиты, если они используются в системе.


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

Вопросы производительности: оптимизация и кэширование

При обработке больших массивов данных или анализе всей структуры метаданных (например, при поиске по всем регистрам базы), циклы по метаданным могут стать "узким местом". Рассмотрим основные советы по оптимизации:

  1. Избегайте избыточного создания объектов: Операция Новый Массив внутри глубоко вложенных циклов может замедлять работу. Однако, как показывает практика современной платформы 8.3, конкатенация строк (Стр = Стр + Имя) работает еще медленнее на больших объемах из-за постоянного перераспределения памяти. Использование массива с финальным СтрСоединить() — наиболее сбалансированный вариант.
  2. Кэширование метаданных: Если ваша обработка должна многократно обращаться к одним и тем же таблицам, создайте структуру или Соответствие в оперативной памяти (или в кэшируемом модуле), где ключом будет имя таблицы, а значением — список найденных полей.
  3. Замер производительности: Всегда используйте встроенный в конфигуратор замер производительности. Иногда "три строчки кода" могут выполняться дольше, чем вызов сложной, но оптимизированной функции БСП, которая уже учитывает кэширование на уровне платформы.

Особенности работы в условиях расширений конфигурации

Проанализируем ситуацию, когда в системе используются расширения. Если реквизит "Организация" был добавлен в документ через расширение, обычный перебор метаданных основной конфигурации может его не увидеть. При написании кода следует учитывать контекст выполнения. Если вы используете Метаданные.НайтиПоПолномуИмени(), платформа вернет актуальную структуру с учетом активных расширений.

Посмотрим на пример правильного получения метаданных для анализа:


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

Резюме

Для решения задачи поиска по типу в 1С лучше всего использовать комбинацию стандартных методов БСП и собственных проверок. Помните:

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

← На главную