Преобразование csv в таблицу значений Ключевые слова: csv, dsv, преобразовать, открыть
На выходе - в Список - список колонок, Таблица - таблица с данными.
Функция СтрокаВСписок(Стр,Разделитель = ";")
Список = СоздатьОбъект("СписокЗначений");
Б = СтрДлина(Разделитель)-1;
Пока СтрДлина(Стр)>0 Цикл
А = Найти(Стр,Разделитель);
Если А>0 Тогда
ВрСтр = СокрЛП(Лев(Стр,А-1));
Стр = СокрЛП(Прав(Стр,СтрДлина(Стр)-А-Б));
Иначе
// последняя
ВрСтр = СокрЛП(Стр);
Стр = "";
КонецЕсли;
Если (Лев(ВрСтр,1) = """") И (Прав(ВрСтр,1) = """") Тогда
ВрСтр = Сред(ВрСтр,2,СтрДлина(ВрСтр)-2);
КонецЕсли;
Список.ДобавитьЗначение(ВрСтр);
КонецЦикла;
Возврат(Список)
КонецФункции
Процедура Парсер(ИмяФайла, Список, Таблица);
Текст = СоздатьОбъект("Текст");
Сообщить(ИмяФайла);
Текст.Открыть(ИмяФайла);
Если Текст.КоличествоСтрок()=0 Тогда
Возврат;
КонецЕсли;
Заголовки = СокрЛП(Текст.ПолучитьСтроку(1));
Список = СоздатьОбъект("СписокЗначений");
Список = СтрокаВСписок(Заголовки);
Таблица = СоздатьОбъект("ТаблицаЗначений");
Для Сч = 1 По Список.РазмерСписка() Цикл
Таблица.НоваяКолонка(Список.ПолучитьЗначение(Сч));
КонецЦикла;
Для Сч = 2 По Текст.КоличествоСтрок() Цикл
Список1 = СтрокаВСписок(Текст.ПолучитьСтроку(Сч));
Если СокрЛП(Текст.ПолучитьСтроку(Сч))="" Тогда
Продолжить;
КонецЕсли;
Таблица.НоваяСтрока();
Для Сч1 = 1 По Список1.РазмерСписка() Цикл
Таблица.УстановитьЗначение(Сч-1,Сч1,Список1.ПолучитьЗначение(Сч1));
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Заляпуха, конечно, но работает в простейших случаях
Также можно сделать через ADO:
Файл = Новый Файл(ИмяФайла);
Если Не Файл.Существует() Тогда
Предупреждение("Файл не существует!");
Возврат;
КонецЕсли;
Connection = Новый ComОбъект("ADODB.Connection");
Command = Новый ComОбъект("ADODB.Command");
СтрокаПодключения = "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq="+Файл.Путь
+";Extensions=csv;";
Connection.ConnectionString = СтрокаПодключения;
Connection.Open();
Command.ActiveConnection = Connection;
Команда = "SELECT * FROM ["+файл.Имя+"]";
Command.CommandText = Команда;
Recordset = Command.Execute();
Сообщить("Выполнил");
ЧислоПолей = Recordset.Fields.Count;
и т.д.
==========
Дополнение:
функция, которая правильно раскладывает строки типа вида:
20100912; 17.19;"Назначение платежа; которое не нужно делить на подстроки"
То есть на три подстроки а не четыре:
RegExp = Новый COMОбъект("VBScript.RegExp");
Результат = Новый Массив();
RegExp.IgnoreCase = Ложь; //Игнорировать регистр
RegExp.Global = Истина; //Поиск всех вхождений шаблона
RegExp.MultiLine = Ложь; //Многострочный режим
RegExp.Pattern = "(?:^|;)(\""(?:[^\""]+|\""\"")*\""|[^;]*)"; //вот наш супер шаблон
//RegExp.Pattern = ";|;|;|;|;;|;|;|;|;|;|;|;|;;|;|;"; //вот наш супер шаблон
Matches=RegExp.Execute(Стр);
ЧислоВхождений=Matches.Count();
//Сообщить(Стр,СтатусСообщения.Важное);
Если ЧислоВхождений>0 Тогда
Для к = 0 По ЧислоВхождений-1 Цикл
Match = Matches.Item(к);
SubMatches = Match.SubMatches;
ЧислоПодвыражений=SubMatches.Count();
Для н = 0 По ЧислоПодвыражений-1 Цикл
SubMatch=SubMatches.Item(н);
Если SubMatch="" Тогда
//Продолжить;
КонецЕсли;
Результат.Добавить(SubMatch);
//Сообщить("Подстрока: "+SubMatch);
КонецЦикла;
КонецЦикла;
Иначе
//Сообщить("Вхождений шаблона не найдено");
КонецЕсли;
Возврат Результат;
Пример:
http://screencast.com/t/WeZtHFKzhsob
Парсинг строки сделан рекурсивно, допускается любое вложение разделителей:
20100912; 17.19;"Назначение платежа; ""фирма ""ООО"" ;АТ; "" которое не нужно делить на
подстроки"
// На вход: Строка формата csv
// На выходе: массив значений
Функция ПарсингСтрокиВМассив(Знач СтрокаВходящая,РазделительПолей = ",",РазделительТекста =
"""")
МассивРезультат = Новый Массив;
СтрокаНаПарсинг = СтрокаВходящая;
Если Прав(СтрокаНаПарсинг,1) <> РазделительПолей Тогда
СтрокаНаПарсинг = СтрокаНаПарсинг + РазделительПолей;
КонецЕсли;
инд = СтрДлина(СтрокаНаПарсинг);
Пока инд > 1 Цикл
Кусок = ПолучитьСтроку(СтрокаНаПарсинг,РазделительПолей,РазделительТекста);
МассивРезультат.Добавить(ОчисткаСтроки(Кусок,РазделительПолей,РазделительТекста));
СтрокаНаПарсинг = Сред(СтрокаНаПарсинг,СтрДлина(Кусок)+1);
инд = СтрДлина(СтрокаНаПарсинг);
КонецЦикла;
Возврат МассивРезультат;
КонецФункции
// На вход: тип "ТекстовыйДокумент"
// На выходе: таблица значений
Функция ПарсингВТаблицуЗначений(Знач Текст,РазделительПолей = ",",РазделительТекста = """")
ТЗ = Новый ТаблицаЗначений;
КвоСтрок = Текст.КоличествоСтрок();
Для инд_строк = 1 По КвоСтрок Цикл
СтрокаНаПарсинг = Текст.ПолучитьСтроку(инд_строк);
Если Прав(СтрокаНаПарсинг,1) <> РазделительПолей Тогда
СтрокаНаПарсинг = СтрокаНаПарсинг + РазделительПолей;
КонецЕсли;
СтрокаТЗ = ТЗ.Добавить();
ТЗКолонка = -1;
и_перебор = СтрДлина(СтрокаНаПарсинг);
Пока и_перебор > 1 Цикл
ТЗКолонка = ТЗКолонка + 1;
Если инд_строк = 1 Тогда
ТЗ.Колонки.Добавить();
КонецЕсли;
Кусок =
ПолучитьСтроку(СтрокаНаПарсинг,РазделительПолей,РазделительТекста);
СтрокаТЗ[ТЗКолонка] =
ОчисткаСтроки(Кусок,РазделительПолей,РазделительТекста);
СтрокаНаПарсинг = Сред(СтрокаНаПарсинг,СтрДлина(Кусок)+1);
и_перебор = СтрДлина(СтрокаНаПарсинг);
КонецЦикла;
КонецЦикла;
Возврат ТЗ;
КонецФункции
Функция ПолучитьСтроку(СтрокаВходная,РазделительПолей = ",",РазделительТекста = """")
Результат = "";
инд = 1;
Пока инд < СтрДлина(СтрокаВходная) Цикл
Если Сред(СтрокаВходная,инд,1) = РазделительПолей Тогда
Результат = Результат + РазделительПолей;
Прервать;
ИначеЕсли Сред(СтрокаВходная,инд,1) = РазделительТекста Тогда
ЧастковийРезультат = Сред(СтрокаВходная,инд,1) +
ПолучитьСтроку(Сред(СтрокаВходная,инд+1),РазделительТекста,РазделительТекста);
Результат = Результат + ЧастковийРезультат;
инд = инд + СтрДлина(ЧастковийРезультат);
Иначе
Результат = Результат + Сред(СтрокаВходная,инд,1);
инд = инд + 1;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ОчисткаСтроки(Знач СтрокаВходная,РазделительПолей = ",",РазделительТекста = """")
Если Прав(СтрокаВходная,1) = РазделительПолей Тогда
СтрокаВходная = Сред(СтрокаВходная,1,СтрДлина(СтрокаВходная)-1);
КонецЕсли;
Если Сред(СтрокаВходная,0,1) = РазделительТекста Тогда
СтрокаВходная = Сред(СтрокаВходная,2,СтрДлина(СтрокаВходная)-2);
СтрокаВходная = СтрЗаменить(СтрокаВходная,РазделительТекста
+РазделительТекста,РазделительТекста);
КонецЕсли;
Возврат СтрокаВходная;
КонецФункции
// Пример импорта из CSV файла в Таблицу Значений
TXTФайл = Новый ТекстовыйДокумент;
TXTФайл.Прочитать(ФайлCSV);
ТЗТест = ПарсингВТаблицуЗначений(TXTФайл,",","""");
Если ТЗТест.Количество() > 0 Тогда
ТЗТест.ВыбратьСтроку();
КонецЕсли;
// Пример импорта каждой строки CSV-формата в массив значений
TXTФайл = Новый ТекстовыйДокумент;
TXTФайл.Прочитать(ФайлCSV);
КвоСтрок = TXTФайл.КоличествоСтрок();
Для инд = 1 По КвоСтрок Цикл
очереднаяСтрока = TXTФайл.ПолучитьСтроку(инд);
МасивТест = ПарсингСтрокиВМассив(очереднаяСтрока,",","""");
Сообщить("--------------< " + инд + " >---------------");
Для Каждого инд_масс из МасивТест Цикл
Сообщить(инд_масс);
КонецЦикла;
КонецЦикла;
Обработка для теста импорта CSV-файлов:
http://commerce.at.ua/load/0-0-0-3-20
==========
Дополнение2:
функция, которая правильно считывает многострочные поля:
//ПреобразоватьТекстCSVвТЗ () импортирует данные в ТЗ из текста формата CSV
//Параметры:
//ТекстCSV - Строка, содержащая текст в формате csv
//Разделитель - Для формата CSV разделителем является ',', но т.к.
// Excel берет разделитель из региональных стандартов, то
// используется ';', поддерживает многострочные поля
//
&НаСервереБезКонтекста
Функция ПреобразоватьТекстCSVвТЗ(ТекстCSV="", Разделитель=";") Экспорт
ТЗ = Новый ТаблицаЗначений;
ОсобаяСтрока = "$#%^&*!xyxb$#%&*!^"; // для замены ""
НомерСтроки = 1;
Стр = СтрПолучитьСтроку(ТекстCSV,НомерСтроки);
Пока НомерСтроки <= СтрЧислоСтрок(ТекстCSV) Цикл
СтрокаТЗ = ТЗ.Добавить();
НомерПоля = 0;
Пока Стр <> "" Цикл
Токен = "";
ПозицияРазделителя = Найти(стр, Разделитель);
ПозицияОткрКавычек = Найти(стр, """");
Если (ПозицияРазделителя > ПозицияОткрКавычек ИЛИ ПозицияРазделителя =
0) И ПозицияОткрКавычек > 0 Тогда
// начинающееся с кавычек читаем до тех пор
Токен = Сред(Стр, 1, ПозицияОткрКавычек);
Стр = СтрЗаменить(Сред(Стр, ПозицияОткрКавычек+1), """""",
ОсобаяСтрока);
ПозицияЗакрКавычек = Найти(Стр, """");
Пока ПозицияЗакрКавычек = 0 Цикл
Токен = Токен + Стр + Символы.ПС;
НомерСтроки = НомерСтроки + 1;
Стр = СтрПолучитьСтроку(ТекстCSV, НомерСтроки);
Стр = СтрЗаменить(Стр, """""", ОсобаяСтрока);
// пока не встретим закрывающие
ПозицияЗакрКавычек = Найти(Стр, """");
КонецЦикла;
ПозицияРазделителя=Найти(Сред(Стр,ПозицияЗакрКавычек),
Разделитель);
ПозицияРазделителя = ?(ПозицияРазделителя>0, ПозицияЗакрКавычек
+ ПозицияРазделителя-1, 0);
КонецЕсли;
Токен = Токен + ?(ПозицияРазделителя>0, Сред(Стр, 1,
ПозицияРазделителя-1), Стр);
Стр = ?(ПозицияРазделителя>0, Сред(Стр, ПозицияРазделителя+1), "");
Если Лев(Токен, 1) = """" Тогда
Токен = Сред(Токен, 2);
Токен = ?(Прав(Токен, 1) = """", Сред(Токен, 1,
СтрДлина(Токен)-1), Токен);
КонецЕсли;
Токен = СтрЗаменить(Токен, ОсобаяСтрока, """");
НомерПоля = НомерПоля + 1;
Если ТЗ.Колонки.Количество()<НомерПоля Тогда
ТЗ.Колонки.Добавить("Колонка"+НомерПоля, Новый
ОписаниеТипов("Строка"));
КонецЕсли;
СтрокаТЗ[НомерПоля-1] = Токен;
КонецЦикла;
НомерСтроки = НомерСтроки + 1;
Стр = СтрПолучитьСтроку(ТекстCSV, НомерСтроки);
КонецЦикла;
Возврат ТЗ;
КонецФункции
//ПреобразоватьТЗвТекстCSV () экспортирует данные ТЗ в текст в формате CSV
//Параметры:
//ТЗ - Таблица значений данные которые сохраняются в файл
//флЭкспортироватьИменаКолонок - Первой строкой выводить имена колонок
//Разделитель - Для формата CSV разделителем является ',', но т.к.
// Excel берет разделитель из региональных стандартов, то
// используется ';'
//
&НаСервереБезКонтекста
Функция ПреобразоватьТЗвТекстCSV(ТЗ, Разделитель = ";", флЭкспортироватьИменаКолонок = Ложь)
Экспорт
ТекстCSV = "";
Если флЭкспортироватьИменаКолонок Тогда
//Если нужно выгружать наименование колонок Выгружаем
ПодготовленнаяСтрока = "";
Для Каждого Колонка Из ТЗ.Колонки Цикл
ПодготовленнаяСтрока = ПодготовленнаяСтрока + Колонка.Имя +
Разделитель;
КонецЦикла;
ПодготовленнаяСтрока = Лев
(ПодготовленнаяСтрока,СтрДлина(ПодготовленнаяСтрока)-1);
ТекстCSV = ТекстCSV + ПодготовленнаяСтрока + Символы.ПС;
КонецЕсли;
Для Каждого Строка Из ТЗ Цикл
ПодготовленнаяСтрока = "";
Для Каждого Колонка Из ТЗ.Колонки Цикл
ПреобразованноеПоле = Строка[Колонка.Имя];
//по правилам CSV если поле содержит двойные ковычки они должны
повторятся дважды
Если Найти(ПреобразованноеПоле,"""") Тогда
ПреобразованноеПоле =
СтрЗаменить(ПреобразованноеПоле,"""","""""");
КонецЕсли;
//по правилам CSV если поле содержит перенос строки или запятую оно
должно заключатся в двойные кавычки
Если Найти(ПреобразованноеПоле,Разделитель) ИЛИ
Найти(ПреобразованноеПоле,Символы.ПС) ИЛИ Найти(ПреобразованноеПоле,"""") Тогда
ПреобразованноеПоле = """" + ПреобразованноеПоле + """";
КонецЕсли;
ПодготовленнаяСтрока = ПодготовленнаяСтрока + ПреобразованноеПоле +
Разделитель;
КонецЦикла;
ПодготовленнаяСтрока = Лев
(ПодготовленнаяСтрока,СтрДлина(ПодготовленнаяСтрока)-1);
ТекстCSV = ТекстCSV + ПодготовленнаяСтрока + Символы.ПС;
КонецЦикла;
Возврат ТекстCSV;
КонецФункции
Обработка для теста:
http://infostart.ru/public/541555/ |