Чтение CSV в 1С:Предприятии 8.3: табличный документ, текстовый поток и разбор полей
Содержание
Прочитать CSV файл в 1С проще всего построчно: объект ЧтениеТекста отдаёт строку за строкой, а поля вы делите сами по разделителю ; или ,. Для небольших файлов с предпросмотром подходит ТекстовыйДокумент с выводом в табличный документ.
Частая ошибка — делить строку одной функцией СтрРазделить и считать дело сделанным. Первое же поле вида "ООО ""Ромашка""; склад 2" ломает разбор: точка с запятой внутри кавычек становится лишней колонкой, и весь хвост строки съезжает. Ниже — код, который это учитывает, и разбор кодировок, на которых спотыкаются чаще всего.
Что выяснить о CSV-файле до написания кода
CSV — это не стандартный формат, а договорённость. Один и тот же «прайс.csv» от двух поставщиков может отличаться по четырём параметрам. Откройте файл в Блокноте или Notepad++ (не в Excel) и запишите ответы.
| Параметр | Типичные варианты | Как определить |
|---|---|---|
| Разделитель полей | ; (Excel в русской локали), ,, табуляция | Посмотреть первую строку |
| Кодировка | UTF-8, UTF-8 с BOM, Windows-1251 | В Notepad++ — меню «Кодировки», внизу окна |
| Строка заголовков | Есть / нет | Первая строка — названия колонок или данные |
| Кавычки | Только у полей с разделителем / у всех полей | Видно по тексту |
Ещё три вещи стоит проверить сразу:
- 🔢 Формат чисел.
1 234,56с неразрывным пробелом,1234.56или1234,56— от этого зависит функция преобразования. - 📅 Формат дат.
25.03.2025,2025-03-25или25.03.2025 14:30:00. - ↩️ Переносы внутри полей. В выгрузках из CRM в поле «Комментарий» встречаются многострочные значения в кавычках. Если они есть, построчное чтение без доработки разорвёт запись пополам.
Попросите у источника данных 10–20 строк образца, где есть самые «грязные» случаи: кавычки, пустые значения, длинные комментарии. Отладка на таком файле экономит часы.
Способ 1. Чтение CSV через текстовый и табличный документ
Способ подходит для разовой загрузки и обработок с формой: пользователь видит данные в таблице, проверяет колонки и только потом нажимает «Загрузить». Файл целиком поднимается в память, поэтому для файлов до нескольких десятков тысяч строк это нормально, для миллиона строк — нет.
Метод ТабличныйДокумент.Прочитать() открывает форматы mxl, xls, xlsx, ods, но CSV как таблицу он не разбирает. Поэтому текст читаем через ТекстовыйДокумент, а ячейки заполняем сами:
&НаСервере
Функция CSVВТабличныйДокумент(ИмяФайла, Разделитель = ";")
Текст = Новый ТекстовыйДокумент;
Текст.Прочитать(ИмяФайла, КодировкаТекста.UTF8);
ТД = Новый ТабличныйДокумент;
Для НомерСтроки = 1 По Текст.КоличествоСтрок() Цикл
Поля = РазобратьСтрокуCSV(Текст.ПолучитьСтроку(НомерСтроки), Разделитель);
Для Индекс = 0 По Поля.ВГраница() Цикл
ТД.Область("R" + НомерСтроки + "C" + (Индекс + 1)).Текст = Поля[Индекс];
КонецЦикла;
КонецЦикла;
Возврат ТД;
КонецФункции
Функция РазобратьСтрокуCSV приведена в разделе про разделители и кавычки. Готовый табличный документ выводите в поле формы и читайте обратно по адресам ячеек: ТД.Область("R2C3").Текст, границы — ТД.ВысотаТаблицы и ТД.ШиринаТаблицы.
Обходной путь через Excel
Если загрузка разовая и пишет её не программист, можно открыть CSV в Excel, сохранить как .xlsx и прочитать готовым методом:
ТД = Новый ТабличныйДокумент;
ТД.Прочитать(ИмяФайлаXLSX, СпособЧтенияЗначенийТабличногоДокумента.Текст);
Минус: Excel молча «чинит» данные. Артикул 00123 становится числом 123, код 1-2 — датой. Для регулярного обмена этот путь не годится.
Готовая загрузка в типовых конфигурациях
В конфигурациях на Библиотеке стандартных подсистем (Бухгалтерия 3.0, ЗУП 3, УТ 11) в списке номенклатуры и в табличных частях документов есть команда загрузки из файла. Она принимает табличные форматы, а в ряде релизов и CSV. Если нужно один раз залить прайс в номенклатуру, сначала проверьте эту команду — писать код может и не понадобиться.
Способ 2. Построчное чтение CSV текстовым потоком
ЧтениеТекста не загружает файл в память целиком: в каждый момент в памяти одна строка. Это основной способ для больших файлов и для обмена по расписанию. Файл на 500 тыс. строк читается так же спокойно, как на 500.
Процедура ЗагрузитьCSV(ИмяФайла, Разделитель = ";", Кодировка = Неопределено) Экспорт
Если Кодировка = Неопределено Тогда
Кодировка = КодировкаТекста.UTF8;
КонецЕсли;
Чтение = Новый ЧтениеТекста(ИмяФайла, Кодировка);
Заголовки = Неопределено;
НомерСтроки = 0;
ТекСтрока = Чтение.ПрочитатьСтроку();
Пока ТекСтрока <> Неопределено Цикл
НомерСтроки = НомерСтроки + 1;
// Многострочное поле: нечётное число кавычек — запись не закончена
Пока СтрЧислоВхождений(ТекСтрока, """") % 2 = 1 Цикл
Продолжение = Чтение.ПрочитатьСтроку();
Если Продолжение = Неопределено Тогда
Прервать;
КонецЕсли;
ТекСтрока = ТекСтрока + Символы.ПС + Продолжение;
НомерСтроки = НомерСтроки + 1;
КонецЦикла;
Если Не ПустаяСтрока(ТекСтрока) Тогда
Поля = РазобратьСтрокуCSV(ТекСтрока, Разделитель);
Если Заголовки = Неопределено Тогда
Поля[0] = СтрЗаменить(Поля[0], Символ(65279), ""); // BOM
Заголовки = Поля;
Иначе
ОбработатьЗапись(Заголовки, Поля, НомерСтроки);
КонецЕсли;
КонецЕсли;
ТекСтрока = Чтение.ПрочитатьСтроку();
КонецЦикла;
Чтение.Закрыть();
КонецПроцедуры
ПрочитатьСтроку() возвращает Неопределено, когда файл закончился, — на этом держится цикл. Пустая строка в середине файла вернётся как "", поэтому её отдельно пропускаем.
Сравнение способов
| Способ | Когда брать | Объём файла | Риски |
|---|---|---|---|
ТекстовыйДокумент + табличный документ | Обработка с предпросмотром, разовая загрузка | До десятков тысяч строк | Расход памяти, многострочные поля не склеиваются |
ЧтениеТекста построчно | Регулярный обмен, большие файлы | Без практического ограничения | Нужно самому писать разбор и проверки |
Через Excel в .xlsx | Разово, без программиста | Любой, что откроет Excel | Excel искажает коды, нули, даты |
| Типовая команда загрузки | Номенклатура, табличные части | Обычные прайсы | Только под поддерживаемые объекты |
Откуда берётся файл в управляемой форме
В тонком и веб-клиенте файл выбирает пользователь на своём компьютере, а читать его удобно на сервере. Передаём через временное хранилище:
&НаКлиенте
Процедура ВыбратьФайл(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
Если Результат Тогда
ЗагрузитьНаСервере(Адрес);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ЗагрузитьНаСервере(Адрес)
ИмяФайла = ПолучитьИмяВременногоФайла("csv");
ПолучитьИзВременногоХранилища(Адрес).Записать(ИмяФайла);
ЗагрузитьCSV(ИмяФайла, ";");
УдалитьФайлы(ИмяФайла);
КонецПроцедуры
Разделители, кавычки и многострочные поля в CSV
Правило CSV простое: поле, где есть разделитель, кавычка или перенос строки, заключается в кавычки. Кавычка внутри такого поля удваивается. Строка
"ООО ""Ромашка""; склад 2";1250,00;25.03.2025
содержит три поля: ООО "Ромашка"; склад 2, 1250,00 и 25.03.2025. СтрРазделить вернёт четыре — и с неверным содержимым. Функция ниже идёт по строке посимвольно и помнит, находится ли она внутри кавычек:
Функция РазобратьСтрокуCSV(ТекСтрока, Разделитель = ";") Экспорт
Поля = Новый Массив;
Значение = "";
ВКавычках = Ложь;
Длина = СтрДлина(ТекСтрока);
Позиция = 1;
Пока Позиция <= Длина Цикл
Знак = Сред(ТекСтрока, Позиция, 1);
Если ВКавычках Тогда
Если Знак = """" Тогда
Если Сред(ТекСтрока, Позиция + 1, 1) = """" Тогда
Значение = Значение + """"; // удвоенная кавычка
Позиция = Позиция + 1;
Иначе
ВКавычках = Ложь;
КонецЕсли;
Иначе
Значение = Значение + Знак;
КонецЕсли;
Иначе
Если Знак = """" Тогда
ВКавычках = Истина;
ИначеЕсли Знак = Разделитель Тогда
Поля.Добавить(Значение);
Значение = "";
Иначе
Значение = Значение + Знак;
КонецЕсли;
КонецЕсли;
Позиция = Позиция + 1;
КонецЦикла;
Поля.Добавить(Значение);
Возврат Поля;
КонецФункции
Если вы точно знаете, что кавычек в файле нет (например, выгрузка вашей же системы), берите СтрРазделить(ТекСтрока, ";", Истина). Третий параметр Истина сохраняет пустые поля — без него a;;c превратится в два значения вместо трёх, и колонки съедут.
Автоопределение разделителя
Когда файлы приходят от разных людей, разделитель удобно угадывать по строке заголовков:
Функция ОпределитьРазделитель(СтрокаЗаголовков)
Варианты = Новый Массив;
Варианты.Добавить(";");
Варианты.Добавить(",");
Варианты.Добавить(Символы.Таб);
Лучший = ";";
Максимум = 0;
Для Каждого Вариант Из Варианты Цикл
Количество = СтрЧислоВхождений(СтрокаЗаголовков, Вариант);
Если Количество > Максимум Тогда
Максимум = Количество;
Лучший = Вариант;
КонецЕсли;
КонецЦикла;
Возврат Лучший;
КонецФункции
Запятая как разделитель конфликтует с русскими дробными числами 1250,50. В корректном файле такие числа стоят в кавычках. Если кавычек нет — файл неразбираем однозначно, просите источник сменить разделитель на ;.
Проверка данных и обработка ошибок при загрузке CSV
Строка CSV — это набор строк, не чисел и не дат. Каждое поле нужно привести к типу и при неудаче не падать, а запомнить ошибку с номером строки.
Числа и даты
Функция СтрокаВЧисло(Значение, Результат)
Чистая = СокрЛП(Значение);
Чистая = СтрЗаменить(Чистая, " ", "");
Чистая = СтрЗаменить(Чистая, Символы.НПП, ""); // неразрывный пробел из Excel
Чистая = СтрЗаменить(Чистая, ",", ".");
Если Чистая = "" Тогда
Результат = 0;
Возврат Истина;
КонецЕсли;
Попытка
Результат = Число(Чистая);
Возврат Истина;
Исключение
Возврат Ложь;
КонецПопытки;
КонецФункции
Функция СтрокаВДату(Значение, Результат)
Части = СтрРазделить(Лев(СокрЛП(Значение), 10), ".-/");
Если Части.Количество() <> 3 Тогда
Возврат Ложь;
КонецЕсли;
Попытка
Если СтрДлина(Части[0]) = 4 Тогда // 2025-03-25
Результат = Дата(Число(Части[0]), Число(Части[1]), Число(Части[2]));
Иначе // 25.03.2025
Результат = Дата(Число(Части[2]), Число(Части[1]), Число(Части[0]));
КонецЕсли;
Возврат Истина;
Исключение
Возврат Ложь;
КонецПопытки;
КонецФункции
Второй параметр СтрРазделить — набор символов-разделителей, поэтому ".-/" делит и по точке, и по дефису, и по косой черте.
Журнал ошибок вместо падения
Заведите таблицу значений с колонками «Строка», «Поле», «Значение», «Ошибка». В ОбработатьЗапись при каждой неудаче добавляйте туда строку и переходите к следующей записи. После загрузки покажите пользователю итог: «Загружено 4 812, ошибок 17» и сами ошибки.
Что стоит проверять, кроме типов:
- 📋 Число полей. Если в строке меньше колонок, чем в заголовке, — почти наверняка сломан разбор или в файле лишний перенос.
- 🔑 Обязательные поля. Пустой артикул или ИНН — запись пропускаем.
- 🔍 Поиск ссылок. Номенклатуру, контрагентов ищите по коду или ИНН одним запросом на всю пачку, а не
НайтиПоРеквизитув цикле по каждой строке. - ♻️ Повторная загрузка. Решите заранее, что делать с уже существующим элементом: обновить или пропустить.
Для регламентной загрузки, где пользователя нет, пишите итог в журнал регистрации:
ЗаписьЖурналаРегистрации("Обмен.ЗагрузкаCSV",
УровеньЖурналаРегистрации.Ошибка, , ,
"Строка " + НомерСтроки + ": " + ТекстОшибки);
Перед первой загрузкой в рабочую базу сделайте резервную копию и прогоните файл на копии. Тысяча ошибочно созданных элементов справочника удаляется гораздо дольше, чем создаётся.
Большие файлы записывайте порциями по 500–1000 объектов в транзакции. Одна транзакция на весь файл держит блокировки долго и при ошибке в последней строке откатывает всё.
,, а разбираете по ; (или наоборот). Проверьте первую строку файла или включите автоопределение.СтрЗаменить.Число().Кодировки, BOM и спецсимволы в CSV
Кодировка — главный источник проблем при чтении CSV в 1С. Платформа не угадывает её сама: что передали в конструктор, то и применит.
| Источник файла | Обычная кодировка | Что указать |
|---|---|---|
| Excel, «CSV (разделители — запятые)» | Windows-1251 | "windows-1251" |
| Excel, «CSV UTF-8» | UTF-8 с BOM | КодировкаТекста.UTF8 |
| Выгрузки веб-сервисов, Python, PHP | UTF-8 без BOM | КодировкаТекста.UTF8 |
| Старые DOS-программы | CP866 | КодировкаТекста.OEM |
Если источник неизвестен, помогает простая проверка: прочитайте файл как UTF-8 и поищите символ замены с кодом 65533. Он появляется, когда байты не складываются в корректный UTF-8:
Текст = Новый ТекстовыйДокумент;
Текст.Прочитать(ИмяФайла, КодировкаТекста.UTF8);
Если СтрНайти(Текст.ПолучитьТекст(), Символ(65533)) > 0 Тогда
Кодировка = "windows-1251";
Иначе
Кодировка = КодировкаТекста.UTF8;
КонецЕсли;
Для больших файлов проверяйте не весь текст, а первые 100–200 строк.
Спецсимволы, которые стоит чистить в каждом поле:
- ⎵ Неразрывный пробел (
Символы.НПП) — Excel вставляет его в числа и ФИО.СокрЛПего не убирает. - 🧩 BOM (
Символ(65279)) — только в начале файла, прилипает к первому заголовку. - ↵ Возврат каретки (
Символы.ВК) — может остаться в конце последнего поля, если файл с переносами Windows разбирали как Unix. ПроверкаПоле = "Да"при этом не срабатывает. - ⇥ Табуляция внутри текстовых полей в файлах с разделителем
;— безвредна, но мешает поиску по точному совпадению.
Загрузка CSV по расписанию
Когда поставщик раз в день кладёт файл в общую папку, загрузку переводят на регламентное задание.
- В Конфигураторе создайте общий модуль с флажком «Сервер» и экспортной процедурой без параметров, например
ЗагрузкаCSVПоРасписанию(). - В ветке
Общие → Регламентные заданиядобавьте задание, в поле «Имя метода» укажите эту процедуру. - Задайте расписание и включите флажок «Использование». Флажок «Предопределенное» создаст задание в базе автоматически.
- Обновите конфигурацию базы. В конфигурациях на БСП расписание потом меняется без Конфигуратора:
Администрирование → Обслуживание → Регламентные операции → Регламентные и фоновые задания.
Сама процедура обходит папку и переносит обработанные файлы, чтобы не загрузить их дважды:
Процедура ЗагрузкаCSVПоРасписанию() Экспорт
Каталог = "\\fileserver\obmen\in\";
Для Каждого Файл Из НайтиФайлы(Каталог, "*.csv") Цикл
Попытка
ЗагрузитьCSV(Файл.ПолноеИмя, ";");
ПереместитьФайл(Файл.ПолноеИмя, Каталог + "done\" + Файл.Имя);
Исключение
ЗаписьЖурналаРегистрации("Обмен.ЗагрузкаCSV",
УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
ПереместитьФайл(Файл.ПолноеИмя, Каталог + "error\" + Файл.Имя);
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Тонкие места регламентной загрузки:
- 🖥️ Права на папку. В клиент-серверной базе код выполняется на сервере 1С от имени пользователя, под которым работает служба (часто
USR1CV8). Пути видаZ:\там не существуют — указывайте UNC-путь\\сервер\папкаи дайте этому пользователю права на чтение и запись. - 📂 Файловая база. Регламентные задания в файловом варианте выполняются, только пока с базой работает хотя бы один сеанс. Ночью при выключенных компьютерах загрузки не будет.
- ⏳ Недописанный файл. Если источник ещё пишет файл, а задание уже читает, загрузится половина. Договоритесь, что источник пишет во временное имя
.tmpи переименовывает в.csvв конце. - 🚫 Никаких диалогов. В регламентном задании нет пользователя:
Сообщить,Вопроси выбор файла не сработают. Все сообщения — в журнал регистрации.
Частые вопросы
Как выгрузить данные из 1С обратно в CSV?
ЗаписьТекста: собирайте строку из полей через ;, поля с разделителем, кавычкой или переносом берите в кавычки, а кавычки внутри удваивайте. Для Excel в русской локали удобнее кодировка "windows-1251".Почему после Excel пропали ведущие нули в ИНН и артикулах?
Работает ли чтение CSV в веб-клиенте?
НачатьПомещениеФайла и временное хранилище, а разбор идёт на сервере. Код чтения от клиента не зависит.Как прочитать CSV с разделителем-табуляцией?
Символы.Таб вместо ";". Такие файлы часто имеют расширение .tsv или .txt, но читаются так же.Сколько строк можно загрузить за раз?
ЧтениеТекста ограничение задаёт не файл, а время записи объектов. Сотни тысяч строк — рабочий объём, если писать порциями по транзакциям и искать ссылки запросом на пачку.