Имя: Пароль:
1C
 
Разбить строку на подстроки, но хитро... (внутри подробности)
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
ладно, попробую сейчас
http://www.connectionstrings.com/textfile
расскажу
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
Программист всегда исправляет последнюю ошибку.