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