Чтение CSV-файла в 1С 8.3: от кодировки до таблицы значений

· 10 мин

Содержание

CSV в 1С читают как обычный текст: открывают файл объектом ЧтениеТекста, берут строки по одной, режут каждую по разделителю функцией СтрРазделить и складывают результат в ТаблицуЗначений. Специального объекта «ЧитательCSV» в платформе нет, и это нормально: формат простой, всё решают три вещи — кодировка, разделитель и кавычки.

Если файл пришёл из Excel, чаще всего это windows-1251 и разделитель ;. Если из выгрузки интернет-магазина или скрипта — UTF-8 и запятая. Ошибиться с кодировкой — получить «кракозябры» в первой же колонке, ошибиться с разделителем — получить одну длинную колонку вместо десяти.

Что проверить в файле до начала загрузки

Откройте файл в любом текстовом редакторе, а не в Excel. Excel «исправляет» файл на лету: срезает ведущие нули в артикулах, превращает 1-2 в дату, а длинные штрихкоды в 4,6E+12. Увидеть реальное содержимое можно только в редакторе.

Что смотреть:

  • 🔤 Кодировка. Русские буквы читаются нормально — значит, редактор угадал верно; сомневаетесь — переключите кодировку вручную и посмотрите, что изменится.
  • ✂️ Разделитель. Точка с запятой, запятая, табуляция или вертикальная черта. Русский Excel по умолчанию сохраняет с ;, потому что запятая у нас десятичная.
  • 📌 Строка заголовков. Есть ли она, и совпадают ли названия колонок с тем, что вы ждёте.
  • 💬 Кавычки. Встречаются ли значения вида "ООО ""Ромашка"", Москва" — с разделителем и кавычками внутри поля.
  • 🔢 Формат чисел и дат. 1 234,56 или 1234.56; 15.01.2026 или 2026-01-15.
  • 📏 Размер. До нескольких мегабайт хватит простого кода, от десятков мегабайт нужны приёмы из раздела про производительность.

Если у вас есть BOM — три служебных байта в начале файла UTF-8, — в редакторе его не видно, зато в 1С первая колонка может получить «невидимый» символ в начале имени. Ниже есть, как от этого защититься.

Как задать кодировку при чтении

Кодировка указывается вторым параметром конструктора ЧтениеТекста. Без неё платформа применит кодировку по умолчанию, и русский текст из файла в другой кодировке превратится в мусор.

Чтение = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8);

Для файла из русского Excel подставьте КодировкаТекста.ANSI — на русскоязычной системе это windows-1251. Можно передать и имя строкой: "windows-1251", "utf-8".

Автоопределения кодировки в платформе нет. Практичный приём — читать первую строку и проверять результат:

Функция КодировкаПодходит(ПутьКФайлу, Кодировка)
    Чтение = Новый ЧтениеТекста(ПутьКФайлу, Кодировка);
    Строка = Чтение.ПрочитатьСтроку();
    Чтение.Закрыть();
    Возврат Строка <> Неопределено И СтрНайти(Строка, "�") = 0;
КонецФункции

Символ � (знак замены) появляется, когда UTF-8 прочитали неверно. Для обратной ситуации — windows-1251, прочитанная как UTF-8, — обычно виден тот же знак. Если проверка не прошла для UTF8, пробуйте ANSI.

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

Откуда взять файл

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

ИмяВремФайла = ПолучитьИмяВременногоФайла("csv");
ДвоичныеДанные.Записать(ИмяВремФайла);
// ... чтение ...
УдалитьФайлы(ИмяВремФайла);

Временный файл удаляйте всегда, в том числе при ошибке — используйте Попытка … Исключение.

Построчное чтение: рабочий каркас

Основной способ — читать файл строка за строкой. Память не растёт вместе с размером файла, потому что в каждый момент в ней одна строка.

Функция ПрочитатьCSV(ПутьКФайлу, Кодировка = Неопределено, Разделитель = ";")
    
    Таблица = Новый ТаблицаЗначений;
    Если Кодировка = Неопределено Тогда
        Кодировка = КодировкаТекста.UTF8;
    КонецЕсли;
    
    Чтение = Новый ЧтениеТекста(ПутьКФайлу, Кодировка);
    Попытка
        Заголовок = Чтение.ПрочитатьСтроку();
        Если Заголовок = Неопределено Тогда
            Чтение.Закрыть();
            Возврат Таблица;
        КонецЕсли;
        
        // Убираем BOM, если он остался в первой строке
        Если Лев(Заголовок, 1) = Символ(65279) Тогда
            Заголовок = Сред(Заголовок, 2);
        КонецЕсли;
        
        Для Каждого Имя Из РазобратьСтрокуCSV(Заголовок, Разделитель) Цикл
            Таблица.Колонки.Добавить("К" + Формат(Таблица.Колонки.Количество() + 1, "ЧГ="), , Имя);
        КонецЦикла;
        
        Строка = Чтение.ПрочитатьСтроку();
        Пока Строка <> Неопределено Цикл
            Если НЕ ПустаяСтрока(Строка) Тогда
                Поля = РазобратьСтрокуCSV(Строка, Разделитель);
                НоваяСтрока = Таблица.Добавить();
                Для Индекс = 0 По Мин(Поля.ВГраница(), Таблица.Колонки.Количество() - 1) Цикл
                    НоваяСтрока[Индекс] = Поля[Индекс];
                КонецЦикла;
            КонецЕсли;
            Строка = Чтение.ПрочитатьСтроку();
        КонецЦикла;
    Исключение
        Чтение.Закрыть();
        ВызватьИсключение;
    КонецПопытки;
    Чтение.Закрыть();
    
    Возврат Таблица;
КонецФункции

Колонки называются К1, К2… — настоящие названия из заголовка попадают в синоним. Так проще: в именах колонок нельзя использовать пробелы и многие символы, а в заголовках CSV они встречаются постоянно.

Закрывайте файл всегда. Незакрытый ЧтениеТекста держит файл открытым, и следующая попытка перезаписать или удалить его завершится ошибкой доступа.

А что с ТабличнымДокументом

ТабличныйДокумент читает файлы своих форматов: mxl, Excel, OpenDocument. Прочитать через него «обычный» CSV надёжно нельзя, и расчёт на это — частая ловушка. Если файл нужен в виде таблицы на экране, сначала загрузите данные в ТаблицуЗначений, а потом выведите её в табличный документ циклом по строкам.

Есть и обратный путь: открыть CSV в Excel, пересохранить как .xlsx и читать уже ТабличныйДокумент — но это ручной шаг, для автоматического обмена он не годится.

Разделители, кавычки и переносы строк

Простой СтрРазделить(Строка, ";", Ложь) работает, пока в данных нет самого разделителя. Как только в названии контрагента появилась запятая или точка с запятой, формат прячет такое поле в кавычки, а внутри кавычек заменяет " на "".

Пример строки:

1001;"ООО ""Ромашка""; филиал";15.01.2026;1 234,56

Здесь четыре поля, но СтрРазделить по ; даст пять. Нужен разбор с учётом кавычек:

Функция РазобратьСтрокуCSV(Строка, Разделитель = ";")
    
    Результат = Новый Массив;
    Поле = "";
    ВКавычках = Ложь;
    Длина = СтрДлина(Строка);
    Позиция = 1;
    
    Пока Позиция <= Длина Цикл
        Символ = Сред(Строка, Позиция, 1);
        
        Если ВКавычках Тогда
            Если Символ = """" Тогда
                Если Сред(Строка, Позиция + 1, 1) = """" Тогда
                    Поле = Поле + """";
                    Позиция = Позиция + 1;
                Иначе
                    ВКавычках = Ложь;
                КонецЕсли;
            Иначе
                Поле = Поле + Символ;
            КонецЕсли;
        ИначеЕсли Символ = """" Тогда
            ВКавычках = Истина;
        ИначеЕсли Символ = Разделитель Тогда
            Результат.Добавить(Поле);
            Поле = "";
        Иначе
            Поле = Поле + Символ;
        КонецЕсли;
        
        Позиция = Позиция + 1;
    КонецЦикла;
    
    Результат.Добавить(Поле);
    Возврат Результат;
    
КонецФункции

Функция идёт по символам и помнит, внутри кавычек она сейчас или нет. Удвоенная кавычка внутри поля превращается в одну.

Что ещё встречается:

СитуацияКак выглядитЧто делать
Табуляция вместо ;Файл .tsv или .txtПередать Символы.Таб как разделитель
Перенос строки внутри поляЗапись «ломается» на две строкиСклеивать строки, пока число кавычек нечётное
Лишние пробелы вокруг значений" 1001 "Применить СокрЛП к каждому полю
Разное число полей в строкахСтрока короче заголовкаДополнять пустыми значениями, как в каркасе выше
Строка итогов в конце файла«Итого;;;5000»Отбрасывать по признаку первой колонки

Перенос строки внутри кавычек — самая коварная проблема. Построчное чтение разрежет такую запись на две строки, и разбор покажет мусор. Если такие файлы вам встречаются, накапливайте строки в буфере, пока количество символов " не станет чётным, и только потом разбирайте запись целиком.

Приведение значений к нужным типам

После разбора все поля — строки. Чтобы сравнивать, суммировать и записывать в реквизиты документов, значения нужно привести к числам, датам и ссылкам.

Числа

Формат 1 234,56 с пробелом-разделителем тысяч и запятой напрямую в число не превращается надёжно: поведение зависит от настроек системы. Нормализуйте строку сами:

Функция СтрокаВЧисло(Значение)
    Текст = СтрЗаменить(СтрЗаменить(СтрЗаменить(Значение, " ", ""), Символ(160), ""), ",", ".");
    Если ПустаяСтрока(Текст) Тогда
        Возврат 0;
    КонецЕсли;
    Описание = Новый ОписаниеТипов("Число");
    Возврат Описание.ПривестиЗначение(Текст);
КонецФункции

Символ с кодом 160 — неразрывный пробел, он часто прячется в числах, выгруженных из Excel и сайтов. Обычный пробел с ним не совпадает, поэтому убираем оба.

Для строки, которую невозможно распознать, ПривестиЗначение вернёт 0 — молча. Если нужно ловить ошибки, проверяйте строку на допустимые символы заранее и считайте отказы.

Даты

Формат 15.01.2026 разбираем по частям — так результат не зависит от региональных настроек:

Функция СтрокаВДату(Значение)
    Части = СтрРазделить(СокрЛП(Значение), ".");
    Если Части.Количество() <> 3 Тогда
        Возврат Дата(1, 1, 1);
    КонецЕсли;
    Возврат Дата(Число(Части[2]), Число(Части[1]), Число(Части[0]));
КонецФункции

Для формата 2026-01-15 разделитель другой, а порядок частей обратный: год, месяц, день. Не пытайтесь угадывать формат по одной строке — задайте его явно параметром.

Ссылки и справочники

Артикул или ИНН из CSV превращают в ссылку запросом или методом НайтиПоКоду. Делать это в цикле по каждой строке медленно — подробнее в следующем разделе.

Ещё две ловушки:

  • ИНН и артикулы с ведущими нулями (0012345) должны остаться строками. Если файл уже побывал в Excel, нули могли пропасть до того, как он попал к вам, — вернуть их можно только дополнением до нужной длины, и то если длина известна.
  • Пустое поле — это не ноль. Отличайте «нет данных» от «значение 0», если для вас это разные вещи.

Большие файлы: как не ждать часами

На файле в 100 тысяч строк обычный код с обращением к базе внутри цикла может работать десятки минут. Основные потери — не в чтении, а в том, что происходит с каждой строкой.

Что реально ускоряет:

  1. Не обращайтесь к базе в цикле. Соберите все уникальные артикулы или ИНН в массив, одним запросом получите соответствие «ключ → ссылка» и храните его в Соответствие. Поиск по Соответствию в памяти на порядки быстрее запроса на каждую строку.
  2. Складывайте в таблицу значений, а не в документы. Сначала загрузка и проверка, потом — пакетная запись.
  3. Выполняйте загрузку на сервере. Каждый вызов клиент-сервер стоит времени; весь цикл должен идти в одной серверной процедуре.
  4. Выносите длинную загрузку в фоновое задание, чтобы пользователь не смотрел на зависший интерфейс, и показывайте прогресс.
  5. Записывайте порциями — например, по 1000 объектов в транзакции, а не всё одной огромной транзакцией и не по одной записи.
  6. Отключайте лишнее. Для технической загрузки справочников используйте ОбменДанными.Загрузка = Истина, если логика проведения вам не нужна, — но только если понимаете, какие проверки и регистрации обхода это отключает.

Запись порциями и отключение проверок — это вмешательство в учёт. Перед массовой загрузкой сделайте копию базы и прогоните файл на тестовой базе: ошибочный файл на 50 тысяч строк в рабочей базе потом придётся откатывать.

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

Перед загрузкой большого CSV
Выполнено: 0 / 5

Разбор типичных сбоев при чтении

Диагностика: выберите симптом

Частые вопросы

Можно ли прочитать CSV без программирования, штатными средствами?
Да, в типовых конфигурациях есть обработка загрузки данных из табличного документа и внешние обработки загрузки. Они умеют читать Excel, а CSV часто проще сначала открыть в Excel и пересохранить как .xlsx.
Как узнать, сколько строк в файле, не читая его целиком?
Точного способа без чтения нет. Для оценки сравните размер файла со средней длиной строки по первой сотне строк.
Как загрузить файл, где заголовка нет?
Пропустите блок чтения заголовка и задайте колонки сами, по списку названий в коде или в настройке.
Чем `ЧтениеТекста` отличается от `ТекстовыйДокумент`?
ЧтениеТекста читает последовательно и не держит файл в памяти. ТекстовыйДокумент загружает весь файл целиком, зато даёт доступ к строкам по номеру. Для больших CSV берите ЧтениеТекста.
Как читать CSV, лежащий на веб-сервере, не сохраняя на диск?
Получите данные как ДвоичныеДанные и откройте поток на них; ЧтениеТекста умеет работать с потоком, а не только с именем файла.