Как программно получить значение из коллекции пользовательских настроек компоновки данных

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

Работа с Системой компоновки данных (СКД) — это стандарт для современной разработки на платформе 1С. Однако начинающие разработчики часто сталкиваются с трудностями при попытке программно «достать» значение, которое пользователь ввел в форму отчета. Коллекция ПользовательскиеНастройки устроена не так просто, как обычная таблица значений или структура: элементы в ней связаны с основными настройками через уникальные идентификаторы, а типы данных могут динамически меняться (например, от одиночного значения до списка значений).

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

Почему нельзя просто найти элемент по имени?

Давайте проанализируем ситуацию. В КомпоновщикеНастроек есть две основные коллекции: Настройки (статичные настройки схемы) и ПользовательскиеНастройки (то, что видит и меняет пользователь). Проблема заключается в том, что в коллекции ПользовательскиеНастройки.Элементы нет прямого доступа к полю по его имени, например, «Организация». Вместо этого элементы там хранятся под внутренними идентификаторами.

Чтобы найти нужное значение, нам необходимо выполнить двухэтапный поиск: сначала найти элемент в основных настройках по имени поля, получить его ИдентификаторПользовательскойНастройки, и только потом по этому идентификатору найти значение в пользовательской коллекции.

Способ 1: Поиск значения отбора по имени поля

Рассмотрим самый распространенный случай: нам нужно получить значение отбора по полю «Организация». Пройдем по шагам вместе:

  1. Создадим объект ПолеКомпоновкиДанных с нужным именем.
  2. Обойдем циклом коллекцию отборов в основных настройках.
  3. Найдем совпадение и заберем идентификатор.
  4. Обратимся к пользовательским настройкам.

Посмотрим на пример кода, реализующий эту логику:


ОргПроверка = Новый ПолеКомпоновкиДанных("Организация");
ИдентификаторОрганизации = Неопределено;

// Шаг 1: Ищем идентификатор в основных настройках отбора
Для каждого СтрНастроек Из КомпоновщикНастроекКД.Настройки.Отбор.Элементы Цикл
    Если ТипЗнч(СтрНастроек) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
        Если СтрНастроек.ЛевоеЗначение = ОргПроверка Тогда
            ИдентификаторОрганизации = СтрНастроек.ИдентификаторПользовательскойНастройки;
            Прервать;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

// Шаг 2: Получаем значение из пользовательских настроек
Если ИдентификаторОрганизации <> Неопределено Тогда
    ЭлементПользовательскойНастройки = КомпоновщикНастроекКД.ПользовательскиеНастройки.Элементы.Найти(ИдентификаторОрганизации);
    Если ЭлементПользовательскойНастройки <> Неопределено Тогда
        ВыбранноеЗначение = ЭлементПользовательскойНастройки.ПравоеЗначение;
        // Здесь ВыбранноеЗначение может быть как СправочникСсылка, так и СписокЗначений
    КонецЕсли;
КонецЕсли;

Важный нюанс: всегда проверяйте ТипЗнч(СтрНастроек). В коллекции отборов могут находиться не только элементы, но и группы (И, ИЛИ, НЕ). Если поле «Организация» находится внутри группы, простой перебор элементов верхнего уровня его не найдет. В таких случаях требуется рекурсивный обход групп.

Способ 2: Универсальные функции для параметров

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

Рассмотрим функцию для получения параметра из пользовательских настроек:


Функция ПолучитьПараметрКомпоновкиПользовательскихНастроек(ПараметрИмя, Компоновщик, ПроверятьИспользование = Истина) Экспорт
    ПараметрПоле = Новый ПараметрКомпоновкиДанных(ПараметрИмя);
    ПараметрКд = Неопределено;
    НастройкиКомпоновки = Компоновщик.ПользовательскиеНастройки;

    Для каждого ЗнчПараметр Из НастройкиКомпоновки.Элементы Цикл
        // Проверяем, является ли элемент коллекции параметром
        Если ТипЗнч(ЗнчПараметр) = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
            Если ЗнчПараметр.Параметр = ПараметрПоле Тогда
                Если ПроверятьИспользование Тогда
                    Если ЗнчПараметр.Использование Тогда
                        ПараметрКд = ЗнчПараметр;
                    КонецЕсли;
                Иначе
                    ПараметрКд = ЗнчПараметр;
                КонецЕсли;
                Прервать;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;

    Возврат ПараметрКд;
КонецФункции

Проанализируем этот код. Мы используем ЗначениеПараметраНастроекКомпоновкиДанных для фильтрации элементов коллекции ПользовательскиеНастройки.Элементы. Это необходимо, так как в этой коллекции «вперемешку» лежат и отборы, и параметры, и даже настройки оформления.

Способ 3: Использование метода ПолучитьНастройки()

Существует еще более элегантный способ, который часто незаслуженно игнорируется. Метод ПолучитьНастройки() объекта КомпоновщикНастроек выполняет «слияние» основных и пользовательских настроек в один объект. В результате мы получаем готовую структуру, где в отборах уже стоят те значения, которые ввел пользователь.

Выясним, как это работает на практике:


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

Этот метод рекомендуется, если вам нужно просто прочитать значения для использования в коде (например, для передачи в другой запрос), не меняя сами настройки на форме.

Обработка типов данных: Одиночное значение или список?

Как отмечалось в обсуждении, пользователь может выбрать разные виды сравнения: «Равно» или «В списке». В зависимости от этого ПравоеЗначение будет иметь разный тип. Проанализируем, как правильно обработать результат:


Если ТипЗнч(ВыбранноеЗначение) = Тип("СписокЗначений") Тогда
    // Пользователь выбрал несколько организаций
    Если ВыбранноеЗначение.Количество() > 0 Тогда
        // Обработка списка
    КонецЕсли;
ИначеЕсли ЗначениеЗаполнено(ВыбранноеЗначение) Тогда
    // Пользователь выбрал одну конкретную организацию
КонецЕсли;

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

Рекомендации по стабильности кода

Никогда не используйте поиск по индексу, например, Элементы.Получить(11). Как справедливо замечено в материалах форума, индексы меняются мгновенно, стоит пользователю изменить вариант отчета или добавить новое поле в настройки. Поиск по ПолеКомпоновкиДанных или ПараметрКомпоновкиДанных — единственный надежный способ идентификации настроек.

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

  1. Определить, ищем мы Параметр или Элемент отбора.
  2. Связать имя поля из основных настроек с идентификатором в пользовательской коллекции.
  3. Проверить флаг Использование.
  4. Обработать возможные типы значения (ссылка или список).

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

← На главную