К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как в 1С определить, что элемент справочника новый

Как в 1С определить, что элемент справочника новый: методы ЭтоНовый(), Ссылка.Пустая() и НовыйОбъект в форме, примеры кода, типичные ошибки и FAQ.

Задача определить, что элемент справочника ещё не записан в базу, возникает постоянно: при программном создании данных, в обработчиках событий формы, при обмене и при проверках перед записью. В 1С для этого есть несколько механизмов, и выбор зависит от контекста — работаете вы с объектом на сервере, со ссылкой или с формой элемента.

Основной инструмент — метод ЭтоНовый(), который возвращает Истина, если объект ещё не имеет записи в базе данных. Однако у него есть ограничения: он применим к объектам (справочник-объектам), но не к ссылкам. Для ссылок используется другая проверка — на пустую ссылку или сравнение с уникальным идентификатором.

Ниже разобраны все рабочие способы с примерами кода, типичные ошибки и границы применения каждого подхода.

Проверка через метод ЭтоНовый() у объекта справочника

Когда вы создаёте элемент программно через Справочники.Номенклатура.СоздатьЭлемент() или получаете объект методом ПолучитьОбъект(), у вас на руках объект типа «СправочникОбъект». Именно у него есть метод ЭтоНовый().

НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();

НовыйЭлемент.Наименование = "Тестовый товар";

Если НовыйЭлемент.ЭтоНовый() Тогда

Сообщить("Элемент ещё не записан в базу");

КонецЕсли;

НовыйЭлемент.Записать();

Если Не НовыйЭлемент.ЭтоНовый() Тогда

Сообщить("Теперь элемент записан, ссылка: " + НовыйЭлемент.Ссылка);

КонецЕсли;

Важно понимать механику: до вызова Записать() у объекта уже может быть установлена ссылка (методом УстановитьСсылкуНового() или автоматически), но записи в базе ещё нет. ЭтоНовый() проверяет именно факт наличия записи, а не наличие ссылки.

После успешной записи метод вернёт Ложь. Если запись завершилась с ошибкой и была откачена транзакцией — объект останется «новым».

Проверка по ссылке: Пустая() и ПолучитьОбъект()

Во многих сценариях у вас есть только ссылка, а не объект. Например, значение реквизита документа или параметр, переданный в функцию. Здесь работают два подхода.

Первый — проверка на пустую ссылку. Она показывает, что ссылка не заполнена, но не гарантирует, что элемент «новый» в смысле «не записан»: незаписанный объект может уже иметь непустую ссылку.

Если ЭлементСсылка.Пустая() Тогда

// Ссылка не заполнена вовсе

КонецЕсли;

// Альтернатива:

Если Не ЗначениеЗаполнено(ЭлементСсылка) Тогда

// То же самое

КонецЕсли;

Второй способ — получить объект и проверить его. Метод ПолучитьОбъект() вернёт Неопределено, если по ссылке нет записи в базе (битая ссылка или объект ещё не записан):

ЭлементОбъект = ЭлементСсылка.ПолучитьОбъект();

Если ЭлементОбъект = Неопределено Тогда

// Записи в базе нет: либо элемент новый, либо ссылка битая

КонецЕсли;

Учтите: ПолучитьОбъект() — дорогая операция, она читает всю запись из базы. В циклах по тысячам ссылок это заметно замедлит код. Если нужно только проверить существование, эффективнее запрос к таблице справочника.

Определение нового элемента в форме

В модуле формы элемента справочника контекст другой: данные доступны через реквизит Объект. Проверка на новый элемент обычно нужна в обработчиках ПриСозданииНаСервере и ПриОткрытии — например, чтобы подставить значения по умолчанию только для новых элементов.

Проверка через ссылку объекта формы

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

Если Объект.Ссылка.Пустая() Тогда

// Открыт новый, ещё не записанный элемент

Объект.Ответственный = Пользователи.ТекущийПользователь();

КонецЕсли;

КонецПроцедуры

Для нового элемента в форме Объект.Ссылка всегда пустая, пока пользователь не нажал «Записать». Это надёжный признак, потому что форма при открытии существующего элемента сразу получает его ссылку.

Проверка через параметр Ключ

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

Если Параметры.Ключ.Пустая() Тогда

// Форма открыта для нового элемента

КонецЕсли;

КонецПроцедуры

Параметр Ключ содержит ссылку, с которой открыта форма. Для нового элемента он пуст. Оба способа равнозначны; на практике чаще используют Объект.Ссылка.Пустая().

Порядок действий при заполнении нового элемента в форме
  1. 1
    В обработчике ПриСозданииНаСервере проверьте Объект.Ссылка.Пустая()
  2. 2
    Если ссылка пустая — заполните значения по умолчанию (ответственного, дату, группу)
  3. 3
    Не перезаписывайте поля, если элемент существующий — иначе сотрёте данные пользователя
  4. 4
    После записи проверка вернёт Ложь, и повторного заполнения не произойдёт

Сравнение способов проверки

Разные ситуации требуют разных инструментов. Сводное сравнение поможет выбрать правильный.

СпособКонтекстЧто показываетОграничение
Объект.ЭтоНовый()СправочникОбъектОбъект не записан в базуНужен именно объект, не ссылка
Ссылка.Пустая()СсылкаСсылка не заполненаНе отличает незаписанный объект с установленной ссылкой
Ссылка.ПолучитьОбъект() = НеопределеноСсылкаЗаписи в базе нетДорогая операция чтения
Объект.Ссылка.Пустая() в формеФорма элементаОткрыт новый элементТолько в контексте формы
Запрос к таблицеСсылкаСуществование записиТребует написания запроса
Маршрут решения

Как выбрать способ

У вас объект, созданный через СоздатьЭлемент() или ПолучитьОбъект()Используйте ЭтоНовый() — самый точный способ
У вас только ссылка и нужна быстрая проверка заполненностиИспользуйте Ссылка.Пустая() или ЗначениеЗаполнено()
Нужно проверить существование записи по ссылке в циклеИспользуйте запрос к таблице справочника, а не ПолучитьОбъект()
Работаете в форме элементаПроверяйте Объект.Ссылка.Пустая() в ПриСозданииНаСервере

Проверка существования элемента запросом

Когда нужно определить, существует ли элемент с конкретной ссылкой, и при этом не читать весь объект, оптимален запрос:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ ПЕРВЫЕ 1

| Номенклатура.Ссылка КАК Ссылка

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ПроверяемаяСсылка);

Если Запрос.Выполнить().Пустой() Тогда

// Записи с такой ссылкой в базе нет

КонецЕсли;

Такой запрос читает минимум данных и подходит для массовых проверок. Обратите внимание: он отвечает на вопрос «есть ли запись в базе», что для битых ссылок и незаписанных объектов даёт одинаковый результат «нет».

Особые случаи: УстановитьСсылкуНового и обмен данными

Метод УстановитьСсылкуНового() назначает объекту ссылку до записи. Это нужно, когда ссылку на новый элемент надо использовать заранее — например, записать в другой объект. После этого Ссылка.Пустая() вернёт Ложь, хотя элемент всё ещё новый. Единственная корректная проверка здесь — ЭтоНовый().

НовыйЭлемент = Справочники.Контрагенты.СоздатьЭлемент();

НоваяСсылка = Справочники.Контрагенты.ПолучитьСсылку(Новый УникальныйИдентификатор);

НовыйЭлемент.УстановитьСсылкуНового(НоваяСсылка);

// НоваяСсылка.Пустая() = Ложь, но записи в базе ещё нет

// НовыйЭлемент.ЭтоНовый() = Истина

В планах обмена и подписках на события (ПриЗаписи, ОбработкаЗаполнения) также применяйте ЭтоНовый(): в момент ПередЗаписью объект ещё не сохранён, и метод корректно покажет, создаётся элемент или изменяется существующий.

Типичные ошибки при проверке нового элемента

  • Вызов ЭтоНовый() у ссылки. У типа СправочникСсылка этого метода нет — возникнет ошибка выполнения. Сначала получите объект.
  • Проверка ссылки вместо объекта после УстановитьСсылкуНового(). Ссылка уже непустая, но записи нет — логика «существующего» элемента сработает неверно.
  • ПолучитьОбъект() в цикле. Массовая проверка ссылок через получение объектов многократно замедляет обработку. Используйте запрос.
  • Заполнение полей в форме без проверки. Если не проверить Объект.Ссылка.Пустая() в ПриСозданииНаСервере, значения по умолчанию перезапишут данные существующего элемента при каждом открытии.
  • Путаница между «новый» и «пустая ссылка». Пустая ссылка — это незаполненное значение реквизита, а новый элемент — объект без записи в базе. Это разные состояния.
Типичные ошибки
01
Вызов ЭтоНовый() у ссылки — ошибка «Метод объекта не обнаружен» во время выполнения
02
Проверка Пустая() после УстановитьСсылкуНового — незаписанный элемент принят за существующий
03
Массовые вызовы ПолучитьОбъект() в цикле — резкое падение производительности
04
Заполнение полей в ПриСозданииНаСервере без проверки — затирание данных существующих элементов
Контрольные точки

Как проверить результат

Код с СоздатьЭлемент() до Записать()
Норма

ЭтоНовый() возвращает Истина

Тревожный признак

Возвращает Ложь — объект был получен из базы, а не создан

Тот же объект после успешной Записать()
Норма

ЭтоНовый() возвращает Ложь, ссылка заполнена

Тревожный признак

Возвращает Истина — запись не прошла, ищите ошибку транзакции

Форма существующего элемента
Норма

Объект.Ссылка.Пустая() = Ложь, данные не перезаполняются

Тревожный признак

Проверка срабатывает как для нового — поля затираются значениями по умолчанию

Краткие итоги

Базовое правило простое: есть объект — используйте ЭтоНовый(), есть только ссылка — проверяйте Пустая() или существование записи запросом. В форме элемента опирайтесь на Объект.Ссылка.Пустая() в обработчике создания на сервере. А если в коде встречается УстановитьСсылкуНового(), доверять можно только методу ЭтоНовый().

Итог

Что важно запомнить

ЭтоНовый() — метод объекта, а не ссылки. Ссылка проверяется через Пустая() или запрос к базе. После УстановитьСсылкуНового() корректна только проверка ЭтоНовый(). В форме нового элемента Объект.Ссылка всегда пустая до первой записи.

Частые вопросы

Чем ЭтоНовый() отличается от проверки Ссылка.Пустая()?

ЭтоНовый() проверяет наличие записи в базе данных и вызывается у объекта. Пустая() проверяет заполненность самой ссылки. Если объекту назначили ссылку через УстановитьСсылкуНового(), ссылка непустая, но записи в базе нет — результаты проверок разойдутся.

Можно ли вызвать ЭтоНовый() в модуле формы элемента?

Напрямую у реквизита формы Объект вызвать ЭтоНовый() нельзя — это данные формы, а не СправочникОбъект. В форме используйте проверку Объект.Ссылка.Пустая() или Параметры.Ключ.Пустая().

Как проверить, новый ли элемент, в подписке ПередЗаписью?

В обработчике подписки параметр Источник — это объект, поэтому вызывайте Источник.ЭтоНовый(). В момент ПередЗаписью метод корректно покажет, создаётся элемент или изменяется существующий.

Что вернёт ПолучитьОбъект() для незаписанного элемента?

Метод вернёт Неопределено, если по ссылке нет записи в базе. Тот же результат будет для битой ссылки, поэтому по одному этому признаку отличить «новый» элемент от «битого» нельзя.

Почему после Записать() ЭтоНовый() всё равно возвращает Истина?

Значит, запись фактически не выполнилась: произошло исключение, отказ в обработчике ПередЗаписью или откат транзакции. Проверьте код записи и журнал регистрации на наличие ошибок.

Как массово проверить, какие ссылки из списка существуют в базе?

Используйте запрос с условием «Ссылка В (&СписокСсылок)» и сравните результат с исходным списком. Это значительно быстрее, чем вызывать ПолучитьОбъект() для каждой ссылки.