Почему не сохраняются данные при изменении реквизита в процедуре ПередЗаписьюНаСервере?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Разберем архитектуру: Объект vs ТекущийОбъект

Для начала проанализируем, с чем мы работаем. В модуле формы существует реквизит Объект. Это не прямой доступ к записи в таблице базы данных, а ДанныеФормыСтруктура — своего рода «слепок» данных, который отображается пользователю в элементах интерфейса. Когда вы меняете значение в поле ввода на форме, платформа синхронизирует состояние этого «слепка».

Однако процесс записи объекта в базу — это сложный механизм. Когда пользователь нажимает кнопку «Записать», платформа инициирует цепочку событий. Важнейшим этапом является вызов обработчика ПередЗаписьюНаСервере. В этот момент у нас появляется важный параметр: ТекущийОбъект.

Важное отличие: ТекущийОбъект — это уже экземпляр объекта (например, СправочникОбъект), который платформа подготовила специально для записи в базу данных. Если вы вносите изменения в Объект (реквизит формы) после начала процесса записи, эти изменения не попадут в ТекущийОбъект, так как процесс копирования данных из формы в «черновик» записи уже завершен.

Как правильно изменять данные перед записью

Чтобы гарантированно записать данные, полученные, например, из внешней системы или в результате вычислений, необходимо обращаться непосредственно к параметру ТекущийОбъект. Рассмотрим пример реализации:

Представим, что мы получаем данные из внешней системы (ФИС) и хотим записать их в реквизит IDжильца:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПарамыЗаписи)
    // Открываем сессию и получаем данные
    ЗначениеСессии = _ФИС.ОткрытьСессию("SYSTEM", "parsec", "parsec");
    КлючСессииДляИС = _ФИС.ОбъектПоТипу("guid", ЗначениеСессии.SessionID);
    
    // Создаем жителя
    Житель = _ФИС.СоздатьЖителя(КлючСессииДляИС, ТекущийОбъект.Фамилия, ТекущийОбъект.Имя, ТекущийОбъект.Отчество, ЗначениеСессии.RootOrgUnitID);
    
    // ВАЖНО: записываем результат в ТекущийОбъект, а не в Объект
    ТекущийОбъект.IDжильца = Житель.Value;
    
    // Закрываем сессию
    _ФИС.ЗакрытьСессию(КлючСессииДляИС);
КонецПроцедуры

Почему это работает

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

Итоги и рекомендации

Проанализировав ситуацию, мы пришли к выводу, что работа с Объект внутри обработчиков записи — это типичная ошибка проектирования. Запомните главное правило: если вам нужно модифицировать данные в момент сохранения, всегда используйте ТекущийОбъект.

Разберем еще один нюанс: если вы меняете Объект.Реквизит до вызова записи (например, по нажатию другой кнопки на форме), это изменит отображение на экране. Но если вы хотите быть уверены, что в базу попадет именно то значение, которое вам нужно, в момент записи «переложите» его в ТекущийОбъект. Это обеспечит надежность и предсказуемость работы вашего кода.

← На главную