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