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