В практике разработки на платформе 1С нередко возникает ситуация, когда данные распределены между несколькими информационными базами. Одной из специфических задач является потребность собрать «составной» объект: например, когда текстовые описания и ссылочные данные хранятся в одной базе, а числовые показатели (остатки, цены, обороты) — в другой. Разберем детально, как реализовать такой механизм максимально эффективно и архитектурно правильно.
Предположим, у нас есть База №1 и База №2 с идентичной структурой метаданных. При формировании печатной формы в Базе №1 нам необходимо подтянуть значения из аналогичных таблиц Базы №2, используя для связи уникальный идентификатор (GUID), хранящийся в строковом поле. Рассмотрим основные способы решения этой задачи, начиная от программных интерфейсов и заканчивая глубокой интеграцией на уровне СУБД.
Рассмотрим наиболее «гуманный» и современный способ интеграции — использование HTTP-сервисов. В отличие от устаревшего COM-соединения, HTTP-сервисы работают быстрее, стабильнее и не зависят от разрядности сервера приложений.
Алгоритм реализации:
Проанализируем пример кода для получения данных из второй базы через 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);
КонецЕсли;
Возврат Неопределено;
КонецФункции
Если обе базы находятся в одной локальной сети или доступны через ODBC, наиболее производительным методом будет использование стандартного механизма 1С — Внешние источники данных. Это позволяет подключать таблицы другой базы напрямую и использовать их в обычных запросах 1С.
Разберем преимущества этого подхода:
Для настройки выполним следующие шаги:
_InfoRg123 — регистр сведений или _Document456).Для отчетов лучшим архитектурным решением будет использование СКД. Мы можем создать два набора данных: НаборДанныхЗапрос (для локальной базы) и НаборДанныхОбъект (для данных из внешней базы).
Рассмотрим ситуацию подробнее. Выясним, как связать эти данные программно:
Пример программного заполнения внешнего набора данных:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Выполняем первый запрос для получения ID
СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Получаем данные из внешней базы (например, через функцию из Варианта 1)
ТаблицаВнешнихДанных = СформироватьТаблицуЧиселИзБазы2();
// Создаем структуру внешних наборов данных
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ДанныеИзБазы2", ТаблицаВнешнихДанных);
// Запускаем компоновку
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Если вы опытный администратор или разработчик, работающий напрямую с 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С забирать числа из другого сервера базы данных.
Чтобы реализовать «универсальный паровоз» (как выразился автор темы), который будет работать для всех печатных форм, проанализируем использование Расширений. Мы можем перехватить процедуру печати в общих модулях подсистемы «Печать» (если используется БСП).
Рассмотрим шаги по унификации:
&Вместо("СформироватьДанныеДляПечатнойФормы") или аналогичным.ТаблицаЗначений с данными для печати, вызываем нашу функцию «дообогащения» данными из Базы №2.Пример логики в расширении:
&Вместо("СформироватьКоллекциюПечатныхФорм")
Процедура Расш_СформироватьКоллекциюПечатныхФорм(ПараметрыПечати)
// Сначала вызываем стандартный функционал
ПродолжитьВызов(ПараметрыПечати);
// Проходим по сформированным таблицам данных
Для Каждого ДанныеДляПечати Из ПараметрыПечати.ДанныеДляВывода Цикл
// Добавляем колонку, если её нет
Если ДанныеДляПечати.Колонки.Найти("ЧислоИзБазы2") = Неопределено Тогда
ДанныеДляПечати.Колонки.Добавить("ЧислоИзБазы2", Новый ОписаниеТипов("Число"));
КонецЕсли;
// Массово получаем данные и заполняем
ЗаполнитьЧислаИзВнешнегоИсточника(ДанныеДляПечати);
КонецЦикла;
КонецПроцедуры
Выбор конкретного метода зависит от объемов данных и инфраструктуры. Внешние источники данных — самый быстрый и надежный способ для работы на уровне СУБД. HTTP-сервисы — наиболее гибкий и безопасный вариант для распределенных систем. Использование СКД с объектными наборами данных позволяет сохранить всю мощь гибких настроек отчетов 1С, даже если данные приходят из «чужой» базы.
Помните о производительности: всегда старайтесь получать данные пакетно (массивом идентификаторов), а не в цикле по каждой строке, чтобы минимизировать количество сетевых вызовов между базами.