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