При заполнении реквизитов номенклатуры (артикулов, наименований, описаний) операторы часто случайно переключают раскладку клавиатуры или копируют данные из сторонних источников. В результате в тексте появляются слова, содержащие смесь кириллических и латинских символов с одинаковым начертанием (например: «А», «В», «С», «Е», «Н», «О», «Р», «Т», «Х», «У» и соответствующие латинские A, B, C, E, H, O, P, T, X, Y). Это приводит к созданию неявных дублей, ошибкам поиска и сбоям при сканировании штрихкодов. Разберем по шагам, как программно определять и исправлять такие фрагменты в строках.
Рассмотрим базовый сценарий, когда все символы артикула должны быть гарантированно латинскими, но часть из них была введена в русской раскладке. Если в строке встречаются русские буквы, не имеющие визуальных аналогов в латинице (например: «Б», «Г», «Д», «Ж»), артикул считается ошибочным и не корректируется автоматически.
Посмотрим на пример функции, выполняющей такую проверку и замену:
Функция ЛатинскийАртикул(Артикул) Экспорт
Алфавит = "ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ";
РусскиеАналоги = "АВЕКМНОРСТХ";
ЛатинскАналоги = "ABEKMHOPCTX";
НовыйАртикул = "";
ПлохиеБуквыЕсть = Ложь;
Для й = 1 По СтрДлина(Артикул) Цикл
Буква = Сред(Артикул, й, 1);
Если Найти(Алфавит, ВРег(Буква)) > 0 Тогда
ИндексАналога = Найти(РусскиеАналоги, ВРег(Буква));
Если ИндексАналога = 0 Тогда
ПлохиеБуквыЕсть = Истина;
Прервать;
КонецЕсли;
НовыйАртикул = НовыйАртикул + Сред(ЛатинскАналоги, ИндексАналога, 1);
Иначе
НовыйАртикул = НовыйАртикул + Буква;
КонецЕсли;
КонецЦикла;
Если ПлохиеБуквыЕсть Тогда
Возврат Артикул;
Иначе
Возврат НовыйАртикул;
КонецЕсли;
КонецФункции
Проанализируем более сложную задачу: в произвольном тексте (наименовании или описании) встречаются слова, где алфавит нужно определить автоматически по однозначным символам (не имеющим визуальных аналогов), а затем привести всё слово к выбранному языку.
Разберем логику разделения алфавитов на группы:
"ЙЦГШЩЗЪФЫПЛДЖЭЯЧИЬБЮ")."АВЕКМНОРСТХУ")."QWRUISDFGJLZVN")."ABEKMHOPCTXY").Определим вспомогательные функции для доступа к наборам символов:
Функция РусБуквы() Экспорт
Возврат "ЙЦГШЩЗЪФЫПЛДЖЭЯЧИЬБЮ";
КонецФункции
Функция РусАналоги() Экспорт
Возврат "АВЕКМНОРСТХУ";
КонецФункции
Функция ЛатБуквы() Экспорт
Возврат "QWRUISDFGJLZVN";
КонецФункции
Функция ЛатАналоги() Экспорт
Возврат "ABEKMHOPCTXY";
КонецФункции
Функция ВсеБуквы() Экспорт
Возврат РусБуквы() + РусАналоги() + ЛатБуквы() + ЛатАналоги();
КонецФункции
Рассмотрим функцию посимвольного исправления слова с сохранением регистра исходных букв:
Функция ИсправленноеРусЛатСлово(Строка, РусЛатИсправление) Экспорт
ИсправленноеСлово = "";
Для СчетчикСимволов = 1 По СтрДлина(Строка) Цикл
Символ = Сред(Строка, СчетчикСимволов, 1);
ИндексАналога = Найти(?(РусЛатИсправление, ЛатАналоги(), РусАналоги()), ВРег(Символ));
Если ИндексАналога = 0 Тогда
ИсправленноеСлово = ИсправленноеСлово + Символ;
Иначе
БукваЗамены = Сред(?(РусЛатИсправление, РусАналоги(), ЛатАналоги()), ИндексАналога, 1);
ИсправленноеСлово = ИсправленноеСлово + ?(Символ = ВРег(Символ), БукваЗамены, НРег(БукваЗамены));
КонецЕсли;
КонецЦикла;
Возврат ИсправленноеСлово;
КонецФункции
Теперь объединим разбор строки и логику принятия решения в единую функцию поиска ошибочных слов:
Функция НайтиРусЛатСлово(Строка, РусЛатСлово = "", ИсправленноеСлово = "") Экспорт
ЕстьРусБуквы = Ложь; ЕстьРусАналоги = Ложь; ЕстьЛатБуквы = Ложь; ЕстьЛатАналоги = Ложь;
Для СчетчикСимволов = 1 По СтрДлина(Строка) Цикл
Символ = Сред(Строка, СчетчикСимволов, 1);
ПредыдущийСимвол = Прав(РусЛатСлово, 1);
Если (Найти(ВсеБуквы(), ВРег(ПредыдущийСимвол)) = 0) = (Найти(ВсеБуквы(), ВРег(Символ)) = 0) Тогда
РусЛатСлово = РусЛатСлово + Символ;
ЕстьРусБуквы = ЕстьРусБуквы Или Не(Найти(РусБуквы(), ВРег(Символ)) = 0);
ЕстьРусАналоги = ЕстьРусАналоги Или Не(Найти(РусАналоги(), ВРег(Символ)) = 0);
ЕстьЛатБуквы = ЕстьЛатБуквы Или Не(Найти(ЛатБуквы(), ВРег(Символ)) = 0);
ЕстьЛатАналоги = ЕстьЛатАналоги Или Не(Найти(ЛатАналоги(), ВРег(Символ)) = 0);
Иначе
Если Не ПустаяСтрока(РусЛатСлово) Тогда
Если ЕстьРусБуквы И ЕстьЛатБуквы Тогда
Возврат Истина; // Неисправляемая комбинация рус./лат. букв
ИначеЕсли ЕстьРусБуквы И ЕстьЛатАналоги Тогда
ИсправленноеСлово = ИсправленноеРусЛатСлово(РусЛатСлово, Истина);
Возврат Истина; // Исправлено на русское
ИначеЕсли ЕстьЛатБуквы И ЕстьРусАналоги Тогда
ИсправленноеСлово = ИсправленноеРусЛатСлово(РусЛатСлово, Ложь);
Возврат Истина; // Исправлено на латинское
КонецЕсли;
РусЛатСлово = "";
КонецЕсли;
ЕстьРусБуквы = Ложь; ЕстьРусАналоги = Ложь; ЕстьЛатБуквы = Ложь; ЕстьЛатАналоги = Ложь;
КонецЕсли;
КонецЦикла;
Если Не ПустаяСтрока(РусЛатСлово) Тогда
Если ЕстьРусБуквы И ЕстьЛатБуквы Тогда
Возврат Истина;
ИначеЕсли ЕстьРусБуквы И ЕстьЛатАналоги Тогда
ИсправленноеСлово = ИсправленноеРусЛатСлово(РусЛатСлово, Истина);
Возврат Истина;
ИначеЕсли ЕстьЛатБуквы И ЕстьРусАналоги Тогда
ИсправленноеСлово = ИсправленноеРусЛатСлово(РусЛатСлово, Ложь);
Возврат Истина;
КонецЕсли;
РусЛатСлово = "";
КонецЕсли;
Возврат Ложь;
КонецФункции
Выясним ключевые особенности при работе с подобными алгоритмами в 1С:
"СОРТ" или "COPT") и не содержит однозначных символов, эвристический алгоритм без внешнего словаря не сможет определить правильный язык.Найти() со строками можно использовать проверку числовых кодов символов через КодСимвола() или применять регулярные выражения через COMОбъект("VBScript.RegExp").