При разработке отчетов в системе 1С:Предприятие 8.3 начинающие программисты часто сталкиваются с трудностями при попытке связать визуальную форму, программный код и макет. Основная сложность заключается в понимании того, где именно должен исполняться код и как правильно обращаться к объектам метаданных в условиях управляемого приложения. Разберем пошагово, как реализовать формирование отчета по кнопке и разберемся в архитектуре модулей.
Прежде чем писать код, проанализируем ситуацию с доступностью объектов. В управляемом приложении код разделен на две части: &НаКлиенте (то, что видит пользователь) и &НаСервере (где происходят основные вычисления и работа с базой данных).
Рассмотрим типичную ошибку: попытка вызвать метод ПолучитьМакет() непосредственно в процедуре кнопки на клиенте. Система выдаст ошибку «Переменная не определена (Отчеты)», так как глобальный контекст Отчеты доступен только на сервере или в толстом клиенте. С другой стороны, метод Показать() для табличного документа работает только на клиенте, так как сервер не может напрямую открывать окна в интерфейсе пользователя.
Для того чтобы при нажатии кнопки «Сформировать» открывался печатный макет, нам необходимо создать связку из клиентской процедуры и серверной функции. Выясним причину, по которой это делается именно так: мы идем на сервер за данными и макетом, формируем там результат и возвращаем его на клиент для отображения.
Рассмотрим пример правильной реализации в модуле формы отчета:
&НаКлиенте
Процедура Сформировать(Команда)
// Создаем пустой табличный документ на клиенте
ТабДок = Новый ТабличныйДокумент;
// Вызываем серверную функцию для его заполнения
ЗаполнитьТабличныйДокументНаСервере(ТабДок);
// Выводим результат пользователю
ТабДок.Показать("Результат отчета");
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьТабличныйДокументНаСервере(ТабДок)
// Получаем макет нашего отчета.
// Если отчет внешний, используем РеквизитФормыВЗначение("Объект").ПолучитьМакет("Макет")
// Если отчет в составе конфигурации, можно так:
Макет = Отчеты.ИмяВашегоОтчета.ПолучитьМакет("ОсновнойМакет");
// Получаем области из макета
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
// Выводим области в итоговый документ
ТабДок.Вывести(ОбластьЗаголовок);
ТабДок.Вывести(ОбластьШапка);
// Здесь обычно идет цикл по результату запроса
// Для примера просто выведем одну строку
ТабДок.Вывести(ОбластьСтрока);
КонецПроцедуры
Иногда требуется, чтобы результат отображался не в новом окне, а прямо внутри формы отчета. Для этого проанализируем ситуацию с реквизитами формы. Нам не нужно создавать Новый ТабличныйДокумент, вместо этого мы будем использовать существующий реквизит формы.
Посмотрим на алгоритм действий:
ТабличныйДокумент (например, с именем Результат).Результат или ЭтотОбъект.Результат.Пример кода для вывода на форму:
&НаСервере
Процедура СформироватьНаСервере()
// Очищаем поле перед новым формированием
Результат.Очистить();
// Получаем макет
Макет = ПолучитьМакет("МойМакет");
// Заполняем параметры области (если они есть в макете)
Область = Макет.ПолучитьОбласть("Данные");
Область.Параметры.ДатаОтчета = ТекущаяДата();
// Выводим в реквизит формы
Результат.Вывести(Область);
КонецПроцедуры
Разберем подробнее, в каком модуле и что следует писать. Это один из самых частых вопросов при обучении 1С.
Модуль формы:
Здесь живет логика «интерфейса». Нажатия кнопок, изменение видимости полей, вопросы пользователю («Уверены, что хотите сформировать?»). В этом модуле мы пишем процедуры с префиксами &НаКлиенте и &НаСервере.
Модуль объекта:
Это сердце отчета. Здесь правильно размещать основную логику получения данных (Запросы). Если вы используете СКД (Систему компоновки данных), то именно в модуле объекта переопределяется событие ПриКомпоновкеРезультата. Использование модуля объекта позволяет вызывать формирование отчета из любой другой точки программы, не открывая его форму.
Модуль менеджера:
Используется для функций, которые не привязаны к конкретному экземпляру отчета (с его настройками), а относятся к самому метаданному. Например, здесь часто описывают команды печати, которые должны быть доступны из списков документов или справочников.
Запросы к базе данных (к регистрам, справочникам) технически могут быть выполнены только на сервере. Рассмотрим, как это интегрировать в наш отчет. Проанализируем наиболее правильный подход: запрос выполняется на сервере, данные обходятся в цикле, и каждая итерация заполняет свою область макета.
Пример интеграции запроса:
&НаСервере
Функция СформироватьОтчетСЗапросом()
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("МакетСРегистрами");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПродажиОбороты.Номенклатура,
| ПродажиОбороты.КоличествоОборот
|ИЗ
| РегистрНакопления.Продажи.Обороты(&Начало, &Конец) КАК ПродажиОбороты";
Запрос.УстановитьПараметр("Начало", Объект.ДатаНачала);
Запрос.УстановитьПараметр("Конец", КонецДня(Объект.ДатаОкончания));
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Пока Выборка.Следующий() Цикл
// Заполняем параметры области данными из запроса
ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, Выборка);
// Выводим заполненную область в документ
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
Возврат ТабДок;
КонецФункции
Хотя «ручной» вывод макета через ПолучитьОбласть() и Вывести() дает полный контроль над процессом, современным стандартом в 1С является Система компоновки данных (СКД). Мы рекомендуем по возможности использовать её, так как она автоматически берет на себя:
Даже если вам нужен специфический макет, в СКД можно создать Макет оформления или Собственный макет для конкретных полей, сохранив при этом мощь автоматических расчетов.
Для успешного решения задачи программного вывода макета важно соблюдать три правила: первое — всегда разделять получение данных (сервер) и показ результата (клиент); второе — корректно обращаться к макету через контекст метаданных или объект; третье — не забывать использовать метод Показать() для объектов типа ТабличныйДокумент, созданных программно.