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

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

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

Шаг 1. Поиск и чтение текстовых файлов

Для начала нам необходимо получить список файлов в целевом каталоге и прочитать их содержимое. В 1С для поиска файлов используется функция НайтиФайлы. Проанализируем базовый подход к чтению через объект ТекстовыйДокумент.

Рассмотрим пример кода, который обходит файлы в папке и считывает их построчно:


МассивФайлов = НайтиФайлы("C:\sp\", "*.txt");
Текст = Новый ТекстовыйДокумент;

Для Каждого Файл Из МассивФайлов Цикл
    Текст.Прочитать(Файл.ПолноеИмя);
    Для НомерСтроки = 1 По Текст.КоличествоСтрок() Цикл
        ТекущаяСтрока = Текст.ПолучитьСтроку(НомерСтроки);
        // Здесь будет логика обработки строки
    КонецЦикла;
КонецЦикла;

Важное замечание: Использование ТекстовыйДокумент удобно для небольших файлов. Однако, если файлы имеют огромный объем, метод Прочитать() загрузит всё содержимое в оперативную память сразу. В таких случаях мы рекомендуем использовать объект ЧтениеТекста, который позволяет считывать файл поток за потоком, что гораздо экономнее с точки зрения ресурсов сервера.

Шаг 2. Разбор строки и получение фрагментов данных

Допустим, наша строка имеет формат 1111-2222-3333-4444. Нам нужно извлечь первую часть для поиска документа, а остальные — для заполнения реквизитов. Самый эффективный способ сделать это в современных версиях платформы 1С:Предприятие 8.3 — использовать функцию СтрРазделить.

Давайте разберем, как разделить строку на части по дефису:


// Исходная строка из файла
ИсходнаяСтрока = "1111-2222-3333-4444";

// Разделяем строку, используя дефис в качестве разделителя
МассивЧастей = СтрРазделить(ИсходнаяСтрока, "-");

// Теперь мы можем обращаться к частям по индексу (начиная с 0)
Если МассивЧастей.Количество() >= 4 Тогда
    Префикс   = МассивЧастей[0]; // "1111"
    Данные1   = МассивЧастей[1]; // "2222"
    Данные2   = МассивЧастей[2]; // "3333"
    Данные3   = МассивЧастей[3]; // "4444"
КонецЕсли;

Проанализируем ситуацию, когда длина префикса может меняться (например, иногда 4 символа, иногда 5 или 6). Использование функции Лев(Строка, 4) в этом случае будет ошибочным, так как она жестко привязана к количеству знаков. Метод СтрРазделить решает эту проблему автоматически: он заберет всё, что находится до первого дефиса, независимо от длины текста.

Шаг 3. Поиск документа по фрагменту строки

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

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   МойДокумент.Ссылка КАК Ссылка
    |ИЗ
    |   Документ.МойДокумент КАК МойДокумент
    |ГДЕ
    |   МойДокумент.Номер ПОДОБНО &НомерПоиска";

// Добавляем символ процента для поиска по частичному совпадению, 
// если в 1С номера содержат ведущие нули или префиксы
Запрос.УстановитьПараметр("НомерПоиска", "%" + Префикс);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Нюанс с номерами документов: В 1С номера часто хранятся с ведущими нулями (например, "000000111"). Если в файле указано просто "111", прямое сравнение Номер = &Номер не сработает. Именно поэтому в параметре ПОДОБНО мы добавляем знак %. Также можно программно дополнить строку нулями до нужной длины, используя функцию Прав().

Шаг 4. Обновление реквизитов документа

Когда ссылка на документ найдена, нам необходимо изменить его данные. Для этого нужно получить объект документа из ссылки с помощью метода ПолучитьОбъект().

Разберем процесс записи по шагам:


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

Шаг 5. Оптимизация производительности (Профессиональный подход)

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

  1. Соберите данные в таблицу: Сначала прочитайте весь файл и заполните временную таблицу значений или массив всеми префиксами.
  2. Один запрос вместо тысячи: Передайте весь массив префиксов в запрос, используя оператор В (&МассивПрефиксов).
  3. Используйте транзакции: Оберните цикл записи документов в конструкцию НачатьТранзакцию() ... ЗафиксироватьТранзакцию(). Это ускорит запись в базу данных в несколько раз.

Рассмотрим пример оптимизированного кода с проверкой границ массива:


// Проверка на корректность формата строки перед обращением к индексам
Если МассивЧастей.Количество() < 4 Тогда
    Продолжить; // Пропускаем строку, если в ней недостаточно данных
КонецЕсли;

// Пример использования транзакции для массовой записи
НачатьТранзакцию();
Попытка
    // Логика поиска и записи документов...
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    Сообщить("Ошибка при массовой обработке: " + ОписаниеОшибки());
КонецПопытки;

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

← На главную