Как адаптировать отчет «Продажи» для анализа данных из нескольких информационных баз?

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

Разберем актуальную задачу: создание консолидированного отчета «Продажи», который должен в режиме реального времени собирать, агрегировать и выводить данные из нескольких территориально распределенных информационных баз. При этом решение должно быть универсальным (работать в толстом, тонком и веб-клиенте) и оформлено в виде внешнего отчета .erf.

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

Метод 1: Использование COM-соединения (COMConnector)

Рассмотрим наиболее классический вариант для внешнего отчета — использование механизма COM. Этот метод позволяет подключиться к удаленной базе напрямую, выполнить там запрос и забрать результат. Однако важно помнить, что этот метод плохо подходит для веб-клиента и серверов на базе Linux.

Выясним алгоритм действий для реализации этого метода в модуле отчета:

  1. Создаем цикл по списку информационных баз.
  2. Для каждой базы устанавливаем соединение через V83.COMConnector.
  3. Выполняем запрос к регистру накопления «Выручка и продажи» (или аналогичному в УТ 11) на стороне удаленной базы.
  4. Выгружаем результат в таблицу значений и объединяем все таблицы в одну общую структуру.

Посмотрим на пример кода для установки соединения и получения данных:


// Функция получения данных из одной удаленной базы
Функция ПолучитьДанныеИзУдаленнойБазы(СтрокаПодключения, ПараметрыОтчета)
    
    COMСоединитель = Новый COMОбъект("V83.COMConnector");
    
    Попытка
        УдаленнаяБаза = COMСоединитель.Connect(СтрокаПодключения);
    Исключение
        ЗаписатьЛогОшибок("Не удалось подключиться к базе: " + ОписаниеОшибки());
        Возврат Неопределено;
    КонецПопытки;
    
    Запрос = УдаленнаяБаза.NewObject("Запрос");
    Запрос.Текст = 
    "ВЫБРАТЬ
    |   ВыручкаИПродажи.Номенклатура.Наименование КАК Номенклатура,
    |   СУММА(ВыручкаИПродажи.Количество) КАК Количество,
    |   СУММА(ВыручкаИПродажи.СуммаВыручки) КАК Сумма
    |ИЗ
    |   РегистрНакопления.ВыручкаИПродажи КАК ВыручкаИПродажи
    |ГДЕ
    |   ВыручкаИПродажи.Период МЕЖДУ &НачалоПериода И &КонецПериода
    |СГРУППИРОВАТЬ ПО
    |   ВыручкаИПродажи.Номенклатура.Наименование";
    
    Запрос.УстановитьПараметр("НачалоПериода", ПараметрыОтчета.НачалоПериода);
    Запрос.УстановитьПараметр("КонецПериода", ПараметрыОтчета.КонецПериода);
    
    РезультатЗапроса = Запрос.Выполнить().Выгрузить();
    
    // Преобразование COM-таблицы в локальную таблицу значений 1С
    ЛокальнаяТЗ = ПреобразоватьComТЗвЛокальную(РезультатЗапроса);
    
    Возврат ЛокальнаяТЗ;
    
КонецФункции

Важный нюанс: при использовании COM данные возвращаются в виде специфических объектов. Чтобы передать их в СКД центральной базы, их необходимо перегнать в обычную ТаблицаЗначений.

Метод 2: Использование HTTP-сервисов (для веб-клиента и низких скоростей)

Проанализируем современный подход. Если в задании указано требование работы в веб-клиенте и наличие низкоскоростных соединений, то HTTP-сервисы — лучший выбор. В каждой региональной базе публикуется HTTP-сервис, который принимает параметры (период, отборы), выполняет запрос на месте и возвращает сжатый JSON.

Разберем преимущества этого способа:

  1. Минимальный трафик: Мы передаем не сырые данные, а уже агрегированные (сгруппированные) результаты в формате текста.
  2. Кроссплатформенность: Работает везде, где есть доступ к сети, независимо от операционной системы сервера.
  3. Безопасность: Не нужно открывать доступ к портам SQL или DCOM, достаточно стандартного 80 или 443 порта.

В тексте внешнего отчета выполнение запроса будет выглядеть так:


HTTPСоединение = Новый HTTPСоединение("region-server.com", , "user", "password");
HTTPЗапрос = Новый HTTPЗапрос("/v1/sales_report?start=" + ФорматДаты(НачалоПериода));
Ответ = HTTPСоединение.Получить(HTTPЗапрос);

Если Ответ.КодСостояния = 200 Тогда
    ДанныеJSON = Ответ.ПолучитьТелоКакСтроку();
    ТаблицаРегиона = ПрочитатьJSONВТаблицу(ДанныеJSON);
КонецЕсли;

Интеграция с СКД через внешний набор данных

Как сделать так, чтобы полученная таблица значений отобразилась в стандартном отчете с пользовательскими настройками? Выясним, как использовать Систему Компоновки Данных (СКД) с внешним источником.

Рассмотрим шаги настройки схемы компоновки:

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

Пример программного вывода отчета с внешним набором данных:


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

Оптимизация для низкоскоростных соединений

Выясним причину медленной работы подобных отчетов. Чаще всего программисты пытаются выгрузить детальные записи регистра из удаленной базы в центральную. Это в корне неверно.

Золотое правило агрегации: Суммируйте и группируйте данные на стороне «источника». Если пользователю нужен отчет по месяцам в разрезе складов, удаленная база должна вернуть ровно столько строк, сколько комбинаций «Месяц + Склад» существует, а не тысячи строк отдельных документов продажи.

Дополнительно рекомендуется:

Таким образом, мы проанализировали два основных способа реализации. Для быстрого решения «здесь и сейчас» в рамках одного офиса подойдет COM-соединение. Для профессиональной промышленной эксплуатации в распределенной сети с веб-доступом единственным верным решением будет использование HTTP-сервисов и передача агрегированных данных во Внешний набор данных СКД.

← На главную