Как программно сформировать и открыть отчет при начале работы системы в 1С

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

Одной из часто встречающихся задач в 1С:Предприятии является автоматическое оповещение пользователя о важных событиях при запуске программы. Это может быть уведомление о дебиторской задолженности, напоминание о задачах или, как в нашем случае, отчет по истекающим срокам договоров ИТС (или задействовать Универсальный отчет по метаданным). Однако начинающие разработчики часто сталкиваются с тем, что код, написанный для сервера, отказывается открывать окна или выдает загадочную "Ошибку отображения типов" (найти причину подобных проблем поможет Статический анализатор кода проектов). Разберем подробно, почему это происходит и как правильно реализовать такой функционал.

Разбор основной проблемы: Клиент vs Сервер

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

На сервере «нет экрана». Сервер — это программный код, который работает в оперативной памяти сервера приложений или базы данных. Он не знает о существовании монитора пользователя. Поэтому любые попытки вызвать диалоговые окна (Предупреждение, Вопрос) или открыть форму (ОткрытьФорму) непосредственно из серверного метода приведут к ошибке. Кроме того, объект типа ОтчетОбъект (создаваемый через Отчеты.ИмяОтчета.Создать()) существует только на сервере и не может быть передан на клиент «как есть» — это и вызывает ошибку отображения типов.

Решение 1: Правильное распределение логики между модулями

Рассмотрим по шагам, как нужно структурировать код, применяя Шаблоны для применения cтандартов и методик разработки. Логика должна быть следующей: клиент запрашивает у сервера проверку условий, сервер возвращает простой ответ (например, Истина или Ложь), и если ответ положительный, клиент открывает форму отчета.

В общем модуле (с галочкой Сервер и Вызов сервера) создаем функцию для проверки условий:


&НаСервере
Функция НужноПоказатьОтчетПоИТС() Экспорт
    ТекущаяДата = ТекущаяДата();
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |    СрокПоИСТ.Ссылка КАК Ссылка
        |ИЗ
        |    Документ.СрокПоИСТ КАК СрокПоИСТ
        |ГДЕ
        |    СрокПоИСТ.ДатаОкончания <= ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, 45)";
    
    Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата);
    РезультатЗапроса = Запрос.Выполнить();
    
    Возврат Не РезультатЗапроса.Пустой();
КонецФункции

Теперь в модуле управляемого приложения (или в расширении) пропишем логику открытия на клиенте:


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

Решение 2: Использование параметров формы для автоматического формирования

Обратите внимание на параметр СформироватьПриОткрытии. Это стандартный параметр системы компоновки данных (СКД). Вместо того чтобы мучиться с программным вызовом метода СкомпоноватьРезультат, мы просто передаем флаг форме. Платформа сама поймет, что при инициализации окна нужно сразу запустить процесс генерации отчета с настройками по умолчанию.

Выясним причину, почему это лучше ручного формирования:

  1. Меньше кода: не нужно описывать инициализацию компоновщика настроек.
  2. Стабильность: форма отчета сама управляет своим жизненным циклом.
  3. UX: пользователь видит процесс формирования (индикатор), а не «зависшее» на время формирования приложение.

Решение 3: Асинхронные вызовы и обработчик ожидания

Разберем ситуацию, когда запрос к базе данных выполняется долго. Если поместить тяжелый запрос непосредственно в ПриНачалеРаботыСистемы, пользователь будет наблюдать пустой экран или «колесико» загрузки слишком долго. Проанализируем, как сделать вход в систему более плавным с помощью ПодключитьОбработчикОжидания.

Этот метод позволяет запустить нашу проверку через пару секунд после того, как основной интерфейс программы уже отрисовался. Рассмотрим пример:


&НаКлиенте
Процедура ПриНачалеРаботыСистемы()
    // Подключаем процедуру проверки через 1 секунду после запуска
    ПодключитьОбработчикОжидания("ПроверитьСрокиИТС_Обработчик", 1, Истина);
КонецПроцедуры

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

&НаКлиенте
Процедура ПослеПредупреждения(ДополнительныеПараметры) Экспорт
    ОткрытьФорму("Отчет.ОтчетПоСрокамИТС.Форма.ФормаОтчета", Новый Структура("СформироватьПриОткрытии", Истина));
КонецПроцедуры

Важный момент: использование ПоказатьПредупреждение вместо устаревшего Предупреждение критически важно для работы в веб-клиенте и в интерфейсе "Такси". Современная платформа 1С стремится к полной асинхронности, чтобы модальные окна не блокировали работу браузера или других вкладок программы.

Решение 4: Работа через расширение (Аннотация &После)

Если вы не хотите менять типовую конфигурацию, используйте механизм расширений. Как было предложено в одном из сообщений форума, можно использовать аннотацию &После. Посмотрим на реализацию в расширении:


&После("ПриНачалеРаботыСистемы")
Процедура Расш1_ПриНачалеРаботыСистемы()
    // Логика проверки и открытия
    // Важно: в расширении также соблюдайте разделение контекста!
    Если МойМодульВРасширении.ПроверитьДанные() Тогда
        ОткрытьФорму("Отчет.МойОтчет.Форма");
    КонецЕсли;
КонецПроцедуры

Типичные ошибки, которых следует избегать

Проанализируем основные "грабли", на которые наступают разработчики:

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

← На главную