В практике автоматизации нередко возникает задача объединить оперативные данные из нескольких баз 1С в один отчет. Типичный сценарий — две базы конфигурации 1С:Управление торговлей 10.3, в которых ведутся разные организации с идентичными по структуре и составу справочниками, а руководству требуется сводный анализ по регистру накопления Продажи. Разберем архитектурные особенности, возможные технические сложности и рабочие способы решения этой задачи с помощью Системы компоновки данных (СКД).
Прежде чем приступать к реализации, проанализируем ограничения механизмов платформы, с которыми неизбежно придется столкнуться при объединении данных «на лету»:
ОБЪЕДИНИТЬ ВСЕ) между разными наборами данных.COMConnector приводит к отдельным межпроцессным вызовам на каждое обращение к реквизиту объекта, что делает формирование отчета крайне медленным.Наиболее контролируемый подход при формировании отчета «на лету» — выполнение запроса на стороне удаленной базы с получением уже свернутых данных, передача их в виде примитивных типов и последующее объединение в локальном запросе СКД через МенеджерВременныхТаблиц.
Разберем по шагам, как правильно реализовать этот механизм:
ТаблицаЗначений с явной типизацией колонок.ОБЪЕДИНИТЬ ВСЕ с локальным регистром.ПолучитьСсылку() менеджера соответствующего справочника, что возвращает отчету возможность группировок по иерархии и стандартной расшифровки.Посмотрим на пример кода получения данных через COM-соединение:
Функция ПолучитьПродажиУдаленнойБазы(СтрокаПодключения, ДатаНач, ДатаКон)
РезультатТЗ = Новый ТаблицаЗначений;
РезультатТЗ.Колонки.Добавить("НоменклатураГУИД", Новый ОписаниеТипов("Строка",,,, Новый КвалификаторыСтроки(36)));
РезультатТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
РезультатТЗ.Колонки.Добавить("СуммаВыручки", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
Попытка
V83COM = Новый COMОбъект("V83.COMConnector");
Соединение = V83COM.Connect(СтрокаПодключения);
Исключение
ВызватьИсключение "Не удалось подключиться ко второй базе: " + ОписаниеОшибки();
КонецПопытки;
ЗапросCOM = Соединение.NewObject("Запрос");
ЗапросCOM.Текст =
"ВЫБРАТЬ
| ПродажиОбороты.Номенклатура.УникальныйИдентификатор КАК НоменклатураГУИД,
| ПродажиОбороты.КоличествоОборот КАК Количество,
| ПродажиОбороты.СтоимостьОборот КАК СуммаВыручки
|ИЗ
| РегистрНакопления.Продажи.Обороты(&ДатаНач, &ДатаКон, Авто, ) КАК ПродажиОбороты";
ЗапросCOM.УстановитьПараметр("ДатаНач", ДатаНач);
ЗапросCOM.УстановитьПараметр("ДатаКон", ДатаКон);
Выборка = ЗапросCOM.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Стр = РезультатТЗ.Добавить();
Стр.НоменклатураГУИД = Строка(Выборка.НоменклатураГУИД);
Стр.Количество = Выборка.Количество;
Стр.СуммаВыручки = Выборка.СуммаВыручки;
КонецЦикла;
Возврат РезультатТЗ;
КонецФункции
Теперь рассмотрим, как объединить эту таблицу с данными текущей информационной базы в модуле отчета перед формированием схемы компоновки:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Получаем внешние данные
ВнешниеПродажи = ПолучитьПродажиУдаленнойБазы(ПараметрыПодключения, ПериодНачало, ПериодКонец);
// Добавляем локальные ссылки по GUID
ВнешниеПродажи.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Для Каждого Стр Из ВнешниеПродажи Цикл
Стр.Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(Стр.НоменклатураГУИД));
КонецЦикла;
// Передаем таблицу параметров в запрос СКД через набор данных
ВнешниеНаборы = Новый Структура;
ВнешниеНаборы.Вставить("ТаблицаВнешнихПродаж", ВнешниеПродажи);
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(Макет, ВнешниеНаборы, ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
В тексте запроса набора данных СКД используем временную таблицу и оператор объединения:
ВЫБРАТЬ
ТЗ.Номенклатура КАК Номенклатура,
ТЗ.Количество КАК Количество,
ТЗ.СуммаВыручки КАК СуммаВыручки
ПОМЕСТИТЬ ВТ_ВнешниеПродажи
ИЗ
&ТаблицаВнешнихПродаж КАК ТЗ
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ПродажиОбороты.Номенклатура КАК Номенклатура,
ПродажиОбороты.КоличествоОборот КАК Количество,
ПродажиОбороты.СтоимостьОборот КАК СуммаВыручки
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК ПродажиОбороты
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ВТ.Номенклатура,
ВТ.Количество,
ВТ.СуммаВыручки
ИЗ
ВТ_ВнешниеПродажи КАК ВТ
Если базы физически распределены, находятся в разных сегментах сети или сервер 1С работает под управлением 64-разрядной ОС (где использование 32-разрядного COMConnector требует отдельной настройки приложений COM+), COM-соединение становится ненадежным. В этом случае правильнее поднять сервис во второй базе.
Важно помнить: объект ТаблицаЗначений не поддерживается фабрикой XDTO напрямую. Для его передачи через сервис применяем один из способов:
ЗаписьXML и метода СериализаторXDTO.ЗаписатьXML().ЗначениеВСтрокуВнутр() или ЗначениеВФайл() с передачей через SOAP как base64Binary.Динамическое получение данных при каждом нажатии кнопки «Сформировать» имеет существенный недостаток: если удаленная база заблокирована, выполняет регламентные операции или связь нестабильна, формирование отчета завершается аварийно либо надолго блокирует сеанс пользователя.
Для стабильной работы применяем архитектуру с кэшированием:
ПродажиУдаленнойБазы) с измерениями ПериодДень, Номенклатура, Организация и ресурсами Количество, Сумма.ОБЪЕДИНИТЬ ВСЕ.Такой подход полностью изолирует пользователей от проблем сетевого взаимодействия, гарантирует мгновенное формирование отчета в СКД и исключает зависимость от внешних сессий.