При переносе данных между сильно измененными или устаревшими конфигурациями 1С специалисты часто сталкиваются с непредвиденными ошибками компиляции. Типичный пример — перенос справочника физических лиц из старой базы (например, Управлении торговым предприятием образца 2008 года) в современную базу (например, Зарплата и Управление Персоналом). Попытка выполнить выгрузку через стандартную обработку «Универсальный обмен данными в формате XML» может завершиться аварийно с сообщением об отсутствии общего модуля ОбменДаннымиПовтИсп.
В этой статье мы подробно разберем причины возникновения этой ошибки, выясним, почему «универсальная» обработка отказывается работать в старых базах, и рассмотрим эффективные методы решения этой проблемы. Также мы изучим методологически правильный подход к переносу истории ФИО физических лиц и альтернативные, более простые способы решения задачи без использования тяжеловесного обмена XML.
Проанализируем ситуацию по шагам и выберем оптимальный путь решения.
ОбменДаннымиПовтИсп?Прежде всего выясним причину конфликта. Многие разработчики ошибочно полагают, что внешняя обработка V8Exchan82.epf (или её аналоги для других версий платформы) абсолютно изолирована от метаданных конфигурации. На самом деле это не так.
Современные версии обработки «Универсальный обмен данными в формате XML» разрабатываются с расчетом на интеграцию с Библиотекой стандартных подсистем (БСП). В коде обработки присутствуют вызовы процедур и функций БСП для обеспечения безопасности, логирования операций в Журнал регистрации, работы с профилями безопасности и оптимизации повторного использования значений. Модуль ОбменДаннымиПовтИсп — это как раз один из ключевых модулей БСП, отвечающий за кэширование параметров обмена.
Если мы запускаем современную обработку обмена в конфигурации, выпущенной до появления БСП (или в базе, где эта подсистема вырезана / не обновлялась), платформа при попытке инициализации формы пытается скомпилировать весь код обработки. Натыкаясь на вызовы несуществующих общих модулей, система выдает ошибку компиляции и прекращает работу.
Рассмотрим, как можно решить эту проблему без деструктивного изменения метаданных конфигурации.
Самый простой и безопасный способ обойти ошибку компиляции — отказаться от использования новейшей версии обработки выгрузки. Нам не нужно переписывать код конфигурации или комментировать вызовы функций «наугад» в самой обработке.
Выполним следующие действия:
V8Exchan82.epf ранних релизов. Также можно использовать обработку V8Exchan.epf, предназначенную для платформы 8.1, запустив её в режиме совместимости.Также обратим внимание на важную настройку: в параметрах обработки обмена перед загрузкой правил желательно отключить режим отладки обработчиков выгрузки/загрузки. Именно при включении отладки обработка начинает активно обращаться к подсистемам БСП для создания временных файлов и модулей отладки.
ФИОФизЛиц)Предположим, что выгрузка справочника ФизическиеЛица запустилась. Однако здесь нас подстерегает методологическая ловушка. Если мы просто перенесем элементы справочника в базу ЗУП, то при открытии карточек сотрудников мы увидим пустые поля вместо имен.
Дело в том, что в архитектуре 1С справочник ФизическиеЛица хранит лишь ссылочную сущность, а сами персональные данные (Фамилия, Имя, Отчество) являются периодическими сведениями и хранятся в независимом регистре сведений ФИОФизЛиц (в новых конфигурациях — ФИОФизическихЛиц). Нам необходимо переносить не только справочник, но и связанные записи этого регистра на каждую дату изменения фамилии.
Разберем по шагам, как настроить правила конвертации в программе «Конвертация данных 2.1»:
РегистрСведенийСсылка.ФИОФизЛиц, а приемником — РегистрСведенийСсылка.ФИОФизическихЛиц. Настроим сопоставление измерений (ФизическоеЛицо, Период) и ресурсов (Фамилия, Имя, Отчество).ФизическиеЛица перейдем на вкладку «Обработчики событий» и выберем событие «После выгрузки». Мы напишем алгоритм, который при выгрузке каждого конкретного физлица будет находить в базе-источнике все записи по его ФИО и принудительно отправлять их в файл обмена.Проанализируем пример кода для обработчика ПослеВыгрузки в ПКО справочника:
// Создаем запрос для выборки всей истории ФИО по текущему физическому лицу
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ФИОФизЛиц.Период КАК Период,
| ФИОФизЛиц.ФизическоеЛицо КАК ФизическоеЛицо,
| ФИОФизЛиц.Фамилия КАК Фамилия,
| ФИОФизЛиц.Имя КАК Имя,
| ФИОФизЛиц.Отчество КАК Отчество
|ИЗ
| РегистрСведений.ФИОФизЛиц КАК ФИОФизЛиц
|ГДЕ
| ФИОФизЛиц.ФизическоеЛицо = &ФизическоеЛицо";
Запрос.УстановитьПараметр("ФизическоеЛицо", Источник.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
// Выгружаем каждую найденную запись регистра по соответствующему правилу конвертации
Пока Выборка.Следующий() Цикл
// Создаем структуру для передачи свойств регистра в выгрузку
СтруктураДанныхРегистра = Новый Структура;
СтруктураДанныхРегистра.Вставить("Период", Выборка.Period);
СтруктураДанныхРегистра.Вставить("ФизическоеЛицо", Выборка.ФизическоеЛицо);
СтруктураДанныхРегистра.Вставить("Фамилия", Выборка.Фамилия);
СтруктураДанныхРегистра.Вставить("Имя", Выборка.Имя);
СтруктураДанныхРегистра.Вставить("Отчество", Выборка.Отчество);
// Вызываем платформенный метод выгрузки
ВыгрузитьРегистр(СтруктураДанныхРегистра, , , "ФИОФизическихЛиц");
КонецЦикла;
При такой настройке при загрузке файла в базу ЗУП сначала создадутся элементы справочника ФизическиеЛица, а затем для них автоматически запишутся корректные данные ФИО с сохранением всей истории изменений.
Если перед нами стоит разовая задача переноса ограниченного объема данных (около 3000 записей), использование XML-правил может оказаться избыточным и трудоемким процессом. Рассмотрим гораздо более простой способ, встроенный в современные конфигурации 1С на управляемых формах (включая ЗУП 3).
Посмотрим, как выполнить перенос через промежуточный файл таблицы:
ФИО (желательно одной строкой или разбитыми на Фамилию, Имя, Отчество), ДатаРождения, ИНН, СНИЛС, Пол..xls или .xlsx).Физические лица.Важное преимущество этого метода: программный код современной конфигурации ЗУП при создании нового физического лица через стандартный интерфейс загрузки данных самостоятельно создаст и заполнит запись в регистре сведений ФИОФизическихЛиц. Нам не придется беспокоиться о связях между таблицами и писать обработчики выгрузки.
Для программистов, желающих полностью контролировать процесс переноса данных без создания промежуточных файлов обмена, отличным выбором станет написание внешней обработки для базы-приемника, работающей через COM-соединение.
Разберем пример реализации этого метода. Мы напишем код, который подключается к старой базе, выбирает физических лиц и переносит их напрямую в ЗУП, автоматически проверяя наличие дублей по ИНН или СНИЛС.
Создадим внешнюю обработку в ЗУП и поместим в модуль формы следующий код:
Процедура ВыполнитьПереносНапрямую() Экспорт
// Инициализируем подключение к базе-источнику через COM-соединение
COMConnector = Новый COMОбъект("V83.COMConnector");
// Формируем строку подключения (для файловой базы)
СтрокаПодключения = "File=""C:\DB\UTP_2008""; Usr=""Администратор""; Pwd=""Пароль"";";
Попытка
БазаИсточник = COMConnector.Connect(СтрокаПодключения);
Исключение
Предупреждение("Не удалось подключиться к базе-источнику: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Создаем запрос в базе-источнике для получения физлиц и их актуального ФИО
ЗапросИсточник = БазаИсточник.NewObject("Запрос");
ЗапросИсточник.Текст =
"ВЫБРАТЬ
| ФизическиеЛица.Ссылка КАК Ссылка,
| ФизическиеЛица.Наименование КАК Наименование,
| ФизическиеЛица.ИНН КАК ИНН,
| ФизическиеЛица.СтраховойНомерПФР КАК СНИЛС,
| ФизическиеЛица.ДатаРождения КАК ДатаРождения,
| ФИОФизЛиц.Фамилия КАК Фамилия,
| ФИОФизЛиц.Имя КАК Имя,
| ФИОФизЛиц.Отчество КАК Отчество
|ИЗ
| Справочник.ФизическиеЛица КАК ФизическиеЛица
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ФИОФизЛиц КАК ФИОФизЛиц
| ПО ФизическиеЛица.Ссылка = ФИОФизЛиц.ФизическоеЛицо";
Выборка = ЗапросИсточник.Execute().Select();
Пока Выборка.Next() Цикл
// Проверим, нет ли уже такого физлица в базе ЗУП (по ИНН или СНИЛС)
ФизЛицоСсылка = Справочники.ФизическиеЛица.ПустаяСсылка();
Если ЗначениеЗаполнено(Выборка.ИНН) Тогда
ФизЛицоСсылка = Справочники.ФизическиеЛица.НайтиПоРеквизиту("ИНН", Выборка.ИНН);
КонецЕсли;
Если ФизЛицоСсылка.Пустая() И ЗначениеЗаполнено(Выборка.СНИЛС) Тогда
ФизЛицоСсылка = Справочники.ФизическиеЛица.НайтиПоРеквизиту("СтраховойНомерПФР", Выборка.СНИЛС);
КонецЕсли;
// Если физлицо не найдено, создаем новое
Если ФизЛицоСсылка.Пустая() Тогда
НовоеФизЛицо = Справочники.ФизическиеЛица.СоздатьЭлемент();
НовоеФизЛицо.Наименование = Выборка.Наименование;
НовоеФизЛицо.ИНН = Выборка.ИНН;
НовоеФизЛицо.СтраховойНомерПФР = Выборка.СНИЛС;
НовоеФизЛицо.ДатаРождения = Выборка.ДатаРождения;
Попытка
НовоеФизЛицо.Записать();
ФизЛицоСсылка = НовоеФизЛицо.Ссылка;
Исключение
Сообщить("Ошибка записи физлица " + Выборка.Наименование + ": " + ОписаниеОшибки());
Продолжить;
КонецПопытки;
// Записываем ФИО в периодический регистр сведений базы-приемника
МенеджерЗаписи = РегистрыСведений.ФИОФизическихЛиц.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Период = ?(ЗначениеЗаполнено(Выборка.ДатаРождения), Выборка.ДатаРождения, '19800101');
МенеджерЗаписи.ФизическоеЛицо = ФизЛицоСсылка;
МенеджерЗаписи.Фамилия = Выборка.Фамилия;
МенеджерЗаписи.Имя = Выборка.Имя;
МенеджерЗаписи.Отчество = Выборка.Отчество;
Попытка
МенеджерЗаписи.Записать();
Исключение
Сообщить("Ошибка записи ФИО для " + Выборка.Наименование + ": " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
Сообщить("Перенос успешно завершен!");
КонецПроцедуры
Мы подробно разобрали проблему совместимости механизмов обмена данными и наметили четкие пути ее решения. В зависимости от квалификации разработчика и регулярности выполнения задачи, мы можем выбрать один из четырех подходов:
V8Exchan82.epf без привязки к БСП для успешного обмена XML в нетиповых устаревших базах.ФИОФизЛиц в обработчике ПослеВыгрузки.Каждый из этих вариантов позволяет обойти ошибки конфигурации и гарантирует сохранность критически важных данных при миграции систем.