Как динамически заполнить список выбора в колонке таблицы значений в 1С

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

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

Постановка задачи и анализ ситуации

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

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

Способ 1. Использование события НачалоВыбора

Этот метод является классическим. Мы перехватываем момент, когда пользователь нажимает кнопку выбора в ячейке, и программно формируем список именно для этого конкретного элемента управления.

Разберем алгоритм действий по шагам:

  1. Установим у реквизита колонки свойство КнопкаВыбора в значение Да.
  2. Для элемента формы (поля ввода в таблице) создадим обработчик события НачалоВыбора.
  3. В обработчике получим данные текущей строки.
  4. Вызовем серверную функцию для получения актуального списка значений.
  5. Заполним свойство СписокВыбора элемента управления.

Посмотрим на пример кода, который обсуждался в теме, но с важным дополнением. Важно помнить, что в управляемой форме элемент управления в колонке — один на всю колонку. Если мы просто будем добавлять в него значения, то при переходе от строки к строке список будет бесконечно расти и дублироваться. Поэтому обязательно нужно использовать метод Очистить().


&НаКлиенте
Процедура Таблица1ЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    // Получаем текущие данные строки таблицы
    ТекущаяСтрока = Элементы.Таблица1.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Отменяем стандартное поведение платформы
    СтандартнаяОбработка = Ложь;
    
    // Очищаем старый список выбора, иначе значения будут дублироваться
    Элемент.СписокВыбора.Очистить();
    
    // Получаем новый список с сервера
    ТЗЗнач = ЗаполнитьСписокНовыйНаСервере(ТекущаяСтрока.Вид3CAD);
    
    // Заполняем список выбора элемента
    Для Каждого ЭлементСписка Из ТЗЗнач Цикл
        Элемент.СписокВыбора.Добавить(ЭлементСписка.Значение);
    КонецЦикла;

КонецПроцедуры

&НаСервереБезКонтекста
Функция ЗаполнитьСписокНовыйНаСервере(ВарКАД)
    
    Список = Новый СписокЗначений;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ВидыВариантовЗначения.Значения КАК Значение,
        |	ВидыВариантовЗначения.КодЕКАД КАК Код
        |ИЗ
        |	Справочник.ВидыВариантов3CAD.Значения КАК ВидыВариантовЗначения
        |ГДЕ
        |	ВидыВариантовЗначения.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", ВарКАД);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        Список.Добавить(Строка(Выборка.Значение) + "\" + Выборка.Код);
    КонецЦикла;
    
    Возврат Список;
    
КонецФункции

Почему выбранное значение "пропадает" или не отображается сразу?

Рассмотрим проблему, озвученную в сообщении №6: пользователь выбирает значение, но оно становится видимым только после того, как он переведет фокус на другую ячейку. Проанализируем причину. Это происходит из-за несоответствия типов. Если тип реквизита колонки — СправочникСсылка, а в СписокВыбора вы добавляете Строку, платформа не может сопоставить эти данные автоматически.

Важное правило: тип значения, которое вы добавляете в СписокВыбора, должен строго совпадать с типом реквизита, к которому привязана колонка таблицы. Если колонка ожидает ссылку, добавляйте в список ссылки. Если строку — строки.

Способ 2. Оптимизация через параметр ДанныеВыбора

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


&НаКлиенте
Процедура Таблица1ЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    ВарКАД = Элементы.Таблица1.ТекущиеДанные.Вид3CAD;
    
    // Напрямую заполняем ДанныеВыбора
    ДанныеВыбора = ПолучитьСписокДляВыбора(ВарКАД);
    
КонецПроцедуры

Этот метод считается более "чистым", так как он не перегружает свойства элемента управления на форме на постоянной основе, а работает только в контексте одного акта выбора.

Способ 3. Использование "Связей параметров выбора" (Декларативный метод)

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

Преимущества этого метода:

Практические советы по работе со списками выбора

Проанализируем еще несколько настроек, которые сделают работу пользователя удобнее:

  1. Режим выбора из списка: Если вы хотите запретить пользователю вводить произвольный текст и заставить его выбирать только из предложенных вариантов, включите это свойство в палитре свойств элемента формы.
  2. Быстрый выбор: Для небольших списков (до 20 элементов) включите флаг БыстрыйВыбор. В этом случае список будет выпадать сразу при нажатии на поле, без открытия дополнительных окон.
  3. Ограничение серверных вызовов: Если таблица большая, и пользователь часто переключает строки, вызов сервера в НачалоВыбора может замедлить интерфейс. В таких случаях мы рекомендуем один раз прочитать все возможные варианты при открытии формы и кэшировать их в реквизит формы типа Соответствие.

Подведем итог: для реализации динамических списков лучше всего подходит событие НачалоВыбора с использованием параметра ДанныеВыбора. При этом крайне важно следить за типизацией данных и не забывать про возможность декларативной настройки через связи параметров выбора, если структура данных это позволяет.

← На главную