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