Как реализовать выгрузку и загрузку любого документа 1С в текстовый файл с помощью метаданных?

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

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

Организация выбора любого документа на форме

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

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

После того как реквизит создан, просто перетащим его на форму. Платформа 1С автоматически создаст поле ввода, при нажатии на которое пользователю сначала будет предложено выбрать тип документа, а затем — конкретный экземпляр из списка. Это избавляет нас от написания лишнего кода для формирования списков выбора.

Алгоритм выгрузки данных в TXT через метаданные

Поскольку нам запрещено использовать ЗначениеВСтрокуВнутр и уникальные идентификаторы (UUID), наша задача — превратить объект документа в структурированный текст. Проанализируем, из чего состоит документ: это заголовок (тип документа), основные реквизиты и табличные части. Для программного обхода структуры документа мы будем использовать объект Метаданные.

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

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

Пример кода для выгрузки основных реквизитов:


// Создаем объект для записи
Текст = Новый ЗаписьТекста(ПутьКФайлу, КодировкаТекста.UTF8);

// Записываем тип документа, чтобы знать, что создавать при загрузке
МетаданныеДока = ВыбранныйДокумент.Метаданные();
Текст.ЗаписатьСтроку("[ТипОбъекта]" + МетаданныеДока.Имя);

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

Структурирование текстового файла

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

Важный нюанс: согласно условию, номер документа выгружать не нужно, так как он должен присваиваться автоматически (быть уникальным). Однако дату выгружать необходимо, так как она часто определяет период нумерации.

Проблема ссылочных типов при работе с TXT

Самый сложный момент в этой задаче — передача ссылок на справочники (например, Склад, Контрагент, Номенклатура). Так как UUID использовать нельзя, единственным надежным способом является поиск по уникальным полям самого справочника — Коду или Наименованию.

Рассмотрим ситуацию: в документе есть реквизит «Склад». При выгрузке нам нужно записать не просто «Склад», а тип справочника и его наименование. Например: Склад|Справочник.Склады|Основной склад. При загрузке нам придется парсить эту строку и использовать метод НайтиПоНаименованию().

Проанализируем пример функции для обработки ссылок:


Функция ФормироватьСтрокуИзЗначения(Значение)
    Если ТипЗнч(Значение) = Тип("Число") Тогда
        Возврат "Ч:" + Строка(Значение);
    ИначеЕсли ТипЗнч(Значение) = Тип("Дата") Тогда
        Возврат "Д:" + Формат(Значение, "ДФ=ггггММддЧЧммсс");
    ИначеЕсли ТипЗнч(Значение) = Тип("Булево") Тогда
        Возврат "Б:" + ?(Значение, "1", "0");
    ИначеЕсли Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
        // Для ссылок сохраняем тип и наименование (или код)
        Возврат "С:" + Значение.Метаданные().Имя + "|" + Строка(Значение);
    Иначе
        Возврат "Т:" + Строка(Значение);
    КонецЕсли;
КонецФункции

Реализация загрузки данных и создание копии

Процесс загрузки — это обратное преобразование текста в объект 1С. Выясним последовательность действий:

  1. Чтение файла: Используем объект ЧтениеТекста. Читаем файл построчно в цикле Пока.
  2. Определение типа: Из первой секции узнаем имя документа в метаданных.
  3. Создание объекта: Используем конструкцию Документы[ИмяДокумента].СоздатьДокумент().
  4. Заполнение реквизитов: Читаем строки, разделяем их по символу «=», находим нужный реквизит объекта и присваиваем ему преобразованное значение.
  5. Заполнение табличных частей: При встрече маркера таблицы создаем новую строку в ТЧ документа методом Добавить() и заполняем её колонки.
  6. Запись: После завершения цикла вызываем НовыйОбъект.Записать().

Посмотрим, как выглядит поиск ссылки при загрузке:


// Пример парсинга строки ссылки "С:Склады|Основной склад"
Если Лево(ЗначениеИзФайла, 2) = "С:" Тогда
    ДанныеСсылки = Сред(ЗначениеИзФайла, 3); // "Склады|Основной склад"
    ПозицияРазделителя = Найти(ДанныеСсылки, "|");
    ИмяСправочника = Лев(ДанныеСсылки, ПозицияРазделителя - 1);
    Наименование = Сред(ДанныеСсылки, ПозицияРазделителя + 1);
    
    // Ищем объект в базе
    НайденнаяСсылка = Справочники[ИмяСправочника].НайтиПоНаименованию(Наименование);
    Объект[ИмяРеквизита] = НайденнаяСсылка;
КонецЕсли;

Особенности и ограничения

Нужно понимать, что поиск по наименованию — это «костыль», который может привести к ошибкам, если в базе есть два элемента с одинаковым именем. Именно поэтому в реальных задачах 1С всегда использует УникальныйИдентификатор. Однако в рамках данного учебного задания такой подход позволяет лучше понять механику работы со ссылочными типами данных и строковыми функциями.

Также важно помнить о стандартных реквизитах. Помимо тех реквизитов, что вы создали сами, у документа есть системные поля: Дата, Проведен, ПометкаУдаления. Их также следует включить в цикл обхода, обращаясь к коллекции МетаданныеДокумента.СтандартныеРеквизиты или просто прописав их обработку вручную.

Использование этого метода разработки позволит вам не только решить текущую задачу, но и глубже изучить дерево метаданных 1С, что является критически важным навыком для любого профессионального разработчика.

← На главную