Разработка и Конфигурация · 11 мин
Как проверить, существует ли объект в 1С
Способы проверить существование объекта в 1С: Пустая(), НайтиПоКоду, НайтиПоНаименованию, запросы, ПолучитьОбъект. Примеры кода, ошибки и рекомендации.
Проверка существования объекта — одна из самых частых задач при разработке и доработке конфигураций 1С. Она нужна перед записью данных, при обмене, при поиске дублей и при обработке ссылок, полученных извне. Ошибка на этом этапе приводит либо к созданию дублей, либо к падению кода с исключением.
В 1С нет единого универсального метода «объект существует». Вместо этого используется набор приёмов: проверка ссылки на пустоту, поиск по ключевым полям, запросы к базе и обработка результата ПолучитьОбъект(). Выбор зависит от того, что у вас есть на входе — ссылка, код, наименование или набор реквизитов.
Ниже разобраны основные способы с примерами кода на встроенном языке, их ограничения и типичные ошибки. Материал применим к управляемым и обычным формам, к справочникам, документам и другим ссылочным типам.
Что значит «объект существует» в терминах 1С
В 1С различают объект и ссылку. Ссылка — это уникальный идентификатор записи в базе, объект — данные, загруженные в память для чтения или изменения. Проверка существования почти всегда сводится к проверке ссылки: есть ли в базе запись с таким идентификатором.
Важный нюанс: переменная может содержать ссылку, которая выглядит заполненной, но запись в базе уже удалена. Такие «битые ссылки» — частая ситуация после обменов и удаления данных. Поэтому проверка «ссылка не пустая» и проверка «объект существует в базе» — разные операции.
Проверка ссылки на пустоту
Самая простая проверка — метод Пустая() у ссылки. Он отвечает на вопрос «заполнена ли ссылка», но не «есть ли объект в базе»:
Если НоменклатураСсылка.Пустая() Тогда
Сообщить("Ссылка не заполнена");
КонецЕсли;
Для Неопределено и пустых значений в составных типах используйте комбинированную проверку:
Если Ссылка = Неопределено
Или Не ЗначениеЗаполнено(Ссылка) Тогда
Возврат;
КонецЕсли;
Функция ЗначениеЗаполнено() универсальна: она корректно обрабатывает Неопределено, пустые ссылки любых типов, пустые строки и нулевые даты. Её удобно использовать на входе процедур и функций.
Поиск объекта по коду и наименованию
Для справочников и планов есть встроенные методы поиска: НайтиПоКоду(), НайтиПоНаименованию(), НайтиПоРеквизиту(). Все они возвращают ссылку; если ничего не найдено — пустую ссылку.
НайденнаяСсылка = Справочники.Номенклатура.НайтиПоКоду("0000123");
Если НайденнаяСсылка.Пустая() Тогда
// Объекта с таким кодом нет — можно создавать новый
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Новая позиция";
НовыйЭлемент.Записать();
КонецЕсли;
Метод НайтиПоНаименованию() ищет точное совпадение без учёта регистра в большинстве случаев, но не по части строки. Для поиска по произвольному реквизиту используйте НайтиПоРеквизиту("ИНН", "7707083893"). Учтите: поиск по неиндексированному реквизиту на больших таблицах работает медленно.
Проверка существования объекта по ссылке через запрос
Чтобы убедиться, что ссылка реально существует в базе (не битая), выполните запрос:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ПроверяемаяСсылка);
Если Запрос.Выполнить().Пустой() Тогда
Сообщить("Объект в базе не найден (битая ссылка)");
КонецЕсли;
Это самый надёжный способ: запрос обращается напрямую к таблице и возвращает результат только при наличии записи. Конструкция ВЫБРАТЬ ПЕРВЫЕ 1 минимизирует нагрузку — сервер остановится после первой найденной строки.
- 1Проверьте переменную: Неопределено или ЗначениеЗаполнено()
- 2Проверьте Ссылка.Пустая() — отсеките незаполненные значения
- 3Выполните запрос ВЫБРАТЬ ПЕРВЫЕ 1 по ссылке
- 4Если запрос пустой — объект отсутствует, создайте его или запишите ошибку в журнал
- 5Только после этого вызывайте ПолучитьОбъект() для изменения данных
Проверка через ПолучитьОбъект и когда её избегать
Метод ПолучитьОбъект() загружает данные объекта в память. Если ссылка битая, он вернёт Неопределено:
Объект = Ссылка.ПолучитьОбъект();
Если Объект = Неопределено Тогда
Сообщить("Объект не найден в базе");
КонецЕсли;
Однако использовать ПолучитьОбъект() только ради проверки — плохая практика. Метод вычитывает из базы все данные объекта, включая табличные части, что в разы тяжелее запроса ВЫБРАТЬ ПЕРВЫЕ 1. В циклах по тысячам ссылок это даёт заметную просадку производительности. Вызывайте ПолучитьОбъект() только если объект действительно нужно прочитать или изменить.
Проверка существования документа по номеру и дате
Для документов метода «НайтиПоНомеру» в чистом виде нет — номер уникален только в пределах периода. Правильный путь — запрос с отбором по номеру и диапазону дат:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Реализация.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Номер = &Номер
| И Реализация.Дата МЕЖДУ &НачалоГода И &КонецГода";
Запрос.УстановитьПараметр("Номер", "000000123");
Запрос.УстановитьПараметр("НачалоГода", НачалоГода(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("КонецГода", КонецГода(ТекущаяДатаСеанса()));
Результат = Запрос.Выполнить();
ДокументСуществует = Не Результат.Пустой();
Обратите внимание: номер документа — строка, и в разных базах её длина и лидирующие нули могут отличаться. При загрузке из внешних систем приводите номер к формату базы-приёмника, иначе поиск не найдёт существующий документ и вы создадите дубль.
Сравнение способов проверки
Сравнение вариантов
Самая быстрая, без обращения к базе. Не защищает от битых ссылок — только проверяет заполненность переменной.
Подходит для поиска по ключевым полям справочников. Медленный на неиндексированных реквизитах, не работает для документов по номеру.
Универсальный и надёжный способ для любых условий, включая документы и составные отборы. Требует написания текста запроса.
Даёт готовый объект для работы, но тяжёлый: читает все данные. Оправдан только когда объект нужен для изменения.
Типичные ошибки и частые сценарии
Главная ошибка — путать проверку заполненности с проверкой существования. Код Если Не Ссылка.Пустая() пропускает битые ссылки, и следующее обращение к реквизитам возвращает «<Объект не найден>» вместо данных.
Вторая частая ошибка — поиск по наименованию как ключу. Наименования не уникальны: два контрагента могут называться одинаково. Для идентификации используйте код, ИНН, GUID или специальный реквизит-идентификатор.
Учёт пометки удаления
Если объект помечен на удаление, формально он существует, но использовать его в новых документах обычно нельзя. Добавьте в запрос условие И НЕ Таблица.ПометкаУдаления или проверяйте реквизит ПометкаУдаления у найденной ссылки.
Проверка по GUID из другой базы
При обмене объект часто ищут по уникальному идентификатору. Получить ссылку по GUID можно через Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаGUID)), а затем запросом проверить её существование — сама по себе полученная так ссылка всегда непустая, даже если объекта нет.
Как проверить результат
Ссылка не пустая, запрос по ней находит запись, ПометкаУдаления = Ложь
Ссылка непустая, но запрос пустой — это битая ссылка, объект нужно создавать заново
После Записать() повторный поиск находит ровно один объект
Повторный поиск находит несколько объектов — в логике создания дубль, проверьте условия поиска
Используется один запрос с условием В(&МассивСсылок) вместо запроса в цикле
Запрос выполняется на каждой итерации — время обработки растёт линейно и нагружает сервер
FAQ
Чем отличается Пустая() от ЗначениеЗаполнено()?
Метод Пустая() есть только у ссылок и проверяет, равна ли ссылка пустому значению своего типа. ЗначениеЗаполнено() — универсальная функция: она корректно обрабатывает Неопределено, пустые ссылки, пустые строки, ноль и пустые даты. Для проверки входных параметров произвольного типа используйте ЗначениеЗаполнено().
Как проверить существование объекта, если есть только GUID из другой базы?
Сформируйте ссылку через ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаGUID)) — она всегда будет непустой. Затем выполните запрос ВЫБРАТЬ ПЕРВЫЕ 1 по этой ссылке: если запрос пустой, объекта в базе нет и его нужно создавать с привязкой к этому же идентификатору.
Почему НайтиПоНаименованию не находит объект, который точно есть?
Чаще всего причины — лишние пробелы, неразрывные пробелы из внешних файлов, разный регистр спецсимволов или то, что метод ищет только точное совпадение всей строки. Очистите строку через СокрЛП() и, при необходимости, используйте запрос с ПОДОБНО для частичного поиска.
Можно ли проверить существование объекта без запроса в цикле по тысяче ссылок?
Да. Соберите все ссылки в массив и выполните один запрос с условием ГДЕ Ссылка В(&МассивСсылок). Результат выгрузите в таблицу значений и дальше ищите по ней через Найти() — это на порядки быстрее, чем запрос на каждой итерации.
Что вернёт обращение к реквизиту битой ссылки?
Обращение к реквизитам битой ссылки не вызывает исключение — платформа возвращает строку вида «<Объект не найден> (…guid…)» для ссылочных полей или значения по умолчанию. Это опасно тем, что ошибка проявляется не сразу, а в виде некорректных данных в отчётах и документах.
Нужно ли проверять пометку удаления при поиске объекта?
Да, если найденный объект будет использоваться в новых документах или справочниках. Помеченный на удаление объект формально существует, но его использование приведёт к ошибкам при удалении помеченных. Добавьте в запрос условие НЕ ПометкаУдаления или обработайте этот случай отдельно — например, снимите пометку или создайте новый элемент.
Что важно запомнить
Пустая() проверяет заполненность переменной, а не существование записи в базе. Реальное существование подтверждает только запрос ВЫБРАТЬ ПЕРВЫЕ 1 или ПолучитьОбъект() с проверкой на Неопределено. Ищите объекты по уникальным ключам (код, GUID, ИНН), учитывайте пометку удаления и не вызывайте ПолучитьОбъект() в циклах ради одной проверки.