Рабочий код по загрузке из файла CSV

Клиенту понадобилось загружать прайсы разных поставщиков, в основном в Excel, но были и CSV.

Для Excel я использовал загрузку из табличного документа. А для CSV решил, что проще сразу перегнать его в табличный документ.

У меня был очень медленный код, который посимвольно считывал строку CSV, а там было 70.000 символов, в результате работал медленно. Переписал его на построчное последовательное чтение из файла.

Можете использовать и усовершенствовать.

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

UPD 25.03.18: После того, как опубликовал этот код, попался CSV с переносами строк и пришлось доработать, чтобы корректно считывался. Также корректно работают двойные кавычки, если дважды повторены внутри кавычек.

Функция разбора CSV в массивы строк и колонок:

Функция ПрочитатьCSV(ИмяФайла, Разделитель, Кодировка) Экспорт
	//http://chel1c.ru/%D0%B8%D0%BC%D0%BF%D0%BE%D1%80%D1%82-%D0%B8%D0%B7-csv-%D0%B2-1%D1%81/
	
	Результат = Новый Структура(); 
	
	Строки = Новый Массив();
	Колонки = Новый Массив();
	
	Скобка = ЛОЖЬ;
	Колонка = 0;
	МассивТокенов = новый Массив; // массив колонок в строке
	ПерваяСтрока = истина;
	Токен = "";
	
	
	//Считываем построчно
	ЧтениеТекста = Новый ЧтениеТекста(ИмяФайла, Кодировка); 
	
	Пока Истина Цикл
		
		Строка = ЧтениеТекста.ПрочитатьСтроку();
		Если Строка = Неопределено Тогда
			Прервать;
		КонецЕсли;        
		
		Если ПерваяСтрока Тогда     
			Колонки = СтрРазделить(Строка, Разделитель);
			КоличествоКолонок = Колонки.Количество();
			ПерваяСтрока = ложь;
			Продолжить; //Первую строку не обрабатываем
		КонецЕсли;
		
		ДлинаСтроки = СтрДлина(Строка);
		ДлинаСтрокиПлюс = ДлинаСтроки + 1;
		
		
		Позиция = 1;
		
		Пока Позиция <= ДлинаСтрокиПлюс Цикл // обходим файл посимвольно
			
			Если Позиция = ДлинаСтрокиПлюс Тогда
				Символ = Символы.ПС;
			Иначе
				Символ = Сред(Строка, Позиция, 1);
			КонецЕсли;
			
			//Обрабатываем экранирование кавычками
			//если встречается кавычка, фиксируем ее открытие, прекращаем итерацию и продолжаем цикл.
			Если Символ = """" И Скобка = Ложь Тогда
				Скобка = Истина; 
				Позиция = Позиция + 1;
				Продолжить;
				//Если встречается закрывающаяся кавычка, фиксируем ее закрытие и тоже продолжаем цикл
			ИначеЕсли Символ = """" И Скобка = Истина ТОгда
				//Если два раза подряд кавычка, это кавычка, иначе это завершение скобки
				СледующийСимвол = Сред(Строка, Позиция + 1, 1);
				Если СледующийСимвол <> """" Тогда
					Скобка = Ложь;
					Позиция = Позиция + 1;
					Продолжить;
				Иначе
					Позиция = Позиция + 1; //Используем этот символ, будет переход еще на позицию в конце цикла, итого перейдем на 2 позиции
				КонецЕсли;
			КонецЕсли;
			
			//Если встречается разделитель или перенос строки вне кавычек,
			//вносим информацию в массив
			//Если будет перенос на другую строку, с другой строки просто продолжится работа
			Если (Символ = Символы.ПС И Скобка = Ложь) ИЛИ (Символ = Разделитель И Скобка = Ложь) Тогда
				
				//Конец = Позиция; 
				
				Колонка = Колонка+1;
				
				//Добавляем в строку файла
				МассивТокенов.Добавить(Токен);
				Токен = ""; //Сбрасываем токен
				
				//Если набралось количество колонок, равное их количеству в шапке, записываем всю строку
				//в массив и переходим к следующей
				Если Колонка = КоличествоКолонок ИЛИ Символ = Символы.ПС Тогда
					
					Строки.Добавить(МассивТокенов);
					МассивТокенов = Новый Массив;
					Колонка=0;
					
				КонецЕсли;
				
			Иначе                     
				Токен = Токен + Символ; //Накапливаем токен, в том числе и символ перевода строки, если это разрыв страницы
			КонецЕсли;                                                                                                     
			
			Позиция = Позиция + 1; //Переходим к следующей позиции всегда
			
		КонецЦикла;
	КонецЦикла;
	
    Результат.Вставить("Строки", Строки);
    Результат.Вставить("Колонки", Колонки);
    Результат.Вставить("КоличествоКолонок", КоличествоКолонок);
    Результат.Вставить("КоличествоСтрок", Строки.Количество());
	
	Возврат Результат;
	
КонецФункции

Функция конвертации CSV в табличный документ:

Функция ПрочитатьТабличныйДокументИзФайлаCSV(ИмяФайла, Разделитель, Кодировка) Экспорт
	ТД = Новый ТабличныйДокумент();
	Р = ПрочитатьCSV(ИмяФайла, Разделитель, Кодировка);
	Для Кол = 1 ПО Р.КоличествоКолонок Цикл
		ТД.Область(1, Кол).Текст = Р.Колонки[Кол - 1];
	КонецЦикла;
	Для Стр = 1 ПО Р.КоличествоСтрок Цикл
		Строка = Р.Строки[Стр - 1];
		Для Кол = 1 ПО Р.Колонки.Количество() Цикл
			ТД.Область(Стр + 1, Кол).Текст = Строка[Кол - 1];
		КонецЦикла;
	КонецЦикла;                                 
	Возврат ТД;
КонецФункции   

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *