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

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

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

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

Метод 1: Динамическое заполнение списка выбора через событие «НачалоВыбора»

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

Для начала нам необходимо настроить свойства элемента формы (поля ввода) в колонке табличной части. Установим свойство РежимВыбораИзСписка в значение Истина. Это заставит систему предлагать пользователю готовый набор значений вместо открытия стандартной формы подбора.

Далее создадим обработчик события НачалоВыбора для этого элемента формы. Рассмотрим пример кода:


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

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

Метод 2: Использование механизма «Связи параметров выбора»

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

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

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

Метод 3: Применение метода «ПоказатьВыборИзСписка»

Иногда требуется показать список выбора не в самой ячейке, а в виде компактного выпадающего меню. Для этого отлично подходит метод ПоказатьВыборИзСписка. Это асинхронный метод, который не блокирует работу интерфейса.

Разберем пример реализации в обработчике нажатия кнопки выбора:


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

&НаКлиенте
Процедура ПослеВыбораИзСписка(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    Если ВыбранныйЭлемент <> Неопределено Тогда
        Элементы.ТЧ.ТекущиеДанные.Значение = ВыбранныйЭлемент.Значение;
    КонецЕсли;
КонецПроцедуры

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

Метод 4: Хранение и отображение множественного выбора

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

В такой ситуации мы рекомендуем следующий алгоритм:

  1. Создадим в табличной части скрытый реквизит с типом Строка (неограниченной длины). В нем мы будем хранить сериализованный список значений (например, в формате JSON или через ЗначениеВСтрокуВнутр).
  2. Для отображения пользователю используем текстовую колонку, в которой будем перечислять выбранные значения через запятую.
  3. При активации ячейки вызываем форму со списком флажков (через ОткрытьФорму или ПоказатьВыборИзСписка с множественным выбором).

Проанализируем пример кода для упаковки выбранных значений в строку для отображения:


&НаСервереБезКонтекста
Функция ПредставлениеСписка(МассивЗначений)
    Возврат СтрСоединить(МассивЗначений, ", ");
КонецФункции

Метод 5: Использование вспомогательной таблицы (Мастер-Деталь)

Как было отмечено в обсуждении на форуме, если значений для каждой строки слишком много, заполнение списка выбора при каждом переходе может замедлить работу формы. В этом случае эффективнее использовать архитектуру «Мастер-Деталь».

Мы создаем на форме вторую таблицу, которая отображает детализацию для текущей строки основной таблицы. В событии ПриАктивизацииСтроки основной таблицы мы будем устанавливать отбор для второй таблицы. Это классический подход, который позволяет пользователю быстро перемещаться по списку и видеть все доступные значения в отдельной области экрана без лишних кликов. Для практической реализации такого механизма можно использовать пример связывания главной и подчиненной таблиц на управляемых формах.

Оптимизация и кеширование

Рассмотрим подробнее вопрос производительности. Если вы решили использовать динамическое заполнение списка (Метод 1), важно помнить, что выполнение тяжелых запросов при каждом клике — плохая практика. Мы рекомендуем использовать кеширование данных на стороне клиента или сервера в пределах сеанса работы формы.

Например, можно создать переменную модуля формы КэшСписковВыбора с типом Соответствие. Ключом будет «Категория», а значением — уже готовый СписокЗначений. При активации строки система сначала проверит наличие списка в кэше, и только если его там нет, обратится к серверу за данными. Это значительно повысит отзывчивость интерфейса.

Важный момент: не забудьте про свойство ОграничениеТипа, если во второй колонке могут быть значения разных типов в зависимости от первой. Использование объекта ОписаниеТипов в обработчике ПриНачалеРедактирования позволит системе корректно обрабатывать ввод данных пользователем.

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

← На главную