В процессе разработки на платформе 1С:Предприятие часто возникает задача вынести сложный расчет во вспомогательную или общую форму. Пользователь выбирает входные параметры в первой форме, переходит во вторую форму для указания дополнительных геометрических или физических характеристик, после чего рассчитанный результат должен вернуться в исходное окно.
Разберем, почему возникают ошибки при расчетах на клиенте, и рассмотрим правильный асинхронный механизм передачи данных между управляемыми формами без использования устаревшего модального режима.
Проанализируем типовые ошибки в коде второй формы, из-за которых расчет длины, ширины или итогового веса может выдавать нулевые или некорректные значения:
Профиль передается как ссылка на справочник или значение перечисления, сравнение вида Если Профиль = "Квадрат" Тогда всегда вернет Ложь. Ссылочные типы нельзя напрямую сравнивать со строковыми литералами. Для исправления следует использовать получение представления через Строка(Профиль) или сравнивать реквизит с конкретной ссылкой (например, Справочники.Профили.Квадрат).Длина * Ширина * Высота * Плотность), а одно из полей еще не заполнено пользователем, результат вычисления будет равен 0.Рассмотрим по шагам, как организовать открытие второй формы из первой с передачей исходных параметров (материала и профиля).
В первой форме создаем процедуру-обработчик команды, подготавливаем структуру параметров и вызываем метод ОткрытьФорму. Чтобы получить результат расчета обратно, формируем объект ОписаниеОповещения, указывающий на клиентскую процедуру обработки завершения.
Рассмотрим пример кода первой формы:
&НаКлиенте
Процедура РассчитатьВес(Команда)
// Формируем структуру параметров для передачи во вторую форму
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Профиль", Объект.Профиль);
ПараметрыФормы.Вставить("Материал", Объект.Материал);
// Создаем описание оповещения о закрытии подчиненной формы
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеЗакрытияФормыРасчета", ЭтотОбъект);
// Открываем форму калькулятора асинхронно
ОткрытьФорму("ОбщаяФорма.ФормаРасчета", ПараметрыФормы, ЭтотОбъект, , , , ОписаниеОповещения);
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗакрытияФормыРасчета(РезультатЗакрытия, ДополнительныеПараметры) Экспорт
// Проверяем, что форма закрылась с переданным значением
Если ЗначениеЗаполнено(РезультатЗакрытия) Тогда
Объект.ВесФормы = РезультатЗакрытия;
КонецЕсли;
КонецПроцедуры
Во второй форме необходимо принять переданные параметры при инициализации на сервере, заполнить соответствующие реквизиты и выполнить расчет при изменении габаритов.
Посмотрим на пример обработки параметров в событии ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("Профиль") Тогда
Объект.Профиль = Параметры.Профиль;
КонецЕсли;
Если Параметры.Свойство("Материал") Тогда
Объект.Материал = Параметры.Материал;
КонецЕсли;
КонецПроцедуры
Далее реализуем алгоритм вычисления. Для получения плотности материала обращаемся к серверной функции, а сам расчет выполняем с приведением ссылки профиля к строковому представлению:
&НаКлиенте
Процедура РасчетВеса()
Плотность = ПолучитьПлотностьМатериала(Объект.Материал);
ИмяПрофиля = Строка(Объект.Профиль);
Если ИмяПрофиля = "Квадрат" Тогда
Вес = Объект.Длина * Объект.Ширина * Плотность;
ИначеЕсли ИмяПрофиля = "Круг" Тогда
Вес = 3.14 / 4 * Объект.Диаметр * Объект.Диаметр * Объект.Длина * Плотность;
ИначеЕсли ИмяПрофиля = "Полоса, лист" Тогда
Вес = Объект.Длина * Объект.Ширина * Объект.Высота * Плотность;
Иначе
Вес = 0;
КонецЕсли;
Объект.Вес = Вес;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьПлотностьМатериала(СсылкаМатериал)
Если ЗначениеЗаполнено(СсылкаМатериал) Тогда
Возврат СсылкаМатериал.Плотность;
КонецЕсли;
Возврат 0;
КонецФункции
Чтобы перенести полученный результат обратно в вызвавшую форму, используем штатную процедуру закрытия формы с передачей параметра. На управляемую форму добавляем кнопку «Перенести» или «ОК», в обработчике которой вызывается метод Закрыть().
Разберем код закрытия формы с возвратом результата:
&НаКлиенте
Процедура ПеренестиЗначение(Команда)
// Закрываем форму и передаем рассчитанное значение в РезультатЗакрытия
Закрыть(Объект.Вес);
КонецПроцедуры
При вызове метода Закрыть(Объект.Вес) платформа автоматически закрывает текущую форму калькулятора и передает значение реквизита Объект.Вес в параметр РезультатЗакрытия процедуры ПослеЗакрытияФормыРасчета исходной формы.
Такой подход полностью соответствует стандартам разработки 1С для управляемого приложения, работает без использования блокирующего модального режима и обеспечивает надежную передачу данных между окнами.