Загрузка данных
// Функция принимает на вход сырой текст из файла и возвращает Массив Структур с разобранными данными.
// Требует платформу 1С не ниже 8.3.23!
Функция РаспарситьТекстБилетовНативно(Знач ТекстБилетов) Экспорт
Результат = Новый Массив;
// 1. Очистка от экранирующих кавычек
ТекстБилетов = СтрЗаменить(ТекстБилетов, """", "");
// 2. Разбиваем текст на строки и склеиваем "разорванные" записи
МассивСырыхСтрок = СтрРазделить(ТекстБилетов, Символы.ПС, Ложь);
МассивСтрок = Новый Массив;
// Компилируем основные регулярные выражения один раз (флаг (?i) делает их нечувствительными к регистру)
РегВырНачало = Новый РегулярноеВыражение("(?i)^(Авиабилет|Электронный|Ж/д|Автобусный|Сверхнормативный|Доплата|а/б)");
РегВырТип = Новый РегулярноеВыражение("(?i)^(Авиабилет|Электронный ж/д билет|Ж/д билет|Автобусный билет|Сверхнормативный багаж[^(]*|Доплата за обмен[^(]*|а/б)");
РегВырПеревозчик = Новый РегулярноеВыражение("(?i)\(\s*перевозчик\s*(.*?)(?:,\s*ИНН\s*(\d*))?\s*\)");
РегВырКласс = Новый РегулярноеВыражение("(?i)\((Эконом|Купе|Плацкарт|Сидячий)\)");
РегВырДата = Новый РегулярноеВыражение("(?i)(\d{2}\.\d{2}\.\d{4}(?:\/\d{2}\.\d{2}\.\d{4})?)");
РегВырПассажир = Новый РегулярноеВыражение("(?i)\s+([А-Яа-яЁёA-Za-z\-]+\s+[А-Яа-яЁёA-Za-z]+\s+[А-Яа-яЁёA-Za-z]+|[А-Яа-яЁёA-Za-z\-]+\s+[А-Яа-яЁёA-Za-z]\.?\s*[А-Яа-яЁёA-Za-z]\.?\.?)$");
РегВырНомерМаршрут = Новый РегулярноеВыражение("(?i)^([A-Za-z0-9\s/\.]+?)\s+([А-Яа-яЁёA-Za-z].*)$");
Для Каждого Стр Из МассивСырыхСтрок Цикл
СтрОчищ = СокрЛП(Стр);
Если ПустаяСтрока(СтрОчищ) Тогда
Продолжить;
КонецЕсли;
Если РегВырНачало.Совпадает(СтрОчищ) Тогда
// Это начало нового билета
МассивСтрок.Добавить(СтрОчищ);
Иначе
// Это продолжение предыдущей строки (например, перенос имени/проекта на новую строку)
Если МассивСтрок.Количество() > 0 Тогда
ИндексПоследней = МассивСтрок.ВГраница();
МассивСтрок[ИндексПоследней] = МассивСтрок[ИндексПоследней] + " " + СтрОчищ;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Для Каждого СтрокаБилета Из МассивСтрок Цикл
ДанныеБилета = Новый Структура;
ДанныеБилета.Вставить("ТипБилета", "");
ДанныеБилета.Вставить("Перевозчик", "");
ДанныеБилета.Вставить("ИНН", "");
ДанныеБилета.Вставить("НомерБилета", "");
ДанныеБилета.Вставить("Маршрут", "");
ДанныеБилета.Вставить("Дата", "");
ДанныеБилета.Вставить("Класс", "");
ДанныеБилета.Вставить("Пассажир", "");
ДанныеБилета.Вставить("ДопИнфо", "");
ДанныеБилета.Вставить("ИсходнаяСтрока", СтрокаБилета);
ОстатокСтроки = СтрокаБилета;
Результаты = Неопределено;
// ШАГ 1: Извлекаем ТИП билета
Результаты = РегВырТип.Найти(ОстатокСтроки);
Если Результаты.Количество() > 0 Тогда
ДанныеБилета.ТипБилета = СокрЛП(Результаты[0].Значение);
ОстатокСтроки = СокрЛП(Сред(ОстатокСтроки, Результаты[0].Длина + 1));
КонецЕсли;
// ШАГ 2: Извлекаем ПЕРЕВОЗЧИКА и ИНН
Результаты = РегВырПеревозчик.Найти(ОстатокСтроки);
Если Результаты.Количество() > 0 Тогда
Группы = Результаты[0].Группы;
// В 1С Группы нумеруются с 0 для первой захваченной подстроки (...)
Если Группы.Количество() > 0 И Группы[0] <> Неопределено Тогда
ДанныеБилета.Перевозчик = СокрЛП(Группы[0].Значение);
КонецЕсли;
Если Группы.Количество() > 1 И Группы[1] <> Неопределено Тогда
ДанныеБилета.ИНН = СокрЛП(Группы[1].Значение);
КонецЕсли;
ОстатокСтроки = СокрЛП(СтрЗаменить(ОстатокСтроки, Результаты[0].Значение, ""));
КонецЕсли;
// ШАГ 3: Извлекаем КЛАСС обслуживания
Результаты = РегВырКласс.Найти(ОстатокСтроки);
Если Результаты.Количество() > 0 Тогда
Если Результаты[0].Группы.Количество() > 0 И Результаты[0].Группы[0] <> Неопределено Тогда
ДанныеБилета.Класс = СокрЛП(Результаты[0].Группы[0].Значение);
КонецЕсли;
ОстатокСтроки = СокрЛП(СтрЗаменить(ОстатокСтроки, Результаты[0].Значение, ""));
КонецЕсли;
// ШАГ 4: Извлекаем ДАТУ, ПАССАЖИРА и ДОП. ИНФОРМАЦИЮ
Результаты = РегВырДата.Найти(ОстатокСтроки);
Если Результаты.Количество() > 0 Тогда
ДанныеБилета.Дата = Результаты[0].Значение;
ПозицияДаты = СтрНайти(ОстатокСтроки, ДанныеБилета.Дата);
Хвост = СокрЛП(Сред(ОстатокСтроки, ПозицияДаты + СтрДлина(ДанныеБилета.Дата)));
ОстатокСтроки = СокрЛП(Лев(ОстатокСтроки, ПозицияДаты - 1)); // Отрезаем от остатка
// Разделяем Пассажира и ДопИнфо по первой запятой
ПозЗапятой = СтрНайти(Хвост, ",");
Если ПозЗапятой > 0 Тогда
ДанныеБилета.Пассажир = СокрЛП(Лев(Хвост, ПозЗапятой - 1));
ДанныеБилета.ДопИнфо = СокрЛП(Сред(Хвост, ПозЗапятой + 1));
Иначе
ДанныеБилета.Пассажир = Хвост;
КонецЕсли;
Иначе
// Бездатные билеты - ищем ФИО с конца строки
Результаты = РегВырПассажир.Найти(ОстатокСтроки);
Если Результаты.Количество() > 0 Тогда
Если Результаты[0].Группы.Количество() > 0 И Результаты[0].Группы[0] <> Неопределено Тогда
ДанныеБилета.Пассажир = СокрЛП(Результаты[0].Группы[0].Значение);
КонецЕсли;
ОстатокСтроки = СокрЛП(Лев(ОстатокСтроки, СтрДлина(ОстатокСтроки) - Результаты[0].Длина));
КонецЕсли;
КонецЕсли;
// ШАГ 5: Разделяем оставшееся на НОМЕР БИЛЕТА и МАРШРУТ
ОстатокСтроки = СтрЗаменить(ОстатокСтроки, "Квитанция №", "");
ОстатокСтроки = СтрЗаменить(ОстатокСтроки, "к билету №", "/ ");
ОстатокСтроки = СтрЗаменить(ОстатокСтроки, "Исходный а/б №", "");
ОстатокСтроки = СтрЗаменить(ОстатокСтроки, "Новый а/б №", "/ ");
ОстатокСтроки = СтрЗаменить(ОстатокСтроки, "а/б №", "");
ОстатокСтроки = СтрЗаменить(ОстатокСтроки, "№", "");
ОстатокСтроки = СокрЛП(ОстатокСтроки);
Результаты = РегВырНомерМаршрут.Найти(ОстатокСтроки);
Если Результаты.Количество() > 0 Тогда
Группы = Результаты[0].Группы;
Если Группы.Количество() > 0 И Группы[0] <> Неопределено Тогда
ДанныеБилета.НомерБилета = СокрЛП(Группы[0].Значение);
КонецЕсли;
Если Группы.Количество() > 1 И Группы[1] <> Неопределено Тогда
ДанныеБилета.Маршрут = СокрЛП(Группы[1].Значение);
КонецЕсли;
Иначе
ДанныеБилета.НомерБилета = ОстатокСтроки;
КонецЕсли;
Результат.Добавить(ДанныеБилета);
КонецЦикла;
Возврат Результат;
КонецФункции