Как программно преобразовать строку из слитного написания в слова с пробелами в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При автоматической генерации пользовательского интерфейса, формировании отчетов, обработке имен реквизитов метаданных или разборе внешних данных (например, ключей JSON и XML) разработчики часто сталкиваются с именами, записанными в нотации PascalCase или CamelCase: "ЭтоТестоваяСтрока" или "ОбменСБазой". Для отображения пользователю такую строку необходимо представить в привычном виде: "Это тестовая строка" или "Обмен с базой".

Разберем, предоставляет ли платформа 1С готовые встроенные методы для этой операции, выясним причины имеющихся ограничений и рассмотрим эффективные варианты реализации на встроенном языке.

Существуют ли встроенные механизмы платформы?

Многие разработчики обращают внимание на то, что при создании нового реквизита или объекта в дереве метаданных Конфигуратор автоматически заполняет синоним с пробелами при вводе имени. Однако данный механизм встроен исключительно в оболочку среды разработки и во встроенном языке платформы 1С:Предприятие 8 как готовая функция не доступен.

Проанализируем платформенные строковые функции:

  1. Методы СтрРазделить() и СтрСоединить() работают только с фиксированными подстроками или явно заданным набором символов-разделителей. Разделить строку по условию смены регистра или по шаблону они не могут.
  2. Функция ТРег() переводит первые буквы слов в верхний регистр, но предполагает, что слова уже разделены пробелами, и не умеет вставлять пробелы между слипшимися словами.
  3. Встроенных средств работы с регулярными выражениями (Regex) в базовом синтаксисе 1С нет.

Таким образом, задачу необходимо решать программно с помощью собственного алгоритма обхода строки.

Пошаговый алгоритм на встроенном языке 1С

Рассмотрим алгоритм, который обходит строку посимвольно, отслеживает границы слов по переходу между строчными и заглавными буквами, добавляет пробелы и приводит следующие слова к нижнему регистру.

Посмотрим на пример функции, предложенной в сообщении сообщества:


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

Разберем логику работы этой функции:

  1. Мы берем первый символ строки без изменений, чтобы сохранить первую букву предложения заглавной.
  2. В цикле сравниваем текущий символ и предыдущий. Если предыдущий символ строчный, а текущий — заглавный, фиксируется начало нового слова.
  3. Если за заглавной буквой следует строчная, текущая заглавная буква переводится в нижний регистр с помощью функции НРег() (например, "Строка" превратится в " строка").
  4. Перед буквой вставляется пробел. Символы подчеркивания удаляются на финальном этапе через СтрЗаменить().

Универсальный подход без жесткой привязки к алфавиту

В приведенном выше решении список строчных букв задан жестко строкой "абвгдеё...". Это создает ограничение: алгоритм перестанет корректно определять смену регистра для латинских символов (например, в названиях "IDКлиента" или "CamelCase").

Чтобы сделать определение регистра универсальным для любых языков, выясним особенность работы строковых функций платформы: символ является заглавной буквой тогда и только тогда, когда он совпадает со своим верхним регистром и не равен своему нижнему регистру. Проверка (Символ = ВРег(Символ)) И (Символ <> НРег(Символ)) автоматически отсекает цифры, знаки пунктуации и спецсимволы, для которых верхний и нижний регистр всегда совпадают.

Посмотрим на доработанный вариант универсальной функции:


&НаКлиентеНаСервереБезКонтекста
Функция ИмяВСтрокуСПробелами(Знач ИсходныйТекст) Экспорт
    ИсходныйТекст = СокрЛП(ИсходныйТекст);
    Длина = СтрДлина(ИсходныйТекст);
    
    Если Длина <= 1 Тогда
        Возврат ИсходныйТекст;
    КонецЕсли;
    
    Результат = Лев(ИсходныйТекст, 1);
    
    Для Индекс = 2 По Длина Цикл
        Символ = Сред(ИсходныйТекст, Индекс, 1);
        ПредыдущийСимвол = Сред(ИсходныйТекст, Индекс - 1, 1);
        
        СимволВРег = ВРег(Символ);
        СимволНРег = НРег(Символ);
        
        ЭтоБуква = (СимволВРег <> СимволНРег);
        ЭтоЗаглавная = ЭтоБуква И (Символ = СимволВРег);
        
        ПредБуква = (ВРег(ПредыдущийСимвол) <> НРег(ПредыдущийСимвол));
        ПредСтрочная = ПредБуква И (ПредыдущийСимвол = НРег(ПредыдущийСимвол));
        
        // Граница слова: предыдущий символ был строчной буквой, текущий — заглавной
        Если ПредСтрочная И ЭтоЗаглавная Тогда
            Результат = Результат + " " + СимволНРег;
        Иначе
            Результат = Результат + Символ;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Результат;
КонецФункции

Нюансы обработки аббревиатур и цифр

При практическом применении таких функций важно учитывать граничные случаи:

  1. Аббревиатуры: в строках вида "СуммаНДС" или "КодОКПО" важно не разделять пробелами буквы внутри аббревиатуры. Предложенный алгоритм проверяет смену регистра со строчной на заглавную, поэтому подряд идущие заглавные буквы останутся единым словом: "Сумма НДС".
  2. Цифры: если идентификатор содержит числовой суффикс (например, "СчетНаОплату1"), можно решить, отделять ли цифры пробелом, добавив отдельное условие проверки диапазона символов от "0" до "9".

Использование компактной пользовательской функции полностью решает задачу формирования читаемых синонимов и заголовков в любых типовых и самописных конфигурациях.

← На главную