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