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