Как объединить данные из двух баз 1С для формирования печатных форм и отчетов?

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

В практике разработки на платформе 1С нередко возникает ситуация, когда данные распределены между несколькими информационными базами. Одной из специфических задач является потребность собрать «составной» объект: например, когда текстовые описания и ссылочные данные хранятся в одной базе, а числовые показатели (остатки, цены, обороты) — в другой. Разберем детально, как реализовать такой механизм максимально эффективно и архитектурно правильно.

Постановка задачи и выбор стратегии

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

Вариант 1. Использование программных интерфейсов (HTTP-сервисы и COM)

Рассмотрим наиболее «гуманный» и современный способ интеграции — использование HTTP-сервисов. В отличие от устаревшего COM-соединения, HTTP-сервисы работают быстрее, стабильнее и не зависят от разрядности сервера приложений.

Алгоритм реализации:

  1. В Базе №2 создаем HTTP-сервис, который принимает массив уникальных идентификаторов (GUID).
  2. Сервис выполняет запрос к своим таблицам, собирает числовые данные и возвращает их в формате JSON.
  3. В Базе №1 при формировании печатной формы мы отправляем запрос к этому сервису и получаем структуру данных.

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


// В Базе №1 (клиентская часть или серверный модуль печати)
Функция ПолучитьЧислаИзВторойБазы(МассивИдентификаторов)
    
    Соединение = Новый HTTPСоединение("server_base2", 80, "Логин", "Пароль");
    ЗапросHTTP = Новый HTTPЗапрос("/v1/get_numbers");
    
    // Сериализуем массив GUID в JSON для передачи
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, МассивИдентификаторов);
    СтрокаJSON = ЗаписьJSON.Закрыть();
    
    ЗапросHTTP.УстановитьТелоИзСтроки(СтрокаJSON);
    Ответ = Соединение.ОтправитьДляОбъекта(ЗапросHTTP, "POST");
    
    Если Ответ.КодСостояния = 200 Тогда
        ЧтениеJSON = Новый ЧтениеJSON;
        ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
        Возврат ПрочитатьJSON(ЧтениеJSON);
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Вариант 2. Механизм внешних источников данных

Если обе базы находятся в одной локальной сети или доступны через ODBC, наиболее производительным методом будет использование стандартного механизма 1С — Внешние источники данных. Это позволяет подключать таблицы другой базы напрямую и использовать их в обычных запросах 1С.

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

Для настройки выполним следующие шаги:

  1. В дереве конфигурации перейдем в ветку Внешние источники данных.
  2. Добавим новый источник и настроим строку подключения к SQL-базе второй инфосистемы.
  3. Выберем необходимые таблицы (например, _InfoRg123 — регистр сведений или _Document456).
  4. В коде запроса печатной формы просто обратимся к этой таблице через точку.

Вариант 3. Система компоновки данных (СКД) и несколько наборов данных

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

Рассмотрим ситуацию подробнее. Выясним, как связать эти данные программно:

  1. Первый набор данных извлекает ссылки и строковые идентификаторы.
  2. В модуле отчета мы получаем список этих идентификаторов.
  3. Через веб-сервис или прямой SQL-запрос получаем таблицу с числами из Базы №2.
  4. Передаем эту таблицу во второй набор данных СКД.

Пример программного заполнения внешнего набора данных:


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

Вариант 4. Использование связанных серверов (Linked Servers) на уровне SQL

Если вы опытный администратор или разработчик, работающий напрямую с MS SQL Server, можно настроить Linked Server. Это позволяет обращаться к таблицам Базы №2 прямо из SQL-запроса Базы №1.

Посмотрим на пример SQL-представления (View), которое можно создать в Базе №1 для объединения данных:


CREATE VIEW v_MergedData AS
SELECT 
    b1.ID_String, 
    b1.Name, 
    b2.Value_Number
FROM Base1.dbo._InfoRg100 b1
LEFT JOIN [SERVER2].[Base2].dbo._InfoRg100 b2 ON b1.ID_String = b2.ID_String

После создания такого представления его можно подключить в 1С как внешний источник данных. Для системы это будет выглядеть как одна плоская таблица, хотя фактически SQL-сервер будет «прозрачно» для 1С забирать числа из другого сервера базы данных.

Унификация решения через расширения конфигурации

Чтобы реализовать «универсальный паровоз» (как выразился автор темы), который будет работать для всех печатных форм, проанализируем использование Расширений. Мы можем перехватить процедуру печати в общих модулях подсистемы «Печать» (если используется БСП).

Рассмотрим шаги по унификации:

  1. Создаем расширение конфигурации.
  2. Добавляем в него общий модуль с методом &Вместо("СформироватьДанныеДляПечатнойФормы") или аналогичным.
  3. В этом методе, после получения стандартной ТаблицаЗначений с данными для печати, вызываем нашу функцию «дообогащения» данными из Базы №2.
  4. Функция ищет колонку с идентификатором, запрашивает недостающие числа и заполняет соответствующие колонки в таблице.

Пример логики в расширении:


&Вместо("СформироватьКоллекциюПечатныхФорм")
Процедура Расш_СформироватьКоллекциюПечатныхФорм(ПараметрыПечати)
    // Сначала вызываем стандартный функционал
    ПродолжитьВызов(ПараметрыПечати);
    
    // Проходим по сформированным таблицам данных
    Для Каждого ДанныеДляПечати Из ПараметрыПечати.ДанныеДляВывода Цикл
        // Добавляем колонку, если её нет
        Если ДанныеДляПечати.Колонки.Найти("ЧислоИзБазы2") = Неопределено Тогда
            ДанныеДляПечати.Колонки.Добавить("ЧислоИзБазы2", Новый ОписаниеТипов("Число"));
        КонецЕсли;
        
        // Массово получаем данные и заполняем
        ЗаполнитьЧислаИзВнешнегоИсточника(ДанныеДляПечати);
    КонецЦикла;
КонецПроцедуры

Выводы и рекомендации

Выбор конкретного метода зависит от объемов данных и инфраструктуры. Внешние источники данных — самый быстрый и надежный способ для работы на уровне СУБД. HTTP-сервисы — наиболее гибкий и безопасный вариант для распределенных систем. Использование СКД с объектными наборами данных позволяет сохранить всю мощь гибких настроек отчетов 1С, даже если данные приходят из «чужой» базы.

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

← На главную