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