Перенос данных из устаревшей платформы 1С:Предприятие 7.7 в современные конфигурации на платформе 1С:Предприятие 8.3 — задача, с которой до сих пор сталкиваются многие разработчики. В процессе разработки правил обмена в конфигурации "Конвертация данных 2.0" (КД 2) возникает целый ряд специфических проблем. Они связаны как с синтаксическими различиями платформ, так и с особенностями работы универсальной обработки выгрузки V77Exp.ert.
В этой статье мы подробно разберем, как правильно интегрировать выгружаемый модуль правил в обработку выгрузки 7.7, как обойти отсутствие привычных функций 8.3 в старой платформе, как корректно переносить контактную информацию в новые конфигурации на БСП и как бороться с ложной модифицированностью документов после их импорта.
---
Когда мы пишем алгоритмы и обработчики событий (например, "Перед выгрузкой", "При выгрузке") в Конвертации данных для платформы 7.7, эти фрагменты кода не могут выполняться динамически из XML-файла правил обмена. Платформа 1С 7.7 требует, чтобы весь исполняемый код находился непосредственно в модуле обработки выгрузки.
При выгрузке правил обмена КД 2 формирует вспомогательный файл (обычно с именем МодульВыгрузки.txt). Нам необходимо связать этот код с обработкой выгрузки V77Exp.ert. Существует два способа сделать это.
Мы можем прописать в самом начале модуля обработки V77Exp.ert специальную директиву компилятора:
#ЗагрузитьИзФайла МодульВыгрузки.txt
Важный нюанс: Этот способ часто вызывает ошибки компиляции ("Функция не обнаружена"), если файл модуля лежит в другом каталоге или к нему нет прямого доступа в момент инициализации обработки. Платформа 7.7 ищет этот файл строго в каталоге исполняемого файла обработки или в каталоге базы данных. При работе в терминальном режиме или по сети этот механизм регулярно сбоит.
Чтобы раз и навсегда избежать проблем с путями к файлам, выполним интеграцию вручную через Конфигуратор:
МодульВыгрузки.txt).V77Exp.ert.МодульВыгрузки.txt, скопируем все его содержимое и вставим в пустой модуль обработки V77Exp.ert.---
Часто программисты, привыкшие к разработке на 1С 8.3, по ошибке пишут код в обработчиках КД для 7.7 на современном синтаксисе. Это приводит к критическим ошибкам при выгрузке. Рассмотрим основные различия.
В 1С 7.7 нет встроенного типа Булево (значений Истина и Ложь). Вместо них используются числовые значения: 1 (соответствует истине) и 0 (соответствует лжи).
Если мы напишем код:
// Ошибка! Платформа 7.7 не поймет эти литералы
Значение = ?(Источник.ОплатаДоговора = 2, Истина, Ложь);
Платформа выдаст синтаксическую ошибку. Правильный вариант для 1С 7.7 выглядит так:
Значение = ?(Источник.ОплатаДоговора = 2, 1, 0);
Обратите внимание: При загрузке в 1С 8.3 механизм Конвертации данных автоматически преобразует число 1 в булево Истина, а 0 — в Ложь, если свойство приемника имеет тип Булево.
Функции ЗначениеЗаполнено() в 7.7 не существует. Вместо нее мы должны использовать системную функцию ПустоеЗначение(), которая возвращает 1, если переданное значение пустое, и 0 в противном случае.
Давайте сравним написание условий:
// Код для 1С 8.3 (не взлетит в обработчиках выгрузки из 7.7)
Если ЗначениеЗаполнено(Источник.ДокументДатаВыдачи) Тогда
...
КонецЕсли;
// Корректный код для 1С 7.7
Если ПустоеЗначение(Источник.ДокументДатаВыдачи) = 0 Тогда
...
КонецЕсли;
---
В 1С 7.7 контактная информация обычно хранится в виде простых текстовых строк в реквизитах справочников. В современных конфигурациях 1С 8.3 (использующих Библиотеку Стандартных Подсистем — БСП) контактная информация хранится в табличных частях справочников и имеет сложную XML/JSON структуру в поле ЗначенияПолей.
Если мы попытаемся просто передать строку с комментариями (например, "8-953-820-73-43 дочь") напрямую в представление контактной информации 1С 8.3, то при открытии карточки контрагента поле "Комментарий" окажется пустым. Это происходит потому, что БСП ожидает структурированные XML-данные.
Давайте разберем, как правильно решить эту задачу. Оптимальный подход — передавать простые текстовые данные из 1С 7.7, а сборку XML-структуры БСП производить уже на стороне приемника (в 1С 8.3).
В правилах конвертации свойств (ПКС) для табличной части контактной информации мы пишем алгоритм разбора строки телефона и выделения из нее комментариев, кода города и номера:
ПозицияКомментарий = 0;
Для Счетчик = 1 По СтрДлина(Телефон) Цикл
Символ = Сред(Телефон, Счетчик, 1);
Если Найти("0123456789-(); ", Символ) = 0 Тогда
ПозицияКомментарий = Счетчик;
Прервать;
КонецЕсли;
КонецЦикла;
Комментарий = "";
Представление = Телефон;
Если ПозицияКомментарий > 1 Тогда
Комментарий = Сред(Телефон, ПозицияКомментарий);
Телефон = СокрЛП(Лев(Телефон, ПозицияКомментарий - 1));
Если Найти("0123456789", Прав(Телефон, 1)) = 0 Тогда
Телефон = СокрЛП(Лев(Телефон, СтрДлина(Телефон) - 1));
КонецЕсли;
КонецЕсли;
// Очищаем мусорные комментарии
Если СтрДлина(Комментарий) < 3 Тогда
ПозицияКомментарий = 0;
КонецЕсли;
// Передаем параметры в КоллекциюОбъектов для последующей обработки в 8.3
КоллекцияОбъектов.НоваяСтрока();
КоллекцияОбъектов.Вид = ВидКИ; // Ссылка на Вид контактной информации в приемнике
КоллекцияОбъектов.Тип = "Телефон";
КоллекцияОбъектов.Представление = Представление;
КоллекцияОбъектов.НомерТелефона = Телефон;
КоллекцияОбъектов.Комментарий = Комментарий;
В ПКО Контрагенты (или ФизическиеЛица) в обработчике события ПослеЗагрузки мы пишем код, который обращается к программному интерфейсу БСП для правильного формирования полей:
Для Каждого СтрокаКИ Из Объект.КонтактнаяИнформация Цикл
Если СтрокаКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Телефон Тогда
// Формируем структуру по правилам БСП
СтруктураПолей = Новый Структура;
СтруктураПолей.Вставить("КодСтраны", "");
СтруктураПолей.Вставить("КодГорода", "");
СтруктураПолей.Вставить("НомерТелефона", СтрокаКИ.НомерТелефона);
СтруктураПолей.Вставить("Добавочный", "");
СтруктураПолей.Вставить("Комментарий", СтрокаКИ.Комментарий);
СтруктураПолей.Вставить("Представление", СтрокаКИ.Представление);
// Преобразуем структуру в XML-строку БСП через штатные функции
СтрокаXML = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВXML(СтруктураПолей, "", Перечисления.ТипыКонтактнойИнформации.Телефон);
// Если конфигурация использует современный формат JSON
СтрокаJSON = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияВJSON(СтрокаXML);
СтрокаКИ.ЗначенияПолей = СтрокаJSON;
КонецЕсли;
КонецЦикла;
---
Иногда при переносе данных возникает путаница с открытием правильных форм. Например, в конфигурации "Управление микрофинансовой организацией" (МФО) при попытке открыть контрагента с видом "Физическое лицо" система должна автоматически перенаправлять пользователя на форму элемента справочника ФизическиеЛица. Если этого не происходит, значит, связь между объектами перенесена не полностью.
Проанализируем ситуацию: за это поведение отвечает механизм переопределения форм платформы 1С 8.3. В модуле менеджера справочника Контрагенты описана предопределенная процедура ОбработкаПолученияФормы. Она проверяет наличие заполненной ссылки на физлицо в реквизитах контрагента. Если реквизит связи пуст, перенаправление не срабатывает и открывается стандартная форма контрагента.
Для решения проблемы мы должны гарантировать, что при переносе данных обязательно заполняется реквизит связи. Пример исправления данных обработкой в приемнике после загрузки:
Выборка = Справочники.Контрагенты.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.ВидКонтрагента = Перечисления.ЮрФизЛицо.ФизЛицо Тогда
// Находим соответствующее физлицо по ФИО/ИНН
ФизЛицоСсылка = Справочники.ФизическиеЛица.НайтиПоНаименованию(Выборка.Наименование);
Если ЗначениеЗаполнено(ФизЛицоСсылка) И Выборка.ФизическоеЛицо <> ФизЛицоСсылка Тогда
ОбъектКонтрагент = Выборка.ПолучитьОбъект();
ОбъектКонтрагент.ФизическоеЛицо = ФизЛицоСсылка;
ОбъектКонтрагент.Записать();
КонецЕсли;
КонецЕсли;
КонецЦикла;
---
Частая проблема после переноса документов (например, ПоступлениеТоваровУслуг) в базы 1С 8.3 (УПП, КА, ERP) — появление флага модифицированности (звездочки в заголовке окна) сразу же после открытия документа или перехода по вкладкам, даже если пользователь не вносил никаких изменений.
Выясним причину этого поведения. При переходе на вкладку "Услуги" система вызывает обработчик активизации строки табличной части. В нем отрабатывает типовой механизм приведения типов незаполненных аналитик субконто:
ТипСубк.ПривестиЗначение(ЭлементыСубконто["Субконто" + Сч])
Если при переносе данных пустые субконто записались со значением Неопределено, то принудительное приведение типа в памяти на лету заменяет Неопределено на пустую ссылку конкретного типа (например, СправочникСсылка.СтатьиЗатрат.ПустаяСсылка). С точки зрения платформы, данные строки изменились в оперативной памяти, что моментально взводит флаг модифицированности формы в значение Истина.
Решение заключается в том, чтобы привести типы пустых субконто к их корректным типам непосредственно в момент загрузки документа, до его первой записи в информационную базу. Напишем код в обработчике ПКО документа ПослеЗагрузкиОбъекта:
Для каждого СтрокаТЧ Из Объект.Услуги Цикл
// Приводим типы БУ
ЧислоАктивныхСубконто = СтрокаТЧ.СчетЗатрат.ВидыСубконто.Количество();
ЭлементыСубконто = Новый Структура("Субконто1,Субконто2,Субконто3", СтрокаТЧ.Субконто1, СтрокаТЧ.Субконто2, СтрокаТЧ.Субконто3);
Для Сч = 1 По ЧислоАктивныхСубконто Цикл
ТипСубк = СтрокаТЧ.СчетЗатрат.ВидыСубконто[Сч - 1].ВидСубконто.ТипЗначения;
ЭлементыСубконто["Субконто" + Сч] = ТипСубк.ПривестиЗначение(ЭлементыСубконто["Субконто" + Сч]);
КонецЦикла;
Для Сч = (ЧислоАктивныхСубконто + 1) По 3 Цикл
Если ЭлементыСубконто["Субконто" + Сч] <> Неопределено Тогда
ЭлементыСубконто["Субконто" + Сч] = Неопределено;
КонецЕсли;
КонецЦикла;
СтрокаТЧ.Субконто1 = ЭлементыСубконто.Субконто1;
СтрокаТЧ.Субконто2 = ЭлементыСубконто.Субконто2;
СтрокаТЧ.Subkonto3 = ЭлементыСубконто.Субконто3;
// Аналогично выполняем приведение типов для счетов налогового учета (НУ)
Если ПолучитьФункциональнуюОпцию("ИспользоватьНалоговыйУчет") Тогда
ЧислоАктивныхСубконтоНУ = СтрокаТЧ.СчетЗатратНУ.ВидыСубконто.Количество();
ЭлементыСубконтоНУ = Новый Структура("Субконто1,Субконто2,Субконто3", СтрокаТЧ.СубконтоНУ1, СтрокаТЧ.СубконтоНУ2, СтрокаТЧ.СубконтоНУ3);
Для Сч = 1 По ЧислоАктивныхСубконтоНУ Цикл
ТипСубк = СтрокаТЧ.СчетЗатратНУ.ВидыСубконто[Сч - 1].ВидСубконто.ТипЗначения;
ЭлементыСубконтоНУ["Субконто" + Сч] = ТипСубк.ПривестиЗначение(ЭлементыСубконтоНУ["Субконто" + Сч]);
КонецЦикла;
Для Сч = (ЧислоАктивныхСубконтоНУ + 1) По 3 Цикл
Если ЭлементыСубконтоНУ["Субконто" + Сч] <> Неопределено Тогда
ЭлементыСубконтоНУ["Субконто" + Сч] = Неопределено;
КонецЕсли;
КонецЦикла;
СтрокаТЧ.СубконтоНУ1 = ЭлементыСубконтоНУ.Субконто1;
СтрокаТЧ.СубконтоНУ2 = ЭлементыСубконтоНУ.Субконто2;
СтрокаТЧ.СубконтоНУ3 = ЭлементыСубконтоНУ.Субконто3;
КонецЕсли;
КонецЦикла;
Этот простой алгоритм полностью исключает возникновение ложной модифицированности при открытии документов пользователями, гарантируя чистоту перенесенных данных.
---
В процессе тестирования переноса мы часто сталкиваемся с тем, что в коде приемника происходит зацикливание или ложное срабатывание модифицированности, которое трудно отловить классической точкой останова. В таком случае используйте штатный инструмент Конфигуратора 8.3:
В меню выберите пункт Отладка -> Приостановить (или нажмите соответствующую иконку "Пауза" на панели инструментов). Платформа мгновенно остановит выполнение кода на текущей исполняемой строке, открыв перед вами стек вызовов. Это позволит быстро локализовать проблемный участок кода.