Отчёт из кода 1С 8.3: от ОткрытьФорму до СКД без формы
Содержание
Чтобы программно запустить отчёт в 1С 8.3, есть два пути. Если пользователь должен увидеть привычную форму, на клиенте вызывают ОткрытьФорму("Отчет.ИмяОтчета.Форма", Параметры) с параметром СформироватьПриОткрытии = Истина. Если нужен только результат — табличный документ или таблица значений, — на сервере создают объект через Отчеты.ИмяОтчета.Создать() и вызывают СкомпоноватьРезультат().
Всё, что ниже, относится к платформе 8.3 и управляемым формам и не зависит от конфигурации. В примерах условный отчёт ПродажиПоКлиентам на СКД с параметрами НачалоПериода и КонецПериода. Подставьте имена своего отчёта, полей и параметров.
Открыть форму или собрать отчёт кодом: что выбрать
Выбор зависит от того, кому нужен результат: человеку или программе.
| Задача | Способ | Где выполняется |
|---|---|---|
| Открыть отчёт с заранее заданным периодом и отбором | ОткрытьФорму с параметрами формы | клиент |
| Получить цифры для расчёта, проверки, рассылки | Отчеты.X.Создать() + СкомпоноватьРезультат | сервер |
| Выгрузить данные отчёта в таблицу значений | КомпоновщикМакетаКомпоновкиДанных + вывод в коллекцию | сервер |
Запустить отчёт из файла .erf | ВнешниеОтчеты.Подключить или ВнешниеОтчеты.Создать | сервер, затем клиент |
| Тяжёлый отчёт без блокировки интерфейса | фоновое задание | сервер |
Первый способ самый короткий. Он подходит для команды «Показать продажи по этому клиенту» в карточке контрагента:
&НаКлиенте
Процедура ОткрытьПродажиКлиента(Команда)
Отбор = Новый Структура("Контрагент", Объект.Ссылка);
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", Отбор);
ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
ОткрытьФорму("Отчет.ПродажиПоКлиентам.Форма", ПараметрыФормы, ЭтаФорма);
КонецПроцедуры
Параметр Отбор попадает в отбор настроек, если в отчёте есть поле с таким же именем. Для выбора конкретного варианта передают КлючВарианта — имя варианта настроек из схемы.
Повторный вызов с теми же параметрами активирует уже открытое окно, а не создаёт новое. Чтобы открыть отчёт по второму клиенту рядом с первым, передайте четвёртым параметром ОткрытьФорму ключ уникальности, например ссылку на контрагента. Тогда для каждого клиента откроется своё окно.
💡 Отбор через параметр формы работает только для полей, доступных в отборе СКД. Если поле называется в схеме иначе, отбор молча не применится.
Создание объекта через менеджер Отчеты
Объект отчёта создаётся только в серверном контексте. В тонком и веб-клиенте менеджер Отчеты недоступен, поэтому код помещают в процедуру с директивой &НаСервере, &НаСервереБезКонтекста или в серверный общий модуль.
&НаСервереБезКонтекста
Функция СоздатьОтчет()
ОтчетОбъект = Отчеты.ПродажиПоКлиентам.Создать();
Возврат ОтчетОбъект.СхемаКомпоновкиДанных <> Неопределено;
КонецФункции
После Создать() у объекта доступны:
- 📦
СхемаКомпоновкиДанных— основная схема, если она задана в свойствах отчёта; - ⚙️
КомпоновщикНастроек— текущие настройки: параметры, отбор, группировки; - 🧩 реквизиты и экспортные процедуры модуля объекта.
Старые отчёты без СКД формируются процедурой модуля объекта. Если в модуле есть экспортная процедура вроде Сформировать(ТабДок), её вызывают напрямую: ОтчетОбъект.Сформировать(ТабДок). Имя процедуры у каждого такого отчёта своё, смотрите модуль объекта в Конфигураторе.
Формирование отчёта на СКД программно
Быстрый вариант: СкомпоноватьРезультат
Метод СкомпоноватьРезультат берёт схему и настройки самого отчёта и выводит результат в табличный документ. Перед вызовом полезно явно загрузить настройки по умолчанию, чтобы не зависеть от состояния компоновщика.
&НаСервереБезКонтекста
Функция СформироватьПродажи(НачалоПериода, КонецПериода)
ОтчетОбъект = Отчеты.ПродажиПоКлиентам.Создать();
Схема = ОтчетОбъект.СхемаКомпоновкиДанных;
Компоновщик = ОтчетОбъект.КомпоновщикНастроек;
Компоновщик.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема));
Компоновщик.ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию);
Компоновщик.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("НачалоПериода", НачалоПериода);
Компоновщик.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("КонецПериода", КонецДня(КонецПериода));
ТабДок = Новый ТабличныйДокумент;
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
ОтчетОбъект.СкомпоноватьРезультат(ТабДок, ДанныеРасшифровки);
Возврат ТабДок;
КонецФункции
КонецДня() нужен, если параметр сравнивается с датой документа. Без него документы последнего дня после 00:00:00 выпадут из отчёта.
Полный цикл: компоновщик макета и процессор
Когда схему берут не из отчёта, а, например, из общего макета, или нужен свой макет оформления, цепочку собирают вручную. Это те же четыре шага, что платформа делает внутри СкомпоноватьРезультат.
КомпоновщикМакетаКомпоновкиДанных.Выполнить()строит макет по схеме и настройкам.ПроцессорКомпоновкиДанныхвыполняет запросы.- Процессор вывода собирает результат в нужный приёмник.
- Приёмник — табличный документ или коллекция значений.
&НаСервереБезКонтекста
Функция СкомпоноватьВручную(Схема, Настройки)
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, Настройки, ДанныеРасшифровки);
Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(Макет, , ДанныеРасшифровки, Истина);
ТабДок = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабДок);
ПроцессорВывода.Вывести(Процессор);
Возврат ТабДок;
КонецФункции
Результат в таблицу значений
Для расчётов табличный документ неудобен. Нужен генератор макета для коллекции значений и другой процессор вывода:
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, Настройки, , ,
Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(Макет);
Результат = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(Результат);
ПроцессорВывода.Вывести(Процессор);
В таблицу значений попадают поля из структуры настроек. Если в варианте есть только группировка без детальных записей, вы получите итоги, а не строки документов. Для плоской выгрузки сделайте отдельный вариант с детальными записями и выбранными полями.
Параметры, отбор и вариант настроек
Все настройки меняют до вызова компоновки, в объекте НастройкиКомпоновкиДанных.
Параметры данных
УстановитьЗначениеПараметра удобен, но не сообщает об опечатке в имени. Надёжнее найти параметр и проверить результат:
Параметр = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(
Новый ПараметрКомпоновкиДанных("НачалоПериода"));
Если Параметр = Неопределено Тогда
ВызватьИсключение "В отчете нет параметра НачалоПериода";
КонецЕсли;
Параметр.Значение = НачалоПериода;
Параметр.Использование = Истина;
Флаг Использование важен. У параметров, которые в схеме не обязательны, он может быть снят, и тогда значение не применится.
Если в отчёте один параметр типа СтандартныйПериод, передают объект периода:
Период = Новый СтандартныйПериод(НачалоПериода, КонецДня(КонецПериода));
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Период", Период);
Отбор
ЭлементОтбора = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Контрагент;
ЭлементОтбора.Использование = Истина;
Для списка значений используйте ВидСравненияКомпоновкиДанных.ВСписке и передайте СписокЗначений. Поле реквизита указывают через точку: "Контрагент.ИНН".
Нужный вариант из схемы
Вариант ищут в коллекции ВариантыНастроек по имени и копируют его настройки в компоновщик:
Для Каждого Вариант Из Схема.ВариантыНастроек Цикл
Если Вариант.Имя = "ПоМесяцам" Тогда
Компоновщик.ЗагрузитьНастройки(Вариант.Настройки);
Прервать;
КонецЕсли;
КонецЦикла;
Загружайте вариант до установки параметров и отбора. ЗагрузитьНастройки перезапишет всё, что было задано раньше.
💡 Пользовательские настройки из формы отчёта программно применяют через Компоновщик.ЗагрузитьПользовательскиеНастройки(). Итоговые настройки с учётом пользовательских возвращает Компоновщик.ПолучитьНастройки(), их и передают в компоновщик макета.
Запуск внешнего отчёта из файла
Внешний отчёт (.erf) нельзя открыть одной строкой с клиента: файл сначала должен попасть на сервер.
Файл лежит на сервере 1С
Если путь доступен процессу сервера, хватает одной строки:
ОтчетОбъект = ВнешниеОтчеты.Создать("D:\Reports\Продажи.erf", Ложь);
Второй параметр — безопасный режим. Ложь разрешает отчёту работать с файлами, COM и привилегированными операциями. Ставьте Ложь только для файлов, которым доверяете.
Файл выбирает пользователь
Схема из трёх шагов: передать файл во временное хранилище, подключить отчёт на сервере, открыть форму на клиенте.
&НаКлиенте
Процедура ЗапуститьВнешнийОтчет(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, Адрес, ИмяФайла, ДопПараметры) Экспорт
Если Не Результат Тогда
Возврат;
КонецЕсли;
ИмяОтчета = ПодключитьНаСервере(Адрес);
ОткрытьФорму("ВнешнийОтчет." + ИмяОтчета + ".Форма");
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПодключитьНаСервере(Адрес)
Защита = Новый ОписаниеЗащитыОтОпасныхДействий;
Защита.ПредупреждатьОбОпасныхДействиях = Ложь;
Возврат ВнешниеОтчеты.Подключить(Адрес, , Ложь, Защита);
КонецФункции
Подключённый отчёт живёт до конца сеанса. Повторное подключение с тем же именем заменит его новой версией файла.
Не отключайте безопасный режим для файлов из почты и чужих источников. Внешний отчёт с выключенным безопасным режимом выполняет любой код на сервере с правами сеанса.
В конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) внешний отчёт лучше зарегистрировать в справочнике дополнительных отчётов: Администрирование → Печатные формы, отчеты и обработки → Дополнительные отчеты и обработки. Тогда он появится в разделах программы, а права на него настраиваются штатно, без своего кода.
Вывод результата: показать, сохранить, напечатать
Табличный документ, полученный на сервере, передают на клиент как возвращаемое значение или через реквизит формы типа ТабличныйДокумент.
| Действие | Код | Контекст |
|---|---|---|
| Показать в отдельном окне | ТабДок.Показать("Продажи") | клиент |
| Вывести в поле формы | Результат = СформироватьПродажи(...) | сервер, реквизит формы |
| Сохранить в Excel | ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX) | сервер |
| Сохранить в PDF | ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.PDF) | сервер |
| Напечатать без диалога | ТабДок.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать) | клиент |
Параметры страницы задают до печати или записи в PDF:
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
ТабДок.АвтоМасштаб = Истина;
Для рассылки по расписанию отчёт формируют в регламентном задании и записывают файл во временный каталог: ПолучитьИмяВременногоФайла("xlsx"). После отправки файл удаляют через УдалитьФайлы().
Долгий отчёт в фоне
Если отчёт считается минуту и дольше, клиент «замирает». Формирование переносят в фоновое задание:
Параметры = Новый Массив;
Параметры.Добавить(НачалоПериода);
Параметры.Добавить(КонецПериода);
Параметры.Добавить(АдресРезультата);
ФоновыеЗадания.Выполнить("ОтчетыСервер.СформироватьПродажиВФоне", Параметры);
Процедура СформироватьПродажиВФоне должна быть экспортной и лежать в серверном общем модуле. Результат она кладёт в хранилище по переданному адресу: ПоместитьВоВременноеХранилище(ТабДок, АдресРезультата). Адрес заранее создают на клиенте с привязкой к форме: ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор). Клиент проверяет готовность через обработчик ожидания. В типовых конфигурациях для этого есть готовый модуль ДлительныеОперации из БСП.
Ошибки при запуске отчёта из кода и отладка
Большинство проблем видно по тексту исключения. Оборачивайте вызов в Попытка ... Исключение и пишите подробности в журнал регистрации:
Попытка
ТабДок = СформироватьПродажи(НачалоПериода, КонецПериода);
Исключение
Подробно = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
ЗаписьЖурналаРегистрации("Отчеты.ПродажиПоКлиентам",
УровеньЖурналаРегистрации.Ошибка, , , Подробно);
ВызватьИсключение;
КонецПопытки;
Как увидеть, что реально выполняет СКД
Самый полезный приём отладки — посмотреть итоговый запрос. После КомпоновщикМакета.Выполнить() поставьте точку останова и откройте в табло отладчика выражение:
Макет.НаборыДанных[0].Запрос
Там текст запроса с уже применёнными отборами, а в Макет.ЗначенияПараметров — фактические значения параметров. Скопируйте запрос в консоль запросов и проверьте, возвращает ли он строки. Если запрос пустой — проблема в данных или параметрах, а не в выводе.
Для серверного кода отладку нужно включить и на сервере. Для клиент-серверной базы служба сервера 1С должна быть запущена с ключом -debug. Изменение параметров службы требует её перезапуска: предупредите пользователей, все сеансы будут прерваны. Делайте это вне рабочего времени или на копии базы.