![]() |
![]() |
![]() |
|
Разбить строку на подстроки, но хитро... (внутри подробности) | ☑ | ||
---|---|---|---|---|
0
Живой Ископаемый
03.12.08
✎
18:02
|
Есть csv-файл буквально такого содержания:
Поле1;Поле2;Поле3;Поле4;Поле5;Поле6 999999;99999;UAH;31.10.2008 06:26;"*;666666;888888 ;Такой-сякой налог за 2008г. Без НДС.";0.00 Думал читать по строкам, из первой строки делать структуру - названия полей - ключи... Потом каждую строку тоже разбирать в структуру, в которой ключи как в первую, а значения - это подстроки текущей строки.. Подстроки разделены символом ";"... э... за исключением тех частей, которые заключены в кавычки - эта часть должна восприниматься как одна подстрока... То есть я так понимаю либо усложнять логическу процедуру РазложитьСтрокуВМассивПодстрок, либо читать csv-файл через ОЛЕ екслем или через ОЛЕДБ? Больше вариантов нет? Если есть примеры чтения csv-файла через ОЛЕДБ, был бы благодарен за их приведение... :) |
|||
1
ТелепатБот
гуру
03.12.08
✎
18:02
|
||||
2
Serg_1960
03.12.08
✎
18:07
|
Либо вариант:
МногоСтрочнаяСтрока = СтрЗаменить(ОдноСтрочнаяСтрока, ";", Символы.ПС); ПервыйРеквизит = СтрПолучитьСтроку(МногоСтрочнаяСтрока,1); ВторойРеквизит = СтрПолучитьСтроку(МногоСтрочнаяСтрока,2); ... |
|||
3
Serg_1960
03.12.08
✎
18:10
|
Теперь осталось "малое" - разобраться с кавычками :)
|
|||
4
Живой Ископаемый
03.12.08
✎
18:10
|
(2) Ну... очевидно не вариант, потому что
5-й реквизит д.б. равен "*;666666;888888 ;Такой-сякой налог за 2008г. Без НДС." , при чем лучше без кавычек, и ни в коем случае не "*" |
|||
5
Живой Ископаемый
03.12.08
✎
18:11
|
||||
6
YauheniL
03.12.08
✎
18:12
|
(0) Вот к чему приводит неудачный выбор символа-разделителя :(
|
|||
7
Живой Ископаемый
03.12.08
✎
18:13
|
(6) Мудацкие банки, ага... :(
|
|||
8
НЕА123
03.12.08
✎
18:15
|
(2)(3) +
сначала для каждй строки МногоСтрочнаяСтрока = СтрЗаменить(ОдноСтрочнаяСтрока, ";""", Символы.ПС + "<ТегНачала>"); МногоСтрочнаяСтрока = СтрЗаменить(ОдноСтрочнаяСтрока, """;", "<ТегКонца>"+Символы.ПС); и... трахома... с геморроем.... |
|||
9
hhhh
03.12.08
✎
18:15
|
(0) как то так:
Выполнить("Струк = Новый Структура(""Поле1,Поле2,Поле3,Поле4,Поле5,Поле6"", " + """" + СтрЗаменить(СтрЗаменить(СтрокаФайла, """", """"""""), ";", """,""") + """); "); |
|||
10
Serg_1960
03.12.08
✎
18:47
|
Сорри, домой пора. В этом алгоритме где-то ошибка, - но смысл понятен :)
Строка = "999999;99999;UAH;31.10.2008 06:26;""*;666666;888888;Такой-сякой налог за 2008г. Без НДС."";0.00"; ЧислоСтрок = СтрЧислоВхождений(Строка, ";")+1; Строки = СтрЗаменить(Строка, ";", Символы.ПС); Кавычки = Ложь; Накопитель = ""; Подстрока = ""; Для К = 1 По ЧислоСтрок Цикл Подстрока = СтрПолучитьСтроку(Строки, К); Если Найти(Подстрока,"") Тогда Кавычки = Не Кавычки; Если Кавычки Тогда Накопитель = Накопитель + Подстрока + ";"; Иначе Сообщить(Накопитель + Подстрока); Накопитель = ""; КонецЕсли; Иначе Если Кавычки Тогда Накопитель = Накопитель + Подстрока + ";"; Иначе Сообщить(Подстрока); КонецЕсли; КонецЕсли; КонецЦикла; |
|||
11
Torquader
03.12.08
✎
19:17
|
Есть мнение, что ничего заменять не надо!
Function ПоискОкончания(ИсхСтр) ch=Mid(ИсхСтр,1,1);// читаем первый символ if ch="""" then// если строка "оковыченная" КонПоз=0; ПромСтр=ИсхСтр; while КонПоз>=0 do// не хочется сюда ставить метку СимвПоз=Find(ИсхСтр,"""");// ищем кавычку (точку с запятой можно не искать) if СимвПоз=0 then return 0;endif;// кривой формат строки ch=Mid(ИсхСтр,СимвПоз+1,1);// читаем следующий символ if ch="""" then//две кавычки подряд - просто кавычка в тексте ПромСтр=Mid(ПромСтр,СимвПоз+2); КонПоз=КонПоз+СимвПоз+2;// запоминаем, сколько символов мы проскочили continue; elsif ch=";" then// если он после кавычки - это конец нашего поля return КонПоз+СимвПоз+1;// положение нужной нам точки с запятой else return 0;// встретили после кавычки чёрт знает что endif; else// если строка неоковыченная return Find(ИсхСтр,";"); endif; EndFunction |
|||
12
bd
03.12.08
✎
19:20
|
(0)
- Регулярные выражения с такими задачами справляются лучше всего - В стандартной поставке винды идёт ODBC-драйвер для csv-файлов, а на него уже можно натравить OLEDB-провайдер для ODBC :) |
|||
13
artem666
03.12.08
✎
19:29
|
(0) напиши запрос на ADODB и не парься - нав самое легкоме и быстрое решение
|
|||
14
Rebelx
03.12.08
✎
19:49
|
// Пробразует переданную строку с разделителями в массив значений
// Корректно обрабатывает вложенные строки // // Параметры: // Значение - строка с разделителями, значения из которой необходимо преобразовать в массив // Разделитель - определяет разделитель значений // // Возвращаемое значение: // Массив значений, выделенных из строки // Функция ИзСтрокиСРазделителями(Знач Значение, Знач Разделитель = ",") Экспорт Если СтрДлина(Разделитель) = 0 тогда ВызватьИсключение("Ошибка при вызове функции (ИзСтрокиСРазделителями): Несоответствие типов (параметр номер '2')"); КонецЕсли; ДлинаРазделителя = СтрДлина(Разделитель); Результат = Новый Массив(); Пока СтрДлина(Значение) > 0 Цикл ПозицияРазделителя = Найти(Значение, Разделитель); Если ПозицияРазделителя = 0 тогда Результат.Добавить(СокрЛП(Значение)); Прервать; Иначе КоличествоКавычек = СтрЧислоВхождений(Лев(Значение, ПозицияРазделителя - 1), """"); Пока (Цел(КоличествоКавычек / 2) * 2) <> КоличествоКавычек Цикл НоваяПозицияРазделителя = Найти(Сред(Значение, ПозицияРазделителя + ДлинаРазделителя), Разделитель); Если НоваяПозицияРазделителя > 0 тогда ПозицияРазделителя = ПозицияРазделителя + НоваяПозицияРазделителя - 1 + ДлинаРазделителя; Иначе Результат.Добавить(СокрЛП(Значение)); Перейти ~ВыходИзПроцедуры; КонецЕсли; КоличествоКавычек = СтрЧислоВхождений(Лев(Значение, ПозицияРазделителя - 1), """"); КонецЦикла; Результат.Добавить(СокрЛП(Лев(Значение, ПозицияРазделителя - 1))); Значение = Сред(Значение, ПозицияРазделителя + ДлинаРазделителя); КонецЕсли; КонецЦикла; ~ВыходИзПроцедуры: Возврат Результат; КонецФункции |
|||
15
KAO111
03.12.08
✎
20:46
|
// через рег.выражения
RegExp = Новый COMОбъект("VBScript.RegExp"); RegExp.MultiLine = Истина; RegExp.Global = Истина; RegExp.IgnoreCase = Истина; // проверяет условия с помощью регулярных выражений, // если НЕ ТолькоПроверка - заменяет выражение с помощью шаблона ШаблонЗамены и возвращает в переменной ИтоговаяСтрока Функция ПроверитьУсловие(СтрокаПоиска,ШаблонПоиска,ТолькоПроверка=Истина,ШаблонЗамены="",ИтоговаяСтрока="") Экспорт // RegExp.Replace(СтрокаПоиска,ШаблонПоиска); RegExp.Pattern = ШаблонПоиска; Найдено = RegExp.Test(СтрокаПоиска); Если НЕ Найдено или ТолькоПроверка тогда ИтоговаяСтрока=""; возврат Найдено ; Иначе ИтоговаяСтрока = RegExp.Replace(СтрокаПоиска,ШаблонЗамены); // ИтоговаяСтрока = RegExp.Execute(СтрокаПоиска).Item(0).SubMatches.Item(ШаблонЗамены); возврат Найдено ; КонецЕсли; КонецФункции // ПроверитьУсловие() Функция РазобратьСтроку(СтрокаПоиска) Экспорт НовСтрокаПоиска = СтрЗаменить(СтрокаПоиска,РазделительКолонок,"~SPC~"+РазделительКолонок); ШаблонПоиска = РазделительКолонок+"(?=([^""]*""[^""]*"")*(?![^""]*""))"; ШаблонЗамены = "~REPL~" ; ИтоговаяСтрока = "" ; ТолькоПроверка = Ложь ; УсловиеНайдено = ПроверитьУсловие(НовСтрокаПоиска,ШаблонПоиска,ТолькоПроверка,ШаблонЗамены,ИтоговаяСтрока); Если УсловиеНайдено тогда // заменим кавычки по правилам CSV ИтоговаяСтрока = СтрЗаменить(ИтоговаяСтрока,"""""","~'~"); ИтоговаяСтрока = СтрЗаменить(ИтоговаяСтрока,"""" ,"" ); ИтоговаяСтрока = СтрЗаменить(ИтоговаяСтрока,"~'~" ,"""" ); КонецЕсли; ИтоговыйМассив = ФункцииОбработки.локМассивИзСтроки(ИтоговаяСтрока,ШаблонЗамены); НовыйМассив = Новый Массив() ; Для каждого Эл Из ИтоговыйМассив Цикл НовыйМассив.Добавить(СтрЗаменить(Эл,"~SPC~" ,"" )); КонецЦикла; возврат НовыйМассив; КонецФункции |
|||
16
KAO111
03.12.08
✎
20:49
|
Можно загрузить с помощью обработки
http://infostart.ru/projects/2466/ |
|||
17
Черный всадник
03.12.08
✎
20:54
|
(0) Проще и быстрей подключить к этому ADO. Плюс громадный выигрыш в скорости на больших файлах.
Книга знаний: Пример работы с SQL Server посредством ADO http://www.connectionstrings.com/textfile |
|||
19
Serg_1960
04.12.08
✎
08:33
|
А кто спорит? Конечно скриптами, через ADO или OLE получится быстрее. А вот остаться "в рамках 1С" - интереснее :)
|
|||
20
Serg_1960
04.12.08
✎
08:56
|
(10) Исправленный алгоритм :)
ИсходнаяСтрока = "999999;99999;UAH;31.10.2008 06:26;""*;666666;888888;Такой-сякой налог за 2008г. Без НДС."";0.00"; МногоСтрочная = СтрЗаменить(ИсходнаяСтрока, ";", Символы.ПС); Кавычка = Ложь; СтроковыйРеквизит = ""; ПростойРеквизит = ""; Для К = 1 По СтрЧислоСтрок(МногоСтрочная) Цикл ПростойРеквизит = СтрПолучитьСтроку(МногоСтрочная, К); Если Найти(ПростойРеквизит, """") Тогда Кавычка = Не Кавычка; Если Кавычка Тогда СтроковыйРеквизит = Прав(ПростойРеквизит, СтрДлина(ПростойРеквизит) - 1) + ";"; Иначе СтроковыйРеквизит = СтроковыйРеквизит + Лев(ПростойРеквизит, СтрДлина(ПростойРеквизит) - 1); Сообщить(СтроковыйРеквизит); СтроковыйРеквизит = ""; КонецЕсли; Иначе Если Кавычка Тогда СтроковыйРеквизит = СтроковыйРеквизит + ПростойРеквизит + ";"; Иначе Сообщить(ПростойРеквизит); КонецЕсли; КонецЕсли; КонецЦикла; |
|||
21
Serg_1960
04.12.08
✎
09:56
|
Другой вариант. Мне он больше "нравится" :)
ИсходнаяСтрока = "999999;99999;UAH;31.10.2008 06:26;""*;666666;888888;Такой-сякой налог за 2008г. Без НДС."";0.00"; Пока Истина Цикл Поз = Найти(ИсходнаяСтрока, ";"); Если Поз = 0 Тогда Реквизит = ИсходнаяСтрока; Иначе Если Лев(ИсходнаяСтрока,1) = """" Тогда ИсходнаяСтрока = Сред(ИсходнаяСтрока, 2); Поз = Найти(ИсходнаяСтрока, """"); КонецЕсли; Реквизит = Лев(ИсходнаяСтрока,Поз-1); КонецЕсли; Сообщить(Реквизит); Если СтрДлина(Реквизит) = СтрДлина(ИсходнаяСтрока) Тогда Прервать; КонецЕсли; ИсходнаяСтрока = Сред(ИсходнаяСтрока,СтрДлина(Реквизит)+2); КонецЦикла; |
|||
22
Черный всадник
04.12.08
✎
09:59
|
(19) Да я и сам люблю поизвращаться, когда работе не мешает :)
|
|||
23
Serg_1960
04.12.08
✎
10:05
|
(22) Рыбак рыбака видит издалека :) Поделись потом извращением :)
|
|||
24
Fragster
гуру
04.12.08
✎
10:10
|
вообще-то кажись в (0) - правильный CSV, а его можно и через ADO с драйвером csv получить...
|
|||
25
Serg_1960
04.12.08
✎
10:40
|
(24) Ага. см. (13),(16),(17),(19),... :))
|
|||
26
Живой Ископаемый
04.12.08
✎
11:59
|
(24,17) У меня не хватило терепения ФайлДСН настроить - в общем обламывался по ошибке.. Почему-то... Не могу сказать что это совсем не метод - когда-то у меня вполне получалось, но сейчас... спасибо что напомнили про РегЕксп...
Получилось правильно разобрать строку на подстроки с помощью такого кода: RegExp = Новый COMОбъект("VBScript.RegExp"); RegExp.IgnoreCase = Ложь; //Игнорировать регистр RegExp.Global = Истина; //Поиск всех вхождений шаблона RegExp.MultiLine = Ложь; //Многострочный режим 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); КонецЦикла; КонецЦикла; Иначе Сообщить("Вхождений шаблона не найдено"); КонецЕсли; ===== Полученный код это компиляция слеудующих двух источников: Книга знаний: Использование регулярных выражений (RegExp) в 1С и http://geekswithblogs.net/mwatson/archive/2004/09/04/10658.aspx, но с учетом того, что у меня поля разделены семиколоном а не запятой |
|||
27
Живой Ископаемый
04.12.08
✎
11:59
|
зы. Всем огромное спасибо...
|
|||
28
Живой Ископаемый
04.12.08
✎
12:03
|
Блин.. Не совсем.. :( нужно еще подстроить шаблончек
|
|||
29
Serg_1960
04.12.08
✎
12:15
|
Блин :( Ну проверь ты варианты (20) и (21) - не долго ведь :)
|
|||
30
Живой Ископаемый
04.12.08
✎
12:38
|
2(29) Не хочу, не нравится идея...
|
|||
31
Rebelx
04.12.08
✎
12:40
|
не люблю я людей ищущих геморой на свою ...
|
|||
32
Живой Ископаемый
04.12.08
✎
12:42
|
(31) ой, а я каких людей не люблю.. стану перечислять, можно будет вообще про 1С забыть
(29) Не так.. оставлю на закуску, когда все остальное не получится |
|||
33
Живой Ископаемый
04.12.08
✎
12:45
|
Все, вот такой Паттерн катит:
(?:^|;)(\"(?:[^\"]+|\"\")*\"|[^;]*) Упростил при помощи РегексБадди (www.regexbuddy.com) |
|||
34
Черный всадник
04.12.08
✎
12:48
|
(32) Вот интересно, такое значение разберет - """"? По идее это символ "
|
|||
35
Живой Ископаемый
04.12.08
✎
12:54
|
(34) Давай проверим, что я где пишу?:
http://docs.google.com/Doc?id=df8g2nxh_167g3rx67hn |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |