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