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

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

При разработке в 1С мы часто сталкиваемся с задачей: позволить пользователю выбрать сразу несколько элементов (например, заказов или номенклатуры) и поместить их в табличную часть документа. Ситуация становится сложнее, если колонка табличной части имеет составной тип данных. Если мы просто включим свойство ФормаВыбора.МножественныйВыбор = Истина, то можем получить неожиданное поведение системы: пустые строки, ошибки присвоения или постоянно всплывающее окно выбора типа. Давайте разберем по шагам, как правильно реализовать этот механизм и избежать типичных ошибок.

Почему множественный выбор не работает "из коробки" и как это исправить

Рассмотрим ситуацию: пользователь открывает форму выбора, выделяет несколько заказов и нажимает "Выбрать". При включенном множественном выборе платформа 1С возвращает в обработчик события не одиночную ссылку, а объект типа Массив, который содержит все выделенные элементы.

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

Проанализируем решение. В начале процедуры необходимо обязательно указать:

СтандартнаяОбработка = Ложь;

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

Оптимальный алгоритм распределения выбранных значений по строкам

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

Посмотрим на пример правильного алгоритма. Нам нужно первый элемент массива поместить в уже существующую (текущую) строку, а для остальных элементов — создавать новые строки.


Если ТипЗнч(ВыбранноеЗначение) = Тип("Массив") И ВыбранноеЗначение.Количество() > 0 Тогда
    
    // Заполняем текущую строку первым элементом из массива
    ТекущиеДанныеТЧ = ЭлементыФормы.ТаблицаЗаданий.ТекущиеДанные;
    Если ТекущиеДанныеТЧ <> Неопределено Тогда
        ТекущиеДанныеТЧ.Заказ = ВыбранноеЗначение[0];
    КонецЕсли;
    
    // Для остальных элементов массива добавляем новые строки
    Для Индекс = 1 По ВыбранноеЗначение.ВГраница() Цикл
        НоваяСтрока = ЭтотОбъект.ТаблицаЗаданий.Добавить();
        НоваяСтрока.Заказ = ВыбранноеЗначение[Индекс];
    КонецЦикла;

КонецЕсли;

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

Работа с реквизитом составного типа: ограничение типов

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

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


// Формируем нужный тип на основе выбранного значения
МассивТипов = Новый Массив;
МассивТипов.Добавить(ТипЗнч(ВыбранноеЗначение[0])); // или указываем конкретный тип строкой
Описание = Новый ОписаниеТипов(МассивТипов);

// Применяем ограничение к элементу управления ячейки
Элемент.ОграничениеТипа = Описание;

// Приводим значение к заданному типу для корректного отображения
Элемент.Значение = Элемент.ОграничениеТипа.ПривестиЗначение(ВыбранноеЗначение[0]);

Также, чтобы окно выбора типа точно не появлялось, полезно отключать свойство выбора типа у самого элемента управления ячейкой:

Элемент.ВыбиратьТип = Ложь;

Подведем итоги

Давайте резюмируем, что мы сделали для корректной работы множественного выбора в составное поле:

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

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

← На главную