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

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

В практике разработчика 1С часто возникает задача переноса данных из сторонних систем через простые текстовые форматы. Несмотря на популярность JSON и XML, формат TXT остается актуальным благодаря своей легкости и простоте формирования. В данной статье мы разберем, как создать универсальный механизм загрузки, который может адаптироваться под разные типы документов, автоматически сопоставляя данные из файла с метаданными системы.

Анализ структуры входного файла

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

  1. Первая строка — внутреннее имя документа (например, ПоступлениеТоваровУслуг).
  2. Вторая строка — дата документа.
  3. Последующие строки — пары «Ключ=Значение», где ключ соответствует имени реквизита.
  4. Для табличных частей используются специальные префиксы или разделители.

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

Создание документа и заполнение основных реквизитов

Начнем с чтения файла и инициализации объекта. Для работы с текстовыми данными в 1С используется объект ТекстовыйДокумент. Разберем, как правильно прочитать первые строки и создать новый документ на сервере:


&НаСервере
Процедура ЗагрузитьДанныеИзФайлаНаСервере(ПутьКФайлу)
    Текст = Новый ТекстовыйДокумент;
    Текст.Прочитать(ПутьКФайлу, КодировкаТекста.UTF8);
    
    Если Текст.КоличествоСтрок() < 2 Тогда
        Возврат; // Файл пустой или поврежден
    КонецЕсли;

    ИмяДокумента = Текст.ПолучитьСтроку(1);
    ДатаДокумента = Текст.ПолучитьСтроку(2);

    // Создаем новый документ динамически по имени из метаданных
    НовыйДокумент = Документы[ИмяДокумента].СоздатьДокумент();
    НовыйДокумент.Дата = Дата(ДатаДокумента);
    
    // Переходим к разбору реквизитов, начиная с 3-й строки
    Для Индекс = 3 По Текст.КоличествоСтрок() Цикл
        ТекущаяСтрока = Текст.ПолучитьСтроку(Индекс);
        // Здесь будет логика парсинга строк
    КонецЦикла;
    
    НовыйДокумент.Записать();
КонецПроцедуры

Обратите внимание на использование коллекции Документы[ИмяДокумента]. Это позволяет избежать жесткого кодирования конкретных типов документов, делая обработку универсальной.

Парсинг строк и обработка ссылочных типов

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

Для определения типа реквизита мы будем обращаться к свойству Метаданные. Выясним причину, по которой простое присвоение часто выдает ошибку: ссылочному реквизиту нельзя присвоить объектное значение или строку, нужно получить именно Ссылку.


// Пример парсинга строки вида "Контрагент=00001"
Разделитель = Найти(ТекущаяСтрока, "=");
ИмяРеквизита = Лев(ТекущаяСтрока, Разделитель - 1);
ЗначениеИзФайла = Сред(ТекущаяСтрока, Разделитель + 1);

// Получаем метаданные текущего реквизита
МетаданныеРеквизита = НовыйДокумент.Метаданные().Реквизиты.Найти(ИмяРеквизита);

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

Работа с перечислениями

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


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

Заполнение табличных частей

Загрузка строк табличной части (ТЧ) требует особого внимания. Нам нужно не только найти реквизит, но и создать новую строку в объекте 1С. Проанализируем пример кода, который определяет, к какой ТЧ относится строка данных. Допустим, в файле строки ТЧ помечены как ТабличныеЧасти;ИмяТЧ;Реквизит=Значение.


Если Найти(ТекущаяСтрока, "ТабличныеЧасти;") > 0 Тогда
    МассивДанных = СтрРазделить(ТекущаяСтрока, ";");
    ИмяТЧ = МассивДанных[1];
    ДанныеРеквизита = МассивДанных[2]; // Строка вида "Номенклатура=Код123"
    
    РазделительТЧ = Найти(ДанныеРеквизита, "=");
    ИмяРеквизитаТЧ = Лев(ДанныеРеквизита, РазделительТЧ - 1);
    ЗначениеРеквизитаТЧ = Сред(ДанныеРеквизита, РазделительТЧ + 1);
    
    // В реальной логике здесь нужно определять, когда добавлять новую строку.
    // Например, если реквизит - это первый столбец ТЧ (Номенклатура)
    Если ИмяРеквизитаТЧ = "Номенклатура" Тогда
        НоваяСтрока = НовыйДокумент[ИмяТЧ].Добавить();
    КонецЕсли;
    
    // Заполнение реквизита строки ТЧ (аналогично логике шапки)
    // ... поиск ссылки или простое присвоение ...
    НоваяСтрока[ИмяРеквизитаТЧ] = ЗначениеРеквизитаТЧ;
КонецЕсли;

Обработка многострочных данных и JSON-фрагментов

Иногда в текстовый файл попадают сложные структуры, например, контактная информация или адреса, представленные в формате JSON внутри одной строки. Посмотрим на пример такой строки: { "value": "Москва", "type": "Адрес" }.

Выясним, как с этим работать без полного переписывания парсера на JSON. Если вы столкнулись с такой ситуацией, рекомендуется использовать встроенную функцию ПрочитатьJSON() для конкретного значения или предварительно очищать строку от лишних переносов. Однако в рамках простого TXT-парсера эффективнее всего использовать теги-разделители или заменять символы переноса строки на технические маркеры при выгрузке, а при загрузке восстанавливать их функцией СтрЗаменить(Значение, "|n|", Символы.ПС).

Рекомендации по стабильности кода

Для того чтобы ваша обработка не вызывала критических ошибок при загрузке, всегда внедряйте проверки существования метаданных. Разберем основные правила безопасности:

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

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

← На главную