В практике разработчика 1С часто возникает задача переноса данных из сторонних систем через простые текстовые форматы. Несмотря на популярность JSON и XML, формат TXT остается актуальным благодаря своей легкости и простоте формирования. В данной статье мы разберем, как создать универсальный механизм загрузки, который может адаптироваться под разные типы документов, автоматически сопоставляя данные из файла с метаданными системы.
Прежде чем приступать к написанию кода, определим логику хранения данных в файле. Рассмотрим структуру, предложенную в обсуждении:
ПоступлениеТоваровУслуг).Такой подход позволяет нам динамически создавать объект нужного типа, не прописывая условия для каждого отдельного документа вручную.
Начнем с чтения файла и инициализации объекта. Для работы с текстовыми данными в 1С используется объект ТекстовыйДокумент. Разберем, как правильно прочитать первые строки и создать новый документ на сервере:
&НаСервере
Процедура ЗагрузитьДанныеИзФайлаНаСервере(ПутьКФайлу)
Текст = Новый ТекстовыйДокумент;
Текст.Прочитать(ПутьКФайлу, КодировкаТекста.UTF8);
Если Текст.КоличествоСтрок() < 2 Тогда
Возврат; // Файл пустой или поврежден
КонецЕсли;
ИмяДокумента = Текст.ПолучитьСтроку(1);
ДатаДокумента = Текст.ПолучитьСтроку(2);
// Создаем новый документ динамически по имени из метаданных
НовыйДокумент = Документы[ИмяДокумента].СоздатьДокумент();
НовыйДокумент.Дата = Дата(ДатаДокумента);
// Переходим к разбору реквизитов, начиная с 3-й строки
Для Индекс = 3 По Текст.КоличествоСтрок() Цикл
ТекущаяСтрока = Текст.ПолучитьСтроку(Индекс);
// Здесь будет логика парсинга строк
КонецЦикла;
НовыйДокумент.Записать();
КонецПроцедуры
Обратите внимание на использование коллекции Документы[ИмяДокумента]. Это позволяет избежать жесткого кодирования конкретных типов документов, делая обработку универсальной.
Одной из главных проблем при загрузке из TXT является преобразование строкового представления данных в ссылочные типы (справочники, перечисления). Мы не можем просто присвоить строку реквизиту, который ожидает ссылку. Проанализируем ситуацию: если в файле указан код контрагента, нам необходимо найти этот объект в базе.
Для определения типа реквизита мы будем обращаться к свойству Метаданные. Выясним причину, по которой простое присвоение часто выдает ошибку: ссылочному реквизиту нельзя присвоить объектное значение или строку, нужно получить именно Ссылку.
// Пример парсинга строки вида "Контрагент=00001"
Разделитель = Найти(ТекущаяСтрока, "=");
ИмяРеквизита = Лев(ТекущаяСтрока, Разделитель - 1);
ЗначениеИзФайла = Сред(ТекущаяСтрока, Разделитель + 1);
// Получаем метаданные текущего реквизита
МетаданныеРеквизита = НовыйДокумент.Метаданные().Реквизиты.Найти(ИмяРеквизита);
Если МетаданныеРеквизита <> Неопределено Тогда
ТипРеквизита = МетаданныеРеквизита.Тип;
// Проверяем, является ли тип справочником
Если Справочники.ТипВсеСсылки().СодержитТип(ТипРеквизита.Типы()[0]) Тогда
// Определяем имя справочника для поиска
ИмяСправочника = МетаданныеРеквизита.Тип.Типы()[0];
// Важно: Поиск по коду возвращает ссылку
НайденнаяСсылка = Справочники[МетаданныеРеквизита.Тип.Типы()[0]].НайтиПоКоду(ЗначениеИзФайла);
НовыйДокумент[ИмяРеквизита] = НайденнаяСсылка;
Иначе
// Для простых типов (строка, число) присваиваем напрямую
НовыйДокумент[ИмяРеквизита] = ЗначениеИзФайла;
КонецЕсли;
КонецЕсли;
Если реквизит имеет тип ПеречислениеСсылка, механика поиска меняется. Рассмотрим подробнее: перечисления не имеют кодов или наименований в базе данных, к которым можно обратиться через НайтиПоНаименованию(). Доступ к ним осуществляется по имени значения, заданному в конфигураторе.
Если Перечисления.ТипВсеСсылки().СодержитТип(ТипРеквизита.Типы()[0]) Тогда
// Получаем имя перечисления (например, "СтатусыЗаказов")
ИмяПеречисления = МетаданныеРеквизита.Тип.Типы()[0];
// Присваиваем значение по имени
НовыйДокумент[ИмяРеквизита] = Перечисления[ИмяПеречисления][ЗначениеИзФайла];
КонецЕсли;
Загрузка строк табличной части (ТЧ) требует особого внимания. Нам нужно не только найти реквизит, но и создать новую строку в объекте 1С. Проанализируем пример кода, который определяет, к какой ТЧ относится строка данных. Допустим, в файле строки ТЧ помечены как ТабличныеЧасти;ИмяТЧ;Реквизит=Значение.
Если Найти(ТекущаяСтрока, "ТабличныеЧасти;") > 0 Тогда
МассивДанных = СтрРазделить(ТекущаяСтрока, ";");
ИмяТЧ = МассивДанных[1];
ДанныеРеквизита = МассивДанных[2]; // Строка вида "Номенклатура=Код123"
РазделительТЧ = Найти(ДанныеРеквизита, "=");
ИмяРеквизитаТЧ = Лев(ДанныеРеквизита, РазделительТЧ - 1);
ЗначениеРеквизитаТЧ = Сред(ДанныеРеквизита, РазделительТЧ + 1);
// В реальной логике здесь нужно определять, когда добавлять новую строку.
// Например, если реквизит - это первый столбец ТЧ (Номенклатура)
Если ИмяРеквизитаТЧ = "Номенклатура" Тогда
НоваяСтрока = НовыйДокумент[ИмяТЧ].Добавить();
КонецЕсли;
// Заполнение реквизита строки ТЧ (аналогично логике шапки)
// ... поиск ссылки или простое присвоение ...
НоваяСтрока[ИмяРеквизитаТЧ] = ЗначениеРеквизитаТЧ;
КонецЕсли;
Иногда в текстовый файл попадают сложные структуры, например, контактная информация или адреса, представленные в формате JSON внутри одной строки. Посмотрим на пример такой строки: { "value": "Москва", "type": "Адрес" }.
Выясним, как с этим работать без полного переписывания парсера на JSON. Если вы столкнулись с такой ситуацией, рекомендуется использовать встроенную функцию ПрочитатьJSON() для конкретного значения или предварительно очищать строку от лишних переносов. Однако в рамках простого TXT-парсера эффективнее всего использовать теги-разделители или заменять символы переноса строки на технические маркеры при выгрузке, а при загрузке восстанавливать их функцией СтрЗаменить(Значение, "|n|", Символы.ПС).
Для того чтобы ваша обработка не вызывала критических ошибок при загрузке, всегда внедряйте проверки существования метаданных. Разберем основные правила безопасности:
Метаданные.Реквизиты[Имя] всегда проверяйте, существует ли такой ключ в коллекции методом Найти().НачатьТранзакцию() и ЗафиксироватьТранзакцию(). Если в середине файла произойдет ошибка (например, неверный формат даты), система откатит создание документа, и в базе не останется "мусора".Соответствие для хранения уже найденных ссылок: КэшСсылок.Вставить(Код, Ссылка).Таким образом, мы рассмотрели процесс создания гибкой системы загрузки данных. Использование метаданных позволяет сделать код лаконичным и избавляет от необходимости прописывать каждый реквизит вручную, что значительно упрощает поддержку обработки при изменениях в конфигурации.