В процессе изучения КД3 меня не оставляло ощущение, что выгрузка данных в этом формате должна делаться как-то очень просто. Тут же возникла потребность сделать нестандартную "догрузку" множества физлиц с паспортными данными в ЗУП 3. После отсечения всего лишнего получилась короткая процедура. Что же внутри?
Инициализация
1. Инициализация структуры КомпонентыОбмена
ИмяФайлаПротоколаОбмена=""; // если заполнить - будет писаться лог в файл КомпонентыОбмена = ОбменДаннымиXDTOСервер.ИнициализироватьКомпонентыОбмена("Отправка"); КомпонентыОбмена.ВедениеПротоколаДанных.ВыводВПротоколИнформационныхСообщений = Ложь; КомпонентыОбмена.КлючСообщенияЖурналаРегистрации = ОбменДаннымиСервер.СобытиеЖурналаРегистрацииОбменДанными(); КомпонентыОбмена.ЭтоОбменЧерезПланОбмена = Ложь;
2. Определяем версию формата обмена.
Можно просто указать, скажем, "1.6", но в свежих версиях БСП есть соответствующая функция:
Версии=ОбменДаннымиXDTOСервер.ВерсииФорматаОбменаМассив(ПланыОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.ЭтотУзел()); КомпонентыОбмена.ВерсияФорматаОбмена=Версии[0]; // первой будет максимальная версия, которую поддерживает конфигурация КомпонентыОбмена.XMLСхема = "http://v8.1c.ru/edi/edi_stnd/EnterpriseData/"+КомпонентыОбмена.ВерсияФорматаОбмена;
3. Заканчиваем инициализацию
КомпонентыОбмена.МенеджерОбмена = МенеджерОбменаЧерезУниверсальныйФормат; ОбменДаннымиXDTOСервер.ИнициализироватьТаблицыПравилОбмена(КомпонентыОбмена); ОбменДаннымиXDTOСервер.ИнициализироватьВедениеПротоколаОбмена(КомпонентыОбмена, ИмяФайлаПротоколаОбмена);
4. Разбираемся с файлами
// Открываем файл обмена. Если вторым параметром файл не указывать - выгрузка будет в строку ОбменДаннымиXDTOСервер.ОткрытьФайлВыгрузки(КомпонентыОбмена,""); Если КомпонентыОбмена.ФлагОшибки Тогда КомпонентыОбмена.ФайлОбмена = Неопределено; ОбменДаннымиXDTOСервер.ЗавершитьВедениеПротоколаОбмена(КомпонентыОбмена); Возврат ""; КонецЕсли;
Всё готово для собственно выгрузки объектов.
Выгрузка по сценарию
Сценарий выгрузки представляет собой таблицу значений, в строках которой написаны имена правил обработки данных. Выгрузка по сценарию на момент написания работает без отборов.
Пример сценария выгрузки физических лиц и их документов:
КомпонентыОбмена.СценарийВыгрузки = новый ТаблицаЗначений; КомпонентыОбмена.СценарийВыгрузки.Колонки.Добавить("ИмяПОД"); НоваяСтрока = КомпонентыОбмена.СценарийВыгрузки.Добавить(); НоваяСтрока.ИмяПОД = "Справочник_ФизическиеЛица_Отправка"; НоваяСтрока = КомпонентыОбмена.СценарийВыгрузки.Добавить(); НоваяСтрока.ИмяПОД = "Справочник_ДокументыФизическихЛиц_Отправка";
Запускается сценарий совсем просто:
//ВЫГРУЗКА ДАННЫХ по сценарию. Работает но без отборов Попытка ОбменДаннымиXDTOСервер.ПроизвестиВыгрузкуДанных(КомпонентыОбмена); Исключение ОбменДаннымиXDTOСервер.ЗаписатьВПротоколВыполнения(КомпонентыОбмена, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); ОбменДаннымиXDTOСервер.ЗавершитьВедениеПротоколаОбмена(КомпонентыОбмена); КомпонентыОбмена.ФайлОбмена = Неопределено; Возврат ""; КонецПопытки;
Произвольная выгрузка данных запросом
Гораздо интереснее самим определить, какие именно данные мы хотим выгрузить и заставить систему их отработать.
Прежде чем выгружать наши объекты, нужно запустить обработчик "ПередКонвертацией". Вдруг разработчики там спрятали что-то жизненно важное?
Попытка КомпонентыОбмена.МенеджерОбмена.ПередКонвертацией(КомпонентыОбмена); Исключение ТекстОшибки = Символы.ПС + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Событие: %1. |Обработчик: ПередКонвертацией. | |Ошибка выполнения обработчика. |%2.'"), КомпонентыОбмена.НаправлениеОбмена, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); ОбменДаннымиXDTOСервер.ЗаписатьВПротоколВыполнения(КомпонентыОбмена, СокрЛП(ТекстОшибки)); КонецПопытки;
Выгрузка ссылочных объектов запросом, на примере физических лиц:
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ | ФизическиеЛица.Ссылка КАК Ссылка |ИЗ | Справочник.ФизическиеЛица КАК ФизическиеЛица |ГДЕ | НЕ ФизическиеЛица.ПометкаУдаления"; РезультатЗапроса = Запрос.Выполнить(); ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать(); Пока ВыборкаДетальныеЗаписи.Следующий() Цикл ОбменДаннымиXDTOСервер.ВыгрузкаОбъектаВыборки(КомпонентыОбмена, Стр.Ссылка); КонецЦикла;
В свежих версиях обмена появились регистры сведений. С ними сложнее, но не намного:
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ | ДокументыФизическихЛиц.Период КАК Период, | ДокументыФизическихЛиц.ВидДокумента КАК ВидДокумента, | ДокументыФизическихЛиц.Физлицо КАК Физлицо |ИЗ | РегистрСведений.ДокументыФизическихЛиц КАК ДокументыФизическихЛиц |ГДЕ | ДокументыФизическихЛиц.Физлицо В(&Физлицо) | И НЕ ДокументыФизическихЛиц.ВидДокумента ЕСТЬ NULL"; Рег=РегистрыСведений.ДокументыФизическихЛиц.СоздатьНаборЗаписей(); Рег.Отбор.Физлицо.Использование=Истина; Рег.Отбор.ВидДокумента.Использование=Истина; Рег.Отбор.Период.Использование=Истина; Запрос.УстановитьПараметр("Физлицо", КомпонентыОбмена.ВыгруженныеОбъекты); РезультатЗапроса = Запрос.Выполнить(); ВыборкаРесурсов=РезультатЗапроса.Выбрать(); Пока ВыборкаРесурсов.Следующий() Цикл Если НЕ ЗначениеЗаполнено(ВыборкаРесурсов.ВидДокумента) Тогда Продолжить; КонецЕсли; Рег.Отбор.Физлицо.Значение=ВыборкаРесурсов.Физлицо; Рег.Отбор.ВидДокумента.Значение=ВыборкаРесурсов.ВидДокумента; Рег.Отбор.Период.Значение=ВыборкаРесурсов.Период; Рег.Прочитать(); ОбменДаннымиXDTOСервер.ВыгрузкаОбъектаВыборки(КомпонентыОбмена, Рег); КонецЦикла;
В качестве отбора для документов в коде использован список ранее выгруженных физлиц из КомпонентыОбмена.ВыгруженныеОбъекты.
Завершение выгрузки
1. Запускаем обработчик "ПослеКонвертации"
Попытка КомпонентыОбмена.МенеджерОбмена.ПослеКонвертации(КомпонентыОбмена); Исключение ТекстОшибки = Символы.ПС + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Событие: %1. |Обработчик: ПослеКонвертации. | |Ошибка выполнения обработчика. |%2.'"), КомпонентыОбмена.НаправлениеОбмена, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); ОбменДаннымиXDTOСервер.ЗаписатьВПротоколВыполнения(КомпонентыОбмена, СокрЛП(ТекстОшибки)); КонецПопытки;
2. Закрываем теги, протоколы и файлы.
КомпонентыОбмена.ФайлОбмена.ЗаписатьКонецЭлемента(); // Body КомпонентыОбмена.ФайлОбмена.ЗаписатьКонецЭлемента(); // Message // Фиксация успешного завершения обмена. Если КомпонентыОбмена.СостояниеОбменаДанными.РезультатВыполненияОбмена = Неопределено Тогда КомпонентыОбмена.СостояниеОбменаДанными.РезультатВыполненияОбмена = Перечисления.РезультатыВыполненияОбмена.Выполнено; КонецЕсли; ДанныеВыгрузкиXML=КомпонентыОбмена.ФайлОбмена.Закрыть(); ОбменДаннымиXDTOСервер.ЗавершитьВедениеПротоколаОбмена(КомпонентыОбмена);
Переменная ДанныеВыгрузкиXML содержит строку с данными, которыми дальше можно распорядиться как угодно.
Обработка
В результате вокруг вышеописанной процедуры образовалась обработка.
Функционал её заимствован у бестселлера Универсальная выгрузка/загрузка данных для отличающихся конфигураций (JSON, Такси+ОФ), за что отдельное спасибо ее автору.
Обработка умеет подбирать объекты для выгрузки:
- вручную
- запросом (результат должен содержать колонку "ссылка")
- по выбранному периоду журнала регистрации
И выгружать их в выбранный файл.
Файл можно загрузить в любую базу (в том числе в облаке), командой:
Обработка содержит полный текст описанной здесь процедуры. Код открыт.
Тестировалась на Бухгалтерия предприятия, редакция 3.0 (3.0.71.69).
Будет работать в любой конфигурации на БСП от 3.0.2.300.
P.S.
Собственно механизм и все правила выгрузки в универсальном формате содержаться в коде конфигурации. Обработка лишь предоставляет простой доступ к ним. Поэтому, все обращения типа "почему не выгружается..." следует направлять непосредственно разработчикам.
P.P.S.
Конечно, в составе конфигураций есть универсальная обработка "ВыгрузкаЗагрузкаEnterpriseData", которая делает то же самое. Но мне показалось более изящным решением реализовать программный доступ к самому механизму обмена, чем городить обертку для универсальной обработки.