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