Как правильно заполнить список выбора элемента формы из результата запроса в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке пользовательских интерфейсов в 1С часто возникает задача динамического формирования выпадающих списков. Например, когда необходимо ограничить выбор в поле формы только теми позициями номенклатуры, которые присутствуют в конкретном документе или соответствуют определенному условию. Однако при реализации этого механизма разработчики иногда сталкиваются с ситуацией, когда элементы в поле попадают, но отображаются пустыми, либо выбор работает некорректно.

Рассмотрим причинно-следственные связи этой проблемы, разберем типичную синтаксическую ошибку и изучим оптимальные способы заполнения элементов формы типа СписокВыбора.

Анализ типичной ошибки при ручном обходе выборки

Проанализируем ситуацию, когда разработчик пытается вручную создать объект ТаблицаЗначений, заполнить его в цикле из результата запроса и затем загрузить полученную колонку в элемент формы.

Рассмотрим следующий фрагмент кода:


Выборка = Запрос.Выполнить().Выбрать();
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура");
Пока Выборка.Следующий() Цикл
    НоваяСтрока = ТЗ.Добавить();
    НоваяСтрока = Выборка.Номенклатура; // Ошибка здесь!
КонецЦикла;
Элементы.ДИ_Номенклатура.СписокВыбора.ЗагрузитьЗначения(ТЗ.ВыгрузитьКолонку("Номенклатура"));

В данном примере совершена частая логическая ошибка: переменной НоваяСтрока сначала присваивается ссылка на только что созданную строку таблицы значений (ТЗ.Добавить()), а на следующей строчке эта же переменная полностью перезаписывается значением Выборка.Номенклатура. В итоге сама строка таблицы значений остается не заполнена (ее колонка Номенклатура содержит значение по умолчанию, то есть Неопределено или пустую ссылку).

Чтобы исправить эту ошибку и корректно записать значение в соответствующую колонку созданной строки, необходимо обращаться к свойству этой строки:


Пока Выборка.Следующий() Цикл
    НоваяСтрока = ТЗ.Добавить();
    НоваяСтрока.Номенклатура = Выборка.Номенклатура; // Корректное присвоение
КонецЦикла;

Оптимальный способ: выгрузка результата запроса без ручного цикла

Создание промежуточной таблицы значений вручную с помощью Новый ТаблицаЗначений и последовательный обход через Пока Выборка.Следующий() в данном сценарии являются избыточными. Платформа 1С позволяет получить готовую таблицу значений из запроса одним методом Выгрузить(), после чего сразу выгрузить нужную колонку в массив.

Разберем более лаконичный и быстрый вариант реализации:


ТЗ = Запрос.Выполнить().Выгрузить();
МассивЗначений = ТЗ.ВыгрузитьКолонку("Номенклатура");
Элементы.ДИ_Номенклатура.СписокВыбора.ЗагрузитьЗначения(МассивЗначений);

Или еще короче, объединив операции:


МассивНоменклатуры = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Номенклатура");
Элементы.ДИ_Номенклатура.СписокВыбора.ЗагрузитьЗначения(МассивНоменклатуры);

Метод ВыгрузитьКолонку() возвращает стандартный массив 1С, который напрямую передается в метод ЗагрузитьЗначения() объекта СписокВыбора.

Важные особенности и рекомендации по настройке

Чтобы выгрузка и отображение данных в списке выбора работали безошибочно, учтем следующие нюансы платформы:

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