четверг, 13 октября 2022 г.

1СОшибка ODBC разделитель запятая

Тривиальная задача - импорт CSV в ТЗ, но CSV с точки зрения EXCEL кривой, т.к. имеет многострочные колонки:


Гугл докс нормально кушает файл, загрузка на сайт тоже, а вот Excel нет. Соответственно классический построчный перебор и конвертация строки в массив с последующим вложенным перебором нам не подходит. Наткнулся на статьи на Infostart  и обрадовался, узнав что вариации ODBC умеют многострочные колонки в CSV. Кстати, EXCEL понимает ограничитель строк, но только в том случае, если он на одной строке.

Не долго радовалась старушка, разделитель у меня запятая, вполне разрешенная для CSV, но я получил сходу такую ошибку:

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

На одном из форумов предложили изменить настройки ПК, я изменил, но результата не было (перезагрузку не делал ибо не хотелось), поковырявшись в этих ваших интернетах, таки нашел ответ - указать DecimalSymbol явно в Schema.ini в итоге функция ПрочитатьCSVвТЗ_ADO приняла следующий вид (с моими специфическими корректировками):


&НаСервереБезКонтекста
Функция ПрочитатьCSVвТЗ_ADO(ИмяФайла, Разделитель=";", ЗаголовкиИзПервойСтроки = Ложь)
	ТаблицаРезультат = Новый ТаблицаЗначений;
	Файл = Новый Файл(ИмяФайла);
	
	Connection=Новый COMОбъект("ADODB.Connection");
	Connection.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+Файл.Путь+";Extended Properties=""text;HDR=No;IMEX=1;FMT=Delimited""");

	// Так как FMT=Delimited(;) не работает создадим schema.ini 
	Схема = СтрШаблон("[%1]
		|ColNameHeader=%2
		|Format=Delimited(%3)
		|DecimalSymbol=.", Файл.Имя, Формат(ЗаголовкиИзПервойСтроки, "БЛ=False; БИ=True"), Разделитель);
	ФайлСхемы = Новый ТекстовыйДокумент;
	ФайлСхемы.УстановитьТекст(Схема);
	ФайлСхемы.Записать(Файл.Путь + "Schema.ini", "CESU-8"); // UTF-8 без BOM
	
	RecordSet=Новый COMОбъект("ADODB.Recordset");
	RecordSet.ActiveConnection = Connection;
	
	RecordSet.Open("select * from "+Файл.Имя, Connection);
	
	// определим имена колонок
	Для НомерКолонки = 0 по RecordSet.Fields.Count-1 Цикл
		//Во входящих данных может быть спецсимвол в именах колонок
		ИмяКолонки=СтрЗаменить(RecordSet.Fields(НомерКолонки).Name,"#","");
		ТаблицаРезультат.Колонки.Добавить(ИмяКолонки,Новый ОписаниеТипов("Строка"));
	КонецЦикла;
	
	Сч=0;
	Пока НЕ RecordSet.EOF() Цикл
		Сч=Сч+1;
		
		НоваяСтрока = ТаблицаРезультат.Добавить();
		Для й=0 по RecordSet.Fields.Count-1 Цикл
			//В некоторых выгрузках в наименовании появлются вопросительные знаки
			НоваяСтрока[й] = СтрЗаменить(RecordSet.Fields(й).Value,"?", " ");
		КонецЦикла;
		
		RecordSet.MoveNext();
	КонецЦикла;
	
	RecordSet.Close();
	Connection.Close();
	Возврат(ТаблицаРезультат);
КонецФункции


Правда две не решенных проблемы осталось:

  1. кодировка, как не конвертируя сказать драйверу что используется кодировка UTF-8?
  2. автоматическая типизация колонок, у меня были поля артикула с лидирующими нолями, но драйвер определяет в поле число и удаляет лидирующие нули на этапе запроса.

Комментариев нет:

Отправить комментарий