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