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