Почему ADO считывает не все колонки из CSV-файла в 1С и как это исправить?

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

При использовании COM-объекта ADODB.Recordset для загрузки данных из текстовых файлов CSV разработчики 1С часто сталкиваются с ситуацией, когда вместо реального количества колонок (например, 15) объект возвращает всего 1 или 2 поля. Проанализируем, почему возникает эта проблема, как правильно настроить параметры подключения OLEDB и какие альтернативные способы разбора CSV существуют в платформе 1С.

Причины некорректного распознавания структуры CSV через ADO

Выясним основные факторы, из-за которых провайдер ADO сбоит при определении количества полей:

  1. Некорректная кодировка файла Schema.ini. Если файл настроек схемы данных Schema.ini записывается объектом ТекстовыйДокумент без явного указания кодировки, 1С сохраняет его в кодировке UTF-8 с маркером BOM или UTF-16. Драйверы Microsoft OLEDB (Jet и ACE) не умеют считывать Schema.ini в формате Unicode. В результате драйвер полностью игнорирует файл настройки схемы и считывает CSV с системным разделителем по умолчанию (запятой), из-за чего строка с разделителями-точками с запятой («;») воспринимается как одна монолитная колонка. Файл Schema.ini обязательно должен сохраняться в кодировке ANSI (Windows-1251).
  2. Символы переноса строк и некорректные кавычки внутри данных. Если в значения ячеек попадают символы возврата каретки (ВК / Символы.ВК) или переноса строки (ПС / Символы.ПС), парсер OLEDB сбивается и преждевременно завершает считывание текущей записи или неверно определяет границы полей.
  3. Использование устаревшего драйвера Jet 4.0. Провайдер Microsoft.Jet.OLEDB.4.0 является 32-битным компонентом, который плохо поддерживает современные кодировки (например, CharacterSet=UTF-8) и не работает в 64-разрядном окружении (на 64-битном сервере 1С).
  4. Ошибки в описании параметров Schema.ini. Указание параметра TextDelimiter=none может вызвать сбой синтаксического анализатора ADO. По спецификации драйвера, если разделитель текста отсутствует, этот параметр либо опускают, либо задают в виде пустых кавычек.

Правильная настройка подключения ADO и файла Schema.ini

Рассмотри корректный вариант настройки файла Schema.ini и строки подключения. Для работы рекомендуется использовать более современный провайдер Microsoft.ACE.OLEDB.12.0.

Сформируем и запишем файл схемы в кодировке ANSI, указав номер кодовой страницы 65001 для UTF-8:


Папка = "C:\CSV_Data\";
ИмяФайла = "data.csv";

// Формируем текст файла Schema.ini
ТекстSchema = "[" + ИмяФайла + "]" + Символы.ПС;
ТекстSchema = ТекстSchema + "ColNameHeader=True" + Символы.ПС;
ТекстSchema = ТекстSchema + "Format=Delimited(;)" + Символы.ПС;
ТекстSchema = ТекстSchema + "CharacterSet=65001" + Символы.ПС;

// Обязательно записываем Schema.ini в кодировке ANSI (Windows-1251)
ТекстДок = Новый ТекстовыйДокумент;
ТекстДок.УстановитьТекст(ТекстSchema);
ТекстДок.Записать(Папка + "Schema.ini", КодировкаТекста.ANSI);

// Подключаемся через ADO с использованием провайдера ACE
objRec = Новый COMОбъект("ADODB.Recordset");
strQuery = "SELECT * FROM [" + ИмяФайла + "]";
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=""" + Папка + """;Extended Properties=""Text;FMT=Delimited""";

Попытка
    objRec.Open(strQuery, strConn, 3, 3, 1);
    Сообщить("Количество колонок: " + objRec.Fields.Count);
Исключение
    Сообщить("Ошибка открытия ADO: " + ОписаниеОшибки());
КонецПопытки;

Альтернативные способы разбора CSV в 1С

Хотя ADO позволяет выполнять SQL-запросы к текстовым файлам, работа через COM-объекты имеет ряд недостатков: зависимость от сторонних OLEDB-драйверов, проблемы с разрядностью (32/64 бит) и высокая чувствительность к кавычкам и переносам строк. Рассмотрим более надежные и быстрые механизмы, встроенные в платформу 1С.

1. Использование встроенных объектов ЧтениеCSV и НастройкиЧтенияCSV (Платформа 8.3.6 и новее)

В современных версиях платформы 1С предусмотрен специальный объект ЧтениеCSV, который работает штатно, без использования сторонних библиотек и файлов Schema.ini:


Настройки = Новый НастройкиЧтенияCSV;
Настройки.РазделительПолей = ";";
Настройки.Заголовок = Истина;

Чтение = Новый ЧтениеCSV;
Чтение.ОткрытьФайл("C:\CSV_Data\data.csv", Настройки);

Пока Чтение.Прочитать() Цикл
    // Чтение.ПолучитьЗначение(Индекс) или обработка текущей строки
КонецЦикла;

Чтение.Закрыть();

2. Построчное чтение через ЧтениеТекста

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


ЧтениеТекста = Новый ЧтениеТекста("C:\CSV_Data\data.csv", КодировкаТекста.UTF8);
СтрокаФайла = ЧтениеТекста.ПрочитатьСтроку();

Пока СтрокаФайла <> Неопределено Цикл
    // Разбор строки с помощью СтрРазделить (или собственного алгоритма в старых релизах)
    МассивЗначений = СтрРазделить(СтрокаФайла, ";", Истина);
    
    // Переход к следующей строке
    СтрокаФайла = ЧтениеТекста.ПрочитатьСтроку();
КонецЦикла;

ЧтениеТекста.Закрыть();

3. Использование COM-объекта Scripting.TextStream (для 1С 7.7 и старых платформ)

Если разработка ведется на устаревшей платформе, где отсутствуют методы потокового чтения или функция СтрРазделить, наиболее производительным решением для последовательной обработки больших CSV-файлов является объект Scripting.FileSystemObject:


FSO = Новый COMОбъект("Scripting.FileSystemObject");
ТекстовыйФайл = FSO.OpenTextFile("C:\CSV_Data\data.csv", 1, Ложь);

Пока ТекстовыйФайл.AtEndOfStream = Ложь Цикл
    СтрокаДанных = ТекстовыйФайл.ReadLine();
    // Логика разбора строки по разделителям
КонецЦикла;

ТекстовыйФайл.Close();

Резюме: Если требуется читать CSV через ADO, гарантируйте сохранение Schema.ini строго в кодировке ANSI и используйте провайдер Microsoft.ACE.OLEDB.12.0. При работе на современных релизах 1С рекомендуется полностью отказаться от ADO в пользу встроенного объекта ЧтениеCSV или потокового объекта ЧтениеТекста.

← На главную