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