Как правильно перенести периодические реквизиты из 1С 8 в 1С 7.7 через Конвертацию данных

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Перенос данных между разными поколениями платформ 1С всегда сопряжен с трудностями, но перенос истории изменений — это «задача со звездочкой». Основная сложность заключается в фундаментальном различии архитектур: в 1С:Предприятие 8 история хранится в независимых Регистрах сведений, а в 1С:Предприятие 7.7 она привязана непосредственно к реквизиту справочника и называется периодическим реквизитом.

Если выполнять перенос обычным сопоставлением полей (ПКС), данные в 7.7 запишутся на текущую дату загрузки. В итоге сотрудник, работающий в компании 10. лет, в старой базе будет выглядеть как только что принятый новичок. Рассмотрим, как решить эту проблему с помощью гибких механизмов конфигурации «Конвертация данных 2.0».

Разберем причину проблемы: почему стандартное ПКС не работает

Проанализируем стандартный процесс: когда вы указываете Источник и Приемник для реквизита «Состояние», платформа 7.7 при загрузке выполняет простое присваивание: Спр.Состояние = Значение. Для периодического реквизита в 7.7 это означает запись значения на текущую рабочую дату (обычно дату загрузки). Нам же необходимо, чтобы значение было установлено на дату фактического события (например, на дату приема на работу), хранящуюся в 8-ке.

Для реализации этой задачи нам придется «вклиниться» в процесс формирования XML-файла и процесс его чтения, чтобы передать дату вместе со значением.

Шаг 1: Подготовка данных на стороне 1С 8.х

Выясним, как передать дополнительную информацию (дату), которая не является прямым свойством справочника. Мы будем использовать ручное создание XML-узлов в обработчиках Конвертации данных.

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


// В обработчике "После выгрузки" (ПКО Сотрудники)
// Допустим, мы получили ДатуПриема из регистра сведений
Сообщить(ВходящиеДанные.ДатаПриема);

ИмяРеквизита = "Состояние";
// Создаем специальный узел в XML, который 7.7 сможет распознать
УзелПериодического = СоздатьУзел("Периодика_Сотрудника");
УстановитьАтрибут(УзелПериодического, "Имя", ИмяРеквизита);

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

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

Важный момент: использование СоздатьУзел и ДобавитьПодчиненный позволяет нам выйти за рамки стандартных свойств и передать в приемник любую структуру данных.

Шаг 2: Обработка и запись данных на стороне 1С 7.7

Теперь рассмотрим, как принять эти данные в «семерке». На стороне приемника нам нужно прочитать созданные нами узлы и использовать объект Периодический для записи истории. Это делается в ПКО в обработчике «При загрузке».

Посмотрим на пример реализации логики парсинга и записи:


// В обработчике "При загрузке" (ПКО Сотрудники)
// Ищем наши кастомные узлы в XML
УзлыПериодического = Узел.ВыбратьУзлы("Периодика_Сотрудника");             

Для СчУзлов = 0 По УзлыПериодического.КоличествоУзлов-1 Цикл
    УзелПериодического = УзлыПериодического.ПолучитьУзел(СчУзлов);             
    ИмяРеквизита = УзелПериодического.ПолучитьАтрибут("Имя");
    
    // Инициализируем объект для работы с историей реквизита в 7.7
    ОбъектПериод = СоздатьОбъект("Периодический");
    
    // Привязываем объект к конкретному реквизиту загруженного сотрудника
    ОбъектПериод.ИспользоватьОбъект("Состояние", Объект);
    
    ВыборкаЗначений = УзелПериодического.ВыбратьУзлы("ЗаписьИстории");
    Для Сч = 0 По ВыборкаЗначений.КоличествоУзлов-1 Цикл
        УзелЗначения = ВыборкаЗначений.ПолучитьУзел(Сч);
        
        // Получаем атрибуты. Помним, что в XML они хранятся как строки
        СтрДата = УзелЗначения.ПолучитьАтрибут("ДатаЗнач"); 
        ЗначИз8 = УзелЗначения.ПолучитьАтрибут("Значение");
        
        // Преобразование строковой даты (ГГГГ-ММ-ДД) в тип Дата 7.7
        // XML стандартно выдает дату как "2023-10-25"
        РабочаяДата = Дата(Сред(СтрДата,9,2)+"."+Сред(СтрДата,6,2)+"."+Лев(СтрДата,4));
        
        // Сопоставление перечислений (если нужно)
        Если ЗначИз8 = "ОсновноеМестоРаботы" Тогда
            НужноеЗначение = Перечисление.СостояниеФизЛица.СотрудникОсновной;
        ИначеЕсли (ЗначИз8 = "Совместительство") Тогда
            НужноеЗначение = Перечисление.СостояниеФизЛица.СотрудникНеосновной;
        Иначе
            НужноеЗначение = "";
        КонецЕсли;
        
        // Записываем значение в историю на нужную дату
        ОбъектПериод.ДатаЗнач = РабочаяДата;
        ОбъектПериод.Значение = НужноеЗначение;
        ОбъектПериод.Записать();
    КонецЦикла;
КонецЦикла;

Альтернативные методы записи в 7.7

Проанализируем другие способы работы с периодическими данными, которые предлагает платформа 7.7. В некоторых случаях они могут быть удобнее:

  1. Метод Установить(): Если вам нужно записать всего одно значение на одну дату, можно обойтись без создания объекта Периодический. Код будет выглядеть так: Объект.Реквизит.Установить(НужнаяДата, Значение). Однако при массовом переносе истории (несколько записей для одного сотрудника) этот метод работает менее стабильно, чем прямой доступ через объект Периодический.
  2. Метод ИспользоватьДату(): Можно глобально установить дату для всего объекта справочника перед записью реквизитов: Объект.ИспользоватьДату(НужнаяДата). После этого обычное присваивание Объект.Реквизит = Значение запишет данные на указанную дату. Это удобно, если у всех реквизитов одна дата изменения, но опасно при работе со сложными алгоритмами загрузки.

Важные рекомендации и нюансы

Рассмотрим несколько критических моментов, которые помогут избежать ошибок при реализации:

1. Формат даты: При передаче даты через атрибуты XML (как в нашем примере), 1С 7.7 получит её в строковом формате YYYY-MM-DD. Обязательно используйте функции Лев(), Сред() и Прав() для приведения строки к формату ДД.ММ.ГГГГ, который понимает функция Дата() в 7.7.

2. Типизация данных: В 1С 7.7 нельзя просто записать строку в значение периодического реквизита, если этот реквизит имеет тип «Перечисление» или «Справочник». Вам необходимо предварительно найти ссылку на соответствующий объект или значение перечисления в базе 7.7.

3. Очистка старой истории: Если вы планируете повторные загрузки, имейте в виду, что метод Записать() объекта Периодический просто перезаписывает значение на указанную дату, если оно там уже было. Если же записи на эту дату не было, создается новая. Если нужно полностью синхронизировать историю, перед загрузкой может потребоваться очистка всех существующих значений реквизита через ВыбратьЗначения() и Удалить().

4. Использование "Дополнительных свойств": В современных версиях «Конвертации данных» вместо ручного создания XML-узлов можно использовать коллекцию ДополнительныеСвойства у объекта. В 8-ке вы помещаете туда таблицу значений с историей, а в 7.7 извлекаете её. Это делает код более читаемым и соответствующим стандартам разработки.

Таким образом, мы выяснили, что перенос периодических реквизитов требует отказа от автоматических механизмов ПКС в пользу программного управления объектами в обработчиках загрузки. Это единственный надежный способ сохранить хронологию кадровых и финансовых изменений при переходе на старые версии систем.

← На главную