КД: Передача параметров из 7.7 в 8.x


В «Конвертации Данных» заложен удобный механизм передачи параметров – по сути переменных конвертации – между базами. Одна проблема: передача эта работает только если обмен происходит между двумя «восьмерками». По какой-то причине «семерочная» сторона обмена вообще обделена всякими интересными плюшками КД.

Тем не менее, если нельзя, но очень хочется, всегда можно найти выход. Обработка загрузки читает файлы из семерки и из восьмерки одинаково, не проверяя версию платформы-источника, так что никто не мешает нам создать нужную структуру тегов для «параметров» своими силами!

Приступим. Сразу скажу, что для примера я создал 2 простые конфигурации в 7 и в 8, с одним документом («ОбычныйДокумент») и одним справочником («Организация»).  В семерке еще есть константа «ОсновнаяОрганизация», которую мы и будем передавать  через параметр.

Для начала разберемся, что нам надо получить в выходном файле. После непродолжительного копания в восьмерочной обработке «УниверсальныйОбменДаннымиXML» можно найти, что параметры передаются в теге «ЗначениеПараметра» у которого есть атрибут «Имя» и, собственно, значение. Значением может быть любой объект, передаваемый через КД, по сути значение это читается при помощи той же функции, что и свойства объектов, описываемые в ПКО. Для желающих увидеть все своими глазами: процедуры «ПроизвестиЧтениеДанных()» и «ЗагрузитьЗначенияПараметровОбменаДанными()» в модуле обработки.  

Объем работ теперь более-менее очерчен, посмотрим, как добиться нужного результата. Смотрим в семерочную обработку выгрузки данных и находим код для создания узлов в файле выгрузки (напр. «ВыгрузитьСвойства()»). Творчески его перерабатываем и получаем что-то такое:

УзелПараметра = СоздатьУзел("ЗначениеПараметра");
УстановитьАтрибут(УзелПараметра, "Имя", "СообщениеВсемуМиру");
ЗаписатьЭлемент(УзелПараметра, "Значение", "Здравствуй, Мир!" );
ДобавитьПодчиненный(rootNode, УзелПараметра);

Все хорошо, но таким способом можно передать только значения примитивных типов. Возникает резонный вопрос: что делать, если надо передать что-то более интересное (ссылку, например)?  Выгрузим ссылку и вставим узел выгрузки как значение параметра! Вот так:

УзелПараметра = СоздатьУзел("ЗначениеПараметра");
УзелСсылки = ВыгрузитьПоПравилу(константа.ОсновнаяФирма,,,,"Организации");
УстановитьАтрибут(УзелПараметра, "Имя", "ОсновнаяОрганизация");
ДобавитьПодчиненный(УзелПараметра, узелСсылки);
ДобавитьПодчиненный(rootNode, УзелПараметра);

Как видно из кода, мы не создаем подчиненный узел «Значение», поскольку он необходим только для передачи примитивных типов. В случае передачи ссылочного типа с его работой справляется сам узел ссылки.

Отлично, с кодом выгрузки разобрались. Теперь надо понять, куда его добавить. Хотелось бы, чтобы передаваемый параметр был определен во время загрузки всех объектов, поэтому надо сделать так, чтобы код отработал перед обработкой ПВД.

Можно, например, сделать искусственное ПВД с минимальным порядком выполнения, в обработчик которому добавить вышеописанный код. Но любое ПВД можно выключить вручную в обработке выгрузки, так что этот способ нельзя назвать надежным.  Поэтому посмотрим на события конвертации – «ПередВыгрузкойДанных» как раз подойдет для наших целей.

 Осталось добавить передаваемые параметры в таблице настройки (важно поставить галочку «при загрузке», остальное не обязательно; см. последний скриншот к статье)

 Готово! Теперь параметр будет прочтен в самом начале загрузки данных на стороне приемника  и будет доступен через структуру «Параметры»!

 

Пара слов, зачем это вообще может быть нужно.

Через параметры можно регулировать какие-то опции загрузки. Вместо того, чтобы писать несколько «рабочих» правил с разными задачами, можно параметрами переключать различные сценарии обработки на приемнике.

Через параметры можно передавать какие-нибудь «метаданные» о выгрузке – например, имя  человека, который ее делал.

Параметры можно использовать как глобальные переменные загрузки. Этот случай как раз показан в правилах, приложенных к статье (заметьте, что в семерочной конфигурации у документа нет реквизита «Организация», а в восьмерке он должен быть заполнен)

Можно придумать еще много вариантов использования этого механизма, надеюсь, кому-то он хоть немного облегчит процесс переноса данных между платформами.

 

PS. В прикрепленных файлах есть архив с конфигурациями источника и приемника. Они необязательны для разбора примеров, вся необходимая информация и так содержится в файле правил, но кому-то может быть проще смотреть на метаданные в родном конфигураторе, а не в обработке «Описание конфигурации» из КД.

 

PPS. Спасибо Totoro за дополнение, есть еще один вариант передачи параметров. Иногда бывает необходимо передать параметр не для всей конвертации, а для отдельного объекта (или более того, нескольких объектов). Например, если у приемника нет реквизита для значения, а само значение нужно для выбора варианта заполнения объекта (см. счет учета в основных средствах в семерке и, скажем, в УПП). Тогда поможет такой трюк:

Если вставить в «При выгрузке» или в «После выгрузки» ПКО код:

УзелПараметра = СоздатьУзел("ЗначениеПараметра");
УстановитьАтрибут(УзелПараметра, "Имя", "СообщениеВсемуМиру");
ЗаписатьЭлемент(УзелПараметра, "Значение", "Здравствуй, Мир!");
ДобавитьПодчиненный(Приемник, УзелПараметра);

то в обработчике «После загрузки» этого ПКО параметр можно прочитать через соответствие «ПараметрыОбъекта»:

НашПривет = ПараметрыОбъекта["СообщениеВсемуМиру"];

28 Comments

  1. Новиков

    Молодец! Хорошая серебряная пуля. Как раз с подобным часто встречаюсь, но до такого не допетрил 🙂

    Reply
  2. fomix

    Возможно автор заслужил золотую пулю, однако к нему есть вопрос: в Параметрах конвертации есть свойство «Передавать при выгрузке» — чем оно не угодило автору?! Поправьте, если не так…

    Reply
  3. Rustig

    (2) «Передавать при выгрузке» работает только для обмена между восьмерками. Об этом в статье написано.

    Reply
  4. fomix

    Проверил: параметры передаются, а вот значения действительно не присваиваются… Так что пусть пуля достается автору. В качестве хорошего примера передачи и отработки параметров могу порекомендовать правила обмена для ЗиК-ЗУП от 1с

    Reply
  5. Rustig

    (4)

    (3) Rustig,

    1. Смотрим статью: «Приступим. Сразу скажу, что для примера я создал 2 простые конфигурации в 7 и в 8»

    2. Для начала сам попробовал бы что-ли передать-принять параметры

    Я вас не верно понял. прошу прощения. подумал, что вы невнимательно прочитали. 🙂 а вы, как оказалось, дальше меня пошли, протестировали…

    Reply
  6. vbuots

    Ух как вовремя, как раз пишу правила конвертации. ПАссыба!!!!!!

    Reply
  7. chikov

    Попробовал. Ни хрена не сработало — приемник параметр не получил. Может, я к нему неправильно обращаюсь — написал просто Параметры.НаименованиеОрганизации

    Reply
  8. chikov

    Попробовал еще раз. Снова не получилось ни фига.

    Параметр создал НаименованиеОрганизации (строка), птицу При загрузке поставил.

    Вставил ПередВыгрузкой:

    УзелПараметра = СоздатьУзел(«НаименованиеОрганизации»);

    УстановитьАтрибут(УзелПараметра, «Имя», «НаименованиеОрганизации»);

    ЗаписатьЭлемент(УзелПараметра, «Значение», «Моя организация»);

    В восьмерке ПослеЗагрузки (справочника)

    Наименование = Параметры.НаименованиеОрганизации;

    — пустое.

    Что я сделал неправильно?

    Reply
  9. chikov

    После длительных и бесплодных попыток решил попробовать второй вариант — со ссылкой.

    К моему большому удивлению, он сработал!

    Тем не менее, испытываю большую потребность именно в первом варианте. Очень хочется иметь возможность задать параметр (строку) в диалоге и передать ее в восьмерку.

    Reply
  10. Филин

    (10) chikov,

    У вас в первом теге ошибка. Узел должен называться не по имени параметра, а строго «ЗначениеПараметра». Именно этот тег ищет обработка загрузки.

    Таким образом, для строки код будет выглядеть так:

    УзелПараметра = СоздатьУзел(«ЗначениеПараметра»);

    УстановитьАтрибут(УзелПараметра, «Имя», «НаименованиеОрганизации»);

    ЗаписатьЭлемент(УзелПараметра, «Значение», «Моя организация»);

    ДобавитьПодчиненный(rootNode, УзелПараметра);

    Reply
  11. Филин

    Перечитал статью и нашел у себя неточность: в первом примере переноса, с примитивными типами, забыл добавить созданный узел параметра в файл выгрузки («ДобавитьПодчиненный(rootNode, УзелПараметра);»)

    Исправил.

    Reply
  12. chikov

    Большое спасибо! До «ЗначениеПараметра» я по ходу допер, но оно, естественно, без последней строки таки не работало, да…

    А теперь работет! И, мне кажется, в большинстве случаев примитивных типов вполне достаточно — в параметрах можно ввести на форме то, что нужно, а потом в восьмерке анализировать и выполнять соответствующие действия.

    Reply
  13. NickAn

    Молодец, как раз столкнулся, уже думал что-то мудрить.

    Reply
  14. Totoro

    Добавь в статью пример:

    Если вставить в «При выгрузке» или в «После выгрузки» ПКО код:

    УзелПараметра = СоздатьУзел(«ЗначениеПараметра»);

    УстановитьАтрибут(УзелПараметра, «Имя», «СообщениеВсемуМиру»);

    ЗаписатьЭлемент(УзелПараметра, «Значение», «Здравствуй, Мир!»);

    ДобавитьПодчиненный(Приемник, УзелПараметра);

    то в обработчике «После загрузки» этого ПКО параметр можно прочитать через соответствие «ПараметрыОбъекта»:

    НашПривет = ПараметрыОбъекта[«СообщениеВсемуМиру»];

    Reply
  15. Lili4ka

    В 1С 7.7 был создан аналог регистра сведений 1С8 СоответствиеОбъектовДляОбмена для складов, номенклатуры, контрагентов. Для контрагентов хранятся соответствия многие к одному: в обменной базе много контрагентов, в текущей им соответствуют один. Теперь переносим данные справочника в регистр сведений в 1С8. Собственную ссылку выгружаю так:

    //собственная ссылка

    Если сокрлп(Источник.ИмяТипаПриемника) = «Справочник.Контрагенты» Тогда

    ПравилаДляСсылки = «Контрагенты»;

    ИначеЕсли сокрлп(Источник.ИмяТипаПриемника) = «Справочник.Номенклатура» Тогда

    ПравилаДляСсылки = «Номенклатура»;

    ИначеЕсли сокрлп(Источник.ИмяТипаПриемника) = «Справочник.МестаХранения» Тогда

    ПравилаДляСсылки = «Склады»;

    КонецЕсли;

    УзелПараметра = СоздатьУзел(«ЗначениеПараметра»);

    узелСсылки = ВыгрузитьПоПравилу(Источник.СобственнаяСсылка,,,,ПравилаДляСсылки);

    УстановитьАтрибут(УзелПараметра, «Имя», «СобственнаяСсылка»);

    ДобавитьПодчиненный(УзелПараметра, узелСсылки);

    ДобавитьПодчиненный(Приемник, УзелПараметра);

    В результате ДобавитьПодчиненный(УзелПараметра, узелСсылки); работает через раз (см. скриншот). И косячит именно при соответствии многие к одному: есть несколько строк соответствий, а собственная ссылка выгружается только для последней. Никто не может подсказать, в чем проблема?

    Reply
  16. Gorr

    в событии ПередЗагрузкойДанных правила конветации еще никаких параметров нет. а ведь передача параметров требуется в основном для инициализации базы приемника — ЗагрузитьЗначенияПараметровОбменаДанными() вызывается слишком поздно уже при чтении объектов загрузки.

    Reply
  17. daho

    Блин!! Выдает ошибку:

    Процедура или функция с указанным именем не определена (ЗаписатьЭлемент)

    Кто подскажет что делать?

    Reply
  18. juker

    Автору плюс за статью. Спасибо.

    Reply
  19. Rudakov_D

    Здорово :), спасибо за работу

    Reply
  20. volha-77

    Можно ли сделать обмен параметрами между двумя 7-ми? у меня что-то не получилось (организация в документе пустая, хотя и ошибок не выдает)

    Reply
  21. Yimaida

    для корректной работы пустых ссылок надо передавать тип (обнаружилось в процессе тестирования правил)

    УзелРеквизитов = СоздатьУзел(«ЗначениеПараметра»);
    УзелСсылки = ВыгрузитьПоПравилу(Источник.Регион,,,,»БизнесРегионы»,,);
    УстановитьАтрибут(УзелРеквизитов, «Имя», «БизнесРегион»);
    УстановитьАтрибут(УзелРеквизитов, «Тип», «СправочникСсылка.БизнесРегионы»);
    ДобавитьПодчиненный(УзелРеквизитов, УзелСсылки);
    ДобавитьПодчиненный(Приемник, УзелРеквизитов);
    Reply
  22. pyrkin_vanya

    За статью плюс, но в ней есть много чего недостающего. Здесь описаны все нюансы передачи параметров.

    http://kb.mista.ru/article.php?id=811

    Reply
  23. Ольга_tmp

    Можно ли так передать дату?

    Reply
  24. deaddy64

    Для того чтобы ПараметрыОбъекта были доступны в обработчике «Поля поиска» нужно изменить порядок записи объекта в XML. Первыми подчиненными узлами объекта должны быть элементы «ЗначениеПараметра», иначе при чтении ссылки выполнится обработчик «Последовательность полей поиска», в котором ПараметрыОбъекта ещё не инициализированы.

    Вот пример рабочего кода для обработчика «При выгрузке» ПКО. В параметры выгружаются 2 ссылочных объекта:

    хмлОрганизация = ВыгрузитьПоПравилу(«Наша организация», ,,,»ОрганизацииТолькоСсылка»,,);
    
    РегВНалоговомОрганеСылка = СоздатьОбъект(«СписокЗначений»);
    РегВНалоговомОрганеСылка.Установить(«Владелец»,»Наша организация»);
    РегВНалоговомОрганеСылка.Установить(«КодПоОКТМО»,Источник.КодОКТМО.Получить(Параметры.МесяцНачалаЭксплуатации));
    РегВНалоговомОрганеСылка.Установить(«КодПоОКАТО»,Источник.КодОКАТО);
    РегВНалоговомОрганеСылка.Установить(«КПП»,Источник.КПП);
    хлмРегистрация = ВыгрузитьПоПравилу(РегВНалоговомОрганеСылка, , , , «РегистрацииВНалоговомОргане»,,);
    
    УзелПараметраОрг = СоздатьУзел(«ЗначениеПараметра»);
    УстановитьАтрибут(УзелПараметраОрг, «Имя», «сфОрганизация»);
    УстановитьАтрибут(УзелПараметраОрг, «Тип», «СправочникСсылка.Организации»);
    УстановитьАтрибут(УзелПараметраОрг, «ИмяПКО», «ОрганизацииТолькоСсылка»);
    ДобавитьПодчиненный(УзелПараметраОрг, хмлОрганизация.cloneNode(1));
    Приемник.insertBefore(УзелПараметраОрг, Приемник.firstChild);
    
    УзелПараметраРег = СоздатьУзел(«ЗначениеПараметра»);
    УстановитьАтрибут(УзелПараметраРег, «Имя», «Регистрация»);
    УстановитьАтрибут(УзелПараметраРег, «Тип», «СправочникСсылка.РегистрацииВНалоговомОргане»);
    УстановитьАтрибут(УзелПараметраРег, «ИмяПКО», «РегистрацииВНалоговомОргане»);
    ДобавитьПодчиненный(УзелПараметраРег, хлмРегистрация.cloneNode(1));
    Приемник.insertBefore(УзелПараметраРег, Приемник.firstChild);
    

    Показать

    Reply
  25. slawanix

    Спасибо, автор! Метод работает.

    Reply
  26. user1090556

    А как передать ТаблицуЗначений таким способом?

    Записывается только в таком виде

    <ЗначениеПараметра Имя=»ТабДокументовУдаления» Тип=»ТаблицаЗначений»><Значение>ТаблицаЗначений</Значение></ЗначениеПараметра>

    А вот сами данные ТЗ не попадают в файл обмена

    Reply
  27. Филин

    (28) Судя по всему, в сообщение попадает только представление переменной — собственно, «ТаблицаЗначений».

    Я уже давно не смотрел на КД и не помню, есть ли там код сериализации таблицы значений. В худшем случае остается два варианта:

    1. самому «конструировать» структуру таблицы значений при помощи тегов (строки/ячейки и т.д.)

    2. упростить задачу перемещения данных. Например, передавать не таблицу значений, а строку с экзотическим разделителем (@, |, // или другие символы, которые точно не окажутся в «полезных данных»). На принимающей стороне эту строку надо будет разобрать обратно и дальше работать с ней.

    Reply
  28. user1090556

    (29)я рассматривал такой вариант https://infostart.ru/public/120181/ на принимающей стороне, и помещать ТЗ на стороне 7-ки с помощью ЗначениеВСтрокуВнутр, но потом исходя из моей ситуации решил получить ТЗ через COM соединение.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *