Как открыть уникальную форму отчета из формы документа в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с задачей формирования отчетов непосредственно из документов. Типичный сценарий: в форме документа поступления или реализации создается кнопка, при нажатии на которую открывается отчет с отбором по текущему документу. Однако стандартный программный вызов может преподнести сюрприз. Открыв отчет для одного документа, пользователь переходит во второй документ, нажимает ту же кнопку, но вместо открытия нового отчета система просто переключает его внимание на старое окно с предыдущими данными.

В этой статье мы подробно разберем, почему так происходит, изучим внутренние механизмы работы платформы 1С с уникальностью форм и рассмотрим несколько вариантов решения этой проблемы с точки зрения удобства пользователя (UX) и производительности системы.

Выясняем причину: почему активируется старая форма отчета

Рассмотрим исходный код, который часто используют начинающие разработчики в модуле формы документа:


&НаКлиенте
Процедура ОтчетПоДокументу(Команда)
    
    Если Объект.Проведен Тогда
        
        ПараметрыФормы = Новый Структура("Отбор,СформироватьПриОткрытии,КлючВарианта", 
            Новый Структура("ДокументПоступления", Объект.Ссылка), 
            Истина, 
            "ФормированиеПоПараметрам");
                   
        ОткрытьФорму("Отчет.СебестоимостьПоДокументу.ФормаОбъекта", ПараметрыФормы, ,);
    Иначе
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Отчет формируется только по проведенному документу!";
        Сообщение.Сообщить();
    КонецЕсли;    
    
КонецПроцедуры

Проблема кроется в вызове метода ОткрытьФорму. Мы передаем имя формы, параметры формы, опускаем параметр владельца, а четвертый параметр — Уникальность — оставляем пустым. По умолчанию этот параметр принимает значение Ложь.

Когда платформа 1С выполняет метод ОткрытьФорму с параметром уникальности по умолчанию, она производит поиск среди уже открытых форм данного типа. Если система находит открытую форму этого отчета, она не создает новое окно, а просто активизирует существующее. При этом новые параметры отбора, переданные во втором аргументе, могут проигнорироваться или примениться некорректно, а пользователь увидит старый отчет, сформированный по другому документу.

Вариант решения №1: Принудительное открытие нового окна (Простой способ)

Самый простой способ заставить платформу всегда открывать новое окно — это передать значение Истина в качестве четвертого параметра (параметр Уникальность). Также можно генерировать новый уникальный идентификатор с помощью функции Новый УникальныйИдентификатор().

Давайте посмотрим, как изменится строка вызова:


ОткрытьФорму("Отчет.СебестоимостьПоДокументу.ФормаОбъекта", ПараметрыФормы, , Истина);

Или с использованием явного генератора UUID:


ОткрытьФорму("Отчет.СебестоимостьПоДокументу.ФормаОбъекта", ПараметрыФормы, , Новый УникальныйИдентификатор());

В чем минус этого подхода? Если пользователь нажмет на кнопку отчета в одном и том же документе пять раз, система послушно откроет пять абсолютно одинаковых окон отчета. Это приводит к быстрому захламлению рабочей области экрана, перерасходу оперативной памяти на клиенте и лишней нагрузке на сервер базы данных при повторных формированиях отчета.

Вариант решения №2: Одно окно отчета на один документ (Лучшая практика UX)

Чтобы интерфейс оставался чистым и удобным, идеальным решением будет открывать ровно одно окно отчета для каждого конкретного документа. Если отчет по Документу №1 уже открыт, то при повторном клике в Документе №1 система должна просто активизировать это окно. Если же кнопка нажата в Документе №2, должно открыться новое окно отчета именно для Документа №2.

Для реализации этого сценария в качестве ключа уникальности необходимо передать ссылку на сам документ. Ссылка является уникальным идентификатором объекта в базе данных, что идеально подходит для нашей задачи.

Рассмотрим правильный и лаконичный вариант вызова процедуры:


&НаКлиенте
Процедура ОтчетПоДокументу(Команда)
    
    Если Не Объект.Проведен Тогда
        ПоказатьПредупреждение(, "Отчет формируется только по проведенному документу!");
        Возврат;
    КонецЕсли;
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", Новый Структура("ДокументПоступления", Объект.Ссылка));
    ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
    ПараметрыФормы.Вставить("КлючВарианта", "ФормированиеПоПараметрам");
    
    // Передаем Объект.Ссылка в качестве 4-го параметра (КлючУникальности)
    ОткрытьФорму("Отчет.СебестоимостьПоДокументу.Форма", ПараметрыФормы, ЭтотОбъект, Объект.Ссылка);
    
КонецПроцедуры

При таком подходе платформа выполнит следующие действия:

  1. Проверит, открыта ли уже форма отчета Отчет.СебестоимостьПоДокументу с ключом уникальности, равным Объект.Ссылка текущего документа.
  2. Если такое окно найдено, оно будет выдвинуто на передний план.
  3. Если такого окна нет (например, отчет открывается для нового документа), платформа создаст новую форму отчета, применит к ней переданные отборы и сформирует результат.

Важное дополнение: Контроль модифицированности данных

Обратите внимание на важный нюанс, который часто упускают при ручном написании кода. В исходном алгоритме присутствует проверка проведения: Если Объект.Проведен Тогда. Но представьте ситуацию: документ проведен, пользователь открыл его форму, изменил количество или цену в табличной части (но еще не нажал кнопку «Записать» или «Провести») и сразу же кликнул по кнопке отчета.

Документ в базе данных все еще числится проведенным со старыми значениями. Отчет сформируется по данным из базы данных, и пользователь увидит цифры, которые не соответствуют тому, что он видит на экране формы документа. Это неизбежно вызовет вопросы и недовольство со стороны пользователей.

Чтобы избежать подобных коллизий, рекомендуется проверять свойство формы Модифицированность перед формированием отчета:


&НаКлиенте
Процедура ОтчетПоДокументу(Команда)
    
    Если Модифицированность Тогда
        ПоказатьПредупреждение(, "Документ был изменен! Сначала запишите или проведите документ.");
        Возврат;
    КонецЕсли;
    
    Если Не Объект.Проведен Тогда
        ПоказатьПредупреждение(, "Отчет формируется только по проведенному документу!");
        Возврат;
    КонецЕсли;
    
    // Код открытия формы отчета...
    
КонецПроцедуры

Как это работает "под капотом" платформы

Когда мы передаем структуру ПараметрыФормы в метод ОткрытьФорму, платформа автоматически выполняет сопоставление переданных параметров со свойствами СКД (Схемы компоновки данных) отчета:

  1. Параметр Отбор: Платформа анализирует вложенную структуру. В нашем примере она находит ключ ДокументПоступления. Если в настройках отчета или в доступных полях СКД есть поле с таким именем, платформа автоматически добавляет элемент отбора с видом сравнения Равно и значением нашей ссылки.
  2. Параметр СформироватьПриОткрытии: Принимает булево значение. Если установлено Истина, платформа после инициализации формы отчета на сервере автоматически выполняет компоновку и вывод результата, избавляя пользователя от необходимости лишний раз кликать по кнопке «Сформировать».

Использование стандартных механизмов БСП

Если вы работаете в современной конфигурации, созданной на базе Библиотеки Стандартных Подсистем (БСП), ручное прописание кнопок вызова отчетов в коде форм считается устаревшим подходом. В БСП встроен мощный механизм интеграции отчетов.

Вместо жесткого программирования в форме документа, разработчики регистрируют команду отчета через специальный экспортный метод ОпределитьКомандыПодключенияОтчетов в модуле менеджера документа. В этом случае БСП сама выведет кнопку отчета в стандартное подменю «Отчеты» на командной панели формы, корректно передаст все параметры уникальности, контекста, а также позаботится о правах доступа и сохранении настроек пользователя.

← На главную