При разработке собственных механизмов переноса данных между базами 1С начинающие специалисты часто сталкиваются с ошибками ручного формирования XML. Попытка вручную записать структуру метаданных, атрибуты и значения полей через ЗаписьXML и ЧтениеXML приводит к потере типизации (числа, даты, булевы значения превращаются в строки), потере табличных частей, а также к невозможности корректно восстановить ссылочные связи. Разберем типичные ошибки такого подхода и рассмотрим надежный способ выгрузки и загрузки с использованием СериализаторXDTO.
Рассмотрим, почему ручная запись реквизитов через ЗаписьXML.ЗаписатьАтрибут() не работает для переноса данных:
"55" или "2023-01-01" требует сложного ручного приведения к типу платформы.Платформа 1С:Предприятие 8 предоставляет встроенный инструмент — СериализаторXDTO, который автоматически сохраняет всю структуру объекта (шапку, типы данных, табличные части, ссылки) в XML и восстанавливает её без ручного разбора каждого тега.
Разберем по шагам базовый механизм переноса любого справочника целиком.
Посмотрим на пример процедуры выгрузки данных конкретного справочника в XML-строку и последующего сохранения:
Процедура ВыгрузитьСправочник(ИмяСправочника, ПутьКФайлу)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Спр.Ссылка КАК Ссылка
|ИЗ
| Справочник." + ИмяСправочника + " КАК Спр";
Выборка = Запрос.Выполнить().Выбрать();
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("ДанныеXML");
Пока Выборка.Следующий() Цикл
ОбъектСправочника = Выборка.Ссылка.ПолучитьОбъект();
// Сериализуем объект целиком в XML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ОбъектСправочника);
СтрокаXML = ЗаписьXML.Закрыть();
НоваяСтрока = ТаблицаДанных.Добавить();
НоваяСтрока.ДанныеXML = СтрокаXML;
КонецЦикла;
ЗначениеВФайл(ПутьКФайлу, ТаблицаДанных);
Сообщить("Выгрузка справочника " + ИмяСправочника + " успешно завершена.");
КонецПроцедуры
Теперь разберем процедуру обратной загрузки данных из созданного файла:
Процедура ЗагрузитьСправочник(ПутьКФайлу)
ТаблицаДанных = ЗначениеИзФайла(ПутьКФайлу);
Если ТаблицаДанных = Неопределено Тогда
Сообщить("Не удалось прочитать файл данных!");
Возврат;
КонецЕсли;
Для Каждого Стр Из ТаблицаДанных Цикл
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(Стр.ДанныеXML);
// Десериализуем объект из XML
Объект = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
ЧтениеXML.Закрыть();
// Включаем режим загрузки для отключения прикладных проверок
Объект.ОбменДанными.Загрузка = Истина;
Попытка
Объект.Записать();
Сообщить("Записан объект: " + Объект);
Исключение
Сообщить("Ошибка при записи объекта: " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Сообщить("Загрузка успешно завершена.");
КонецПроцедуры
Если необходимо выгрузить все справочники конфигурации, проанализируем дерево метаданных и организуем цикл по коллекции Метаданные.Справочники. При этом каждый справочник сохраняется в отдельный файл:
Процедура ВыгрузитьВсеСправочники(КаталогВыгрузки)
Для Каждого МД_Справочник Из Метаданные.Справочники Цикл
ИмяСпр = МД_Справочник.Имя;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Спр.Ссылка КАК Ссылка
|ИЗ
| Справочник." + ИмяСпр + " КАК Спр";
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Продолжить;
КонецЕсли;
Выборка = Результат.Выбрать();
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("ДанныеXML");
Пока Выборка.Следующий() Цикл
ОбъектСпр = Выборка.Ссылка.ПолучитьОбъект();
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ОбъектСпр);
НоваяСтр = ТаблицаДанных.Добавить();
НоваяСтр.ДанныеXML = ЗаписьXML.Закрыть();
КонецЦикла;
ПолныйПуть = КаталогВыгрузки + "\" + ИмяСпр + ".dat";
ЗначениеВФайл(ПолныйПуть, ТаблицаДанных);
КонецЦикла;
КонецПроцедуры
СериализаторXDTO использует схему текущей конфигурации (http://v8.1c.ru/8.1/data/enterprise/current-config). База-источник и база-приемник должны иметь строго одинаковую структуру реквизитов переносимых справочников. Если в приемнике удален или переименован реквизит, возникнет ошибка Ошибка преобразования данных XDTO.Объект.ОбменДанными.Загрузка = Истина перед вызовом метода Записать() обязательна. Это отключает выполнение обработчиков событий ПередЗаписью и ПриЗаписи, позволяя загружать объекты «как есть» без дополнительных проверок бизнес-логики.<Объект не найден>, а после его загрузки автоматически станет корректной.