Как в 1С преобразовать полное ФИО в формат 'Фамилия И.О.'?

Программист IT и автоматизация бизнеса
← На главную

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

Исходная проблема была сформулирована так: есть код, который работает, но его сложно читать и поддерживать. Посмотрим на него.


ФИО = "Куравлев Алексей Владимирович"; // Требуется сформировать: "Куравлев А.В."

Фамилия = Сред(ФИО, 0, СтрНайти(ФИО, " ",,,1) - 1);
Имя = Сред(ФИО, СтрНайти(ФИО, " ",,,1) + 1, СтрНайти(ФИО, " ",,,2) - СтрНайти(ФИО, " ",,,1) - 1);
Отчество = Сред(ФИО, СтрНайти(ФИО, " ",,,2) + 1, СтрДлина(ФИО) - СтрНайти(ФИО, " ",,,2));

Сообщить(ФИО + " = " + Фамилия + " " + Лев(Имя, 1) + "." + Лев(Отчество, 1) + ".");

Этот код действительно выполняет свою задачу, но из-за вложенных вызовов функций СтрНайти() и сложных вычислений длин подстрок он выглядит громоздко. Через неделю будет сложно понять, как он работает, не разбирая каждую строчку заново. Давайте рассмотрим, как это можно сделать лучше.

Решение 1: Улучшение читаемости исходного кода

Самый первый шаг к улучшению — сделать код более понятным, не меняя основной логики. Для этого можно вынести повторяющиеся вычисления в отдельные переменные. Это сразу же сделает код чище и нагляднее.

Кроме того, для форматирования строк вместо конкатенации (сложения через "+") рекомендуется использовать более современную функцию СтрШаблон(). Она позволяет вставить параметры в строку по их номерам, что делает финальную строку гораздо нагляднее.

Пример улучшенного кода:


ФИО = "Куравлев Алексей Владимирович";

ПервыйПробел = СтрНайти(ФИО, " "); // Поиск первого пробела
ВторойПробел = СтрНайти(ФИО, " ",, ПервыйПробел + 1); // Поиск второго пробела, начиная после первого

Фамилия = Лев(ФИО, ПервыйПробел - 1);
Имя = Сред(ФИО, ПервыйПробел + 1, 1);
Отчество = Сред(ФИО, ВторойПробел + 1, 1);

Сообщить(СтрШаблон("%1 = %2 %3.%4.", ФИО, Фамилия, Имя, Отчество));

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

Решение 2: Самый популярный способ — через разделение строки в массив

Наиболее идиоматичным и гибким решением для подобных задач в 1С является использование функции СтрРазделить(). Эта функция "разрезает" строку по указанному разделителю (в нашем случае — пробелу) и возвращает массив полученных частей.

Разберем по шагам:

  1. Разделяем строку. Используем СтрРазделить(ФИО, " ", Ложь). Третий параметр Ложь (или Не включать пустые) указывает, что если между словами будет несколько пробелов, то пустые элементы в массив добавляться не будут.
  2. Получаем части ФИО. После разделения, в массиве по индексу 0 будет фамилия, по индексу 1 — имя, а по индексу 2 — отчество.
  3. Собираем результат. Берем нужные части из массива, от имени и отчества оставляем по первой букве и собираем итоговую строку.

Пример кода:


ФИО = "Куравлев Алексей Владимирович";
МассивФИО = СтрРазделить(ФИО, " ", Ложь);

// Проверяем, что в строке достаточно частей, чтобы избежать ошибки "Индекс за границей массива"
Если МассивФИО.Количество() >= 3 Тогда
    Фамилия = МассивФИО[0];
    Имя = Лев(МассивФИО[1], 1);
    Отчество = Лев(МассивФИО[2], 1);

    Результат = СтрШаблон("%1 %2.%3.", Фамилия, Имя, Отчество);
    Сообщить(ФИО + " = " + Результат);
Иначе
    Сообщить("Неверный формат ФИО: " + ФИО);
КонецЕсли;

Важное дополнение: обработка лишних пробелов.

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

Функция СтрРазделить() с параметром Ложь сама справится с двойными пробелами между словами. Однако использование СокрЛП() для очистки каждой части после разделения — это хорошая практика "защитного программирования", которая предотвратит потенциальные ошибки.

Решение 3: Надежный алгоритм для обработки "грязных" данных

Что если в строке могут быть множественные пробелы, которые приведут к появлению пустых элементов в массиве (если использовать СтрРазделить с третьим параметром Истина) или если мы хотим обработать ФИО с разным количеством слов? В этом случае можно перебрать полученный массив в цикле, отбрасывая пустые элементы.

Этот подход является очень надежным и справится с большинством нестандартных входных данных.


// Нормализуем исходную строку
ФИО_Исходное = "  Куравлев   Алексей  Владимирович  ";
ФИО_Обработанное = "";
МассивСтрок = СтрРазделить(СокрЛП(ФИО_Исходное), " ", Ложь);

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

Сообщить(ФИО_Обработанное); // Результат: "Куравлев А.В."

Решение 4: Профессиональный подход — использование готовых функций

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

В теме был приведен пример функции ФамилияИнициалы из ЗУП, которая сначала разбирает ФИО на части с помощью другой сложной функции ЧастиИмени, а затем формирует краткое представление. Это показывает, что в промышленных системах эта, казалось бы, простая задача требует учета множества частных случаев.

Ключевой вывод: если вы работаете в рамках типовой конфигурации, поищите готовые функции в общих модулях, таких как ФизическиеЛицаКлиентСервер, СтроковыеФункцииКлиентСервер и т.п. Это сэкономит ваше время и обеспечит более надежный результат.

Решение 5: Самый надежный способ — запрос к данным

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

Если это так, то парсить строку вообще не нужно! Самый правильный и производительный способ — получить эти части напрямую из базы данных с помощью запроса.

Преимущества такого подхода:

Когда у вас есть возможность получить ФИО по частям, всегда выбирайте этот способ.

← На главную