Как автоматически записывать данные в регистр сведений сразу после изменения реквизита на форме

Программист IT и автоматизация бизнеса
← На главную

В процессе разработки интерфейсов на платформе «1С:Предприятие 8» часто возникает задача улучшения пользовательского опыта (UX). Типовое поведение системы предполагает, что пользователь вносит изменения в данные на форме, а затем нажимает кнопку «Записать» или «Записать и закрыть». Однако в некоторых сценариях, например при работе с быстрыми настройками или оперативными регистрами, удобнее инициировать сохранение данных немедленно, как только значение реквизита было изменено. Рассмотрим подробнее, как реализовать этот механизм правильно и какие нюансы следует учитывать.

Метод 1: Использование стандартного метода формы Записать()

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

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


&НаКлиенте
Процедура ИмяРеквизитаПриИзменении(Элемент)
    
    // Прямой вызов записи формы
    ЭтотОбъект.Записать();
    
КонецПроцедуры

Разберем, что происходит в этот момент. Вызов ЭтотОбъект.Записать() инициирует стандартный серверный цикл записи. Платформа автоматически выполняет проверку заполнения, вызывает серверные события ПередЗаписьюНаСервере, ПриЗаписиНаСервере и ПослеЗаписиНаСервере. Это самый безопасный метод, так как он корректно сбрасывает флаг Модифицированность формы (убирает «звездочку» в заголовке) и обновляет состояние данных.

Метод 2: Использование команды ЗаписатьВФорме()

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


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

Этот подход позволяет более гибко управлять процессом, если форма сложная и содержит множество проверок.

Метод 3: Прямая работа с менеджером записи

Как отмечалось в обсуждении, у формы есть реквизит, содержащий объект записи. Мы можем обратиться к нему напрямую. Выясним причину, почему этот способ стоит использовать с осторожностью. Если вы вызовете Записать() непосредственно у объекта Запись в серверном контексте, форма может «не узнать» о том, что данные в базе уже обновлены, если не выполнить дополнительные действия по синхронизации.


&НаСервере
Процедура ЗаписатьЗаписьНаСервере()
    
    // Обращение к основному реквизиту формы "Запись"
    ОбъектЗаписи = РеквизитФормыВЗначение("Запись");
    ОбъектЗаписи.Записать();
    ЗначениеВРеквизитФормы(ОбъектЗаписи, "Запись");
    
КонецПроцедуры

Однако, как правило, в формах записи регистра лучше придерживаться методов самой формы (Метод 1), так как они инкапсулируют всю необходимую логику обновления интерфейса.

Важные проверки перед записью

Посмотрим на ситуацию со стороны стабильности системы. Если мы будем пытаться записывать данные при каждом изменении, мы можем столкнуться с ошибками «Поле объекта не обнаружено» или «Не заполнено обязательное поле». В регистре сведений критически важно наличие всех измерений, входящих в ключ записи. Если пользователь изменил ресурс, но еще не выбрал измерение, попытка записи приведет к ошибке.

Проанализируем пример безопасной записи с предварительной проверкой:


&НаКлиенте
Процедура ПроверитьИЗаписать()
    
    // Проверяем, что ключевые поля заполнены
    Если ЗначениеЗаполнено(Запись.Организация) 
        И ЗначениеЗаполнено(Запись.Номенклатура) Тогда
        
        ЭтотОбъект.Записать();
        
    КонецЕсли;
    
КонецПроцедуры

Такой подход предотвратит раздражающие пользователя сообщения об ошибках в процессе ввода данных.

Оптимизация производительности: Обработчик ожидания

Если форма содержит много реквизитов и пользователь вводит данные быстро, частая запись (на каждое изменение) может создать лишнюю нагрузку на сервер и вызвать кратковременные зависания («фризы») интерфейса. Чтобы избежать этого, рассмотрим применение обработчика ожидания.

Идея заключается в том, чтобы не записывать данные мгновенно, а подождать, например, 1-2 секунды после последнего изменения. Если пользователь за это время ничего больше не нажал — записываем.


&НаКлиенте
Процедура ИмяРеквизитаПриИзменении(Элемент)
    
    // Отключаем предыдущий обработчик, если он был запущен
    ОтключитьОбработчикОжидания("ВыполнитьОтложеннуюЗапись");
    
    // Запускаем новый отсчет на 1.5 секунды
    ПодключитьОбработчикОжидания("ВыполнитьОтложеннуюЗапись", 1.5, Истина);
    
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьОтложеннуюЗапись()
    
    Если Модифицированность Тогда
        ЭтотОбъект.Записать();
    КонецЕсли;
    
КонецПроцедуры

Этот метод значительно повышает отзывчивость интерфейса, сохраняя при этом требуемую функциональность «автосохранения».

Особенности различных типов регистров

При реализации автоматической записи важно учитывать структуру самого регистра:

  1. Периодические регистры: Обязательно убедитесь, что поле Период заполнено корректным значением. Запись с пустой датой может привести к логическим ошибкам в учете.
  2. Подчиненные регистратору: Если ваш регистр записывается только через документы, попытка вызвать Записать() в форме записи регистра напрямую, скорее всего, будет заблокирована логикой конфигурации. В таких случаях данные меняются через набор записей в контексте документа-владельца.
  3. Режим записи: Помните, что запись через менеджер записи (который является основой формы) всегда работает по принципу «одна строка за раз». Если ваша задача требует изменения сразу группы записей, использование формы записи одного элемента может быть не лучшим решением — здесь стоит посмотреть в сторону формы списка и объекта РегистрСведенийНаборЗаписей.

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

← На главную