При разработке в среде 1С:Предприятие 8.3 часто возникает задача отойти от стандартного отображения конкретного отчета и использовать универсальную форму. Обычно это ОбщаяФорма.ФормаОтчета, которая входит в состав конфигурации или Библиотеки стандартных подсистем (БСП). Однако при попытке программного вызова этой формы разработчики нередко сталкиваются с ошибкой: «Получать форму объекта - отчета возможно только для конкретного отчета». В этой статье мы разберем, почему возникает эта проблема, и рассмотрим несколько надежных способов ее решения.
Проанализируем ситуацию, описанную в теме. Разработчик пытается вызвать общую форму, передавая в параметрах объект отчета, полученный на сервере. Ошибка {ВнешнийОтчет.Выторг2019.Форма.ФормаОтчета.Форма(19)}: Помилка при виклику методу контексту (ОткрытьФорму) возникает из-за фундаментального ограничения платформы 1С: управляемые формы работают в архитектуре «клиент-сервер».
Рассмотрим подробнее код, который приводит к сбою:
&НаСервере
Функция ПолучитьСтруктура()
Возврат Новый Структура("Отчет", РеквизитФормыВЗначение("Отчет"));
КонецФункции
// На клиенте
ОткрытьФорму("ОбщаяФорма.ФормаОтчета", ПолучитьСтруктура());
Главная проблема здесь заключается в использовании метода РеквизитФормыВЗначение("Отчет"). Этот метод создает на сервере объект типа ОтчетОбъект (или ВнешнийОтчетОбъект). Данный тип не является сериализуемым. Это означает, что платформа не может «упаковать» его в пакет данных для передачи с сервера на клиент, а затем обратно в параметры открываемой формы. Как только вы пытаетесь передать такой объект в структуру параметров метода ОткрытьФорму, система выдает ошибку, так как ожидает либо ссылку на метаданные, либо строковый идентификатор, но никак не «живой» объект данных.
Если ваш отчет является частью конфигурации, самый простой и правильный способ вызвать общую форму — передать полное имя отчета в метаданных. В этом случае ОбщаяФорма.ФормаОтчета сама инициализирует нужный объект внутри себя.
Выясним, как это реализовать правильно. Вместо передачи объекта, сформируем структуру параметров с ключом Отчет, значением которого будет строка:
&НаКлиенте
Процедура ОткрытьОбщуюФорму()
ПараметрыФормы = Новый Структура;
// Указываем полное имя отчета, как оно задано в дереве метаданных
ПараметрыФормы.Вставить("Отчет", "Отчет.НазваниеВашегоОтчета");
// Если нужно открыть конкретный вариант
ПараметрыФормы.Вставить("КлючВарианта", "Основной");
ОткрытьФорму("ОбщаяФорма.ФормаОтчета", ПараметрыФормы);
КонецПроцедуры
При таком подходе платформа понимает, для какого именно контекста нужно инициализировать форму, и ошибка «для конкретного отчета» исчезает.
Если вы работаете в современной конфигурации (например, 1С:ERP, УТ 11 или БП 3.0), в ней наверняка интегрирована Библиотека стандартных подсистем (БСП). В БСП работа с отчетами стандартизирована через подсистему «Варианты отчетов».
Посмотрим на пример того, как это делается профессионально. Вместо прямого вызова ОткрытьФорму, следует использовать программный интерфейс БСП. Это гарантирует, что все настройки, фильтры и права доступа будут применены корректно.
// В модуле команды или формы
ПараметрыОтчета = ВариантыОтчетовКлиент.ПараметрыОтчета();
ПараметрыОтчета.Отчет = "Отчет.НазваниеВашегоОтчета";
ПараметрыОтчета.КлючВарианта = "Основной";
ВариантыОтчетовКлиент.ОткрытьФормуОтчета(ПараметрыОтчета);
Метод ОткрытьФормуОтчета самостоятельно определит, какая форма является основной, и корректно передаст все необходимые параметры, избегая прямой передачи объекта ОтчетОбъект.
Ситуация осложняется, если мы имеем дело с внешним файлом (как в примере ВнешнийОтчет.Выторг2019). Общая форма конфигурации «не знает» о существовании внешнего файла на диске. Чтобы внешнему отчету открыться в общей форме, он должен быть зарегистрирован в системе.
Рассмотрим два варианта решения для внешних отчетов:
ОбщаяФорма.ФормаОтчета, то при открытии внешнего файла через «Файл - Открыть» платформа автоматически подставит общую форму.Проанализируем ситуацию, когда необходимо передать специфические настройки. Иногда помогает использование параметра КлючНазначенияИспользования. Это позволяет форме сохранять уникальные настройки пользователя для разных контекстов вызова одного и того же отчета.
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отчет", "Отчет.Продажи");
ПараметрыФормы.Вставить("КлючНазначенияИспользования", "УникальныйКонтекстВызова");
ОткрытьФорму("ОбщаяФорма.ФормаОтчета", ПараметрыФормы);
В обсуждении на форуме прозвучал совет «скопипастить общую форму в отчет». Разберем, почему это плохое решение. Копирование кода ведет к дублированию логики. Если завтра вы обновите конфигурацию или внесете изменения в общую форму (например, добавите новый механизм логирования), ваш внешний отчет со скопированной формой останется со старыми ошибками или неактуальным функционалом. Стремитесь всегда использовать переиспользуемые объекты метаданных.
Чтобы избежать ошибки «Получать форму объекта - отчета возможно только для конкретного отчета», придерживайтесь следующих правил:
РеквизитФормыВЗначение("Отчет") напрямую в параметры открытия формы на клиенте."Отчет.Имя") в структуре параметров.ВариантыОтчетовКлиент.ОткрытьФормуОтчета являются стандартом современной разработки.Применяя эти подходы, вы обеспечите стабильную работу своих отчетов и корректное взаимодействие с интерфейсными механизмами платформы 1С.