При автоматической генерации пользовательского интерфейса, формировании отчетов, обработке имен реквизитов метаданных или разборе внешних данных (например, ключей JSON и XML) разработчики часто сталкиваются с именами, записанными в нотации PascalCase или CamelCase: "ЭтоТестоваяСтрока" или "ОбменСБазой". Для отображения пользователю такую строку необходимо представить в привычном виде: "Это тестовая строка" или "Обмен с базой".
Разберем, предоставляет ли платформа 1С готовые встроенные методы для этой операции, выясним причины имеющихся ограничений и рассмотрим эффективные варианты реализации на встроенном языке.
Многие разработчики обращают внимание на то, что при создании нового реквизита или объекта в дереве метаданных Конфигуратор автоматически заполняет синоним с пробелами при вводе имени. Однако данный механизм встроен исключительно в оболочку среды разработки и во встроенном языке платформы 1С:Предприятие 8 как готовая функция не доступен.
Проанализируем платформенные строковые функции:
СтрРазделить() и СтрСоединить() работают только с фиксированными подстроками или явно заданным набором символов-разделителей. Разделить строку по условию смены регистра или по шаблону они не могут.ТРег() переводит первые буквы слов в верхний регистр, но предполагает, что слова уже разделены пробелами, и не умеет вставлять пробелы между слипшимися словами.Таким образом, задачу необходимо решать программно с помощью собственного алгоритма обхода строки.
Рассмотрим алгоритм, который обходит строку посимвольно, отслеживает границы слов по переходу между строчными и заглавными буквами, добавляет пробелы и приводит следующие слова к нижнему регистру.
Посмотрим на пример функции, предложенной в сообщении сообщества:
// Преобразовывает имя переменной к более читабельному виду
// Например "ОбменСБазой" -> "Обмен с базой"
&НаКлиентеНаСервереБезКонтекста
Функция СформироватьСиноним(Знач ИмяПеременной) Экспорт
Перем МаленькиеБуквы, Буква, Ответ, сч, ПредыдущаяБуква, СледующаяБуква;
ИмяПеременной = СокрЛП(ИмяПеременной);
МаленькиеБуквы = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя_";
Буква = Лев(ИмяПеременной, 1);
Ответ = "" + Буква;
Для сч = 2 По СтрДлина(ИмяПеременной) Цикл
ПредыдущаяБуква = Буква;
Буква = Сред(ИмяПеременной, сч, 1);
Если (Найти(МаленькиеБуквы, Буква) = 0) И (Найти(МаленькиеБуквы, ПредыдущаяБуква) > 0) Тогда
СледующаяБуква = Сред(ИмяПеременной, сч + 1, 1);
Если (СледующаяБуква <> "") И (Найти(МаленькиеБуквы, СледующаяБуква) > 0) Тогда
Буква = НРег(Буква);
КонецЕсли;
Буква = " " + Буква;
КонецЕсли;
Ответ = Ответ + Буква;
КонецЦикла;
Возврат СтрЗаменить(Ответ, "_", "");
КонецФункции
Разберем логику работы этой функции:
НРег() (например, "Строка" превратится в " строка").СтрЗаменить().В приведенном выше решении список строчных букв задан жестко строкой "абвгдеё...". Это создает ограничение: алгоритм перестанет корректно определять смену регистра для латинских символов (например, в названиях "IDКлиента" или "CamelCase").
Чтобы сделать определение регистра универсальным для любых языков, выясним особенность работы строковых функций платформы: символ является заглавной буквой тогда и только тогда, когда он совпадает со своим верхним регистром и не равен своему нижнему регистру. Проверка (Символ = ВРег(Символ)) И (Символ <> НРег(Символ)) автоматически отсекает цифры, знаки пунктуации и спецсимволы, для которых верхний и нижний регистр всегда совпадают.
Посмотрим на доработанный вариант универсальной функции:
&НаКлиентеНаСервереБезКонтекста
Функция ИмяВСтрокуСПробелами(Знач ИсходныйТекст) Экспорт
ИсходныйТекст = СокрЛП(ИсходныйТекст);
Длина = СтрДлина(ИсходныйТекст);
Если Длина <= 1 Тогда
Возврат ИсходныйТекст;
КонецЕсли;
Результат = Лев(ИсходныйТекст, 1);
Для Индекс = 2 По Длина Цикл
Символ = Сред(ИсходныйТекст, Индекс, 1);
ПредыдущийСимвол = Сред(ИсходныйТекст, Индекс - 1, 1);
СимволВРег = ВРег(Символ);
СимволНРег = НРег(Символ);
ЭтоБуква = (СимволВРег <> СимволНРег);
ЭтоЗаглавная = ЭтоБуква И (Символ = СимволВРег);
ПредБуква = (ВРег(ПредыдущийСимвол) <> НРег(ПредыдущийСимвол));
ПредСтрочная = ПредБуква И (ПредыдущийСимвол = НРег(ПредыдущийСимвол));
// Граница слова: предыдущий символ был строчной буквой, текущий — заглавной
Если ПредСтрочная И ЭтоЗаглавная Тогда
Результат = Результат + " " + СимволНРег;
Иначе
Результат = Результат + Символ;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
При практическом применении таких функций важно учитывать граничные случаи:
"СуммаНДС" или "КодОКПО" важно не разделять пробелами буквы внутри аббревиатуры. Предложенный алгоритм проверяет смену регистра со строчной на заглавную, поэтому подряд идущие заглавные буквы останутся единым словом: "Сумма НДС"."СчетНаОплату1"), можно решить, отделять ли цифры пробелом, добавив отдельное условие проверки диапазона символов от "0" до "9".Использование компактной пользовательской функции полностью решает задачу формирования читаемых синонимов и заголовков в любых типовых и самописных конфигурациях.