Как программно сформировать отчет на Системе Компоновки Данных (СКД) в 1С 8.3 с заданными отборами и вывести его без открытия формы?

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

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

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

Основные этапы программного формирования отчета СКД

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

  1. Получение схемы компоновки данных. Это первый и основополагающий шаг, который позволяет нам получить описание структуры отчета, его источников данных, доступных полей, параметров и настроек по умолчанию.
  2. Создание и инициализация компоновщика настроек. Объект КомпоновщикНастроекКомпоновкиДанных позволяет нам управлять настройками отчета, такими как отборы, параметры, группировки, порядок и другие.
  3. Установка отборов. Мы научимся программно добавлять элементы отбора, указывая поле, вид сравнения и значение.
  4. Установка параметров. Аналогично отборам, мы рассмотрим, как программно задавать значения параметров отчета, таких как период, дата или другие специфические значения.
  5. Компоновка макета. После того как все настройки заданы, мы используем компоновщик макета для создания исполнительного макета компоновки данных.
  6. Инициализация процессора компоновки данных. Этот процессор отвечает за непосредственное выполнение запросов к базе данных согласно полученному макету.
  7. Инициализация процессора вывода. Мы будем использовать процессор вывода для преобразования результата работы процессора компоновки в привычный табличный документ.
  8. Вывод результата. На последнем этапе мы получим готовый табличный документ, который можно сохранить, распечатать или отобразить.

Шаг 1: Получение схемы компоновки данных

Прежде всего, нам необходимо получить саму схему компоновки данных отчета. Схема СКД обычно хранится в макетах объекта отчета или в отдельном общем макете. Для получения схемы используем метод ПолучитьМакет(). Как правило, стандартные отчеты имеют схему с именем ОсновнаяСхемаКомпоновкиДанных.

Рассмотрим пример:


// Предположим, что мы работаем в модуле формы или объекта,
// и ОтчетОбъект - это ссылка на объект отчета, например,
// если ОтчетОбъект = РеквизитФормыВЗначение("ОтчетОбъект")
// или если мы имеем дело с объектом, который содержит схему СКД.

// Получаем схему компоновки данных отчета
СхемаКомпоновкиДанных = ОтчетОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");

В этом примере ОтчетОбъект может быть экземпляром объекта, содержащего схему отчета. Если вы вызываете код из модуля отчета, то ОтчетОбъект будет ссылаться на сам текущий отчет. Если это внешний отчет или обработка, то ОтчетОбъект нужно будет получить по-другому, например, через ОбъектыМетаданных.Отчеты.ИмяВашегоОтчета.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных").

Шаг 2: Создание и инициализация компоновщика настроек

Объект КомпоновщикНастроекКомпоновкиДанных является ключевым для управления настройками отчета. Он позволяет загружать стандартные настройки, а затем программно изменять их. Мы инициализируем его полученной схемой компоновки данных и загружаем в него настройки по умолчанию из схемы. Для тех, кто хочет максимально упростить этот процесс, существует СКДБилдер — модуль-обёртка над объектной моделью СКД, который позволяет сократить объем кода и сделать его более читаемым, а ускорить отладку поможет инструментарий разработчика 1С с консолями запросов и СКД.


// Создаем компоновщик настроек
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;

// Инициализируем компоновщик настроек нашей схемой
КомпоновщикНастроек.Инициализировать(СхемаКомпоновкиДанных);

// Загружаем в компоновщик стандартные настройки из схемы, чтобы не создавать их с нуля
КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);

Теперь объект КомпоновщикНастроек содержит все стандартные настройки отчета, и мы можем начать их модификацию.

Шаг 3: Установка отборов

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

Давайте рассмотрим, как установить отборы по складу и по списку номенклатуры, как это требовалось в исходной задаче.


// Установка отбора по складу
// 1. Создаем новый элемент отбора и добавляем его в коллекцию
ЭлементОтбораСклад = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

// 2. Указываем левое значение (поле, по которому отбираем)
ЭлементОтбораСклад.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Склад"); // Важно: имя поля должно соответствовать имени в схеме СКД

// 3. Указываем вид сравнения (например, "Равно", "В Списке", "Больше" и т.д.)
ЭлементОтбораСклад.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;

// 4. Указываем правое значение (значение, с которым сравниваем)
// Получаем нужный элемент справочника "Склады"
СкладДляОтбора = Справочники.Склады.НайтиПоНаименованию("Основной склад");
Если СкладДляОтбора <> Неопределено Тогда
    ЭлементОтбораСклад.ПравоеЗначение = СкладДляОтбора;
Иначе
    Сообщить("Склад 'Основной склад' не найден!");
КонецЕсли;

// 5. Обязательно устанавливаем использование отбора в Истина
ЭлементОтбораСклад.Использование = Истина;


// Установка отбора по списку номенклатуры
ЭлементОтбораНоменклатура = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбораНоменклатура.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Номенклатура"); // Имя поля в СКД
ЭлементОтбораНоменклатура.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке; // Отбор по списку значений

// Создаем список значений для отбора
СписокНоменклатурыДляОтбора = Новый СписокЗначений;
СписокНоменклатурыДляОтбора.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Товар 1"));
СписокНоменклатурыДляОтбора.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Товар 2"));
СписокНоменклатурыДляОтбора.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Товар 3")); // Добавим еще один для примера

// Проверяем, что элементы номенклатуры найдены
Для Каждого ЭлементСписка Из СписокНоменклатурыДляОтбора Цикл
    Если ЭлементСписка.Значение = Неопределено Тогда
        Сообщить("Не найдена номенклатура: " + ЭлементСписка.Представление);
        // Можно исключить из списка или обработать ошибку
    КонецЕсли;
КонецЦикла;

ЭлементОтбораНоменклатура.ПравоеЗначение = СписокНоменклатурыДляОтбора;
ЭлементОтбораНоменклатура.Использование = Истина;

Важный момент: Имена полей ("Склад", "Номенклатура") должны точно соответствовать именам полей, доступных в схеме компоновки данных. Вы можете посмотреть эти имена в конструкторе СКД, на вкладке "Поля", либо в отладчике, изучая объект СхемаКомпоновкиДанных.Поля.

Также важно устанавливать свойство Использование элемента отбора в Истина, иначе отбор не будет применен.

Шаг 4: Установка параметров

Многие отчеты СКД используют параметры, такие как период отчета (начало/конец), организацию, дату и другие. Мы можем программно задавать значения этих параметров. Доступ к параметрам осуществляется через коллекцию КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы. Это критически важно при построении сложных отчетов, таких как отчет по движениям товаров с резервами нарастающим итогом, где параметры периода определяют точность вычислений.

Рассмотрим пример установки параметров "НачалоПериода" и "КонецПериода":


// Получаем коллекцию элементов параметров данных
ПараметрыДанных = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы;

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

    // Устанавливаем КонецПериода
    ИначеЕсли ЭлементПараметра.Параметр.Имя = "КонецПериода" Тогда
        ЭлементПараметра.Значение = КонецМесяца(ТекущаяДата()); // Например, конец текущего месяца
        ЭлементПараметра.Использование = Истина; // Обязательно активируем параметр
    КонецЕсли;

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

КонецЦикла;

Как и в случае с отборами, свойство Использование для параметра должно быть установлено в Истина.

Шаг 5: Компоновка макета

После того как мы определили все необходимые настройки (отборы, параметры, группировки и т.д.), следующим шагом является создание макета компоновки данных. Макет компоновки данных — это, по сути, "план" выполнения отчета, сформированный на основе схемы и настроек. Для этого мы используем объект КомпоновщикМакетаКомпоновкиДанных.


// Создаем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

// Выполняем компоновку макета, передавая схему, настройки, и, при необходимости,
// внешние наборы данных (если отчет использует их)
// Четвертый параметр (ВнешниеНаборыДанных) обычно не нужен, если все данные из базы 1С.
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, , , Тип("ВнешниеНаборыДанных"));

В случае, если отчет использует внешние наборы данных (например, данные из файлов или других систем), последний параметр Тип("ВнешниеНаборыДанных") будет полезен. Для большинства стандартных отчетов он может быть опущен или передан как Неопределено.

Шаг 6: Инициализация процессора компоновки данных

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


// Создаем процессор компоновки данных
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;

// Инициализируем его нашим макетом компоновки
// Последний параметр (Истина) указывает, что нужно расшифровывать данные.
// Это может быть полезно, если вы собираетесь обрабатывать клики по ячейкам отчета.
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, , , Истина);

Шаг 7: Инициализация процессора вывода

Результат работы ПроцессораКомпоновкиДанных сам по себе является потоком данных, который неудобен для непосредственного просмотра. Для преобразования этого потока в привычный табличный документ мы используем ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент. Он "рисует" отчет в указанном табличном документе.


// Создаем новый табличный документ, куда будет выведен результат
ТабличныйДокумент = Новый ТабличныйДокумент;

// Создаем процессор вывода результата в табличный документ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;

// Устанавливаем, в какой табличный документ будет производиться вывод
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);

Вы можете настроить свойства ТабличныйДокумент перед выводом, например, установить ориентацию страницы, поля и другие параметры печати.

Шаг 8: Вывод результата

Наконец, мы запускаем процесс вывода. Процессор вывода последовательно обрабатывает элементы результата, полученные от процессора компоновки данных, и записывает их в табличный документ. Мы используем цикл Пока Истина для чтения всех элементов результата до тех пор, пока ПроцессорКомпоновкиДанных.Следующий() не вернет Неопределено, что означает окончание потока данных.


// Начинаем вывод результата
ПроцессорВывода.НачатьВывод();

// В цикле получаем следующий элемент результата от компоновщика и выводим его
Пока Истина Цикл
    ЭлементРезультата = ПроцессорКомпоновкиДанных.Следующий();
    Если ЭлементРезультата = Неопределено Тогда
        Прервать; // Все элементы выведены
    КонецЕсли;
    ПроцессорВывода.ВывестиЭлемент(ЭлементРезультата);
КонецЦикла;

// Завершаем вывод
ПроцессорВывода.ЗакончитьВывод();

// ТабличныйДокумент теперь содержит полностью сформированный отчет.
// Его можно сохранить, показать пользователю или отправить по почте.
// Пример сохранения в файл:
// ТабличныйДокумент.Записать("C:\Temp\МойОтчетПоОстаткам.xlsx", ТипФайлаТабличногоДокумента.XLSX);
// ТабличныйДокумент.Показать("Отчет по остаткам товаров");

После выполнения этого кода переменная ТабличныйДокумент будет содержать готовый отчет. Если вам требуется автоматизировать этот процесс на регулярной основе, пригодится универсальная отправка отчетов о продажах и остатках на e-mail, которая позволяет отправлять результат в форматах PDF или Excel.

Пример полного кода для формирования отчета "Остатки товаров" из УТ 11

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


Функция СформироватьИВывестиОтчетОстаткиТоваров(СкладДляОтбора, СписокНоменклатурыДляОтбора, НачалоПериодаОтчета, КонецПериодаОтчета)

    // Проверяем входные параметры на корректность
    Если СкладДляОтбора = Неопределено ИЛИ ТипЗнч(СкладДляОтбора) <> Тип("СправочникСсылка.Склады") Тогда
        Сообщить("Некорректно указан склад для отбора.", СтатусСообщения.Важное);
        Возврат Неопределено;
    КонецЕсли;

    Если СписокНоменклатурыДляОтбора = Неопределено ИЛИ СписокНоменклатурыДляОтбора.Количество() = 0 Тогда
        Сообщить("Список номенклатуры для отбора пуст или некорректен.", СтатусСообщения.Важное);
        Возврат Неопределено;
    КонецЕсли;

    Если ТипЗнч(НачалоПериодаОтчета) <> Тип("Дата") ИЛИ ТипЗнч(КонецПериодаОтчета) <> Тип("Дата") Тогда
        Сообщить("Некорректно указан период отчета.", СтатусСообщения.Важное);
        Возврат Неопределено;
    КонецЕсли;

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

        // 2. Создаем и инициализируем компоновщик настроек
        КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
        КомпоновщикНастроек.Инициализировать(СхемаКомпоновкиДанных);
        КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);

        // 3. Устанавливаем отборы
        ЭлементОтбораСклад = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлементОтбораСклад.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Склад");
        ЭлементОтбораСклад.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
        ЭлементОтбораСклад.ПравоеЗначение = СкладДляОтбора;
        ЭлементОтбораСклад.Использование = Истина;

        ЭлементОтбораНоменклатура = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлементОтбораНоменклатура.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Номенклатура");
        ЭлементОтбораНоменклатура.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
        ЭлементОтбораНоменклатура.ПравоеЗначение = СписокНоменклатурыДляОтбора;
        ЭлементОтбораНоменклатура.Использование = Истина;
        
        // 4. Устанавливаем параметры отчета (период)
        Для Каждого ЭлементПараметра Из КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы Цикл
            Если ЭлементПараметра.Параметр.Имя = "НачалоПериода" Тогда
                ЭлементПараметра.Значение = НачалоПериодаОтчета;
                ЭлементПараметра.Использование = Истина;
            ИначеЕсли ЭлементПараметра.Параметр.Имя = "КонецПериода" Тогда
                ЭлементПараметра.Значение = КонецПериодаОтчета;
                ЭлементПараметра.Использование = Истина;
            КонецЕсли;
        КонецЦикла;

        // 5. Компонуем макет
        КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
        МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, , , Тип("ВнешниеНаборыДанных"));

        // 6. Инициализируем процессор компоновки данных
        ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
        ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, , , Истина);

        // 7. Инициализируем процессор вывода
        ТабличныйДокумент = Новый ТабличныйДокумент;
        ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
        ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);

        // 8. Выводим результат
        ПроцессорВывода.НачатьВывод();
        Пока Истина Цикл
            ЭлементРезультата = ПроцессорКомпоновкиДанных.Следующий();
            Если ЭлементРезультата = Неопределено Тогда
                Прервать;
            КонецЕсли;
            ПроцессорВывода.ВывестиЭлемент(ЭлементРезультата);
        КонецЦикла;
        ПроцессорВывода.ЗакончитьВывод();
        
        Возврат ТабличныйДокумент;

    Исключение
        Сообщить("Ошибка при формировании отчета: " + ОписаниеОшибки(), СтатусСообщения.Важное);
        Возврат Неопределено;
    КонецПопытки;

КонецФункции

Дополнительные возможности и советы

Мы рассмотрели базовый сценарий программного формирования отчета СКД. Однако система СКД предлагает гораздо более широкие возможности для тонкой настройки.

  1. Изменение состава выводимых полей: Если вам необходимо изменить набор полей, вы можете получить доступ к коллекции КомпоновщикНастроек.Настройки.Выбор.Элементы.
  2. Настройка группировок: Группировки данных также могут быть программно настроены через коллекцию КомпоновщикНастроек.Настройки.Структура.Элементы.
  3. Сортировка: Порядок сортировки данных в отчете можно изменить с помощью КомпоновщикНастроек.Настройки.Порядок.Элементы.
  4. Условное оформление: Для применения условного оформления используйте коллекцию КомпоновщикНастроек.Настройки.УсловноеОформление.Элементы.
  5. Работа с вариантами отчетов: Вы можете загружать их настройки в КомпоновщикНастроек с помощью метода КомпоновщикНастроек.ЗагрузитьНастройки().
  6. Внешние отчеты: Для внешних отчетов сначала нужно прочитать файл в объект СхемаКомпоновкиДанных.
  7. Обработка ошибок: Всегда используйте блоки Попытка...Исключение при работе с СКД.
  8. Производительность: Для очень больших отчетов стоит учитывать производительность и возможность использования специализированных инструментов.

Заключение

Мы подробно рассмотрели процесс программного формирования отчетов на СКД в 1С 8.3, включая все ключевые этапы от получения схемы до вывода готового табличного документа. Этот механизм является мощным инструментом для автоматизации работы с отчетами и позволяет гибко управлять данными, настройками и представлением информации. Надеемся, что представленные примеры кода и объяснения помогут вам в решении ваших задач по автоматизации и разработке на платформе 1С:Предприятие.

← На главную