Перенос данных между разными поколениями платформ 1С — например, из современной «1С:Предприятие 8.2» в устаревшую, но все еще активно используемую «1С:Предприятие 7.7» — часто сопровождается техническими трудностями. Одной из главных преград становится разница в архитектуре платформ. Версия 8.2 с легкостью выполняет динамический код «на лету» из файлов XML-правил, тогда как версия 7.7 требует жесткой компиляции программных модулей. В рамках этой статьи мы подробно разберем, как решить ключевые проблемы при такой конвертации, настроить автоматическую загрузку обработчиков, провести документы после загрузки и предотвратить засорение базы-приемника пустыми элементами справочников.
При использовании конфигурации «Конвертация данных 2.x» (КД) для переноса в 1С 7.7 программисты часто сталкиваются с ошибкой отсутствия обработчиков событий (например, Конвертация_ПослеЗагрузкиОбъекта). Выясним причину этого поведения.
Платформа 1С 8.х считывает код обработчиков непосредственно из XML-файла правил обмена и выполняет его с помощью встроенной функции Выполнить(). В платформе 1С 7.7 такой механизм отсутствует. Чтобы написанный вами код в правилах обмена (на языке 7.7) сработал при загрузке, он должен быть физически добавлен в текстовый модуль обработки загрузки V77Imp.ert.
Обычно разработчики вручную копируют сгенерированный КД текст модуля и вставляют его в конфигураторе 1С 7.7 в обработку загрузки. Но это крайне неудобно при частой отладке правил. Рассмотрим красивый и быстрый лайфхак, который избавит вас от рутины:
МодульЗагрузки.txt). Сохраните его в определенную папку на вашем компьютере или сервере.V77Imp.ert в конфигураторе 1С 7.7.
#ЗагрузитьИзФайла C:\ПутьКПапке\МодульЗагрузки.txt
Укажите ваш реальный путь к сохраненному текстовому файлу. Теперь при каждом запуске обработки загрузки в режиме «1С:Предприятие 7.7» платформа будет автоматически подтягивать актуальный код ваших обработчиков непосредственно перед выполнением. Вам больше не придется открывать конфигуратор 7.7 для изменения кода правил.
Попытка напрямую сопоставить булево свойство «Проведен» из 1С 8.2 с реквизитом документа в 1С 7.7 приведет к ошибке, так как в 7.7 статус проведения документа определяется не реквизитом шапки, а состоянием его движений в регистрах. Создавать искусственный реквизит «Проведен» в конфигурации-приемнике не имеет практического смысла.
Проанализируем правильный алгоритм решения этой задачи через использование параметров и обработчиков событий КД:
Проведен (тип данных: Число или Булево).Проведен укажите назначение: Передавать в параметр. В качестве имени параметра выберите созданный ранее параметр Проведен.Посмотрим на пример кода для обработчика «После загрузки»:
Если ПараметрыОбъекта.Получить("Проведен") = 1 Тогда
ОбъектБД.Записать();
Если ОбъектБД.Провести() = 0 Тогда
Сообщить("Не удалось провести загруженный документ: " + ОбъектБД);
КонецЕсли;
КонецЕсли;
Важное примечание: Обратите внимание, что в контексте обработчиков загрузки КД для 1С 7.7 загружаемый объект доступен через переменную ОбъектБД, а коллекция переданных параметров — через ПараметрыОбъекта.
Разберем также альтернативный, более надежный вариант проведения. Непосредственное проведение документов «на лету» в процессе их загрузки может значительно замедлить процесс импорта. Кроме того, документ может не провестись из-за того, что подчиненные справочники или связанные документы еще не загружены. Чтобы избежать этого, перенесем проведение в финальную стадию загрузки данных:
СписокДокументовДляПроведения = СоздатьОбъект("СписокЗначений");
Если ПараметрыОбъекта.Получить("Проведен") = 1 Тогда
СписокДокументовДляПроведения.ДобавитьЗначение(ОбъектБД.ТекущийЭлемент());
КонецЕсли;
Для Ном = 1 По СписокДокументовДляПроведения.РазмерСписка() Цикл
ВремДок = СписокДокументовДляПроведения.ПолучитьЗначение(Ном);
Если ВремДок.Выбран() = 1 Тогда
Док = СоздатьОбъект("Документ." + ВремДок.Вид());
Если Док.НайтиДокумент(ВремДок) = 1 Тогда
Если Док.Провести() = 0 Тогда
Сообщить("Ошибка проведения документа при пост-обработке: " + ВремДок);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Рассмотрим ситуацию, когда при переносе документа реквизит шапки (например, «Фирма») заполняется через виртуальный источник (выражение типа Источник.Фирма.ЮрЛицо). В процессе загрузки КД пытается сопоставить этот объект в базе-приемнике по полям поиска (например, по ИНН и Наименованию). Если сопоставление завершается неудачей, КД автоматически генерирует новую запись. Но так как в источнике было заполнено лишь несколько полей, созданный элемент справочника «Фирмы» или «Контрагенты» оказывается пустым или полупустым, что приводит к замусориванию базы данных.
Выясним причины сбоя поиска. Зачастую они кроются в разном формате хранения данных в базах 1С 8.2 и 7.7: например, ИНН в одной базе заведен с пробелами, в другой — без; наименования содержат разные кавычки или лишние пробелы на концах строк.
Ниже подробно описаны три эффективных метода решения этой проблемы.
Самое простое решение — запретить КД создавать новые элементы, если поиск по ключевым полям не дал результатов. Для этого откройте правила конвертации объектов (ПКО) для подчиненного справочника (в нашем примере это ПКО «ЮрЛица-Фирмы») и на вкладке основных настроек установите флаг Не создавать новый объект, если он не найден. В этом случае, если фирма с указанным ИНН не будет найдена в базе 1С 7.7, реквизит документа просто останется незаполненным, но пустой элемент в справочнике создан не будет.
Если автоматический поиск по стандартным реквизитам не срабатывает из-за различий в форматировании строк, мы можем написать жесткий и надежный алгоритм сопоставления непосредственно в обработчике Поля поиска на стороне 1С 7.7:
Если ИмяРеквизита = "ИНН" Тогда
// Очищаем значение ИНН от случайных пробелов
ОчищенныйИНН = СокрЛП(Значение);
Спр = СоздатьОбъект("Справочник.Фирмы");
Если Спр.НайтиПоРеквизиту("ИНН", ОчищенныйИНН, 1) = 1 Тогда
Ссылка = Спр.ТекущийЭлемент();
ПрекратитьПоиск = 1; // Указываем КД, что объект успешно найден
КонецЕсли;
КонецЕсли;
Если вы хотите полностью контролировать процесс привязки фирмы к документу и отказаться от использования ПКО для этого реквизита, можно передать ИНН фирмы как обычный текстовый параметр документа:
ИННФирмы).
ИНН_Параметр = ПараметрыОбъекта.Получить("ИННФирмы");
Если ПустоеЗначение(ИНН_Параметр) = 0 Тогда
СпрФирмы = СоздатьОбъект("Справочник.Фирмы");
Если СпрФирмы.НайтиПоРеквизиту("ИНН", СокрЛП(ИНН_Параметр), 1) = 1 Тогда
ОбъектБД.Фирма = СпрФирмы.ТекущийЭлемент();
Иначе
Сообщить("Предупреждение: Фирма с ИНН " + ИНН_Параметр + " не найдена в базе-приемнике!");
КонецЕсли;
КонецЕсли;
Использование этого метода гарантирует, что новые элементы в справочнике фирм не будут создаваться ни при каких обстоятельствах, а вы всегда будете оперативно получать сообщения о ненайденных объектах в процессе импорта данных.