Как в запросе 1С получить первое слово из строки

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

Нередко разработчикам 1С требуется выделить отдельную часть строки непосредственно на уровне выборки данных. Классический пример — извлечение фамилии руководителя или сотрудника из поля с полным ФИО (например, получение «Иванов» из строки «Иванов Иван Иванович»). На первый взгляд кажется, что достаточно воспользоваться стандартной функцией ПОДСТРОКА(), однако сразу возникает препятствие: длина первого слова заранее неизвестна, а позиция первого пробела в каждой строке уникальна.

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

Решение в запросе на современных версиях платформы (начиная с 8.3.20)

В ранних версиях платформы 1С язык запросов был существенно ограничен в работе со строками: поддерживалась только операция сложения строк и функция ПОДСТРОКА() с жестко заданными числовыми параметрами. Однако начиная с версии 1С:Предприятие 8.3.20 разработчики получили полноценный набор строковых функций непосредственно в языке запросов:

  1. СтрНайти(Строка, Подстрока) — возвращает номер позиции первого символа найденной подстроки.
  2. Лев(Строка, Длина) — возвращает указанное количество символов с начала строки.
  3. СокрЛ(Строка) и СокрЛП(Строка) — удаляют незначащие пробелы слева или с обеих сторон.
  4. ДлинаСтроки(Строка) — вычисляет общую длину строки.

Благодаря этим возможностям задача решается прямо в тексте запроса через конструкцию ВЫБОР. Проанализируем пример кода:


ВЫБРАТЬ
    ВЫБОР
        КОГДА СтрНайти(СокрЛ(ФИОРуководителя.ФИОПолные), " ") > 0
            ТОГДА Лев(СокрЛ(ФИОРуководителя.ФИОПолные), СтрНайти(СокрЛ(ФИОРуководителя.ФИОПолные), " ") - 1)
        ИНАЧЕ СокрЛ(ФИОРуководителя.ФИОПолные)
    КОНЕЦ КАК Фамилия
ИЗ
    Справочник.Организации КАК ФИОРуководителя

Важные нюансы реализации:

  1. Функция СокрЛ() обязательна, чтобы исключить случайные ведущие пробелы. Если их не убрать, позиция первого пробела будет равна единице, и вычисление длины приведет к неверному результату.
  2. Проверка ВЫБОР КОГДА СтрНайти(...) > 0 защищает запрос от ошибок в тех случаях, когда строка состоит всего из одного слова (например, указана только фамилия без имени и отчества). Если пробела нет, выражение вернет всю строку целиком.

Ограничения на версиях платформы ниже 8.3.20

Если проект работает на платформе версии 8.3.19 и старше, реализовать подобный алгоритм внутри запроса крайне сложно. В этих версиях параметры длины и смещения функции ПОДСТРОКА() обязаны быть статическими целочисленными константами. Передать в них вычисленное значение, результат подзапроса или поле соединения невозможно — платформа выдаст синтаксическую ошибку.

Попытки реализовать разбор через временную таблицу чисел и соединение посимвольно (эмуляция цикла) технически возможны, но создают колоссальную нагрузку на СУБД, резко усложняют чтение запроса и категорически не рекомендуются к использованию в рабочих базах.

Решение через Систему компоновки данных (СКД)

Если запрос формируется для отчета, построенного на СКД, задачу можно изящно решить независимо от версии платформы и используемой СУБД. Язык выражений СКД значительно богаче языка запросов.

Разберем по шагам, как настроить получение первого слова:

  1. Оставляем в запросе исходное поле ФИОПолные без модификаций.
  2. Переходим на вкладку Вычисляемые поля схемы компоновки данных.
  3. Добавляем новое поле Фамилия и прописываем выражение:

ВЫБОР 
    КОГДА СтрНайти(СокрЛП(ФИОПолные), " ") > 0 
        ТОГДА Лев(СокрЛП(ФИОПолные), СтрНайти(СокрЛП(ФИОПолные), " ") - 1) 
    ИНАЧЕ СокрЛП(ФИОПолные) 
КОНЕЦ

Кроме того, в выражениях СКД допускается вызывать экспортные функции общих модулей, что дает возможность применить типовые алгоритмы разбора строк БСП.

Обработка результата на встроенном языке

Когда вычисление требуется в обработке, алгоритме заполнения документа или на старой платформе, оптимальным подходом является постобработка выборки средствами встроенного языка 1С. Посмотрим на наиболее производительные способы.

Способ 1. Использование функции СтрРазделить():


Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    ЧастиФИО = СтрРазделить(СокрЛП(Выборка.ФИОПолные), " ", Ложь);
    Если ЧастиФИО.Количество() > 0 Тогда
        Фамилия = ЧастиФИО[0];
    Иначе
        Фамилия = "";
    КонецЕсли;
КонецЦикла;

Способ 2. Комбинация СтрНайти() и Лев():


СтрокаФИО = СокрЛ(Выборка.ФИОПолные);
ПозицияПробела = СтрНайти(СтрокаФИО, " ");
Если ПозицияПробела > 0 Тогда
    Фамилия = Лев(СтрокаФИО, ПозицияПробела - 1);
Иначе
    Фамилия = СтрокаФИО;
КонецЕсли;

Типовые механизмы хранения ФИО

В большинстве типовых конфигураций 1С (1С:ERP, 1С:ЗУП, 1С:УТ, 1C:Бухгалтерия) разработчики платформы изначально заложили раздельное хранение составляющих имени. Для этого используется периодический регистр сведений (например, ФИОФизическихЛиц), содержащий отдельные реквизиты: Фамилия, Имя и Отчество.

Если стоит задача получить фамилию физического лица или ответственного руководителя, наиболее правильным архитектурным решением будет соединение с регистром сведений ФИОФизическихЛиц.СрезПоследних(), а не парсинг строкового представления. Это гарантирует корректную работу со сложными фамилиями, составными именами и иностранными приставками.

← На главную