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