В практике разработчика 1С иногда возникают специфические задачи, когда стандартные средства обмена, такие как XML, JSON или Enterprise Data, недоступны или запрещены условиями технического задания. В такой ситуации необходимо разработать собственный текстовый формат и логику парсинга, которая позволит корректно восстановить объект в базе данных со всеми его реквизитами и табличными частями. Проанализируем, как это реализовать максимально эффективно.
Основная сложность при чтении данных из простого текстового файла заключается в том, что все значения считываются как тип Строка. Однако реквизиты документа могут иметь типы Число, Дата, Булево или быть ссылками на другие объекты (Справочники, Документы, Перечисления). Простое присвоение НовДокумент[ИмяРеквизита] = ЗначениеИзФайла не сработает для ссылочных типов. Нам необходимо выполнить преобразование типов, основываясь на метаданных документа.
Рассмотрим наиболее надежный способ ручного восстановления данных. Чтобы превратить строку из файла в полноценное значение 1С, мы будем использовать информацию о типе реквизита из метаданных. Посмотрим на алгоритм реализации:
// Предположим, Мас[0] - имя реквизита, Мас[1] - строковое значение из файла
МетаДок = НовДокумент.Метаданные();
РеквизитМета = МетаДок.Реквизиты.Найти(Мас[0]);
Если РеквизитМета <> Неопределено Тогда
// Используем XMLЗначение для стандартных типов и простых ссылок
// Важно: в файле значение должно быть сохранено через XMLСтрока()
Попытка
НовДокумент[Мас[0]] = XMLЗначение(РеквизитМета.Тип, Мас[1]);
Исключение
// Если это сложная ссылка или составной тип, здесь потребуется доп. логика
Сообщить("Ошибка приведения типа для реквизита: " + Мас[0]);
КонецПопытки;
КонецЕсли;
Для корректной работы этого метода при выгрузке данных обязательно используйте функцию XMLСтрока(Значение). Она преобразует любое значение (даже ссылку) в уникальный строковый идентификатор, который 1С умеет распознавать обратно через XMLЗначение.
Если вы не хотите полагаться на XML-сериализацию, проанализируем способ работы через уникальные идентификаторы (GUID). Это самый точный метод связи объектов между разными базами.
При выгрузке вместо наименования справочника записывайте его внутренний идентификатор. Рассмотрим, как восстановить ссылку при загрузке:
// В файле сохранена строка вида: "Справочник.Контрагенты|8f3e5b12-..."
ДанныеСсылки = СтрРазделить(ЗначениеИзФайла, "|");
ИмяМетаданных = ДанныеСсылки[0]; // Например, "Справочник.Контрагенты"
Идентификатор = Новый УникальныйИдентификатор(ДанныеСсылки[1]);
// Получаем ссылку по идентификатору
СсылкаНаОбъект = Справочники.Контрагенты.ПолучитьСсылку(Идентификатор);
Важный нюанс: Если вы используете поиск по наименованию или коду (НайтиПоНаименованию), будьте осторожны — в базе могут существовать дубликаты, или наименование может измениться, что приведет к ошибке привязки данных.
Выясним причину, по которой опытные разработчики иногда используют "старые" методы. Существует системная функция ЗначениеВСтрокуВнутр(). Она переводит любой объект (включая целые документы с ТЧ) в специальный текстовый формат 1С. Это самый простой способ выполнить задание "выгрузить в текст", если формат текста не регламентирован жестко.
Запись в файл:
Текст = Новый ЗаписьТекста("C:\Export\doc.txt");
Текст.ЗаписатьСтроку(ЗначениеВСтрокуВнутр(ОбъектДокумент));
Текст.Закрыть();
Восстановление из файла:
Текст = Новый ЧтениеТекста("C:\Export\doc.txt");
СтрокаДанных = Текст.Прочитать();
НовыйОбъект = ЗначениеИзСтрокиВнутр(СтрокаДанных);
НовыйОбъект.УстановитьСсылкуНового(Документы.ИмяДокумента.ПолучитьСсылку());
НовыйОбъект.Записать();
Внимание: Этот метод имеет недостатки. Полученный текст не предназначен для чтения человеком, и он может перестать работать, если структура документа в конфигурации изменится (например, удалят реквизит).
Проанализируем ситуацию с табличными частями. Для их корректного воссоздания нам нужно сначала очистить ТЧ в созданном документе, а затем добавлять строки в цикле. Рассмотрим пример реализации логики для ТЧ:
[ТабличнаяЧасть.Товары]).НовДокумент[ИмяТЧ].Добавить() для создания новой строки и заполняем её реквизиты аналогично шапке документа.
// Пример загрузки строки табличной части
НоваяСтрока = НовДокумент.Товары.Добавить();
Для Каждого Колонка Из МетаДок.ТабличныеЧасти.Товары.Реквизиты Цикл
// Логика поиска значения в массиве данных из файла и его типизация
ИмяРеквизитаТЧ = Колонка.Имя;
НоваяСтрока[ИмяРеквизитаТЧ] = XMLЗначение(Колонка.Тип, ЗначениеИзФайла);
КонецЦикла;
Рассмотрим подробнее вопрос производительности. При работе с большими объемами данных (многострочные документы или пакетная выгрузка) не используйте объект ТекстовыйДокумент. Он загружает весь текст в оперативную память, что может привести к зависанию системы.
Вместо этого используйте потоковые объекты ЗаписьТекста и ЧтениеТекста. Они позволяют обрабатывать файл построчно, не нагружая память. Это критически важно для серверных процедур 1С.
Подытожим: Для создания надежного механизма выгрузки в текст мы рекомендуем сочетать использование UUID для ссылок и Метаданные для определения типов при загрузке. Это обеспечит гибкость кода и независимость от изменений порядка реквизитов в конфигурации.