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

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

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

Анализируем причину проблемы

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

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

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

Решение №1: Использование события «ПередЗаписьюНаСервере»

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

Рассмотрим пример кода:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    // Проверим условие и заполним дату, если она не заполнена
    Если ТекущийОбъект.ДатаПоступленияПроекта = '00010101' Тогда
        ТекущийОбъект.ДатаПоступленияПроекта = ТекущийОбъект.Дата;
    КонецЕсли;
    
    // Любые изменения ТекущийОбъект здесь будут автоматически 
    // включены в общую транзакцию записи.
    
КонецПроцедуры

Важный нюанс: Обратите внимание, что мы работаем именно с ТекущийОбъект, а не с Объект. Реквизит формы Объект — это данные, которые видит пользователь на экране (данные формы). ТекущийОбъект — это объект прикладного типа (например, СправочникОбъект.Проекты), который непосредственно будет записан в таблицу БД.

Решение №2: Перенос логики в модуль объекта

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

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


Процедура ПередЗаписью(Отказ)
    
    // Проверка на ОбменДанными.Загрузка важна, чтобы не затирать данные 
    // при миграции между базами
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    Если Не ЗначениеЗаполнено(ДатаПоступленияПроекта) Тогда
        ДатаПоступленияПроекта = ТекущаяДата();
    КонецЕсли;
    
КонецПроцедуры

Почему не стоит создавать свою кнопку записи?

В ходе обсуждения часто звучит предложение «создать свою кнопку и описать там всё действие». Рассмотрим, почему это плохой совет:

  1. Вы теряете стандартное поведение платформы (проверку заполнения, обработку модифицированности, работу с расширениями).
  2. Это усложняет поддержку кода. Другой разработчик будет ожидать стандартную логику в стандартных событиях.
  3. Платформа 1С спроектирована так, чтобы минимизировать ручное управление транзакциями в формах.

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

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

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

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

← На главную