Имя: Пароль:
1C
1С v8
Чем загрузить "сложный" CSV ?
,
0 Smallrat
 
31.05.13
13:47
Есть вот такой CSV, в котором встречаются такие штуки: разделитель в поле и перевод строки (LF) в поле. Excel умудряется такой файл корректно  прочитать.
Чем его можно загрузить в таблицу значений ? Файл довольно большой - 140000 строк.
пробовал через ADODB: http://infostart.ru/public/98398/ несмотря на то что заявлено что "Файлы с кавычкими и вложенными запятым обрабатываются верно" - у меня поле с разделителем раскидывает в два поля, ну и перевод строки считает за новую строку.
Мучался, мучался - так и не получилось изменить поведение. Мутить чтение через excel? долго наверное будет, да и муторно. Может есть у кого работающий код?
1 NWsFF
 
31.05.13
13:50
Код не сохранился, делал это на регулярных выражениях, вся соль в самом регулярном выражении, правда у меня перевода строки не было в полях, так что копай в строну регулярок.
2 zladenuw
 
31.05.13
13:52
(0) а если конвертнуть его в ексель. а дальше читать через адо ?
3 Serginio1
 
31.05.13
13:56
4 Serginio1
 
31.05.13
13:58
5 Smallrat
 
31.05.13
14:00
(1) регулярки... не доводилось щупать, но попробую если не найду способа попроще
(2) думаю долго будет, сперва он будет в эксель грузится, потом его оттуда читать построчно. хотя он сразу читает всё верно.
(3) щас зачту
6 Smallrat
 
31.05.13
14:20
(4) не отлавливает чтото разделитель и LF в поле (

попробую этот код из книги Книга знаний: Преобразование csv в таблицу значений
если не взлетит - приедтся наверное браться за регулярки
7 Serginio1
 
31.05.13
14:31
А как пишешь?
ExtractFields(S,aList,Delimiter,QuoteChar) ?
Ты должен подать на вход строку S, массив aList. Функция заполнит массив
8 Smallrat
 
31.05.13
14:41
(7) мда, невнимательно скопипастил.
Теперь разделитель правильно находит и колнки делит правильно.
А вот с переводом строки выдает ошибку "Нет закрывающей скобки" (
9 Smallrat
 
31.05.13
14:42
щас или вечером попробую допилить
10 Serginio1
 
31.05.13
15:54
(8) Ты должен подать на вход строку без перевода строки.
Обычно это делается через чтение файла.
Функция ИзСтрокиСРазделителями(S,Delimiter=",",QuoteChar="""") Экспорт
   перем aList;
   ExtractFields(S,aList,Delimiter,QuoteChar);    
   Возврат aList
КонецФункции

Текст=Новый ЧтениеТекста(Файл,"windows-1251");

Стр = Текст.ПрочитатьСтроку();
       Пока Стр <> Неопределено Цикл
МассивЗначений=ИзСтрокиСРазделителями(Стр,РазделительПолей,ОграничительСтрок);
КонецЦикла
11 Serginio1
 
31.05.13
15:55
Стр = Текст.ПрочитатьСтроку();
       Пока Стр <> Неопределено Цикл
МассивЗначений=ИзСтрокиСРазделителями(Стр,РазделительПолей,ОграничительСтрок);
Стр = Текст.ПрочитатьСтроку();
КонецЦикла
12 Smallrat
 
31.05.13
16:53
что-то у меня не распознает конец строки ((
Стр = ЧтениеТекста.ПрочитатьСтроку(Символы.ВК+Символы.ПС);
считывает весь оставшийся текст.


Стр = ЧтениеТекста.ПрочитатьСтроку();
разбивает строку с LF (он же Символы.ПС) на несколько
13 Serginio1
 
31.05.13
16:55
То есть у тебя LF это разделитель колонок?
14 Smallrat
 
31.05.13
16:58
(13) не - разделитель колонок точка с запятой - ";"
сама колонка порой представляет многострочный текст - внутри строки разделяются LF, в то время как строки таблицы отделяются CR+LF
вот и я не могу заставить ЧтениеТекста разделять строки друг от друга по CR+LF
15 Serginio1
 
31.05.13
17:00
Можно попробовать двумя способами справится
Либо СтрЗаменить(ИсходныйТекст,Символ.ПС,"")
или

Для Счетчик = 1 По СтрЧислоСтрок(ИсходныйТекст) Цикл
   ТекСтрока = СтрПолучитьСтроку(ИсходныйТекст, Счетчик);
   ...
КонецЦикла;

Сейчас алгоритм посмотрю
16 Serginio1
 
31.05.13
17:03
Что выдает СтрДлина(S) для строки содержащей LF?
17 Smallrat
 
31.05.13
17:05
(15) щас попробую
(16) у меня не получается ее получить - либо он ее обрезает по LF, либо в строке весь текст файла.
18 Serginio1
 
31.05.13
17:13
А у тебя точно разделитель  CR+LF?

Я обчно в таких ситуация в Попытке исключение ловлю исключение и склеиваю строки
19 Smallrat
 
31.05.13
17:13
не успел на работе, буду дома пробовать
20 Smallrat
 
31.05.13
17:15
вот примерно так выглядит
http://savepic.net/3770423.png
21 Serginio1
 
31.05.13
17:58
Можно попробовать
Новый ЧтениеТекста(<ИмяФайла>, <Кодировка>, <РазделительСтрок>, <КонвертируемыйРазделительСтрок>, <МонопольныйРежим>)

<КонвертируемыйРазделительСтрок> (необязательный)

Тип: Строка.
Определяет разделение строк в файле для конвертации в стандартный перевод строк ПС.
Значение по умолчанию: ВК + ПС.
Разделитель задается в КонвертируемыйРазделительСтрок
А разделитель строк ПС.

Можно Ради интереса попробовать
Новый ЧтениеТекста(ИмяФайла, Кодировка,Символы.ВК, Символы.ВК+Символы.ПС, <МонопольныйРежим>)

Просто получается внутри переводом строки уже является ПС.
Вообще замутили они с этими переносами. Без пол литра не обойтись.
22 Smallrat
 
31.05.13
18:26
>>Без пол литра не обойтись.

это еще упрощенный пример. сам файл настолько долбанутый, что у меня чуть руки не опустились.
ладно бы один раз надо было грузануть - я бы его поконвертировал в чтото удобное, а надо постоянную загрузку написать.

вот шапка так вылядит

;Прайс-лист;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;"ООО ""Компания компания""";;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;В валютах цен.;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Цены указаны на 22.05.2013;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Ценовая группа/ Номенклатура/ Характеристика номенклатуры;Номенклатура.Код;Номенклатура.Артикул;Номенклатура.Наименование;Номенклатура.Полное наименование;Номенклатура.Группа;Номенклатура.Бренд;Номенклатура.Группа.Код;Номенклатура.Группа.Группа;Номенклатура.Группа.Группа.Код;Номенклатура.Группа.Группа.Группа;Номенклатура.Группа.Группа.Группа.Код;Номенклатура.Группа.Группа.Группа.Группа;Номенклатура.Группа.Группа.Группа.Группа.Код;Номенклатура.Группа.Группа.Группа.Группа.Группа;Номенклатура.Группа.Группа.Группа.Группа.Группа.Код;Номенклатура.Группа.Группа.Группа.Группа.Группа.Группа;Номенклатура.Группа.Группа.Группа.Группа.Группа.Группа.Код;Номенклатура.Группа.Группа.Группа.Группа.Группа.Группа.Группа;Номенклатура.Группа.Группа.Группа.Группа.Группа.Группа.Группа.Код;Номенклатура.Единица хранения остатков;Номенклатура.Единица хранения остатков.Объем;Номенклатура.Количество в упаковке;Номенклатура.Количество на паллете;Номенклатура.Единица хранения остатков.Длина;Номенклатура.Единица хранения остатков.Высота;Номенклатура.Единица хранения остатков.Ширина;Розничная;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;Цена;Ед.

причем в "описании" структуры количество колонок из-за какой-то ошибки меньше чем в структуре, в конце должно быть Розничная Цена;Ед.
я аж прифигел когда такой "csv" увидел
23 Kreont
 
31.05.13
18:26
CSV - файл не правильный, сделай без переносов и все пойдет.

wiki:CSV

CSV (от англ. Comma-Separated Values — значения, разделённые запятыми) — текстовый формат, предназначенный для представления табличных данных. Каждая строка файла — это одна строка таблицы.
24 Smallrat
 
31.05.13
18:32
(23) в самой вики кстати в первом же примере csv с переносами и запятыми в полях.
25 Kreont
 
31.05.13
18:37
(24) ну я например пишу импорт, только из правильных CSV, а если какойто прогер, тот что например мне хочеть втулить "свой" вариант реализации CSV идет или лесом, или сам меняет свою программу. Без вариантов. А ложиться под чужие кривые форматы просто глупо.
26 Kreont
 
31.05.13
18:39
(24) вики правят добровольцы, как видишь неудачно, тут уж ничего не поделаешь
Ищи оригинал RFC, для стандарта CSV, его и покажи автору твоего CSV, пусть правит.
27 Kreont
 
31.05.13
18:42
http://www.rfc-editor.org/rfc/rfc4180.txt
и самое главное:
1.  Each record is located on a separate line, delimited by a line break (CRLF)
28 Smallrat
 
31.05.13
18:43
(25) задача пока поставлена грузить из чего есть - и прогера там нет, это похоже на какую-ту стандартную конвертацию отчета  "прайс-лист" из УТ, ее манагеры делают и ничео другого, окромя mxl прислать не могут.
29 Smallrat
 
31.05.13
18:46
6.  Fields containing line breaks (CRLF), double quotes, and commas
      should be enclosed in double-quotes.  For example:

      "aaa","b CRLF
      bb","ccc" CRLF
      zzz,yyy,xxx

у меня правда не CRLF а просто LF
30 Kreont
 
31.05.13
18:51
(29) прикольно, я так далеко не читал ))), ну дай им рфс без 6-го пункта :)
Значит не повезло тебе с файлом, уменя такие ниразу не попадались, придется писать.
31 Jaap Vduul
 
31.05.13
19:07
>> пробовал через ADODB
Покажь свой schema.ini
32 Smallrat
 
31.05.13
19:21
Примерно так:
[222.csv]
ColNameHeader=False
Format=Delimited(;)
TextDelimiter=none
CharacterSet=ANSI
Col1=Field1 Text
Col2=Field2 Text
33 Ковычки
 
31.05.13
19:25
заменить перевод строки на пробел
34 Smallrat
 
31.05.13
19:37
(33) как бы этот перевод строки отличить от возврата каретки. чтото у меня пока не получается.
35 Ковычки
 
31.05.13
19:43
(34) СтрЗаменить(СтрЗаменить(Стр,Символы.ПС," "),Символы.ВК,Символы.ВК+Символы.ПС);
36 Ковычки
 
31.05.13
19:43
хотя х.з. как это в объекте текст
37 Smallrat
 
31.05.13
19:46
(35) ну в принципе можно - эт получается что сначала надо весь 50мегабайтный файл считать, заменить символы, записать, а потом снова распарсить уже как нормальный csv. янадо по времени замерить
38 Smallrat
 
31.05.13
19:46
(36) в чтении текста пока не получается (
39 Ковычки
 
31.05.13
19:47
Стр="аываыва"+Символы.ВК+Символы.ПС+"sdfsdsdfsd"+Символы.ПС+"ваываываыв";
   Сообщить(СтрЗаменить(СтрЗаменить(Стр,Символы.ПС," "),Символы.ВК,Символы.ВК+Символы.ПС));
40 Smallrat
 
31.05.13
20:16
Внезапно получилось так:
ЧтениеТекста  = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.ANSI,Символы.ВК, Символы.ПС - тут может быть любой символ кроме Символы.ВК);
правда каждая строка, получаемая из файла теперь впереди с переводом каретки (или строки, я пока не понял), но СокрЛ() это правит

то есть http://savepic.net/3743815.png
первая строка считывается как:
клиент;адрес
а вторая как
"ИП Ив
анов А.А.";"Москва;ул.Ленина;53"
41 Smallrat
 
31.05.13
20:18
млииин - все же в (21) написано, вот я балда
42 Smallrat
 
31.05.13
20:19
а нет - как раз так у меня не получилось
Новый ЧтениеТекста(ИмяФайла, Кодировка,Символы.ВК, Символы.ВК+Символы.ПС, <МонопольныйРежим>)

вместо Символы.ВК+Символы.ПС надо любое другое указать но без
Символы.ВК
43 Serginio1
 
31.05.13
20:25
(40) Чесно говоя я такие файлы на C# обработываю http://www.rsdn.ru/forum/dotnet/3303143.1
44 Serginio1
 
31.05.13
20:29
А если ничего не указываь?
45 Ковычки
 
31.05.13
20:30
балда ты, давай файл
46 Serginio1
 
31.05.13
20:33
То есть что получается при
Новый ЧтениеТекста(ИмяФайла, Кодировка,Символы.ВК)
Там по умлчанию  Символы.ВК+Символы.ПС
При указании Символы.ПС она отработывает только Символы.ПС.
То есть если символ идет сначала строки то у тебя Символы.ПС+Символы.ВК
47 Smallrat
 
31.05.13
20:35
48 Serginio1
 
31.05.13
20:35
нет спереди у тебя стоит как раз Символы.ПС
49 Serginio1
 
31.05.13
20:38
А что делается если указать Символы.ВК+Символы.ПС
50 Smallrat
 
31.05.13
20:40
(48) ага. правда я вот понимаю что разделить получилось только потому что у меня перенос идет только одним символом LF, в то время как по RFC двумя и все  задается только кавычками   -типа так
"aaa","b CRLF
      bb","ccc" CRLF
      zzz,yyy,xxx

(49) весь файл в одну строку сваливается
клиент;адрес
"ИП Ив
анов А.А.";"Москва;ул.Ленина;53"
51 Ковычки
 
31.05.13
20:48
Текст=Новый ТекстовыйДокумент;
   Текст.Прочитать("C:\Users\ginzburg\Downloads\333.csv");
   Сообщить(СтрЗаменить(СтрЗаменить(Текст.ПолучитьТекст(),Символы.ПС," "),Символы.ВК,Символы.ВК+Символы.ПС));
52 Smallrat
 
31.05.13
21:00
(51) вот так получилось клиент;адрес  "ИП Ив анов А.А.";"Москва;ул.Ленина;53"
53 Serginio1
 
31.05.13
21:06
Ну до к этому и здесь пришли http://www.1c-pro.ru/topic50801.html
54 Ковычки
 
31.05.13
21:13
ФСО=Новый COMОбъект("Scripting.FileSystemObject");
   Текст=ФСО.OpenTextFile("C:\Users\ginzburg\Downloads\333.csv");
   Стр="";
   Пока Не Текст.AtEndOfStream Цикл
       Симв=Текст.Read(1);
       Если Не Симв=Символы.ПС Тогда
           Стр=Стр+Симв;
       ИначеЕсли Симв=Символы.ВК Тогда
           Стр=Стр+Символы.ВК+Символы.ПС;
       КонецЕсли;
   КонецЦикла;
55 Jaap Vduul
 
31.05.13
23:29
(32)
Убери или закомментируй строку "TextDelimiter=none" и всё.
56 Serginio1
 
31.05.13
23:50
55+ http://it-proposition.blogspot.ru/2011/08/schemaini-microsoftaceoledb120.html
TextDelimiter - определяет символ, которым отделяется текст. По умолчанию "
57 Serginio1
 
01.06.13
12:37
56 + но при этом часто бывает, что файла не всегда корректные и приходится их дорабатывать своими парсерами
58 Smallrat
 
03.06.13
22:52
(54) посимвольное чтение ? это ж я поседею в процессе.

(55) бинго! ну еклмн, как все просто....

(57) вроде бы 40 мегабайт csv загрузились корректно, на первый взгляд, щас напишу обработку таблицы и там видно будет.

Всем большое спасибо! не оставили в беде )))
59 Eugeneer
 
03.06.13
22:56
(58) вот готовое - гарантируем работу
http://subsystems.ru/catalog/27/158/
Читайет эксель и CSV напрямую - своя суперкомпонента. Скорость считывания 100 000 за 1 минуту.
60 zak555
 
03.06.13
22:59
(59) что за суперко
61 zak555
 
03.06.13
23:00
и что за 500 придурков, которые вечно что-то грузят из эксель  ?
62 Eugeneer
 
03.06.13
23:03
(61) ;))
63 Serginio1
 
04.06.13
11:05
(59) 100 000 на Это менее 1 секунды http://www.rsdn.ru/forum/dotnet/3303143.1
Минута это очень много.