Как программно получить данные из ХранилищаНастроекКомпоновкиДанных и вывести их в таблицу?

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

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

Шаг 1. Получение схемы и настроек

Прежде всего, нам необходимо получить саму схему (макет СКД) и объект настроек, который сохранен в хранилище. Рассмотрим ситуацию на примере типовой конфигурации (ERP или УТ), где используется схема ОтборСтрокНоменклатура.

Для начала извлечем настройки и макет. Проанализируем код:


// Получаем настройки из реквизита объекта
Настройки = Объект.ХранилищеНастроекКомпоновкиДанных.Получить();

// Получаем саму схему компоновки данных (макет)
СхемаСКД = Справочники.СкидкиНаценки.ПолучитьМакет("ОтборСтрокНоменклатура");

Здесь важно понимать, что Настройки — это объект типа НастройкиКомпоновкиДанных. Если в хранилище пусто, метод Получить() вернет Неопределено, поэтому в реальном коде стоит добавить проверку или инициализировать настройки по умолчанию из схемы.

Шаг 2. Программная инициализация процесса компоновки

Чтобы превратить схему и настройки в результат (таблицу значений), нам нужно пройти через цепочку стандартных объектов 1С: КомпоновщикМакета, ПроцессорКомпоновки и ПроцессорВывода. Разберем этот процесс по шагам:

  1. Компоновщик макета: Объединяет схему и пользовательские настройки в готовый "исполняемый" макет.
  2. Процессор компоновки: Выполняет запрос к базе данных.
  3. Процессор вывода: Направляет полученные данные в нужную нам коллекцию (в данном случае — в ТаблицаЗначений).

Рассмотрим пример кода для вывода данных:


ДеревоРезультата = Новый ТаблицаЗначений;

// 1. Создаем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

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

// 2. Инициализируем процессор компоновки
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных);

// 3. Выводим результат в таблицу значений
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ДеревоРезультата);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);

Шаг 3. Решение проблемы «пустых колонок» и выбранных полей

Часто программисты сталкиваются с тем, что после выполнения кода выше в таблице значений оказывается всего одна колонка (например, только КлючСвязи), а нужные данные (номенклатура, цена и т.д.) отсутствуют. Выясним причину такого поведения.

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

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


// Проверим, выбрано ли поле "Номенклатура", и если нет — добавим его
ИмяПоля = "Номенклатура";
ПолеУжеЕсть = Ложь;

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

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

Шаг 4. Оптимизация и «Роль: Обязательное»

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

Если вы разрабатываете собственную схему, то в конфигураторе на закладке «Наборы данных» для критически важных полей (которые всегда должны быть в выборке) можно установить флаг в колонке «Обязательное». Это гарантирует, что поле попадет в итоговый SQL-запрос, независимо от настроек пользователя.

Если же вы работаете с типовой схемой и не хотите её менять, рассмотрите возможность использования фиксированных настроек. Это настройки, которые накладываются «сверху» и не могут быть изменены пользователем:


КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаСКД));
КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);

// Добавляем фиксированное поле
ВыбранноеПоле = КомпоновщикНастроек.ФиксированныеНастройки.ВыбранныеПоля.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("Номенклатура");

// Теперь используем настройки из компоновщика
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаСКД, КомпоновщикНастроек.ПолучитьНастройки(), ...);

Шаг 5. Динамическое изменение текста запроса

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


ТекстЗапроса = СхемаСКД.НаборыДанных.НаборДанных1.Запрос;
// Добавляем нужное поле в строку запроса
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ", "ВЫБРАТЬ Таблица.Номенклатура КАК Номенклатура, ");
СхемаСКД.НаборыДанных.НаборДанных1.Запрос = ТекстЗапроса;

Важное предостережение: прямой парсинг строки запроса — это «хрупкое» решение. Если в запросе используются расширения языка запросов СКД (фигурные скобки {}), автоматическая замена может нарушить синтаксис. Старайтесь всегда отдавать предпочтение работе через коллекции ВыбранныеПоля и ДоступныеПоляВыбора.

Итоги

Для успешного получения данных из ХранилищеНастроекКомпоновкиДанных необходимо:

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

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

← На главную