При работе с системой 1С:Предприятие 8.3 в управляемых формах часто возникает задача получить ссылку на конкретный объект базы данных (например, элемент справочника «Номенклатура» или «Контрагенты»), если у нас есть только его текстовое наименование или полное представление, которое отображается пользователю. Стандартные методы поиска не всегда обеспечивают нужную точность, особенно когда существуют дубли наименований или когда требуется найти по сложному представлению, включающему код или другие реквизиты. Давайте подробно рассмотрим различные подходы к решению этой проблемы, начиная от простых и заканчивая более универсальными.
Мы разберем основные методы, которые позволят вам точно идентифицировать и получить нужную ссылку на объект, чтобы в дальнейшем использовать её в запросах, алгоритмах или при заполнении документов.
Первый и наиболее очевидный способ – это использование метода НайтиПоНаименованию(), доступного для каждого справочника. Этот метод предназначен для быстрого поиска элемента по его полному и точному наименованию. Мы рассмотрим его применение:
Определение объекта справочника: Прежде всего, нам нужно указать, в каком именно справочнике мы ищем. Для этого мы обращаемся к коллекции глобальных объектов Справочники.
Вызов метода НайтиПоНаименованию(): В качестве параметра мы передаем точное наименование элемента, который ищем.
Анализ результата: Метод возвращает ссылку на первый найденный элемент с таким наименованием. Если элемент не найден, будет возвращено значение Неопределено.
Посмотрим на пример кода:
// Предположим, мы ищем номенклатуру с наименованием "Моя номенклатура"
ИскомоеНаименование = "Моя номенклатура";
СсылкаНаНоменклатуру = Справочники.Номенклатура.НайтиПоНаименованию(ИскомоеНаименование);
Если СсылкаНаНоменклатуру.Пустая() Тогда
Сообщить("Номенклатура с наименованием " + ИскомоеНаименование + " не найдена.");
Иначе
Сообщить("Найдена номенклатура: " + СсылкаНаНоменклатуру + ", ПолноеНаименование: " + СсылкаНаНоменклатуру.ПолноеНаименование);
КонецЕсли;
Мы видим, что данный метод очень прост в использовании, но имеет существенное ограничение: он возвращает только первый попавшийся элемент, если в справочнике есть несколько элементов с одинаковым наименованием. В случаях, когда требуется более точный или уникальный поиск, этот метод может быть недостаточен.
Когда стандартные методы не справляются с задачей или когда требуется более сложная логика поиска (например, по нескольким реквизитам, с условиями "подобно" или по дополнительным фильтрам), мы обращаемся к механизму запросов 1С. Запросы предоставляют значительно большую гибкость и позволяют точно сформулировать условия поиска.
Разберем шаги по созданию запроса для поиска ссылки на объект по наименованию:
Создание объекта Запрос: Мы инициализируем новый объект запроса.
Формирование текста запроса: Мы пишем SQL-подобный текст запроса, указывая, какие данные мы хотим получить (в данном случае – Ссылка) и из какой таблицы (например, Справочник.Номенклатура).
Установка параметров запроса: Для повышения безопасности и производительности, а также для защиты от SQL-инъекций, мы используем параметры запроса. Это позволяет динамически изменять условия поиска без перекомпиляции текста запроса.
Выполнение запроса и обработка результата: Запрос выполняется, и мы получаем объект РезультатЗапроса, из которого можем извлечь нужные данные.
Рассмотрим пример запроса, который ищет номенклатуру по точному наименованию, исключая помеченные на удаление элементы:
// Искомое наименование
ИскомоеНаименование = "Моя номенклатура";
// Создаем новый запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СправочникНоменклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК СправочникНоменклатура
|ГДЕ
| СправочникНоменклатура.Наименование = &Наименование
| И СправочникНоменклатура.ПометкаУдаления = ЛОЖЬ"; // Дополнительное условие, исключающее удаленные элементы
// Устанавливаем параметр запроса
Запрос.УстановитьПараметр("Наименование", ИскомоеНаименование);
// Выполняем запрос
Результат = Запрос.Выполнить();
// Обрабатываем результат
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
СсылкаНаНоменклатуру = Выборка.Ссылка;
Сообщить("Номенклатура найдена запросом: " + СсылкаНаНоменклатуру);
Иначе
Сообщить("Номенклатура с наименованием " + ИскомоеНаименование + " не найдена запросом.");
КонецЕсли;
Этот подход значительно надежнее, так как мы можем добавить любые необходимые условия в секцию ГДЕ для более точного поиска. Например, если нам нужно найти номенклатуру с определенным кодом или в определенной группе.
Одна из самых сложных задач – это поиск объекта по его "полному представлению", которое пользователь видит в списках или отчетах. Часто это представление формируется из нескольких реквизитов (например, "Наименование (Код)" или "Наименование [Артикул]"). Универсального метода для прямого поиска по такому сложному представлению в 1С нет.
В этом случае нам придется выполнить несколько шагов:
Разбор строки представления: Мы должны "разобрать" полученную строку представления на составляющие реквизиты (например, выделить наименование и код). Для этого мы будем использовать строковые функции 1С.
Формирование запроса с множественными условиями: После того как мы выделили отдельные части (наименование, код), мы можем использовать их в запросе, чтобы найти нужный элемент по нескольким реквизитам одновременно.
Давайте посмотрим на пример, как разобрать представление вида "Торт Наполеон (00001)" и затем найти соответствующую номенклатуру:
СтрокаПредставления = "Торт Наполеон (00001)";
// 1. Разбор строки представления
// Ищем позицию открывающей скобки
ПозСкобки = СтрНайти(СтрокаПредставления, "(");
Имя = "";
Код = "";
Если ПозСкобки > 0 Тогда
// Выделяем наименование (часть до скобки)
Имя = СокрЛП(Лев(СтрокаПредставления, ПозСкобки - 1));
// Выделяем код (часть внутри скобок)
КодСтрока = Сред(СтрокаПредставления, ПозСкобки + 1, СтрДлина(СтрокаПредставления) - ПозСкобки - 2); // -2 для учета закрывающей скобки
Код = СокрЛП(КодСтрока);
Иначе
// Если скобок нет, считаем всю строку наименованием
Имя = СокрЛП(СтрокаПредставления);
КонецЕсли;
Сообщить("Разобрано: Наименование = " + Имя + ", Код = " + Код);
// 2. Формирование запроса с множественными условиями
Если Не ПустаяСтрока(Имя) И Не ПустаяСтрока(Код) Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СправочникНоменклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК СправочникНоменклатура
|ГДЕ
| СправочникНоменклатура.Наименование = &Наименование
| И СправочникНоменклатура.Код = &Код
| И СправочникНоменклатура.ПометкаУдаления = ЛОЖЬ";
Запрос.УстановитьПараметр("Наименование", Имя);
Запрос.УстановитьПараметр("Код", Код);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
СсылкаНаНоменклатуру = Выборка.Ссылка;
Сообщить("Номенклатура найдена по наименованию и коду: " + СсылкаНаНоменклатуру);
Иначе
Сообщить("Номенклатура с наименованием '" + Имя + "' и кодом '" + Код + "' не найдена.");
КонецЕсли;
ИначеЕсли Не ПустаяСтрока(Имя) Тогда
// Если код не был выделен, ищем только по наименованию (как в п.1 или п.2)
Сообщить("Поиск только по наименованию...");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СправочникНоменклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК СправочникНоменклатура
|ГДЕ
| СправочникНоменклатура.Наименование = &Наименование
| И СправочникНоменклатура.ПометкаУдаления = ЛОЖЬ";
Запрос.УстановитьПараметр("Наименование", Имя);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
СсылкаНаНоменклатуру = Выборка.Ссылка;
Сообщить("Номенклатура найдена по наименованию: " + СсылкаНаНоменклатуру);
Иначе
Сообщить("Номенклатура с наименованием '" + Имя + "' не найдена.");
КонецЕсли;
Иначе
Сообщить("Не удалось разобрать строку представления или она пуста.");
КонецЕсли;
Этот подход требует более тщательного анализа структуры строки представления, которую вы используете. Если форматы представления могут сильно различаться, то функция разбора строки должна быть достаточно универсальной, чтобы корректно извлекать нужные части. В некоторых случаях, если представление включает много реквизитов, возможно, будет проще перебрать все элементы справочника и сравнить их программно с помощью функций ПредставлениеОбъекта() или ПолучитьПредставлениеЭлемента(), но это будет крайне неоптимально для больших справочников и следует избегать такого подхода при возможности.
Самый надежный и быстрый способ поиска объекта в 1С, если у нас есть его уникальный идентификатор (УИД или UUID), это использование функции НайтиПоУникальномуИдентификатору(). УИД – это глобально уникальный идентификатор, который однозначно определяет каждый объект в информационной базе 1С. Если вы можете получить УИД объекта из исходных данных (например, из внешних систем или файлов обмена), то это всегда будет предпочтительным методом.
Посмотрим на пример:
// Предположим, у нас есть строка с УИД объекта
СтрокаУИД = "4ff3b26c-d1e9-11ea-8153-00155d045d01"; // Пример УИД
// Преобразуем строку в тип УникальныйИдентификатор
УИД = Новый УникальныйИдентификатор(СтрокаУИД);
// Находим ссылку на объект по УИД
СсылкаНаОбъект = Справочники.НайтиПоУникальномуИдентификатору(УИД);
Если СсылкаНаОбъект = Неопределено Тогда
Сообщить("Объект с УИД " + СтрокаУИД + " не найден.");
Иначе
Сообщить("Объект найден по УИД: " + СсылкаНаОбъект);
КонецЕсли;
Этот метод не поможет, если у вас есть только наименование или представление, но его важно знать как самый эффективный способ поиска при наличии соответствующего идентификатора. Если же задача изначально стоит в поиске по наименованию, то следует сосредоточиться на запросах и разборе представлений.
Мы видим, что в 1С:Предприятие 8.3 существует несколько способов для поиска ссылок на объекты по их текстовому представлению. Выбор метода зависит от конкретной ситуации:
Для простого и быстрого поиска по точному и предположительно уникальному наименованию используйте Справочники.ИмяСправочника.НайтиПоНаименованию().
Для более точного поиска, с возможностью применения сложных условий (по нескольким реквизитам, с учетом флагов удаления, групп и т.д.), всегда используйте запросы. Это наиболее гибкий и производительный метод.
Если вам необходимо найти объект по его сложному пользовательскому представлению (например, "Наименование (Код)"), то сначала вам придется разобрать эту строку представления на составляющие части, а затем использовать их в запросе с множественными условиями.
Если доступен Уникальный Идентификатор (УИД), то Справочники.НайтиПоУникальномуИдентификатору() является самым быстрым и надежным способом.
Всегда старайтесь минимизировать количество операций чтения из базы данных и используйте параметризованные запросы для лучшей производительности и безопасности. Мы рассмотрели ключевые подходы, которые позволят вам эффективно решать задачи по поиску объектов в 1С:Предприятие 8.3.