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