При использовании COM-объекта ADODB.Recordset для загрузки данных из текстовых файлов CSV разработчики 1С часто сталкиваются с ситуацией, когда вместо реального количества колонок (например, 15) объект возвращает всего 1 или 2 поля. Проанализируем, почему возникает эта проблема, как правильно настроить параметры подключения OLEDB и какие альтернативные способы разбора CSV существуют в платформе 1С.
Выясним основные факторы, из-за которых провайдер ADO сбоит при определении количества полей:
Schema.ini. Если файл настроек схемы данных Schema.ini записывается объектом ТекстовыйДокумент без явного указания кодировки, 1С сохраняет его в кодировке UTF-8 с маркером BOM или UTF-16. Драйверы Microsoft OLEDB (Jet и ACE) не умеют считывать Schema.ini в формате Unicode. В результате драйвер полностью игнорирует файл настройки схемы и считывает CSV с системным разделителем по умолчанию (запятой), из-за чего строка с разделителями-точками с запятой («;») воспринимается как одна монолитная колонка. Файл Schema.ini обязательно должен сохраняться в кодировке ANSI (Windows-1251).Символы.ВК) или переноса строки (ПС / Символы.ПС), парсер OLEDB сбивается и преждевременно завершает считывание текущей записи или неверно определяет границы полей.Microsoft.Jet.OLEDB.4.0 является 32-битным компонентом, который плохо поддерживает современные кодировки (например, CharacterSet=UTF-8) и не работает в 64-разрядном окружении (на 64-битном сервере 1С).Schema.ini. Указание параметра TextDelimiter=none может вызвать сбой синтаксического анализатора ADO. По спецификации драйвера, если разделитель текста отсутствует, этот параметр либо опускают, либо задают в виде пустых кавычек.Рассмотри корректный вариант настройки файла 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: " + ОписаниеОшибки());
КонецПопытки;
Хотя ADO позволяет выполнять SQL-запросы к текстовым файлам, работа через COM-объекты имеет ряд недостатков: зависимость от сторонних OLEDB-драйверов, проблемы с разрядностью (32/64 бит) и высокая чувствительность к кавычкам и переносам строк. Рассмотрим более надежные и быстрые механизмы, встроенные в платформу 1С.
В современных версиях платформы 1С предусмотрен специальный объект ЧтениеCSV, который работает штатно, без использования сторонних библиотек и файлов Schema.ini:
Настройки = Новый НастройкиЧтенияCSV;
Настройки.РазделительПолей = ";";
Настройки.Заголовок = Истина;
Чтение = Новый ЧтениеCSV;
Чтение.ОткрытьФайл("C:\CSV_Data\data.csv", Настройки);
Пока Чтение.Прочитать() Цикл
// Чтение.ПолучитьЗначение(Индекс) или обработка текущей строки
КонецЦикла;
Чтение.Закрыть();
Для старых версий платформы или при необходимости полного контроля над обработкой строк разбор файловым потоком работает быстрее и не расходует память на загрузку всего файла сразу:
ЧтениеТекста = Новый ЧтениеТекста("C:\CSV_Data\data.csv", КодировкаТекста.UTF8);
СтрокаФайла = ЧтениеТекста.ПрочитатьСтроку();
Пока СтрокаФайла <> Неопределено Цикл
// Разбор строки с помощью СтрРазделить (или собственного алгоритма в старых релизах)
МассивЗначений = СтрРазделить(СтрокаФайла, ";", Истина);
// Переход к следующей строке
СтрокаФайла = ЧтениеТекста.ПрочитатьСтроку();
КонецЦикла;
ЧтениеТекста.Закрыть();
Если разработка ведется на устаревшей платформе, где отсутствуют методы потокового чтения или функция СтрРазделить, наиболее производительным решением для последовательной обработки больших 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 или потокового объекта ЧтениеТекста.