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