При разработке в среде 1С:Предприятие начинающие программисты часто сталкиваются с проблемой: при добавлении реквизита на форму обработки, заполнении его значения и закрытии формы, при повторном открытии поле оказывается пустым. Даже включение стандартных флажков сохранения настроек не всегда приносит желаемый результат. В этой статье мы подробно разберем, почему так происходит, изучим архитектурные особенности платформ 1С и рассмотрим несколько надежных способов сохранения данных.
Для начала проанализируем разницу между объектами метаданных в 1С. Такие объекты, как Справочники или Документы, имеют физические таблицы в базе данных SQL. Когда мы нажимаем кнопку «Записать», платформа физически создает или обновляет запись в таблице базы данных.
Объект типа Обработка устроен иначе. Он предназначен для выполнения определенных действий (алгоритмов, расчетов, импорта/экспорта данных) и существует только в оперативной памяти компьютера в момент его работы. Обработка не имеет собственной таблицы в базе данных. Соответственно, стандартная кнопка «Записать и закрыть» на форме обработки по умолчанию не выполняет запись самого объекта в БД — ей просто некуда записывать эти данные.
В управляемых формах 1С есть стандартное свойство формы АвтоматическоеСохранениеДанныхВНастройках. Однако автор темы столкнулся с тем, что даже при включении этого свойства и выборе реквизита данные не сохраняются. Выясним основные причины этой проблемы:
Объект.ИмяРеквизита (то есть создан внутри самого объекта обработки, а не в списке реквизитов формы), стандартный механизм сохранения настроек формы его игнорирует. Данный механизм работает только с «чистыми» реквизитами самой формы.Рассмотрим правильные и надежные способы реализации данной задачи.
Если статус «Срок» (срочность) логически характеризует сам заказ клиента, то и храниться он должен в самом документе Документ.ЗаказКлиента. Мы можем вынести этот реквизит на форму обработки, но при сохранении записывать его в базу данных внутри объекта заказа.
Разберем по шагам, как это реализовать:
Шаг 1. Чтение данных при открытии обработки. При инициализации формы нам необходимо запросом или прямым обращением получить текущее значение срочности из заказа и поместить его в реквизит формы обработки.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, заполнена ли ссылка на заказ в обработке
Если ЗначениеЗаполнено(Объект.СсылкаНаЗаказ) Тогда
// Считываем значение реквизита "Срочность" из документа заказа
Объект.Срок = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Объект.СсылкаНаЗаказ, "Срочность");
КонецЕсли;
КонецПроцедуры
Шаг 2. Запись данных при изменении или закрытии. При нажатии кнопки сохранения на форме обработки мы должны программно получить объект заказа, присвоить ему новое значение и записать его в базу данных.
&НаСервере
Процедура ЗаписатьСрочностьВДокументНаСервере()
Если ЗначениеЗаполнено(Объект.СсылкаНаЗаказ) Тогда
// Получаем объект документа для изменения
ДокументОбъект = Объект.СсылкаНаЗаказ.ПолучитьОбъект();
// Заполняем реквизит документа значением из формы обработки
ДокументОбъект.Срочность = Объект.Срок;
Попытка
// Записываем документ в базу данных
ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
Сообщить("Срочность заказа успешно сохранена в документе!");
Исключение
ВызватьИсключение "Не удалось записать документ: " + ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Что делать, если конфигурация находится на поддержке и мы не можем добавлять новые реквизиты в документ «Заказ клиента»? В таком случае идеальным решением будет создание независимого регистра сведений, например, РегистрСведений.СрочностьЗаказов.
Структура регистра будет следующей:
Заказ (Тип: ДокументСсылка.ЗаказКлиента).Срочность (Тип: СправочникСсылка.СрочностьЗаказов).При таком подходе код чтения и записи на форме обработки будет выглядеть следующим образом:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если ЗначениеЗаполнено(Объект.СсылкаНаЗаказ) Тогда
// Читаем значение из регистра сведений
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СрочностьЗаказов.Срочность КАК Срочность
|ИЗ
| РегистрСведений.СрочностьЗаказов КАК СрочностьЗаказов
|ГДЕ
| СрочностьЗаказов.Заказ = &Заказ";
Запрос.УстановитьПараметр("Заказ", Объект.СсылкаНаЗаказ);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Объект.Срок = Выборка.Срочность;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ЗаписатьСрочностьВРегистрНаСервере()
Если ЗначениеЗаполнено(Объект.СсылкаНаЗаказ) Тогда
// Создаем менеджер записи регистра для точечной работы с записью
МенеджерЗаписи = РегистрыСведений.СрочностьЗаказов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Заказ = Объект.СсылкаНаЗаказ;
// Пытаемся прочитать существующую запись
МенеджерЗаписи.Прочитать();
// Устанавливаем новое значение ресурса
МенеджерЗаписи.Срочность = Объект.Срок;
// Записываем данные в базу данных
МенеджерЗаписи.Записать(Истина);
КонецЕсли;
КонецПроцедуры
Если вам действительно нужно сохранить глобальную настройку (например, значение по умолчанию для реквизита «Срок», которое будет подставляться для всех новых заказов текущего пользователя), можно использовать программную работу с настройками формы.
Для этого в свойствах формы должно быть включено свойство СохранениеДанныхВНастройках в значение Использовать. После этого мы можем задействовать предопределенные события формы для ручной обработки реквизитов объекта:
&НаСервере
Процедура ПриСохраненииДанныхВНастройкахНаСервере(Настройки)
// Вручную помещаем реквизит объекта в структуру настроек
Настройки.Вставить("ПредопределенныйСрок", Объект.Срок);
КонецПроцедуры
&НаСервере
Процедура ПриЗагрузкеДанныхИзНастроекНаСервере(Настройки)
// Извлекаем сохраненное значение и присваиваем его реквизиту объекта
СохраненноеЗначение = Неопределено;
Если Настройки.Свойство("ПредопределенныйСрок", СохраненноеЗначение) Тогда
Объект.Srok = СохраненноеЗначение;
КонецЕсли;
КонецПроцедуры
Используя предложенные методы, вы сможете гибко управлять сохранением данных в ваших обработках 1С, избегая потери информации при перезапуске сеанса пользователя.