Работа с отчетами через COM-соединение — это классическая задача при интеграции различных баз 1С. Одной из самых частых трудностей, с которыми сталкиваются разработчики, является передача сложных типов данных, таких как СписокЗначений или Массив, в параметры схемы компоновки данных (СКД). Часто возникает ситуация, когда код кажется верным, соединение установлено, но отчет возвращает пустой результат. Разберем детально, как правильно реализовать этот механизм, и на что обратить внимание, чтобы избежать типичных ошибок.
Прежде чем переходить к коду, проанализируем фундаментальное правило работы COM-соединения в 1С: объект считается «своим» только тогда, когда он создан в контексте того же самого соединения. Если мы создадим СписокЗначений в текущей базе и попытаемся передать его в метод внешней базы через COM, внешняя база не сможет распознать его как корректный объект 1С. Она увидит его как универсальный COMОбъект, который нельзя напрямую использовать в запросе или фильтре СКД.
Рассмотрим выдержку из технической документации, которая объясняет это поведение: если 1С:Предприятие получает объект типа VT_DISPATCH, оно преобразует его в COMОбъект. Но если объект был создан тем же самым экземпляром соединения, 1С «узнает» его и позволит работать с ним как с родным типом. Именно поэтому для создания коллекций значений (массивов, списков) мы должны использовать метод NewObject() самого COM-соединения.
Начнем с инициализации подключения и получения макета отчета. Предположим, мы подключаемся к базе ЗУП для получения данных по подразделениям. Посмотрим на пример кода:
// Устанавливаем соединение с внешней базой
ЗУП = ПодключениеComС("ПутьКБазе", "Логин", "Пароль");
// Получаем схему компоновки из внешнего отчета
СхемаКомпоновкиДанных = ЗУП.Отчеты.Отчет1.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// Инициализируем компоновщик настроек во внешней базе
КомпоновщикНастроекНастройки = ЗУП.NewObject("КомпоновщикНастроекКомпоновкиДанных");
ИсточникДоступныхНастроек = ЗУП.NewObject("ИсточникДоступныхНастроекКомпоновкиДанных", СхемаКомпоновкиДанных);
КомпоновщикНастроекНастройки.Инициализировать(ИсточникДоступныхНастроек);
Выясним причину, почему обычное создание списка значений в нашей базе не сработает. Нам необходимо, чтобы список содержал ссылки, понятные для удаленной базы. Для этого мы выполняем запрос во внешней базе, получаем результат и заполняем список, созданный через ЗУП.NewObject("СписокЗначений").
// Загружаем настройки по умолчанию
КомпоновщикНастроекНастройки.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);
Настройки = КомпоновщикНастроекНастройки.ПолучитьНастройки();
// Формируем список подразделений во внешней базе
Запрос = ЗУП.NewObject("Запрос");
Запрос.Текст =
"ВЫБРАТЬ
| ПодразделенияОрганизаций.Ссылка КАК Подразделение
|ИЗ
| Справочник.ПодразделенияОрганизаций КАК ПодразделенияОрганизаций";
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
СписокПодразделений = ЗУП.NewObject("СписокЗначений");
Для Каждого Строка Из РезультатЗапроса Цикл
// Добавляем ссылку, которая уже является COM-объектом удаленной базы
СписокПодразделений.Добавить(Строка.Подразделение);
КонецЦикла;
Важный нюанс: Если вы планируете передавать ссылки по их коду или наименованию, используйте методы поиска удаленной базы, например: ЗУП.Справочники.ПодразделенияОрганизаций.НайтиПоКоду("001"). Это гарантирует, что в параметр попадет объект, который удаленная СКД сможет сопоставить со своими данными.
Теперь рассмотрим момент, где чаще всего совершается ошибка. После того как мы получили объект Настройки и установили в нем параметр, мы должны использовать именно этот измененный объект при генерации макета. Проанализируем типичную ошибку:
// Устанавливаем значение параметра
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("СписокПодразделений", СписокПодразделений);
// ОШИБКА: Использование КомпоновщикНастроекНастройки.Настройки вместо переменной Настройки
// КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроекНастройки.Настройки...);
// ПРАВИЛЬНО: Передаем объект Настройки, в котором мы реально меняли параметры
КомпоновщикМакета = ЗУП.NewObject("КомпоновщикМакетаКомпоновкиДанных");
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, , ,
ЗУП.NewObject("ОписаниеТипов", "ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений").Типы().Получить(0));
Разберем подробнее: когда мы вызываем КомпоновщикНастроек.ПолучитьНастройки(), мы создаем копию текущих настроек. Изменяя параметры в этой копии (переменная Настройки), мы не меняем состояние самого КомпоновщикНастроекНастройки.Настройки автоматически. Поэтому при вызове КомпоновщикМакета.Выполнить необходимо передавать именно тот объект, в котором были произведены изменения.
Завершающим этапом является инициализация процессора компоновки и вывод данных. Поскольку мы работаем через COM, результат удобнее всего выгружать в ТаблицуЗначений, созданную также на стороне внешней базы, чтобы затем передать её обратно в нашу информационную систему.
ПроцессорКомпоновкиДанных = ЗУП.NewObject("ПроцессорКомпоновкиДанных");
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных);
ПроцессорВывода = ЗУП.NewObject("ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений");
ДанныеТЗ = ЗУП.NewObject("ТаблицаЗначений");
ПроцессорВывода.УстановитьОбъект(ДанныеТЗ);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
// Теперь ДанныеТЗ содержит результат выполнения отчета с учетом переданных фильтров
Проанализируем альтернативные способы передачи данных, если стандартный СписокЗначений через COM работает нестабильно (например, при специфических настройках прав или использовании 64-разрядного сервера с 32-разрядными компонентами):
В (&Параметр) одинаково хорошо работает как со списком, так и с массивом.UUID подразделений. На стороне внешней базы в коде или прямо в тексте запроса СКД можно преобразовать эти строки обратно в ссылки, используя метод ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаGUID)).XML или JSON. Вы превращаете список параметров в строку на своей стороне, передаете её как один текстовый параметр через COM, а на удаленной стороне (внутри экспортной функции) десериализуете её обратно в объекты 1С.СправочникСсылка.ПодразделенияОрганизаций, а вы передаете СписокЗначений, не забудьте убедиться, что в настройках параметра в самой схеме разрешено использование списка (флаг "Доступен список значений").Таким образом, успех передачи параметров через COM зависит от двух факторов: создания объектов коллекций в контексте внешней базы и правильного использования переменных настроек при компоновке макета. Соблюдение этих правил позволит вам эффективно использовать мощь СКД при работе с распределенными базами данных.