Часто при работе с управляемыми формами в 1С мы сталкиваемся с ситуацией: мы добавили на форму реквизиты, которые не хранятся в базе данных, а рассчитываются динамически. Пользователь видит нужные цифры, нажимает кнопку "Записать", и... эти поля становятся пустыми. Давайте вместе разберемся, почему так происходит и какие существуют способы решить эту задачу.
Выясним причину: корень проблемы лежит в жизненном цикле управляемой формы. Когда вы нажимаете "Записать", платформа выполняет следующие действия: записывает объект в базу данных, а затем заново считывает данные из базы, чтобы обновить форму и показать актуальную информацию. Поскольку наши расчетные реквизиты не являются частью объекта в базе данных, при этом обновлении они просто сбрасываются до своих значений по умолчанию. Проанализируем несколько подходов к решению этой проблемы.
Самый простой и прямолинейный подход — это заново выполнять расчет наших полей каждый раз, когда форма нуждается в обновлении. Это гарантирует, что пользователь всегда видит актуальную информацию.
Разберем по шагам, как это реализовать:
ПриСозданииНаСервере — сработает один раз, когда форма только открывается.ПослеЗаписиНаСервере — сработает каждый раз после успешной записи объекта.Посмотрим на пример: допустим, у нас есть документ "Заказ", а на форме мы хотим видеть расчетное поле ПроцентВыполненияЗаказа, которое не хранится в документе.
&НаСервере
Процедура РассчитатьДополнительныеРеквизиты()
// Здесь ваша сложная логика расчета
// Например, получаем данные из других регистров по этому заказу
Объект.ПроцентВыполненияЗаказа = РассчитатьПроцентВыполнения(Объект.Ссылка);
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
РассчитатьДополнительныеРеквизиты();
КонецПроцедуры
&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
РассчитатьДополнительныеРеквизиты();
КонецПроцедуры
Этот метод отлично подходит для несложных расчетов, которые не сильно влияют на производительность. Для большинства повседневных задач его более чем достаточно.
Если вычисляемые данные важны не только для отображения на форме, но и могут понадобиться в отчетах, печатных формах или другой бизнес-логике, то логичным решением будет их сохранение. Рассмотрим два варианта.
1. Добавление реквизитов в сам объект.
Это самый надежный способ. Мы просто добавляем новый реквизит (например, ПроцентВыполненияЗаказа) в сам объект конфигурации (документ "Заказ"). Расчет этого реквизита можно производить в серверном обработчике ПередЗаписьюНаСервере. Таким образом, данные будут записаны вместе с документом и всегда будут доступны.
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
ТекущийОбъект.ПроцентВыполненияЗаказа = РассчитатьПроцентВыполнения(ТекущийОбъект.Ссылка);
КонецПроцедуры
2. Использование отдельного регистра сведений.
Иногда не хочется "засорять" основной объект вспомогательными данными. В этом случае можно создать отдельный, подчиненный документу РегистрСведений. Этот подход особенно удобен при работе с расширениями, так как позволяет добавить хранилище для наших данных, не изменяя основную конфигурацию.
Этот способ позволяет "перенести" наши расчетные данные через процедуру записи. Механизм работает так: перед записью мы сохраняем данные в специальное временное хранилище на сервере, а после записи — забираем их оттуда и снова помещаем на форму.
Разберем по шагам:
ПередЗаписьюНаСервере мы помещаем значение нашего реквизита во временное хранилище с помощью функции ПоместитьВоВременноеХранилище(). Эта функция возвращает уникальный адрес, который мы сохраняем в переменную.ПослеЗаписиНаСервере мы используем этот адрес и функцию ПолучитьИзВременногоХранилища(), чтобы получить наши данные обратно и присвоить их реквизиту формы.Посмотрим на пример кода:
&НаСервере
Перем АдресВременногоХранилища;
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Помещаем значение нашего реквизита формы во временное хранилище
АдресВременногоХранилища = ПоместитьВоВременноеХранилище(Объект.ПроцентВыполненияЗаказа, УникальныйИдентификатор);
КонецПроцедуры
&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
// Получаем данные из хранилища и снова устанавливаем в реквизит
ДанныеИзХранилища = ПолучитьИзВременногоХранилища(АдресВременногоХранилища);
Если ДанныеИзХранилища <> Неопределено Тогда
Объект.ПроцентВыполненияЗаказа = ДанныеИзХранилища;
КонецЕсли;
КонецПроцедуры
Этот метод элегантен и не требует изменения структуры базы данных, идеально подходя для данных, которые нужны только в рамках текущей сессии работы с формой.
Если расчеты действительно ресурсоемкие, а входные данные для них в течение сеанса пользователя не меняются, нет смысла выполнять их многократно. В этом случае нам поможет кэширование.
Платформа 1С предоставляет отличный механизм: общие модули с повторным использованием возвращаемых значений. Для этого нужно:
Теперь, при первом вызове этой функции с определенными параметрами, она выполнит расчет и сохранит результат в кэше. Все последующие вызовы этой же функции с теми же параметрами в течение сеанса будут мгновенно возвращать результат из кэша, не выполняя сам код расчета.
Пример функции в таком модуле:
// Общий модуль "РасчетныеФункцииСерверКэшируемый"
Функция РассчитатьСложныйПоказатель(Параметр1, Параметр2) Экспорт
// ... здесь очень долгие и сложные вычисления ...
Результат = ...;
Возврат Результат;
КонецФункции
Этот подход значительно ускоряет работу формы при многократных обращениях к одним и тем же расчетным данным.
← К списку