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

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

При построении консолидированной отчетности часто возникает задача собрать данные из нескольких информационных баз (например, нескольких филиальных конфигураций 1С:Бухгалтерия) в одну центральную базу. Типичная реализация строится на базе системы компоновки данных (СКД): первый набор данных выбирает данные локальной базы, второй получает данные из удаленных баз через COM-соединение или веб-сервисы, после чего наборы объединяются.

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

Причина проблемы: типизация полей в наборах данных СКД

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

Чтобы предоставить пользователю возможность выбирать привычные элементы локального справочника и при этом корректно фильтровать данные внешних источников, рассмотрим несколько проверенных подходов.

Способ 1. Приведение данных внешней базы к ссылкам текущей базы

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

Разберем по шагам реализацию этого механизма:

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

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


// В ТаблицаВнешнихДанных содержатся поля: ИНН, Сумма
ТаблицаВнешнихДанных.Колонки.Добавить("Контрагент", Новый ОписаниеТипов("СправочникСсылка.Контрагенты"));

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВнешниеДанные.ИНН КАК ИНН,
    |	ВнешниеДанные.Сумма КАК Сумма
    |ПОМЕСТИТЬ ВТ_Внешние
    |ИЗ
    |	&ТаблицаВнешнихДанных КАК ВнешниеДанные
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	Спр.Ссылка КАК Контрагент,
    |	ВТ_Внешние.Сумма КАК Сумма
    |ИЗ
    |	ВТ_Внешние КАК ВТ_Внешние
    |	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Спр
    |		ПО ВТ_Внешние.ИНН = Спр.ИНН";

Запрос.УстановитьПараметр("ТаблицаВнешнихДанных", ТаблицаВнешнихДанных);
ТаблицаДляСКД = Запрос.Выполнить().Выгрузить();

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

Способ 2. Параметризация внешних запросов без динамической сборки текста

Если объем внешних данных велик, передавать всю таблицу в текущую базу и фильтровать ее в памяти неэффективно: отбор должен применяться на стороне внешней СУБД. Чтобы не конструировать строковые условия ГДЕ программно («не дербанить запрос»), применим универсальную параметризацию с логическими флагами.

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


ВЫБРАТЬ
	Остатки.Номенклатура.Наименование КАК НоменклатураНаименование,
	Остатки.КоличествоОстаток КАК Количество
ИЗ
	РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки
ГДЕ
	(&ОтборПоНоменклатуреВключен = ЛОЖЬ 
		ИЛИ Остатки.Номенклатура.Наименование В (&СписокНоменклатуры))

Разберем алгоритм передачи параметров перед выполнением внешнего запроса:

  1. В процедуре ПриКомпоновкеРезультата модуля отчета считываем настройки компоновщика.
  2. Находим нужный элемент в коллекции КомпоновщикНастроек.ПолучитьНастройки().Отбор.Элементы.
  3. Если отбор включен (ЭлементОтбора.Использование = Истина), извлекаем выбранные пользователем ссылки из поля ПравоеЗначение.
  4. Запросом в текущей базе получаем массив наименований или ИНН по выбранным ссылкам.
  5. Передаем полученный массив в параметр &СписокНоменклатуры внешнего подключения, а параметру &ОтборПоНоменклатуреВключен присваиваем Истина.
  6. Если отбор не установлен или выключен пользователем, передаем пустой массив и флаг Ложь.

Посмотрим, как безопасно прочитать значение отбора из компоновщика настроек:


Настройки = КомпоновщикНастроек.ПолучитьНастройки();
СписокДляВнешнейБазы = Новый Массив;
ОтборВключен = Ложь;

Для Каждого Элемент Из Настройки.Отбор.Элементы Цикл
	Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") 
		И Элемент.Использование 
		И Строка(Элемент.ЛевоеЗначение) = "Контрагент" Тогда
		
		ОтборВключен = Истина;
		Если ТипЗнч(Элемент.ПравоеЗначение) = Тип("СписокЗначений") Тогда
			Для Каждого ЭлементСписка Из Элемент.ПравоеЗначение Цикл
				СписокДляВнешнейБазы.Добавить(ЭлементСписка.Значение.Наименование);
			КонецЦикла;
		ИначеЕсли ЗначениеЗаполнено(Элемент.ПравоеЗначение) Тогда
			СписокДляВнешнейБазы.Добавить(Элемент.ПравоеЗначение.Наименование);
		КонецЕсли;
	КонецЕсли;
КонецЦикла;

ВнешнийЗапрос.УстановитьПараметр("СписокНоменклатуры", СписокДляВнешнейБазы);
ВнешнийЗапрос.УстановитьПараметр("ОтборПоНоменклатуреВключен", ОтборВключен);

Способ 3. Синхронизация по УИД и типовым регистрам соответствий

Если между базами настроен регулярный обмен или элементы синхронизируются по уникальным идентификаторам (UUID), сопоставление по строковым наименованиям становится избыточным. Наиболее надежный способ — обращение к регистру сведений СоответствиеОбъектовИнформационныхБаз.

В типовых решениях (таких как 1С:Бухгалтерия) данный регистр хранит связь между ссылкой локальной базы и уникальным строковым идентификатором объекта в удаленном узле. В таком сценарии:

  1. Пользователь указывает стандартный отбор по справочнику в консолидирующей базе.
  2. По выбранным ссылкам из регистра сведений извлекаются идентификаторы объектов внешней базы (УникальныйИдентификатор).
  3. Во внешней базе по строковым UUID через метод ПолучитьСсылку() соответствующего менеджера справочника восстанавливаются ссылки удаленной базы и передаются в параметры запроса.

Это исключает проблемы несовпадения наименований из-за опечаток, лишних пробелов или переименований контрагентов в разных базах.

Ограничения и подводные камни при работе с внешними наборами данных

При проектировании отчетов на СКД с внешними источниками важно учитывать следующие технические особенности платформы:

  1. Работа с иерархией: Отбор с видом сравнения «В иерархии» невозможно применить напрямую к строковому полю. Если используется сопоставление через ссылки текущей базы (Способ 1), отбор по иерархии отработает корректно только в рамках структуры папок консолидирующей базы. Если во внешней базе товар лежит в другой группе, результат может разойтись.
  2. Связывание наборов в оперативной памяти: Если объединять локальный набор данных типа «Запрос» и внешний набор типа «Объект» через вкладку «Связи наборов данных», процессор компоновки выполняет левое или полное соединение в оперативной памяти сервера 1С. При выборках объемом свыше десятков тысяч строк это может вызывать повышенный расход RAM и замедление формирования отчета.
  3. Ограничения COM-соединения: При использовании прямого COM-подключения к внешним базам следует помнить о разрядности процессов. 64-разрядный сервер 1С:Предприятия не может обращаться к 32-разрядному COM-коннектору без настройки выделенного пула приложений COM+. Кроме того, интенсивное создание сеансов COM без явного завершения и сборки мусора приводит к утечкам памяти в рабочих процессах сервера.

Альтернативные архитектурные решения

Если регламент выполнения отчетов или объем данных приводят к нестабильной работе соединений, рекомендуется рассмотреть альтернативные варианты консолидации:

  1. Публикация HTTP-сервисов или использование OData: Вместо COM-соединения внешние базы могут отдавать данные через HTTP-сервис. Текущая база отправляет запрос с параметрами фильтрации в формате JSON и получает готовую отфильтрованную таблицу. Это снимает проблемы с разрядностью библиотек и платформенными блокировками сеансов.
  2. Регламентная репликация в служебный регистр: Если оперативные данные с точностью до секунды не требуются, сбор агрегированных показателей из внешних баз переносится в ночное фоновое задание. Данные записываются в служебный регистр сведений текущей базы. В таком случае отчет строится по стандартной схеме на единственном наборе данных «Запрос», что гарантирует максимальную производительность и полную поддержку всех видов отборов СКД.
← На главную