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