Как выгрузить и загрузить данные документа 1С в текстовый файл без использования GUID, XML и JSON?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В практике программирования на платформе 1С:Предприятие часто встречаются задачи, связанные с обменом данными. Одной из наиболее интересных и сложных вариаций является выгрузка данных документа в простой текстовый файл с последующей загрузкой в другую информационную базу (или тот же документ) при соблюдении жестких ограничений. Зачастую в таких задачах запрещается использовать стандартные механизмы сериализации, такие как XML, JSON или системные функции ЗначениеВСтрокуВнутр() и УникальныйИдентификатор().

В этой статье мы подробно разберем, как реализовать универсальный механизм выгрузки и загрузки реквизитов документа, опираясь исключительно на работу с метаданными и поиск объектов по строковым представлениям. Мы проанализируем процесс получения типов, работу с менеджерами объектов и логику восстановления ссылочных данных.

Постановка задачи и анализ ограничений

Представим ситуацию: нам необходимо передать данные документа через txt файл. Если реквизит имеет тип Строка, Число или Дата, проблем не возникает — они легко преобразуются в текст и обратно. Однако, если реквизит является ссылкой (например, СправочникСсылка.Номенклатура или ПеречислениеСсылка.Статусы), простая запись наименования в файл не позволит системе автоматически восстановить ссылку при загрузке. Нам потребуется алгоритм, который определит, к какому справочнику относится данное название, и найдет соответствующий элемент в базе.

Выгрузка данных: сохраняем информацию правильно

Для того чтобы загрузка прошла успешно, в текстовый файл нужно записывать не только значение реквизита, но и информацию о его типе. Рассмотрим, как программно обойти реквизиты документа и подготовить данные для записи.

Для начала проанализируем способ обхода метаданных документа. Нам необходимо получить коллекцию реквизитов и их значения:


Для Каждого РеквизитМетаданные Из Объект.Метаданные().Реквизиты Цикл
    ИмяРеквизита = РеквизитМетаданные.Имя;
    Значение = Объект[ИмяРеквизита];
    ТипЗнч = ТипЗнч(Значение);
    
    // Формируем строку для записи: Имя|Тип|Значение
    СтрокаВыгрузки = ИмяРеквизита + "|" + Строка(ТипЗнч) + "|" + СокрЛП(Значение);
    // Записываем строку в ТекстовыйДокумент
КонецЦикла;

Важно понимать разницу между ТипЗнч() и описанием типов в метаданных. При выгрузке конкретного документа мы работаем с уже заполненными данными, поэтому ТипЗнч(Значение) даст нам точное понимание, что именно записано в поле, даже если тип реквизита составной.

Загрузка данных: поиск ссылок по наименованию

Самый ответственный этап — это восстановление ссылочных типов при чтении файла. Разберем по шагам, как превратить строку "Яблоки" обратно в объект СправочникСсылка.Номенклатура.

Когда мы считываем строку из файла, мы получаем строковое представление типа. Нам нужно получить доступ к менеджеру соответствующего объекта (справочника или перечисления), чтобы вызвать метод НайтиПоНаименованию().

Рассмотрим алгоритм поиска менеджера через метаданные:

  1. Сначала мы определяем, к какому виду относится объект (Справочник, Перечисление или Документ).
  2. Используя коллекцию Метаданные, находим нужный объект по имени.
  3. Обращаемся к менеджеру через глобальный контекст.

Посмотрим на пример кода, который выполняет поиск ссылки:


Функция НайтиСсылкуПоНаименованию(ИмяОбъектаМетаданных, ЗначениеПоиска)
    // Предположим, ИмяОбъектаМетаданных пришло в виде "Справочник.Номенклатура"
    МассивСлов = СтрРазделить(ИмяОбъектаМетаданных, ".");
    ВидОбъекта = МассивСлов[0]; // Справочник
    ИмяОбъекта = МассивСлов[1]; // Номенклатура
    
    Если ВидОбъекта = "Справочник" Тогда
        Возврат Справочники[ИмяОбъекта].НайтиПоНаименованию(ЗначениеПоиска);
    ИначеЕсли ВидОбъекта = "Перечисление" Тогда
        // С перечислениями сложнее, у них нет метода НайтиПоНаименованию
        Возврат НайтиЗначениеПеречисления(ИмяОбъекта, ЗначениеПоиска);
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Особенности работы с Перечислениями

Проанализируем ситуацию с перечислениями. Поскольку у них нет методов поиска, нам придется перебирать их значения через метаданные или использовать индекс. Если в текстовый файл мы выгрузили синоним или имя значения, алгоритм восстановления будет выглядеть так:


Функция НайтиЗначениеПеречисления(ИмяПеречисления, ЗначениеСтрокой)
    Менеджер = Перечисления[ИмяПеречисления];
    Для Каждого Значение Из Метаданные.Перечисления[ИмяПеречисления].ЗначенияПеречисления Цикл
        Если Значение.Имя = ЗначениеСтрокой Или Значение.Синоним = ЗначениеСтрокой Тогда
            Индекс = Метаданные.Перечисления[ИмяПеречисления].ЗначенияПеречисления.Индекс(Значение);
            Возврат Менеджер[Индекс];
        КонецЕсли;
    КонецЦикла;
    Возврат Неопределено;
КонецФункции

Проблема дублей и уникальности данных

При использовании НайтиПоНаименованию() мы можем столкнуться с проблемой, когда в справочнике есть два элемента с одинаковым названием. Выясним причину, почему это критично: система вернет первую попавшуюся ссылку, что может привести к ошибке в учете. Если условия задачи позволяют, рекомендуется выгружать дополнительно Код справочника.

В этом случае строка в файле будет выглядеть так: Номенклатура|Яблоки|00001. При загрузке мы сначала используем НайтиПоКоду(), и только если объект не найден — НайтиПоНаименованию().

Работа с табличными частями

Не забудем, что документ — это не только шапка, но и табличные части. Для их выгрузки нам нужно вложить еще один цикл обхода. Рассмотрим структуру файла для ТЧ:

Мы можем использовать специальные маркеры в текстовом файле, например, [НачалоТаблицы:Товары] и [КонецТаблицы]. Это позволит парсеру при загрузке понять, что данные нужно добавлять в строки таблицы, а не в реквизиты объекта.


Для Каждого ТЧ Из Объект.Метаданные().ТабличныеЧасти Цикл
    ЗаписатьСтроку(Файл, "[Table:" + ТЧ.Имя + "]");
    Для Каждого СтрокаТЧ Из Объект[ТЧ.Имя] Цикл
        ДанныеСтроки = "";
        Для Каждого Колонна Из ТЧ.Реквизиты Цикл
            ДанныеСтроки = ДанныеСтроки + Строка(СтрокаТЧ[Колонна.Имя]) + "|";
        КонецЦикла;
        ЗаписатьСтроку(Файл, ДанныеСтроки);
    КонецЦикла;
КонецЦикла;

Использование ОписанияТипов

Разберем важный момент, упомянутый в обсуждении: использование ОписаниеТипов. Если мы загружаем данные и не знаем заранее, какой тип должен быть у реквизита (например, при заполнении пустого документа), мы должны обратиться к метаданным самого документа:


ОписаниеТипаРеквизита = Объект.Метаданные().Реквизиты[ИмяИзФайла].Тип;
// Если тип не составной, получаем первый доступный тип
НужныйТип = ОписаниеТипаРеквизита.Типы()[0]; 
// Теперь, используя НужныйТип, мы можем найти менеджер через Метаданные.НайтиПоТипу(НужныйТип)

Этот подход делает загрузку универсальной. Вам не нужно жестко прописывать условия для каждого справочника. Система сама "поймет", что в реквизит "Склад" нужно искать ссылку в справочнике "Склады", основываясь на конфигурации.

Резюме

Реализация обмена через txt без использования стандартных идентификаторов — это отличный способ глубже изучить работу с метаданными 1С. Мы выяснили, что ключ к успеху лежит в правильном сохранении названия типа и использовании менеджеров объектов для поиска ссылок. Несмотря на ограничения, платформа предоставляет достаточно инструментов (Метаданные, Менеджеры, Типы) для решения подобных задач.

← На главную