-
Notifications
You must be signed in to change notification settings - Fork 0
/
ReadCSVToTable.bsl
106 lines (91 loc) · 5.85 KB
/
ReadCSVToTable.bsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
Функция ПрочитатьCSVФайлВТаблицу(ИмяФайла, Разделитель=";", КоличествоПервыхСтрокПропустить = 0, КоличествоКолонок = Неопределено)
ЧтениеТекста = Новый ЧтениеТекста(ИмяФайла, КодировкаТекста.UTF8 ,,,Ложь);
ТЗ = Новый ТаблицаЗначений;
Колонки = ТЗ.Колонки;
ОписаниеТиповСтрока = Новый ОписаниеТипов("Строка");
Если КоличествоКолонок <> Неопределено Тогда
Для НомерКолоки = 1 По КоличествоКолонок Цикл
Колонки.Добавить("Колонка"+НомерКолоки, ОписаниеТиповСтрока);
КонецЦикла;
КонецЕсли;
НомерСтроки = 1;
Стр = ЧтениеТекста.ПрочитатьСтроку();
Пока Стр <> Неопределено Цикл
Если НомерСтроки < 1 + КоличествоПервыхСтрокПропустить Тогда
Стр = ЧтениеТекста.ПрочитатьСтроку();
НомерСтроки = НомерСтроки + 1;
Продолжить;
КонецЕсли;
СтрокаТЗ = ТЗ.Добавить();
НомерПоля = 0;
Пока Стр <> "" Цикл
Токен = "";
ПозицияРазделителя = Найти(стр, Разделитель);
ПозицияОткрКавычек = Найти(стр, """");
//"";""
Если ПозицияОткрКавычек > 1 И Сред(стр, ПозицияОткрКавычек-1, 1) <> Разделитель Тогда
ПозицияОткрКавычек = 0;
КонецЕсли;
Если (ПозицияРазделителя > ПозицияОткрКавычек ИЛИ ПозицияРазделителя = 0) И ПозицияОткрКавычек > 0 Тогда
// начинающееся с кавычек читаем до тех пор
Токен = Лев(Стр, ПозицияОткрКавычек);
Стр = Сред(Стр, ПозицияОткрКавычек+1);
ПозицияДляПоискаЗакрКавычек = 1;
ПозицияЗакрКавычек = 0;
Пока ПозицияЗакрКавычек = 0 Цикл
Если СтрДлина(Стр) >= ПозицияДляПоискаЗакрКавычек Тогда
ПозицияЗакрКавычек = СтрНайти(Стр, """",,ПозицияДляПоискаЗакрКавычек);
КонецЕсли;
Если ПозицияЗакрКавычек > 0 И Сред(Стр,ПозицияЗакрКавычек + 1, 1) = """" Тогда
ПозицияДляПоискаЗакрКавычек = ПозицияЗакрКавычек + 2;
ПозицияЗакрКавычек = 0;
Продолжить; //это просто экранированная кавычка, а не кавычка закрывающее поле
ИначеЕсли ПозицияЗакрКавычек > 0 Тогда
Прервать;
Иначе
Токен = Токен + Стр + Символы.ПС;
НомерСтроки = НомерСтроки + 1;
Стр = ЧтениеТекста.ПрочитатьСтроку();
Если Стр = Неопределено Тогда
Стр = "";
Прервать; // файл закончился, закрывающую кавычку не нашли
КонецЕсли;
ПозицияДляПоискаЗакрКавычек = 1; // ищем с начала новой, полученной строки
КонецЕсли;
КонецЦикла;
Если СтрДлина(Стр) > ПозицияЗакрКавычек Тогда
ПозицияРазделителя=СтрНайти(Стр, Разделитель,,ПозицияЗакрКавычек + 1);
Иначе
ПозицияРазделителя = 0;
КонецЕсли;
КонецЕсли;
Если ПозицияРазделителя>0 Тогда
Токен = Токен + Лев(Стр, ПозицияРазделителя-1);
Стр = Сред(Стр, ПозицияРазделителя+1);
Иначе
Токен = Токен + Стр; // разделитель не нашли, добавляем оставшуюся часть строки
Стр = ""; // строка полностью обработана
КонецЕсли;
// Уберем экранирующие кавычки у поля, если они там были
Если Лев(Токен, 1) = """" Тогда
Токен = Сред(Токен, 2);
Токен = ?(Прав(Токен, 1) = """", Лев(Токен, СтрДлина(Токен)-1), Токен);
КонецЕсли;
// убираем двойные кавычки
Токен = СтрЗаменить(Токен, """""", """");
НомерПоля = НомерПоля + 1;
Если КоличествоКолонок = Неопределено Тогда
Если Колонки.Количество()<НомерПоля Тогда
Колонки.Добавить("Колонка"+НомерПоля, ОписаниеТиповСтрока);
КонецЕсли;
ИначеЕсли НомерПоля > КоличествоКолонок Тогда
Прервать;
КонецЕсли;
СтрокаТЗ[НомерПоля-1] = Токен;
КонецЦикла;
НомерСтроки = НомерСтроки + 1;
Стр = ЧтениеТекста.ПрочитатьСтроку();
КонецЦикла;
ЧтениеТекста.Закрыть();
Возврат ТЗ;
КонецФункции