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