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

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

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

Методика решения задачи

Для решения этой задачи мы воспользуемся механизмом Набор данных - объект. Основная идея заключается в том, чтобы перехватить процесс формирования отчета, самостоятельно собрать все необходимые данные в таблицу значений (ТЗ) и передать эту таблицу в СКД. Рассмотрим пошаговый алгоритм реализации.

  1. Создадим в схеме компоновки данных (СКД) НаборДанныхОбъект и укажем имя его переменной (например, "АналитикаВремени").
  2. Добавим в этот набор поля с соответствующими типами (Водитель, НомерПропуска, ВремяПрихода и т.д.).
  3. Переопределим процедуру ПриКомпоновкеРезультата в модуле объекта отчета.

Реализация в процедуре ПриКомпоновкеРезультата

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


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // 1. Отключаем стандартный вывод отчета
    СтандартнаяОбработка = Ложь;
    
    // 2. Получаем основные данные из текущей базы запросом
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Водители.Ссылка КАК Водитель,
        |   Водители.НомерПропуска КАК НомерПропуска
        |ИЗ
        |   Справочник.Водители КАК Водители";
    
    РезультатЗапроса = Запрос.Выполнить();
    ТаблицаРезультат = РезультатЗапроса.Выгрузить();
    
    // 3. Добавляем колонку для внешних данных
    ТаблицаРезультат.Колонки.Добавить("ВремяПрихода", Новый ОписаниеТипов("Дата"));
    
    // 4. Опрашиваем внешнюю БД и заполняем таблицу
    Для Каждого СтрокаТаблицы Из ТаблицаРезультат Цикл
        Если ЗначениеЗаполнено(СтрокаТаблицы.НомерПропуска) Тогда
            // Вызываем функцию общего модуля, которая идет во внешнюю базу (SQL, API, COM)
            СтрокаТаблицы.ВремяПрихода = ОбщийМодульСервер.ПолучитьВремяИзВнешнейБД(СтрокаТаблицы.НомерПропуска);
        КонецЕсли;
    КонецЦикла;

    // 5. Инициализируем схему и настройки
    СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // 6. Подготавливаем внешние наборы данных
    ВнешнийНаборДанных = Новый Структура("АналитикаВремени", ТаблицаРезультат);
    
    // 7. Компоновка макета
    ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    // 8. Инициализация процессора компоновки с передачей внешних данных
    ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
    
    // КРИТИЧЕСКИ ВАЖНО: Разрешаем использование внешних функций, если они есть в СКД
    ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешнийНаборДанных, ДанныеРасшифровки, Истина);
    
    // 9. Вывод результата в табличный документ
    ДокументРезультат.Очистить();
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);

КонецПроцедуры

Разбор важных нюансов

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

Оптимизация получения данных: В приведенном примере мы используем цикл Для каждого для обращения к внешней БД. Если в отчете 1000 строк, система сделает 1000 отдельных запросов к сторонней базе, что крайне неэффективно. Рассмотрим более производительный подход:

  1. Выгрузим все уникальные номера пропусков из ТаблицаРезультат в массив.
  2. Передадим этот массив во внешнюю систему одним запросом (например, используя конструкцию WHERE TicketNumber IN (...) в SQL).
  3. Получим одну общую таблицу соответствий и объединим ее с основной таблицей в 1С.

Типизация колонок: При программном создании колонок в ТаблицаЗначений обязательно указывайте ОписаниеТипов. Если колонка будет без типа (содержать Произвольный), СКД может некорректно обрабатывать итоги, группировки или форматирование дат и чисел.

Связи наборов данных (Запрос + Объект)

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

Проанализируем преимущества такого подхода: нам не нужно вручную соединять таблицы в коде. Достаточно на закладке Связи наборов данных в конструкторе СКД указать связь по полю НомерПропуска. В этом случае СКД сама сопоставит строки, а программный код в ПриКомпоновкеРезультата станет значительно проще — достаточно будет только подготовить ТЗ с "приходами" и передать ее в структуру ВнешниеНаборыДанных.

Работа в фоновом задании

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

← На главную