Многие разработчики сталкиваются с ситуацией, когда артикулы в базе данных выглядят идентично, но сортируются в списках и отчетах хаотично. Причина кроется в использовании омографов — символов кириллицы и латиницы, которые пишутся одинаково, но имеют разные коды (например, русская «А» и английская «A»). Рассмотрим, почему стандартная замена в печатных формах не работает и как реализовать надежный механизм унификации данных.
Проанализируем ситуацию, описанную в первом сообщении. Разработчик пытается выполнить СтрЗаменить непосредственно перед выводом артикула в табличный документ. Однако сортировка в 1С (особенно в динамических списках и запросах) происходит на уровне СУБД (SQL Server или PostgreSQL) еще до того, как данные попадут в программный код для печати.
Если в базе данных один артикул записан как "A100" (латиница), а другой как "А100" (кириллица), то в запросе они всегда будут находиться в разных частях списка. Исправление символов "на лету" при выводе на печать изменит внешний вид буквы, но никак не повлияет на порядок строк. Таким образом, мы приходим к выводу: данные должны храниться в базе в унифицированном виде.
Самый правильный подход с точки зрения архитектуры 1С — выполнять нормализацию строки в модуле объекта справочника (например, "Номенклатура"). Разберем по шагам, как это реализовать. Вместо множества вызовов СтрЗаменить, которые замедляют работу, лучше использовать функцию обхода строки. Рассмотрим пример кода, который можно разместить в модуле объекта:
Процедура ПередЗаписью(Отказ)
// Выполняем замену только если это не обмен данными
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Вызываем функцию очистки артикула
Артикул = ИсправитьЛатиницуВСтроке(Артикул);
КонецПроцедуры
Функция ИсправитьЛатиницуВСтроке(Знач ВходнаяСтрока) Экспорт
// Создаем соответствие русских букв английским аналогам
КартаЗамен = Новый Соответствие;
КартаЗамен.Вставить("А", "A"); КартаЗамен.Вставить("В", "B");
КартаЗамен.Вставить("Е", "E"); КартаЗамен.Вставить("К", "K");
КартаЗамен.Вставить("М", "M"); КартаЗамен.Вставить("Н", "H");
КартаЗамен.Вставить("О", "O"); КартаЗамен.Вставить("Р", "P");
КартаЗамен.Вставить("С", "C"); КартаЗамен.Вставить("Т", "T");
КартаЗамен.Вставить("У", "Y"); КартаЗамен.Вставить("Х", "X");
Результат = "";
Для Позиция = 1 По СтрДлина(ВходнаяСтрока) Цикл
Символ = Сред(ВходнаяСтрока, Позиция, 1);
НайденныйСимвол = КартаЗамен.Получить(Врег(Символ));
Если НайденныйСимвол <> Неопределено Тогда
Результат = Результат + НайденныйСимвол;
Иначе
Результат = Результат + Символ;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Этот метод гарантирует, что при каждом сохранении карточки товара артикул будет приведен к единому стандарту латиницы автоматически, независимо от того, какую раскладку использовал пользователь.
Иногда автоматическая замена может быть опасна (например, если в артикуле действительно допустимы и русские, и английские буквы в разных смыслах). В этом случае, как предлагалось в сообщении №15, стоит использовать метод "жесткого отказа". Проанализируем, как реализовать проверку на наличие запрещенных символов кириллицы.
Выясним причину ошибки с помощью функции Библиотеки Стандартных Подсистем (БСП), если ваша конфигурация её использует:
Процедура ПередЗаписью(Отказ)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Используем БСП для проверки состава строки
Если НЕ СтроковыеФункцииКлиентСервер.СодержитТолькоЛатиницу(Артикул) Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
"В артикуле обнаружены русские буквы! Пожалуйста, используйте только латиницу.",
ЭтотОбъект,
"Артикул",
,
Отказ);
КонецЕсли;
КонецПроцедуры
Такой подход заставляет пользователей быть внимательнее и предотвращает появление "мусора" в базе на этапе ввода данных.
Для более сложных случаев, когда нужно проверить не всю строку, а только её часть (например, первые два символа префикса, как упоминалось в сообщении №25), удобно использовать регулярные выражения. Это особенно актуально, если артикул имеет сложную структуру типа "H1500 Gri/серый".
Рассмотрим пример функции, которая находит кириллицу в начале строки:
Функция СодержитКириллицуВНачале(СтрокаАртикула)
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Ложь;
RegExp.Global = Истина;
// Шаблон ищет любые русские буквы от А до Я в первых двух символах
RegExp.Pattern = "^[А-Яа-яЁё]{1,2}";
Возврат RegExp.Test(СтрокаАртикула);
КонецФункции
Если база уже наполнена "кривыми" артикулами, простая вставка кода в модуль объекта не поможет — она сработает только при будущих изменениях. Нам необходимо выполнить групповую обработку. Проанализируем последовательность действий:
ИсправитьЛатиницуВСтроке.Помните, что порядок следования строк в запросе определяется параметром Collation (сопоставление) вашей базы данных. В стандартных настройках 1С для России (Cyrillic_General_CI_AS) латинские буквы и цифры обычно предшествуют кириллице. Именно поэтому "смешанные" артикулы разлетаются по разным концам списка. Единственный надежный способ обеспечить предсказуемую сортировку — полное исключение кириллических омографов из полей, предназначенных для идентификации (артикулов, кодов, серийных номеров).
Резюмируем: для решения проблемы не используйте замену в печатных формах. Перенесите логику в ПередЗаписью модуля объекта, внедрите проверку на стороне пользователя и проведите разовую чистку существующих данных с помощью скрипта или групповой обработки.