Список выбора поля формы из кода: перечисления, справочники, автоподбор
Содержание
Многие ищут у реквизита формы какое-то свойство «список значений» и не находят. Список выбора живёт не у реквизита, а у элемента формы: Элементы.ИмяПоля.СписокВыбора. Это обычный СписокЗначений, его заполняют методом Добавить(Значение, Представление), а чтобы поле показывало кнопку раскрытия и не принимало ручной ввод, включают РежимВыбораИзСписка = Истина.
Всё ниже касается платформы 1С 8.3 и управляемых форм. Код не зависит от конфигурации: одинаково работает в Бухгалтерии, ЗУП, УТ и в своих разработках. Меняется только место, куда его писать: в типовой конфигурации — в расширение, а не в основной модуль.
Что нужно знать до написания кода
Программно установить список выбора 1С позволяет у поля формы вида ПолеВвода. У флажка, надписи и картинки свойства СписокВыбора нет, обращение к нему вызовет ошибку.
Объекты, с которыми придётся работать:
- 📋
СписокЗначений— сама коллекция. Каждый элемент —ЭлементСпискаЗначенийсо свойствамиЗначение,Представление,Пометка,Картинка. - 🧩
ПолеФормы— элемент на форме. У него есть свойстваСписокВыбора,РежимВыбораИзСписка,КнопкаВыпадающегоСписка,РедактированиеТекста. - 🗂 Реквизит формы — то, куда попадёт выбранное значение. Связан с полем через
ПутьКДанным.
Свойства поля, которые влияют на поведение списка:
| Свойство | Что делает | Типичное значение |
|---|---|---|
РежимВыбораИзСписка | Разрешает только значения из списка | Истина |
КнопкаВыпадающегоСписка | Показывает стрелку раскрытия | Истина |
РедактированиеТекста | Разрешает печатать в поле вручную | Ложь для жёсткого списка |
КнопкаВыбора | Кнопка «…», открывает форму выбора | Ложь, если нужен только список |
Те же свойства есть в палитре свойств элемента в конфигураторе. Статичный набор значений можно задать там же, в свойстве «Список выбора». Код нужен, когда состав списка зависит от данных: организации, роли пользователя, значения другого поля.
Где писать заполнение:
ПриСозданииНаСервере— если список не меняется, пока форма открыта. Один вызов, никаких лишних обращений к серверу.- Обработчик
ПриИзменениидругого поля — если список зависит от выбранного значения (выбрали организацию → пересобрали список складов). - Событие
НачалоВыбораИзСписка— если список нужен актуальным в момент раскрытия, например в колонке табличной части.
Заполняем список из перечисления и справочника
Значения перечисления
Перебор метаданных перечисления даёт и ссылку, и синоним для представления:
&НаСервере
Процедура ЗаполнитьСписокВидовОплаты()
Список = Элементы.ВидОплаты.СписокВыбора;
Список.Очистить();
Для Каждого МетаЗначение Из Метаданные.Перечисления.ВидыОплат.ЗначенияПеречисления Цикл
Значение = Перечисления.ВидыОплат[МетаЗначение.Имя];
Список.Добавить(Значение, МетаЗначение.Синоним);
КонецЦикла;
Элементы.ВидОплаты.РежимВыбораИзСписка = Истина;
КонецПроцедуры
Если нужны не все значения, а два-три, проще добавить их явно:
Список.Добавить(Перечисления.ВидыОплат.Наличные);
Список.Добавить(Перечисления.ВидыОплат.Безналичные);
Представление можно не указывать: платформа возьмёт синоним значения сама.
Элементы справочника через запрос
Для справочника используйте запрос, а не Выбрать() у менеджера: в запросе сразу отсекаются помеченные на удаление и группы, и задаётся порядок.
&НаСервере
Процедура ЗаполнитьСписокСкладов()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Склады.Ссылка КАК Ссылка,
| Склады.Наименование КАК Наименование
|ИЗ
| Справочник.Склады КАК Склады
|ГДЕ
| НЕ Склады.ПометкаУдаления
| И НЕ Склады.ЭтоГруппа
|
|УПОРЯДОЧИТЬ ПО
| Наименование";
Список = Элементы.Склад.СписокВыбора;
Список.Очистить();
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Список.Добавить(Выборка.Ссылка, Выборка.Наименование);
КонецЦикла;
КонецПроцедуры
Условие ЭтоГруппа есть только у иерархических справочников с группами. Для плоского справочника уберите его, иначе запрос не выполнится.
Короткий вариант, когда представление по умолчанию устраивает:
Ссылки = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
Элементы.Склад.СписокВыбора.ЗагрузитьЗначения(Ссылки);
Строки и числа
Список выбора не обязан хранить ссылки. Для строкового реквизита формы подойдёт набор строк, для числового — набор чисел:
Для Месяц = 1 По 12 Цикл
Элементы.МесяцОтчета.СписокВыбора.Добавить(Месяц, Формат(Дата(2000, Месяц, 1), "ДФ=ММММ"));
КонецЦикла;
Здесь значение — число от 1 до 12, а пользователь видит название месяца.
Представление, пометки и картинки у элементов
Метод Добавить принимает до четырёх параметров: Добавить(Значение, Представление, Пометка, Картинка). Всё, кроме значения, необязательно.
Что можно настроить у элемента после добавления:
- ✏️ Представление — текст в выпадающем списке. Значение при этом не меняется: в реквизит попадёт ссылка, а пользователь видел, например, «Основной склад (Москва)».
- 🖼 Картинка — значок слева от текста. Берётся из общих картинок:
БиблиотекаКартинок.ИмяКартинки. - ☑️ Пометка — флажок элемента. В выпадающем списке поля он обычно не нужен, зато пригодится, если тот же список показывают через
ПоказатьОтметкуЭлементов.
Пример с составным представлением:
Пока Выборка.Следующий() Цикл
Текст = СтрШаблон("%1 (%2)", Выборка.Наименование, Выборка.Город);
Элементы.Склад.СписокВыбора.Добавить(Выборка.Ссылка, Текст);
КонецЦикла;
Поменять представление уже добавленного элемента можно через поиск:
Элемент = Элементы.Склад.СписокВыбора.НайтиПоЗначению(ОсновнойСклад);
Если Элемент <> Неопределено Тогда
Элемент.Представление = "★ " + Элемент.Представление;
КонецЕсли;
Если нужно вставить пункт на конкретное место, а не в конец, используйте Вставить(Индекс, Значение, Представление). Индексы считаются с нуля: Вставить(0, …) ставит элемент первым.
Сортировка и отбор значений в списке выбора
Сортировка
У СписокЗначений два метода сортировки:
Список.СортироватьПоПредставлению(НаправлениеСортировки.Возр);
Список.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
Для ссылок сортировка по значению даёт непредсказуемый для пользователя порядок, поэтому для справочников берите сортировку по представлению или сразу УПОРЯДОЧИТЬ ПО в запросе.
Отбор
Встроенного «фильтра» у списка выбора нет. Два рабочих способа:
- Пересобрать список с условием в запросе. Самый чистый путь: добавили
И Склады.Организация = &Организация, передали параметр, заново заполнили. - Удалить лишние элементы из уже заполненного списка. Удалять нужно с конца, чтобы не сбить индексы:
Список = Элементы.Склад.СписокВыбора;
Всего = Список.Количество();
Для Сч = 1 По Всего Цикл
Элемент = Список[Всего - Сч];
Если Не СкладДоступен(Элемент.Значение) Тогда
Список.Удалить(Элемент);
КонецЕсли;
КонецЦикла;
Граница цикла Всего вычислена до начала удаления, а индекс идёт от последнего элемента к нулевому. Удаление элемента в конце не сдвигает позиции тех, что ближе к началу.
Если отбор зависит от другого поля формы, вызывайте пересборку в его обработчике ПриИзменении. Не забудьте сбросить текущее значение зависимого реквизита, если его больше нет в новом списке, иначе пользователь увидит в поле значение, которого нельзя выбрать.
Связываем список с полями формы и табличной частью
Зависимый список на клиенте
Элементы формы доступны и на клиенте, но запрос к базе — только на сервере. Типичная связка: клиентский обработчик вызывает серверную функцию без контекста и получает готовый СписокЗначений. Он передаётся между клиентом и сервером без проблем.
&НаКлиенте
Процедура ОрганизацияПриИзменении(Элемент)
Склады = СкладыОрганизации(Объект.Организация);
Элементы.Склад.СписокВыбора.ЗагрузитьЗначения(Склады.ВыгрузитьЗначения());
Если Склады.НайтиПоЗначению(Объект.Склад) = Неопределено Тогда
Объект.Склад = Неопределено;
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция СкладыОрганизации(Организация)
Запрос = Новый Запрос(
"ВЫБРАТЬ Склады.Ссылка КАК Ссылка
|ИЗ Справочник.Склады КАК Склады
|ГДЕ Склады.Организация = &Организация
| И НЕ Склады.ПометкаУдаления");
Запрос.УстановитьПараметр("Организация", Организация);
Результат = Новый СписокЗначений;
Результат.ЗагрузитьЗначения(Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка"));
Возврат Результат;
КонецФункции
&НаСервереБезКонтекста не тянет на сервер всю форму, поэтому вызов быстрее обычного &НаСервере.
Колонка табличной части
У колонки один список выбора на все строки. Если состав зависит от строки, пересобирайте его при раскрытии списка, в событии НачалоВыбораИзСписка элемента-колонки:
&НаКлиенте
Процедура ТоварыХарактеристикаНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)
ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
Варианты = ХарактеристикиНоменклатуры(ТекущиеДанные.Номенклатура);
Элемент.СписокВыбора.ЗагрузитьЗначения(Варианты.ВыгрузитьЗначения());
КонецПроцедуры
Функция ХарактеристикиНоменклатуры устроена так же, как СкладыОрганизации выше.
Поле, созданное из кода
Если поле добавляют на форму программно, список выбора задают сразу после создания элемента. Реквизит формы при этом уже должен существовать: его создают заранее в конфигураторе или через ИзменитьРеквизиты.
&НаСервере
Процедура ДобавитьПолеПриоритета()
Поле = Элементы.Добавить("Приоритет", Тип("ПолеФормы"), Элементы.ГруппаШапка);
Поле.Вид = ВидПоляФормы.ПолеВвода;
Поле.ПутьКДанным = "Приоритет";
Поле.РежимВыбораИзСписка = Истина;
Поле.КнопкаВыпадающегоСписка = Истина;
Поле.СписокВыбора.Добавить(1, "Высокий");
Поле.СписокВыбора.Добавить(2, "Обычный");
Поле.СписокВыбора.Добавить(3, "Низкий");
КонецПроцедуры
Порядок важен: сначала Вид, потом остальные свойства. Пока вид не задан, у элемента нет свойств поля ввода. Здесь реквизит Приоритет числовой, поэтому и значения в списке — числа.
Выбор из списка без поля
Иногда список нужен не в поле, а по нажатию кнопки. Модальный ВыбратьИзСписка в 8.3 с отключённой модальностью не работает
, используйте асинхронный вариант:
&НаКлиенте
Процедура ВыбратьСклад(Команда)
Список = СкладыОрганизации(Объект.Организация);
Оповещение = Новый ОписаниеОповещения("ВыбратьСкладЗавершение", ЭтотОбъект);
ПоказатьВыборИзСписка(Оповещение, Список, Элементы.Склад);
КонецПроцедуры
&НаКлиенте
Процедура ВыбратьСкладЗавершение(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
Если ВыбранныйЭлемент <> Неопределено Тогда
Объект.Склад = ВыбранныйЭлемент.Значение;
КонецЕсли;
КонецПроцедуры
В обработчик приходит ЭлементСпискаЗначений, поэтому значение берём через .Значение. Если пользователь закрыл окно, приходит Неопределено.
Большие списки: автоподбор и обработка получения данных выбора
Список выбора хорош до нескольких десятков значений. Когда пунктов сотни, раскрывающийся список становится неудобным, а его заполнение при открытии формы тормозит. Здесь работают два других механизма.
Событие АвтоПодбор поля
Срабатывает, пока пользователь печатает. В параметр ДанныеВыбора кладётся список, который платформа покажет под полем:
&НаКлиенте
Процедура СкладАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
Если СтрДлина(Текст) < 2 Тогда
Возврат;
КонецЕсли;
СтандартнаяОбработка = Ложь;
ДанныеВыбора = НайтиСклады(Текст, Объект.Организация);
КонецПроцедуры
Состав параметров обработчика зависит от версии платформы. Не набирайте его вручную: создайте обработчик из палитры свойств поля, конструктор подставит правильную сигнатуру.
ОбработкаПолученияДанныхВыбора в модуле менеджера
Если ограничение нужно не на одной форме, а везде, где выбирают этот справочник, пишите обработчик в модуле менеджера справочника:
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
Если Не Параметры.Свойство("Отбор") Тогда
Возврат;
КонецЕсли;
Параметры.Отбор.Вставить("ПометкаУдаления", Ложь);
КонецПроцедуры
Здесь мы не подменяем выдачу, а только добавляем условие к стандартному отбору. Строка, которую ввёл пользователь, лежит в Параметры.СтрокаПоиска.
Что выбрать
| Способ | Когда | Минусы |
|---|---|---|
СписокВыбора в ПриСозданииНаСервере | До 30–50 значений, состав не меняется | Заполняется при каждом открытии формы |
Пересборка в ПриИзменении | Список зависит от другого поля | Серверный вызов на каждое изменение |
АвтоПодбор | Сотни значений, поиск по вводу | Вызов при наборе текста, нужен порог длины |
ОбработкаПолученияДанныхВыбора | Одинаковое правило для всех форм | Влияет на всю конфигурацию, нужна осторожность |
Ошибки и как не замедлить форму
Что действительно тормозит форму:
- 🐢 Запрос в цикле. Не получайте представление каждого элемента отдельным обращением к базе. Возьмите всё одной выборкой.
- 🐢 Серверный вызов на каждый символ. В
АвтоПодборставьте порог длины текста и не обращайтесь к серверу при одном-двух символах. - 🐢 Полный контекст формы. Для получения данных используйте
&НаСервереБезКонтекста, а не&НаСервере. - 🐢 Повторная загрузка одного и того же. Если список не меняется, заполните его один раз в
ПриСозданииНаСервереи не трогайте на клиенте.
В типовых конфигурациях не правьте модули форм напрямую. Заполнение списка выбора оформляйте в расширении: так код переживёт обновление конфигурации.
Частые вопросы
Можно ли задать список выбора для реквизита документа, а не для формы?
ОбработкаПроверкиЗаполнения.Как сделать значение по умолчанию из списка?
ПриСозданииНаСервере, например первый элемент: Объект.Склад = Элементы.Склад.СписокВыбора[0].Значение. Перед этим проверьте, что список не пустой.Почему список выбора в колонке одинаков для всех строк?
НачалоВыбораИзСписка по текущим данным строки.Как разрешить ручной ввод, но подсказывать варианты?
РежимВыбораИзСписка = Ложь и РедактированиеТекста = Истина. Список будет работать как подсказка, а пользователь сможет ввести своё значение.