Как сохранить значение реквизита на форме обработки в 1С?

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

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

Почему обработка не сохраняет значения «сама по себе»?

Для начала проанализируем разницу между объектами метаданных в 1С. Такие объекты, как Справочники или Документы, имеют физические таблицы в базе данных SQL. Когда мы нажимаем кнопку «Записать», платформа физически создает или обновляет запись в таблице базы данных.

Объект типа Обработка устроен иначе. Он предназначен для выполнения определенных действий (алгоритмов, расчетов, импорта/экспорта данных) и существует только в оперативной памяти компьютера в момент его работы. Обработка не имеет собственной таблицы в базе данных. Соответственно, стандартная кнопка «Записать и закрыть» на форме обработки по умолчанию не выполняет запись самого объекта в БД — ей просто некуда записывать эти данные.

Почему не сработало «Автоматическое сохранение данных в настройках»?

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

  1. Привязка к реквизитам объекта: Если ваш реквизит на форме имеет путь к данным вида Объект.ИмяРеквизита (то есть создан внутри самого объекта обработки, а не в списке реквизитов формы), стандартный механизм сохранения настроек формы его игнорирует. Данный механизм работает только с «чистыми» реквизитами самой формы.
  2. Логическая привязка к конкретному объекту: Механизм сохранения настроек формы сохраняет последнее введенное значение для конкретного пользователя глобально. Если вы откроете обработку для Заказа клиента №1, выберете срок «Срочно» и закроете форму, то при открытии обработки для Заказа клиента №2 на форме тоже отобразится «Срочно». Это логическая ошибка: статус срочности должен быть привязан к конкретному заказу, а не к форме обработки в целом.

Рассмотрим правильные и надежные способы реализации данной задачи.

Решение 1: Запись значения напрямую в документ «Заказ клиента» (Рекомендуемый способ)

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

Разберем по шагам, как это реализовать:

Шаг 1. Чтение данных при открытии обработки. При инициализации формы нам необходимо запросом или прямым обращением получить текущее значение срочности из заказа и поместить его в реквизит формы обработки.


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

Шаг 2. Запись данных при изменении или закрытии. При нажатии кнопки сохранения на форме обработки мы должны программно получить объект заказа, присвоить ему новое значение и записать его в базу данных.


&НаСервере
Процедура ЗаписатьСрочностьВДокументНаСервере()
    
    Если ЗначениеЗаполнено(Объект.СсылкаНаЗаказ) Тогда
        // Получаем объект документа для изменения
        ДокументОбъект = Объект.СсылкаНаЗаказ.ПолучитьОбъект();
        
        // Заполняем реквизит документа значением из формы обработки
        ДокументОбъект.Срочность = Объект.Срок;
        
        Попытка
            // Записываем документ в базу данных
            ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
            Сообщить("Срочность заказа успешно сохранена в документе!");
        Исключение
            ВызватьИсключение "Не удалось записать документ: " + ОписаниеОшибки();
        КонецПопытки;
    КонецЕсли;
    
КонецПроцедуры

Решение 2: Использование независимого регистра сведений

Что делать, если конфигурация находится на поддержке и мы не можем добавлять новые реквизиты в документ «Заказ клиента»? В таком случае идеальным решением будет создание независимого регистра сведений, например, РегистрСведений.СрочностьЗаказов.

Структура регистра будет следующей:

При таком подходе код чтения и записи на форме обработки будет выглядеть следующим образом:


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

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

Решение 3: Программное сохранение глобальных настроек формы

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

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


&НаСервере
Процедура ПриСохраненииДанныхВНастройкахНаСервере(Настройки)
    // Вручную помещаем реквизит объекта в структуру настроек
    Настройки.Вставить("ПредопределенныйСрок", Объект.Срок);
КонецПроцедуры

&НаСервере
Процедура ПриЗагрузкеДанныхИзНастроекНаСервере(Настройки)
    // Извлекаем сохраненное значение и присваиваем его реквизиту объекта
    СохраненноеЗначение = Неопределено;
    Если Настройки.Свойство("ПредопределенныйСрок", СохраненноеЗначение) Тогда
        Объект.Srok = СохраненноеЗначение;
    КонецЕсли;
КонецПроцедуры

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

← На главную