Загрузка данных



    // Упаковываем шаблоны (строки) регулярных выражений в структуру.
    // (?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)^([A-Za-z0-9\s/\.\-]+?)\s+([А-Яа-яЁёA-Za-z].*)$");
    
    // Шаблон для бездатных билетов: строго извлекает "Номер", "Маршрут" и "ФИО" (с инициалами или из 3-х слов)
    Шаблоны.Вставить("Бездатный",    "(?i)^([A-Za-z0-9\s/\.\-]+?)\s+(.*?)\s+([А-Яа-яЁёA-Za-z\-]+\s+[А-Яа-яЁёA-Za-z]\s*\.?\s*[А-Яа-яЁёA-Za-z]\s*\.*|[А-Яа-яЁёA-Za-z\-]+\s+[А-Яа-яЁёA-Za-z\-]+\s+[А-Яа-яЁёA-Za-z\-]+)\s*$");
    
    // Мусор для очистки номеров
    Шаблоны.Вставить("МусорСлеш",    "(?i)(к билету\s*№|Новый а/б\s*№)");
    Шаблоны.Вставить("МусорУдалить", "(?i)(Квитанция\s*№|Исходный а/б\s*№|а/б\s*№|№)");
    


// Выполняет пошаговый разбор одной склеенной строки билета
Функция РаспарситьСтрокуБилета(Знач СтрокаБилета, Шаблоны)
    
    ДанныеБилета = Новый Структура;
    ДанныеБилета.Вставить("ТипБилета", "");
    ДанныеБилета.Вставить("Перевозчик", "");
    ДанныеБилета.Вставить("ИНН", "");
    ДанныеБилета.Вставить("НомерБилета", "");
    ДанныеБилета.Вставить("Маршрут", "");
    ДанныеБилета.Вставить("Дата", "");
    ДанныеБилета.Вставить("Класс", "");
    ДанныеБилета.Вставить("Пассажир", "");
    ДанныеБилета.Вставить("ДопИнфо", "");
    ДанныеБилета.Вставить("ИсходнаяСтрока", СтрокаБилета); 
    
    ОстатокСтроки = СтрокаБилета;
    
    // ШАГ 1: Тип билета
    ДанныеБилета.ТипБилета = ИзвлечьТипБилета(ОстатокСтроки, Шаблоны.Тип);
    
    // ШАГ 2: Перевозчик и ИНН
    ЗаполнитьЗначенияСвойств(ДанныеБилета, ИзвлечьПеревозчикаИИнн(ОстатокСтроки, Шаблоны.Перевозчик));
    
    // ШАГ 3: Класс обслуживания
    ДанныеБилета.Класс = ИзвлечьКлассБилета(ОстатокСтроки, Шаблоны.Класс);
    
    // ШАГ 4 и 5: Обработка оставшейся строки (Дата, Пассажир, ДопИнфо, Номер, Маршрут)
    ДанныеОстатка = РазобратьОстатокБилета(ОстатокСтроки, Шаблоны);
    ЗаполнитьЗначенияСвойств(ДанныеБилета, ДанныеОстатка);
    
    Возврат ДанныеБилета;

КонецФункции

// --- ШАГ 1: ТИП БИЛЕТА ---
Функция ИзвлечьТипБилета(ОстатокСтроки, ШаблонТип)
    ТипБилета = "";
    
    РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ОстатокСтроки, ШаблонТип);
    Если РезультатПоиска <> Неопределено Тогда
        Блок = РезультатПоиска.Значение;
        ТипБилета = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, ШаблонТип, "$1"));
        ОстатокСтроки = СокрЛП(Сред(ОстатокСтроки, РезультатПоиска.Длина + 1));
    КонецЕсли;
    
    Возврат ТипБилета;
КонецФункции

// --- ШАГ 2: ПЕРЕВОЗЧИК И ИНН ---
Функция ИзвлечьПеревозчикаИИнн(ОстатокСтроки, ШаблонПеревозчик)
    Результат = Новый Структура("Перевозчик, ИНН", "", "");
    
    РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ОстатокСтроки, ШаблонПеревозчик);
    Если РезультатПоиска <> Неопределено Тогда
        Блок = РезультатПоиска.Значение;
        
        Результат.Перевозчик = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, ШаблонПеревозчик, "$1"));
        ТекстИНН = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, ШаблонПеревозчик, "$2"));
        Результат.ИНН = СтрЗаменить(ТекстИНН, "$2", ""); 
        
        ОстатокСтроки = СокрЛП(СтрЗаменить(ОстатокСтроки, Блок, ""));
    КонецЕсли;
    
    Возврат Результат;
КонецФункции

// --- ШАГ 3: КЛАСС ОБСЛУЖИВАНИЯ ---
Функция ИзвлечьКлассБилета(ОстатокСтроки, ШаблонКласс)
    КлассБилета = "";
    
    РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ОстатокСтроки, ШаблонКласс);
    Если РезультатПоиска <> Неопределено Тогда
        Блок = РезультатПоиска.Значение;
        КлассБилета = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, ШаблонКласс, "$1"));
        ОстатокСтроки = СокрЛП(СтрЗаменить(ОстатокСтроки, Блок, ""));
    КонецЕсли;
    
    Возврат КлассБилета;
КонецФункции

// --- ШАГ 4 и 5: ДАТА, НОМЕР, МАРШРУТ, ФИО ---
Функция РазобратьОстатокБилета(Знач ОстатокСтроки, Шаблоны)
    Результат = Новый Структура("Дата, Пассажир, ДопИнфо, НомерБилета, Маршрут", "", "", "", "", "");
    
    // Очищаем мусор перед номерами (№, Квитанция и т.д.)
    ОстатокСтроки = СтрЗаменитьПоРегулярномуВыражению(ОстатокСтроки, Шаблоны.МусорСлеш, "/ ");
    ОстатокСтроки = СтрЗаменитьПоРегулярномуВыражению(ОстатокСтроки, Шаблоны.МусорУдалить, "");
    ОстатокСтроки = СокрЛП(ОстатокСтроки);
    
    РезультатПоискаДата = СтрНайтиПоРегулярномуВыражению(ОстатокСтроки, Шаблоны.Дата);
    Если РезультатПоискаДата <> Неопределено Тогда
        
        // ------------------ БИЛЕТ С ДАТОЙ ------------------
        Результат.Дата = РезультатПоискаДата.Значение;
        
        // Разбиваем строку на две части (до даты и после)
        ПозицияДаты = СтрНайти(ОстатокСтроки, Результат.Дата);
        Хвост = СокрЛП(Сред(ОстатокСтроки, ПозицияДаты + СтрДлина(Результат.Дата)));
        СтрокаНомерМаршрут = СокрЛП(Лев(ОстатокСтроки, ПозицияДаты - 1)); 
        
        // Разбор хвоста на ФИО и ДопИнфо
        ПозЗапятой = СтрНайти(Хвост, ",");
        Если ПозЗапятой > 0 Тогда
            Результат.Пассажир = СокрЛП(Лев(Хвост, ПозЗапятой - 1));
            Результат.ДопИнфо  = СокрЛП(Сред(Хвост, ПозЗапятой + 1));
        Иначе
            Результат.Пассажир = Хвост;
        КонецЕсли;
        
        // Разбор начала на Номер и Маршрут
        РезультатПоискаНМ = СтрНайтиПоРегулярномуВыражению(СтрокаНомерМаршрут, Шаблоны.НомерМаршрут);
        Если РезультатПоискаНМ <> Неопределено Тогда
            Блок = РезультатПоискаНМ.Значение;
            Результат.НомерБилета = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, Шаблоны.НомерМаршрут, "$1"));
            
            ТекстМаршрута = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, Шаблоны.НомерМаршрут, "$2"));
            Результат.Маршрут = СтрЗаменить(ТекстМаршрута, "$2", "");
        Иначе
            Результат.НомерБилета = СтрокаНомерМаршрут;
        КонецЕсли;
        
    Иначе
        
        // ------------------ БИЛЕТ БЕЗ ДАТЫ ------------------
        РезультатПоискаБездатный = СтрНайтиПоРегулярномуВыражению(ОстатокСтроки, Шаблоны.Бездатный);
        Если РезультатПоискаБездатный <> Неопределено Тогда
            Блок = РезультатПоискаБездатный.Значение;
            
            Результат.НомерБилета = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, Шаблоны.Бездатный, "$1"));
            
            ТекстМаршрута = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, Шаблоны.Бездатный, "$2"));
            Результат.Маршрут = СтрЗаменить(ТекстМаршрута, "$2", "");
            
            ТекстПассажира = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Блок, Шаблоны.Бездатный, "$3"));
            Результат.Пассажир = СтрЗаменить(ТекстПассажира, "$3", "");
        Иначе
            // На случай, если строка вообще нестандартная
            Результат.НомерБилета = ОстатокСтроки;
        КонецЕсли;
        
    КонецЕсли;
    
    Возврат Результат;
КонецФункции