Возникла необходимость в приведении к единому формату хранящихся, и вводимых вновь, автомобильных Регистрационных знаков - Гос.номер.
Понятно, что нужно было оттолкнуться от какого-то стандарта. По-google-в по интересующему вопросу, стало очевидным, что Гос.номера можно систематизировать по буквенно-цифровым последовательностям, из которых состоят номера. К тому же, эти буквенно-цифровые последовательности, оказались относительно уникальными. В редких случаях были замечены совпадения, но это оказалось вполне допустимым:)
Было принято решение прибегнуть к условному кодированию Типа Гос.номера и его Формата, т.е. местоположения и типа разделителей.
1. Код Типа Гос.номера, или его буквенно-цифровой последовательности:
Описывает последовательность парами цифр,
Первая цифра - Количество символов в последовательности
Вторая цифра - Тип символа: 0 - Буква; 1 - Цифра;
Пример: Гос.номер "С 065 МК 78" - имеет последовательность: одна(1)буква(0), три(3)цифры(1), две(2)буквы(0), две(2)цифры(1).
В итоге получаем - 10312021 - Код типа номера для "С 065 МК 78"
2. КодФормата
Описывает непрерывные буквенно-цифровые блоки, отделённые друг от друга условным разделителем.
Каждый такой блок описывается одной цифрой, и содержит информацию о количество символов в блоке.
2.1. Разделителем по-умолчанию является пробел.
2.2. Можно задать любой разделитель, в любом месте.
Пример 1:
Формат вывода для Гос.номера "С 065 МК 78" можно описать так:
Один(1)символ [пробел] Три(3)символа [пробел] Два(2)символа [пробел] Два(2)символа
т.е. - "1322"
Пример 2:
На входе имеем последовательность - "1234АВ 7" - Белорусский номер общего назначения.
Соответственно её Код - "412011"
Нам нужен "КодФормата" с раделителем "тире", отделяеющим последнюю цифру:
Четыре(4)символа [пробел] Два(2)символа Тире[-] Один(1)символ
т.е. - "42-1" - На выходе получим: "1234 АВ-7":
Пример 3:
Необходимо представить Гос.номер "А 733 АН 152" слитно, отделив пробелом только цифры региона - "А733АН 152"
"КодФормата" будет таким - "63"
Примечания:
Примечание 1:
Сумма чисел в "КодФормата" соответствует количеству символов в Гос.Номере
Примечание 2:
Во входящей строке игнорируются любые символы кроме букв (принятых для использования в Гос.номерах) и цифр.
Примечание 3.
Если функция не может отформатировать строку, она вернет не форматированную строку так, как она была передана в функцию.
Примечание 4.
Все буквенные символы в возвращаемой строке по-умолчанию приводятся к Верхнему регистру.
В качестве необязательного параметра можно передать Булево - Ложь
В этом случае буквенные символы будут приведены к Нижнему регистру.
Примечание 5:
Ниже приведена таблица, которая положена в основу работы этой функции.
В таблице перечислены те типы Гос.номеров, которые вошли в круг внимания.
Соответственно она может быть легко дополнена.
Описание Колонок:
"Принадлежность" - Общие сведения, Страна, Струкрура ets.
"Описание" - Дополнительные сведения о формате номера
"Стандарт" - Формат Гос.Номера, как он описан в нормативных документах
"Код" - Код буквенно-цифровой последовательности Гос.Номера
"ФорматВид" - Представление формата выходной строки (шаблон)
"КодФормата"- Код, описывающий формат Строки
Для получения дополнительной информации о "распознанном" Гос.номере, Таблицу можно обернуть в Справочник или иное, пополняемое/редактируемое хранилище.
В данной реализации дело обошлось "Соответствием".
Принадлежность | Описание | Стандарт | Код | ФорматВид | КодФормата |
Беларусь | Общие | 1234 АВ-7 | 412011 | 1234 АВ-7 | 42-1 |
Дипломатические | T — для транспортных средств сотрудников дипломатического представительства без дипломатического статуса D — для транспортных средств сотрудников дипломатического представительства имеющих дипломатический статус. |
002 Т003 78 | 311051 | 002 Т003 78 | 342 |
Дипломатические | посла или других глав дипломатического представительства | 002 CD1 78 | 312031 | 002 CD1 78 | 332 |
Италия | Общие | CZ 898 NF | 203120 | CZ 898 NF | 232 |
Казахстан | Общие | R 123 KMN | 103130 | R 123 KMN | 133 |
Россия | МВД России | А 1234 78 | 1061 | А1234 78 | 52 |
Россия | такси и общественный транспорт | АО 365 78 | 2051 | АО365 78 | 52 |
Россия | прицепы | ОА 1234 78 | 2061 | ОА1234 78 | 62 |
Россия | военные | 0245 ОК 43 | 412021 | 0245 ОК 43 | 422 |
Россия | Общие | С 065 МК 78 | 10312021 | С065МК 78 | 62 |
Россия | Общие | А 733 АН 147 | 10312031 | А733АН 147 | 63 |
Россия | МВД России прицепы | 123 А 39 | 311021 | 123 А 39 | 312 |
Транзитные | Транзитный транспорт | СМ 655 К 78 | 20311021 | СМ 655 К 78 | 2312 |
Узбекистан | Общие | 00 А123NN UZ | 21103140 | 00 А123NN UZ | 262 |
Украина | Общие | АК 1234 АВ | 204120 | АК 1234 АВ | 242 |
Экпортные | Экспортируемый транспорт | Т АО 002 78 | 3051 | Т АО 002 78 | 1232 |
// Функция - Формат гос номера автомобиля
//
// Параметры:
// Параметр - Строка, предположительно содержит Гос.номер автомобиля
// ВерхРегистр - Булево (необязательный)
// Истина - в выходной строке Буквы в верхнем регистри
// Ложь - в выходной строке Буквы в нижнем регистре
//
// Возвращаемое значение:
// - Строка - Отформатированный Гос.Номер автомобиля.
//
// Programmer: Andrey Arsentev, march 2019
Функция ФорматГосНомераАвтомобиля(Параметр,ВерхРегистр = Истина) Экспорт
Если НЕ ЗначениеЗаполнено(Параметр) Тогда
Возврат Параметр;
Иначе
Результат = ВРег(СокрЛП(Параметр));
КонецЕсли;
// 0. Инициализируем Соответствие Форматов
ФорматНомера = Новый Соответствие;
ФорматНомера.Вставить("1061","52");
ФорматНомера.Вставить("2051","52");
ФорматНомера.Вставить("2061","62");
ФорматНомера.Вставить("3051","1232");
ФорматНомера.Вставить("103130","133");
ФорматНомера.Вставить("203120","232");
ФорматНомера.Вставить("204120","242");
ФорматНомера.Вставить("311021","312");
ФорматНомера.Вставить("311051","342");
ФорматНомера.Вставить("312031","332");
ФорматНомера.Вставить("412011","42-1");
ФорматНомера.Вставить("412021","422");
ФорматНомера.Вставить("10312021","62");
ФорматНомера.Вставить("10312031","63");
ФорматНомера.Вставить("20311021","2312");
ФорматНомера.Вставить("21103140","262");
Буфер = "";
Буквы = 0;
Цифры = 0;
КодНомера = "";
// 1. Получаем из Строки Код буквенно-цифровой последовательности
Для Инд = 1 По СтрДлина(Результат) Цикл
Симв = Сред(Результат, Инд, 1);
Если Найти("0123456789", Симв) > 0 Тогда
Буфер = Буфер + Симв;
Если Буквы > 0 И Цифры = 0 Тогда
КодНомера = КодНомера + Строка(Буквы)+"0";
Буквы = 0;
КонецЕсли;
Цифры = Цифры + 1;
КонецЕсли;
Если Найти("АВЕКМНОРСТУХABCDEHKMOPTUXYZ", Симв) > 0 Тогда
Буфер = Буфер + Симв;
Если Цифры > 0 И Буквы = 0 Тогда
КодНомера = КодНомера + Строка(Цифры)+"1";
Цифры = 0;
КонецЕсли;
Буквы = Буквы + 1;
КонецЕсли;
КонецЦикла;
Если Буквы > 0 Тогда
КодНомера = КодНомера + Строка(Буквы)+"0";
КонецЕсли;
Если Цифры > 0 Тогда
КодНомера = КодНомера + Строка(Цифры)+"1";
КонецЕсли;
Если СтрДлина(КодНомера) = 0 Тогда
// В строке не соделжалось допустимых символов
Возврат Параметр;
КонецЕсли;
// 2. Получаем по Коду КодФормата
КодФормата = СокрЛП(ФорматНомера.Получить(КодНомера));
Если НЕ ЗначениеЗаполнено(КодФормата) Тогда
// КодФормата не найден - возвращаем входящую Строку
Возврат Параметр;
КонецЕсли;
// 3. Форматируем Строку по КодуФормата
Результат = "";
Позиция = 1;
Для Инд = 1 По СтрДлина(КодФормата) Цикл
КолСимв = 0;
Симв = Сред(КодФормата, Инд, 1);
Если Найти("0123456789", Симв) = 0 И
Найти("АВЕКМНОРСТУХABCDEHKMOPTUXYZ", Симв) = 0 Тогда
// разделитель пользователя
КолСимв = 1;
Результат = Результат + Симв;
Иначе
// очередной буквенно-цифровой блок + пробел
КолСимв = Число(Симв);
Результат = Результат + Сред(Буфер, Позиция ,КолСимв)+ " ";
КонецЕсли;
Позиция = Позиция + КолСимв;
КонецЦикла;
Результат = СокрЛП(Результат); // отсекаем возможный пробел в конце
// 4. Если второй параметр функции = Ложь - строку к Нижнему регистру
Если НЕ ВерхРегистр Тогда
Результат = НРег(Результат);
КонецЕсли;
// 5. Возвращаем результат работы функции
Возврат Результат;
КонецФункции