Почему при программном изменении запроса динамического списка в СКД не появляются новые поля и как это исправить?

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

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

Анализ проблемы: почему исполняемая схема «зависает»?

Рассмотрим стандартную ситуацию, с которой сталкиваются разработчики. Имеется форма, на которой расположен динамический список (например, с именем Список), отображаемый в таблице ТаблицаАВК. Код для получения данных программно выглядит следующим образом:


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

Проанализируем ситуацию: даже если вы изменили Список.ТекстЗапроса непосредственно перед выполнением этого кода, метод ПолучитьИсполняемуюСхемуКомпоновкиДанных может вернуть старую структуру. Это происходит по нескольким причинам:

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

Способ 1. Принудительное обновление через КомпоновщикНастроек

Выясним причину, по которой КомпоновщикНастроек не видит изменений. Часто проблема кроется в том, что КомпоновщикНастроек динамического списка хранит старое состояние доступных полей. Чтобы исправить это, нам необходимо выполнить «сброс» или переинициализацию настроек после изменения запроса.

Рассмотрим пример кода, который помогает обновить состав полей:


// Изменяем запрос
Список.ТекстЗапроса = "ВЫБРАТЬ * ИЗ Справочник.Номенклатура ГДЕ ЭтоГруппа = ЛОЖЬ";

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

// Иногда требуется загрузить пустые настройки для полного сброса кэша полей
НастройкиПоУмолчанию = Список.КомпоновщикНастроек.ПолучитьНастройки();
Список.КомпоновщикНастроек.ЗагрузитьНастройки(НастройкиПоУмолчанию);

Обратите внимание на использование ИсточникДоступныхНастроекКомпоновкиДанных. Это сообщает системе, что нужно перечитать описание полей из обновленной схемы запроса.

Способ 2. Управление хранилищем настроек

Посмотрим на ситуацию со стороны пользовательских настроек. В свойствах формы или объекта могут быть заполнены поля ХранилищеВариантов или ХранилищеНастроек. Если система автоматически сохраняет настройки, то при открытии формы она восстанавливает «вчерашний» вариант колонок.

Проанализируем решение: чтобы новые поля всегда были доступны, убедитесь, что в свойствах таблицы на форме (в расширении динамического списка) не стоит жесткое ограничение на состав полей. Также в коде можно явно добавить новые поля в выбранные поля компоновщика:


НовоеПоле = Список.КомпоновщикНастроек.Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
НовоеПоле.Поле = Новый ПолеКомпоновкиДанных("МоеНовоеПолеИзЗапроса");
НовоеПоле.Использование = Истина;

Способ 3. Создание «чистой» схемы компоновки (самый надежный вариант)

Если штатные методы элемента формы продолжают возвращать некорректную схему, разберем более радикальный, но гарантированный способ. Вместо того чтобы полагаться на Элементы.ТаблицаАВК.ПолучитьИсполняемуюСхемуКомпоновкиДанных(), мы создадим схему компоновки программно на основе текущего текста запроса динамического списка. Для более простой и лаконичной программной настройки макетов компоновки отлично подойдет вспомогательный модуль-обёртка для быстрого создания СКД.

Рассмотрим пошагово, как это реализовать:

  1. Создаем объект СхемаКомпоновкиДанных.
  2. Добавляем в нее ИсточникДанных.
  3. Создаем НаборДанныхЗапрос и помещаем туда актуальный текст запроса из динамического списка.
  4. Выполняем компоновку макета, используя эту новую схему.

Пример реализации:


// 1. Создаем свою схему
МояСхема = Новый СхемаКомпоновкиДанных;
ИсточникДанных = МояСхема.ИсточникиДанных.Добавить("ИсточникДанных1");
ИсточникДанных.ТипИсточникаДанных = "Local";

НаборДанных = МояСхема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросКомпоновкиДанных"));
НаборДанных.Имя = "НаборДанных1";
НаборДанных.Запрос = Список.ТекстЗапроса; // Берем измененный запрос
НаборДанных.ИсточникДанных = "ИсточникДанных1";

// 2. Важно включить автозаполнение полей
НаборДанных.АвтоЗаполнениеДоступныхПолей = Истина;

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

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

Этот метод позволяет полностью избежать зависимости от кэша экранных таблиц и гарантирует, что МакетКомпоновки будет содержать все поля, описанные в Список.ТекстЗапроса на данный момент.

Важные рекомендации

При работе с динамическими списками и программным выводом данных следует помнить о следующих нюансах:

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

← На главную