Как определить, создается новый документ или открывается уже существующий объект в 1С?

Программист 1С v8.3 (Управляемые формы)
← К списку

При разработке в 1С часто возникает необходимость понять, работает ли пользователь с новым, еще не записанным в базу данных объектом (например, документом, справочником) или же открывает уже существующий. Это знание критически важно для корректного выполнения логики: предзаполнения полей, инициализации данных, проверки уникальности и многих других операций. Давайте вместе разберем основные подходы и нюансы, которые помогут нам точно определить "новизну" объекта.

Основные подходы к решению проблемы

Мы выясним, что в 1С существует несколько эффективных способов для решения этой задачи, каждый из которых имеет свои особенности и области применения. Выбор конкретного метода часто зависит от контекста: находимся ли мы в модуле объекта, в модуле формы, работаем на клиенте или на сервере, а также используем ли мы обычные или управляемые формы. Рассмотрим их подробнее.

  1. Использование метода ЭтоНовый()
  2. Метод ЭтоНовый() является одним из наиболее прямолинейных и интуитивно понятных способов проверки. Он возвращает значение Истина, если объект еще не был записан в информационную базу, и Ложь, если объект уже существует и имеет ссылку в базе.

    В контексте обычных форм, ЭтоНовый() широко применялся и продолжает использоваться для проверки новизны объекта. Вы могли видеть его в модулях объектов или форм обычных приложений.

    В управляемых формах ситуация немного отличается. На клиентской стороне напрямую вызвать ЭтоНовый() у реквизита формы типа "Объект" не получится. Для того чтобы использовать этот метод в управляемой форме на сервере, нам потребуется сначала получить сам объект из реквизита формы. Для этого мы используем метод РеквизитФормыВЗначение("Объект"), а затем уже у полученного объекта вызываем ЭтоНовый(). Давайте посмотрим на пример:

    
    // Пример использования в модуле формы управляемого приложения (серверный контекст)
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
        // Получаем объект, с которым связана форма
        ОбъектДокумента = РеквизитФормыВЗначение("Объект");
            
        Если ОбъектДокумента.ЭтоНовый() Тогда
            // Это новый документ, выполняем действия для нового
            Сообщить("Создается новый документ.");
            // Например, заполняем какие-то поля по умолчанию
            ОбъектДокумента.Дата = ТекущаяДата();
        Иначе
            // Документ уже существует, открывается для просмотра/редактирования
            Сообщить("Открывается существующий документ.");
        КонецЕсли;
            
        // Передаем изменения обратно в реквизит формы
        ЗначениеВРеквизитФормы(ОбъектДокумента, "Объект");
    КонецПроцедуры
    
  3. Анализ параметра формы Параметры.Ключ.Пустая()
  4. Этот способ является рекомендуемым для управляемых форм, особенно в серверных обработчиках, таких как ПриСозданииНаСервере(). Когда форма открывается, платформа передает ей параметры. Если форма открывается для существующего объекта, то в параметре Параметры.Ключ будет содержаться ссылка на этот объект. Если же мы создаем новый объект, то Параметры.Ключ будет пустым.

    Таким образом, проверка Параметры.Ключ.Пустая() позволяет нам надежно определить, новый ли объект. Рассмотрим пример использования:

    
    // Пример использования в модуле формы управляемого приложения (серверный контекст)
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
        Если Параметры.Ключ.Пустая() Тогда
            // Это новый объект (документ, элемент справочника и т.д.)
            Сообщить("Форма открыта для создания нового объекта.");
            // Здесь мы можем инициализировать поля формы
            Объект.Организация = УправлениеПользователями.ПолучитьОсновнуюОрганизацию();
        Иначе
            // Форма открыта для существующего объекта
            Сообщить("Форма открыта для существующего объекта: " + Параметры.Ключ);
            // Дополнительные действия для существующего объекта
        КонецЕсли;
    КонецПроцедуры
    

    Мы видим, что этот подход очень удобен, поскольку он не требует дополнительного получения объекта из реквизита формы и является одним из основных механизмов, предлагаемых 1С для управляемых форм.

  5. Проверка заполненности ссылки объекта: Объект.Ссылка.Пустая() или Не ЗначениеЗаполнено(Объект.Ссылка)
  6. Ключевое отличие нового, еще не записанного в базу данных объекта от уже существующего заключается в том, что у нового объекта поле Ссылка будет пустым. Как только объект записывается, ему присваивается уникальная ссылка. Основываясь на этом, мы можем использовать следующие проверки:

    Этот метод хорошо работает как в модулях объектов, так и в управляемых формах, если основной реквизит формы является объектом конфигурации, имеющим ссылку. Давайте рассмотрим пример:

    
    // Пример использования в модуле объекта или в модуле формы (серверный контекст)
    // Предполагаем, что "Объект" - это основной реквизит формы или сам объект
        
    Если Объект.Ссылка.Пустая() Тогда
        Сообщить("Объект новый (ссылка пустая).");
    Иначе
        Сообщить("Объект существует (ссылка заполнена).");
    КонецЕсли;
        
    // Или с использованием функции ЗначениеЗаполнено()
    Если Не ЗначениеЗаполнено(Объект.Ссылка) Тогда
        Сообщить("Объект новый (ссылка не заполнена).");
    Иначе
        Сообщить("Объект существует (ссылка заполнена).");
    КонецЕсли;
    

    Типовые конфигурации 1С, такие как УТ или ERP, часто используют именно проверку Если Не ЗначениеЗаполнено(Объект.Ссылка) Тогда, что подтверждает ее надежность и распространенность.

Важный нюанс: Механизм УстановитьСсылкуНового()

Мы должны быть внимательны к одному особому случаю, который может повлиять на результаты наших проверок. В 1С существует метод УстановитьСсылкуНового(). Этот метод позволяет программно присвоить новому объекту (который еще не записан в базу) заранее определенную ссылку.

Для чего это нужно? Чаще всего УстановитьСсылкуНового() применяется в сценариях обмена данными, когда необходимо синхронизировать объекты по уникальному идентификатору (UID) или когда требуется заранее зарезервировать ссылку для объекта до его фактической записи в базу.

Важный момент: После вызова УстановитьСсылкуНового() свойство Объект.Ссылка перестает быть пустым, даже если объект физически еще не записан в базу данных. В таких случаях простая проверка Объект.Ссылка.Пустая() или Не ЗначениеЗаполнено(Объект.Ссылка) может дать ложноотрицательный результат для объекта, который с точки зрения пользователя является "новым", но уже имеет установленную ссылку. В таких ситуациях, если логика требует именно определения "первичной записи" объекта, метод ЭтоНовый() (при условии корректного получения объекта) может оказаться более точным, так как он проверяет факт наличия объекта в базе, а не только заполненность ссылки.

Контекст событий формы и объекта: Где и что проверять

Для определения новизны объекта крайне важно учитывать, в каком именно обработчике события мы находимся. Давайте проанализируем ситуацию по шагам:

  1. Событие ОбработкаЗаполнения() в модуле объекта

    Это событие вызывается только при создании новых объектов. Оно специально предназначено для первоначального заполнения данных нового объекта. Внутри этого обработчика вам не нужно дополнительно проверять, новый ли это объект, поскольку само событие гарантирует, что мы работаем с только что создаваемым экземпляром.

    Параметр ДанныеЗаполнения, передаваемый в этот обработчик, может иметь различные типы: Неопределено (при обычном интерактивном создании), Ссылка (при вводе на основании) или Структура (при создании из отбора списка или программно с передачей структуры).

    
    // Пример в модуле объекта
    Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
        // Здесь мы точно знаем, что объект новый
        Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда
            ЭтотОбъект.Организация = ДанныеЗаполнения.Организация;
            ЭтотОбъект.Контрагент = ДанныеЗаполнения.Контрагент;
        Иначе
            ЭтотОбъект.Дата = ТекущаяДата();
            ЭтотОбъект.Ответственный = Пользователи.ТекущийПользователь();
        КонецЕсли;
    КонецПроцедуры
    
  2. Событие ПриСозданииНаСервере() в модуле формы

    Этот обработчик события формы вызывается при создании формы как для новых, так и для существующих объектов. Он идеален для окончательной подготовки формы (ее представления) к открытию. Именно здесь мы обычно и выполняем проверку на новизну.

    Для определения, новый ли объект, внутри ПриСозданииНаСервере() мы настоятельно рекомендуем использовать Параметры.Ключ.Пустая(), как мы уже рассматривали выше. Это наиболее надежный и производительный способ в управляемых формах.

  3. Событие ПриЧтенииНаСервере() в модуле формы

    Этот обработчик события формы вызывается при открытии формы существующего объекта после его чтения из базы данных. Он используется для подготовки дополнительных данных, зависящих от уже прочитанных данных объекта.

    В этом обработчике, как правило, не требуется проверять "новизну" объекта, так как само событие предназначено для работы с уже существующими объектами. Если вы оказались в ПриЧтенииНаСервере(), это уже означает, что объект не новый.

Резюме и рекомендации

Мы с вами подробно разобрали различные подходы к определению новизны объекта в 1С. Чтобы сделать правильный выбор, давайте подведем итоги:

  1. Для определения нового объекта в управляемых формах наиболее надежными и рекомендуемыми способами являются Параметры.Ключ.Пустая() (в событии ПриСозданииНаСервере()) или Не ЗначениеЗаполнено(Объект.Ссылка) (если уверены, что УстановитьСсылкуНового() не используется).
  2. Если нам требуется выполнить действия, связанные с первоначальным заполнением данных именно нового объекта, всегда используйте событие ОбработкаЗаполнения() в модуле объекта. В этом событии нет необходимости дополнительно проверять новизну.
  3. Будьте особенно внимательны при использовании проверки Объект.Ссылка.Пустая() в сценариях, где применяется метод УстановитьСсылкуНового(). В таких случаях ссылка может быть уже установлена, но объект при этом еще не записан в базу. В этих специфических ситуациях ЭтоНовый() (при корректном получении объекта) может дать более точный результат.

Надеемся, что этот подробный разбор поможет вам уверенно ориентироваться в логике определения новизны объектов в ваших 1С-разработках!

← К списку