В процессе разработки на платформе 1С:Предприятие часто возникает задача обработки строковых представлений объектов метаданных. Например, когда нам нужно из полной строки вида СправочникМенеджер.Организации или ДокументМенеджер.Заявки выделить только базовый тип — «Справочник» или «Документ». На первый взгляд задача кажется тривиальной, но при детальном рассмотрении выясняется, что простые методы могут приводить к ошибкам в сложных случаях. В этой статье мы разберем все возможные способы решения этой задачи: от классической работы со строками до использования современных возможностей платформы и механизмов метаданных.
Рассмотрим самый простой и очевидный подход, который основывается на поиске ключевых слов внутри строки. Если мы заранее знаем структуру строки, мы можем найти позицию вхождения слова Менеджер. и обрезать всё лишнее.
Проанализируем пример кода, предложенный участниками обсуждения:
// Допустим, переменная ИсходнаяСтрока содержит "СправочникМенеджер.Организации"
Позиция = СтрНайти(ИсходнаяСтрока, "Менеджер.");
Если Позиция > 0 Тогда
Результат = Лев(ИсходнаяСтрока, Позиция - 1);
КонецЕсли;
Этот метод хорош своей скоростью, но он требует осторожности. Если в строке случайно окажется текст, не соответствующий ожидаемому формату, функция Лев может вернуть некорректный результат. Поэтому всегда стоит добавлять проверку на то, что Позиция больше нуля.
Разберем более продвинутый вариант. Часто разработчики пытаются сначала избавиться от точки и всего, что идет после нее, а затем удалить лишние части слова. Выясним причину, почему это может быть удобнее: такой подход позволяет сначала локализовать часть строки, отвечающую за тип, а уже потом очищать ее.
Посмотрим на пример использования функции СтрРазделить:
// Исходная строка: "ДокументМенеджер.Заявки"
МассивЧастей = СтрРазделить(ИсходнаяСтрока, ".");
// Берем первую часть (индекс 0): "ДокументМенеджер"
ТипСМенеджером = МассивЧастей[0];
// Удаляем слово "Менеджер"
Результат = СтрЗаменить(ТипСМенеджером, "Менеджер", "");
Важный нюанс: как было отмечено в обсуждении на форуме (сообщение 10), существует риск, если имя самого объекта содержит слово «Справочник» или «Документ». Например, в строке ДокументМенеджер.РегистрацияСправочников простая замена по всей строке может привести к непредсказуемым результатам. Именно поэтому сначала нужно «отрезать» часть до точки.
В современных версиях 1С (начиная с 8.3.10) появились логические функции, которые делают код более читаемым. Вместо того чтобы вычислять индексы, мы можем использовать явную проверку начала строки. Проанализируем, как это упрощает алгоритм:
Если СтрНачинаетсяС(ИсходнаяСтрока, "Справочник") Тогда
Результат = "Справочник";
ИначеЕсли СтрНачинаетсяС(ИсходнаяСтрока, "Документ") Тогда
Результат = "Документ";
ИначеЕсли СтрНачинаетсяС(ИсходнаяСтрока, "ПланВидовХарактеристик") Тогда
Результат = "ПланВидовХарактеристик";
// и так далее для всех нужных типов
КонецЕсли;
Такой подход исключает ложные срабатывания, если ключевое слово встретится в середине или в конце имени объекта. Это наиболее безопасный способ при использовании строковых операций.
Если ваша задача — получить не просто текст, а реально существующий тип метаданных, то лучше всего обратиться к самой платформе. Выясним, почему это самый надежный метод. Платформа 1С хранит всю информацию об объектах в дереве метаданных, и обращение к нему гарантирует 100% точность, даже если в имени объекта есть префиксы расширений (например, СправочникМенеджер.прф_Организации).
Рассмотрим алгоритм получения имени коллекции:
Менеджер.Метаданные.НайтиПоПолномуИмени().
ПолноеИмяМетаданных = СтрЗаменить(ИсходнаяСтрока, "Менеджер", "");
ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ПолноеИмяМетаданных);
Если ОбъектМетаданных <> Неопределено Тогда
// Получаем имя коллекции, например "Справочники"
ИмяКоллекции = ОбъектМетаданных.Родитель().Имя;
// Можно преобразовать "Справочники" в "Справочник" простым удалением последней буквы
Результат = Лев(ИмяКоллекции, СтрДлина(ИмяКоллекции) - 1);
КонецЕсли;
Для тех, кто использует самые актуальные версии платформы, доступен мощный инструмент — встроенные регулярные выражения. Теперь не нужно подключать внешние COM-объекты. Посмотрим, как изящно решить задачу с помощью регулярного выражения.
Нам понадобится шаблон вида ^([А-Яа-я]+)Менеджер. Он найдет последовательность русских букв в начале строки, которая заканчивается словом «Менеджер».
РегВыр = Новый РегулярноеВыражение("^([А-Яа-я]+)Менеджер");
РезультатПоиска = РегВыр.Найти(ИсходнаяСтрока);
Если РезультатПоиска.Количество() > 0 Тогда
// Извлекаем первую группу захвата (то, что в скобках)
Результат = РезультатПоиска[0].Группы[1].Значение;
КонецЕсли;
Этот метод является наиболее гибким, так как позволяет одной строкой кода обработать и префиксы, и различные типы объектов, игнорируя всё, что находится после точки.
Если ваша конфигурация разработана на основе Библиотеки Стандартных Подсистем (БСП), мы можем воспользоваться готовыми инструментами из общего модуля СтроковыеФункцииКлиентСервер. Рассмотрим пример, который сократит количество вашего кода:
// Получаем часть до точки: "СправочникМенеджер"
ЧастьДоТочки = СтроковыеФункцииКлиентСервер.ПолучитьЧастьСтрокиДоПервогоРазделителя(ИсходнаяСтрока, ".");
// Удаляем "Менеджер"
Результат = СтрЗаменить(ЧастьДоТочки, "Менеджер", "");
Этот способ хорош тем, что функции БСП уже содержат в себе необходимые проверки на пустые строки и корректность разделителей, что делает код более стабильным.
Проанализировав все способы, можно сделать следующие выводы:
СтрРазделить с последующей заменой.Метаданные.НайтиПоПолномуИмени.СтрНайти(Строка, ".") > 0 перед началом манипуляций.Выбирайте метод в зависимости от версии вашей платформы и требований к отказоустойчивости системы. Совместное использование строковых функций и логических проверок позволит вам создавать чистый и надежный код.