Разработка и Конфигурация · 9 мин
1С: как выбрать значение из списка — все рабочие способы
Как в 1С выбрать значение из списка: метод ВыбратьЭлемент, ВыбратьИзСписка, отбор ГДЕ В СПИСКЕ в запросе и поиск в списке значений. Примеры кода и ошибки.
Запрос «1С выбрать где в списке» обычно означает одну из трёх задач: показать пользователю диалог выбора элемента из списка значений, найти нужный элемент в списке программно или отобрать записи запросом по условию «ГДЕ поле В списке». Все три сценария решаются разными механизмами платформы, и путаница между ними — частая причина ошибок у начинающих разработчиков.
Ниже разобраны основные приёмы: интерактивный выбор через ВыбратьИзСписка и ВыбратьЭлемент, программный поиск через НайтиПоЗначению, условие В (&Список) в языке запросов и отбор в динамических списках форм. Примеры приведены для управляемых форм, но большинство методов работает и в обычном приложении.
Интерактивный выбор элемента из списка значений
Объект СписокЗначений умеет сам показывать диалог выбора. Метод ВыбратьЭлемент() открывает модальное окно со списком и возвращает выбранный ЭлементСпискаЗначений либо Неопределено, если пользователь нажал «Отмена». В управляемых формах модальные вызовы по умолчанию запрещены, поэтому правильный вариант — асинхронный ПоказатьВыборИзСписка() с описанием оповещения.
&НаКлиенте
Процедура ВыбратьСтатус(Команда)
Список = Новый СписокЗначений;
Список.Добавить("Новый", "Новый");
Список.Добавить("ВРаботе", "В работе");
Список.Добавить("Закрыт", "Закрыт");
Оповещение = Новый ОписаниеОповещения("ПослеВыбораСтатуса", ЭтотОбъект);
ПоказатьВыборИзСписка(Оповещение, Список, Элементы.Статус, Список[0]);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораСтатуса(ВыбранныйЭлемент, ДопПараметры) Экспорт
Если ВыбранныйЭлемент = Неопределено Тогда
Возврат; // пользователь отменил выбор
КонецЕсли;
Статус = ВыбранныйЭлемент.Значение;
КонецПроцедуры
Обратите внимание на четвёртый параметр — элемент, который будет подсвечен при открытии. Это удобно, когда нужно показать текущее значение. Если передать элемент, которого нет в списке, платформа просто не установит позицию курсора, ошибки не будет.
Программный поиск элемента в списке значений
Когда выбор делает не пользователь, а алгоритм, применяется метод НайтиПоЗначению(). Он сравнивает переданное значение со значениями элементов списка и возвращает найденный элемент или Неопределено. Сравнение идёт с учётом типа: строка «001» не совпадёт с числом 1, а ссылка на элемент справочника совпадёт только с той же самой ссылкой.
Элемент = Список.НайтиПоЗначению(ИскомоеЗначение);
Если Элемент = Неопределено Тогда
// значения в списке нет — добавить или сообщить об ошибке
Список.Добавить(ИскомоеЗначение);
Иначе
Индекс = Список.Индекс(Элемент);
КонецЕсли;
Если нужно искать не по значению, а по представлению (тексту, который видит пользователь), готового метода нет — придётся перебирать список в цикле и сравнивать свойство Представление. То же относится к поиску по картинке или пометке. Для больших списков, где поиск выполняется часто, эффективнее перевести данные в соответствие: поиск по ключу в соответствии работает быстрее перебора.
Выбор из списка в поле ввода формы
Частая задача — ограничить ввод в поле формы набором допустимых значений. Для этого у поля ввода есть свойство СписокВыбора. Заполнить его можно в свойствах элемента формы в конфигураторе или программно в обработчике ПриСозданииНаСервере. Тогда при нажатии кнопки выпадающего списка пользователь увидит только заданные варианты.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Элементы.СпособДоставки.СписокВыбора.Добавить("Самовывоз");
Элементы.СпособДоставки.СписокВыбора.Добавить("Курьер");
Элементы.СпособДоставки.СписокВыбора.Добавить("ТК", "Транспортная компания");
КонецПроцедуры
Свойство РежимВыбораИзСписка = Истина заставит поле работать строго как выпадающий список без возможности ввести произвольный текст. Если нужно разрешить и выбор, и ручной ввод, оставьте режим выключенным, но тогда валидируйте введённое значение самостоятельно — платформа не станет сверять его со списком.
Условие «ГДЕ В списке» в запросе
В языке запросов 1С отбор по набору значений записывается оператором В. Список передаётся параметром: в него можно поместить массив, список значений или даже таблицу значений. Это основной способ отобрать документы или элементы справочника по нескольким ссылкам сразу.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Реализация.Ссылка,
| Реализация.СуммаДокумента
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Контрагент В (&СписокКонтрагентов)";
Запрос.УстановитьПараметр("СписокКонтрагентов", СписокКонтрагентов);
Результат = Запрос.Выполнить().Выбрать();
Для иерархических справочников есть вариант В ИЕРАРХИИ (&Группа) — он отбирает элементы, вложенные в указанную группу на любую глубину. Это быстрее и надёжнее, чем собирать список подчинённых элементов вручную. Учтите обратную операцию: НЕ В (&Список) исключает значения, но записи, где поле имеет значение NULL (например, при левом соединении), в результат не попадут — NULL не сравнивается ни с чем.
Отбор в динамическом списке формы
Динамические списки (списки документов, справочников на форме) отбираются через элементы отбора компоновки данных, а не через переписывание запроса. Чтобы показать только записи из заданного перечня, добавьте элемент отбора с видом сравнения ВСписке:
&НаСервере
Процедура УстановитьОтборПоСписку()
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
ЭлементОтбора.ПравоеЗначение = СписокОрганизаций; // СписокЗначений или массив
ЭлементОтбора.Использование = Истина;
КонецПроцедуры
Перед добавлением нового отбора удаляйте ранее установленный программно — иначе при повторном вызове элементы отбора будут накапливаться, и список покажет пустой результат из-за пересечения противоречивых условий. Проще всего помечать свой отбор уникальным представлением и искать его перед обновлением.
- 1Сформируйте СписокЗначений или массив с нужными ссылками
- 2Найдите и удалите ранее добавленный программный элемент отбора
- 3Добавьте элемент отбора с видом сравнения ВСписке и установите Использование = Истина
- 4Проверьте на форме, что список показывает только записи из перечня
Проверка результата и границы применения
После реализации любого из способов проверьте три вещи: поведение при пустом списке (диалог выбора с пустым списком покажет пустое окно, а запрос с пустым параметром вернёт ноль записей), отмену выбора пользователем (всегда обрабатывайте Неопределено) и типы значений (список строк не сматчится со ссылочным полем запроса).
Если значений больше двух-трёх десятков, выпадающий список и ПоказатьВыборИзСписка становятся неудобными — переходите на открытие формы выбора справочника с отбором. Для фиксированных коротких перечней правильнее завести перечисление: оно жёстче контролирует состав значений и поддерживается платформой на уровне типов.
Что важно запомнить
Интерактивный выбор — ПоказатьВыборИзСписка с оповещением, программный поиск — НайтиПоЗначению с проверкой на Неопределено, отбор в запросе — ГДЕ Поле В (&Список), отбор динамического списка — элемент отбора с видом ВСписке. Всегда обрабатывайте отмену выбора и пустой список.
Часто задаваемые вопросы
Чем ВыбратьЭлемент отличается от ПоказатьВыборИзСписка?
ВыбратьЭлемент — модальный метод списка значений, он блокирует выполнение кода до закрытия диалога и недоступен при запрещённой модальности. ПоказатьВыборИзСписка — асинхронный глобальный метод: результат приходит в процедуру, указанную в ОписаниеОповещения. В управляемых формах используйте второй вариант.
Почему НайтиПоЗначению не находит значение, которое точно есть в списке?
Чаще всего не совпадают типы: вы ищете строку, а в списке ссылки, или ищете ссылку, а в списке строковый код. Проверьте тип значения элемента через ТипЗнч() и приведите искомое значение к тому же типу. Также у строк проверяйте лишние пробелы и регистр.
Можно ли передать в параметр запроса таблицу значений вместо списка?
Да, оператор В принимает таблицу значений, но запрос сможет использовать её только как источник для соединения, если выгрузить таблицу во временную таблицу. Для простого условия В (&Параметр) таблица значений не подойдёт — передавайте массив или список значений, выгруженный из колонки таблицы методом ВыгрузитьКолонку().
Как выбрать из списка несколько значений сразу?
Стандартный диалог выбора из списка возвращает один элемент. Для множественного выбора используйте метод списка значений ОтметитьЭлементы() (или ПоказатьОтметкуЭлементов в асинхронном варианте) — пользователь отметит нужные строки флажками, а вы затем переберёте список и возьмёте элементы с установленной пометкой.
Почему условие НЕ В (&Список) возвращает меньше записей, чем ожидалось?
Если отбираемое поле может содержать NULL (типично после левого соединения), такие записи не пройдут ни условие В, ни НЕ В, потому что сравнение с NULL не даёт истины. Добавьте обработку: ГДЕ НЕ Поле В (&Список) ИЛИ Поле ЕСТЬ NULL.
Как ограничить список выбора в поле ввода в зависимости от другого поля?
Очищайте и заново заполняйте свойство СписокВыбора элемента формы в обработчике ПриИзменении управляющего поля. Для ссылочных полей вместо списка выбора правильнее использовать ПараметрыВыбора или СвязиПараметровВыбора — тогда отбор сработает и в стандартной форме выбора, и при быстром вводе.