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