Как организовать импорт данных из CSV в 1С?

Программист IT и автоматизация бизнеса
← На главную

Импорт данных из формата CSV (Comma-Separated Values) — это одна из самых частых задач, с которыми сталкивается разработчик 1С. Этот формат универсален, его легко сформировать из Excel или сторонних систем. Несмотря на кажущуюся простоту (текст с разделителями), процедура импорта имеет множество нюансов: от выбора кодировки до корректной обработки кавычек и сложных переносов строк. В этой статье мы подробно разберем, как реализовать загрузку данных для различных версий платформы 1С.

Метод 1: Реализация импорта в среде 1С:Предприятие 7.7

Начнем с классического подхода для «семерки». Здесь работа строится на использовании объекта Текст. Проанализируем базовый алгоритм, который позволяет выбрать файл и прочитать его построчно.

Для начала нам необходимо предоставить пользователю возможность выбора файла. Используем для этого объект ФС (Файловая Система):


Перем ИмяПути, ИмяФайла;
ИмяФайла = "";
ИмяПути = "";
Если ФС.ВыбратьФайл(0, ИмяФайла, ИмяПути, "Выберите файл CSV", "*.csv", , ) <> 1 Тогда
    Возврат;
КонецЕсли;

ТекстДок = СоздатьОбъект("Текст");
ТекстДок.Открыть(ИмяПути + ИмяФайла);

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


Функция РазобратьСтроку(Стр, Разделитель)
    Сп = СоздатьОбъект("СписокЗначений");
    ТекСтр = Стр;
    Пока Найти(ТекСтр, Разделитель) > 0 Цикл
        Поз = Найти(ТекСтр, Разделитель);
        Значение = СокрЛП(Лев(ТекСтр, Поз - 1));
        Сп.ДобавитьЗначение(Значение);
        ТекСтр = Сред(ТекСтр, Поз + 1);
    КонецЦикла;
    Сп.ДобавитьЗначение(СокрЛП(ТекСтр)); // Добавляем последний фрагмент
    Возврат Сп;
КонецФункции

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


ТЗ = СоздатьОбъект("ТаблицаЗначений");
Для НомСтроки = 1 По ТекстДок.КоличествоСтрок() Цикл
    Стр = ТекстДок.ПолучитьСтроку(НомСтроки);
    Если ПустаяСтрока(Стр) = 1 Тогда Продолжить; КонецЕсли;
    
    Спис = РазобратьСтроку(Стр, ";");
    
    Если НомСтроки = 1 Тогда
        // Создаем колонки по первой строке
        Для н = 1 По Спис.РазмерСписка() Цикл
            ТЗ.НоваяКолонка(Спис.ПолучитьЗначение(н));
        КонецЦикла;
    Иначе
        // Заполняем данные
        ТЗ.НоваяСтрока();
        Для н = 1 По Спис.РазмерСписка() Цикл
            ТЗ.УстановитьЗначение(ТЗ.НомерСтроки, н, Спис.ПолучитьЗначение(н));
        КонецЦикла;
    КонецЕсли;
КонецЦикла;

Важное замечание по оптимизации: создание объекта СписокЗначений внутри цикла может существенно замедлить работу при больших объемах данных. Рекомендуется создать один объект до начала цикла и очищать его методом УдалитьВсе() внутри итераций.

Метод 2: Современный подход в 1С 8.3 (Управляемые формы)

В платформе 8.3 работа с файлами стала значительно проще и быстрее. Мы будем использовать объект ТекстовыйДокумент (или ЧтениеТекста) и встроенную функцию СтрРазделить.

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


&НаСервере
Процедура ИмпортCSVНаСервере(ПолноеИмяФайла)
    ТекстДок = Новый ТекстовыйДокумент;
    // Важно указать правильную кодировку, например КодировкаТекста.UTF8
    ТекстДок.Прочитать(ПолноеИмяФайла, КодировкаТекста.ANSI);
    
    КоличествоСтрок = ТекстДок.КоличествоСтрок();
    
    Для НомерСтроки = 1 По КоличествоСтрок Цикл
        ТекСтрока = ТекстДок.ПолучитьСтроку(НомерСтроки);
        
        // Используем СтрРазделить для получения массива подстрок
        // Третий параметр "Ложь" указывает не пропускать пустые значения
        МассивКолонок = СтрРазделить(ТекСтрока, ";", Ложь);
        
        // Пример создания элемента справочника
        Если МассивКолонок.Количество() >= 2 Тогда
            НовыйОбъект = Справочники.Номенклатура.СоздатьЭлемент();
            НовыйОбъект.Артикул = МассивКолонок[0];
            НовыйОбъект.Наименование = МассивКолонок[1];
            // Попытка записи объекта
            Попытка
                НовыйОбъект.Записать();
            Исключение
                Сообщить("Ошибка в строке " + НомерСтроки + ": " + ОписаниеОшибки());
            КонецПопытки;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Метод 3: Использование специализированного объекта ЧтениеCSV

Начиная с версии платформы 8.3.6, в 1С появился объект ЧтениеCSV. Это самый правильный и надежный метод, так как он автоматически обрабатывает сложные случаи: наличие кавычек внутри текста, переносы строк внутри полей и экранирование спецсимволов.

Разберем, как им пользоваться:


&НаСервере
Процедура ЗагрузитьЧерезЧтениеCSV(ПутьКФайлу)
    ФайлCSV = Новый ЧтениеCSV;
    // Указываем параметры: разделитель, символ кавычек
    ФайлCSV.Открыть(ПутьКФайлу, "UTF-8", ";", """");
    
    // Пропускаем заголовки, если нужно
    Заголовки = ФайлCSV.Прочитать(); 
    
    Пока Истина Цикл
        МассивДанных = ФайлCSV.Прочитать();
        Если МассивДанных = Неопределено Тогда
            Прервать; // Конец файла
        КонецЕсли;
        
        // МассивДанных содержит значения текущей строки
        ОбработатьСтрокуИмпорта(МассивДанных);
    КонецЦикла;
    
    ФайлCSV.Закрыть();
КонецПроцедуры

Технические нюансы и рекомендации по оптимизации

Рассмотрим важные аспекты, которые часто упускают из виду при разработке механизмов импорта:

  1. Проблема кодировок: Если вы видите «кракозябры» вместо русских букв, скорее всего, файл сохранен в UTF-8, а 1С пытается прочитать его как Windows-1251 (ANSI). Всегда уточняйте формат источника. В 8.x используйте КодировкаТекста.UTF8 или КодировкаТекста.ANSI.
  2. Транзакции: Если вы загружаете более 100 объектов, обязательно используйте транзакцию. Это ускорит запись в базу данных в десятки раз. Рекомендуется фиксировать транзакцию порциями (например, каждые 500 строк).
    
    НачатьТранзакцию();
    // Цикл загрузки...
    ЗафиксироватьТранзакцию();
    
  3. Поиск существующих записей: Никогда не делайте Справочники.Номенклатура.НайтиПоНаименованию() внутри цикла. Это создает колоссальную нагрузку на SQL. Выясним причину замедления: каждое такое обращение — это отдельный запрос к БД. Лучше предварительно выгрузить нужные данные в Соответствие или использовать временные таблицы в запросе.
  4. Очистка данных: Значения из CSV всегда приходят как строки. Не забывайте использовать функцию Число() для цен и количеств, предварительно удаляя неразрывные пробелы: СтрЗаменить(Значение, Символы.НПП, "").
  5. Большие файлы: Если файл весит несколько сотен мегабайт, объект ТекстовыйДокумент может вызвать переполнение памяти (так как загружает файл целиком). В таких случаях использование ЧтениеТекста или ЧтениеCSV является обязательным, так как они читают данные потоково.

Резюме: Для старых конфигураций 7.7 используйте ручной парсинг строк через СписокЗначений. Для современных систем на базе 8.3 всегда отдавайте предпочтение объекту ЧтениеCSV, так как он соответствует международным стандартам обработки текстовых данных с разделителями и наиболее устойчив к ошибкам в структуре файла.

← На главную