Почему не работает выбор перечисления в составном типе данных в табличной части и как это исправить?

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

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

Выясним причину странного поведения

Данная проблема не является ошибкой в коде разработчика — это подтвержденный баг платформы 1С, который проявлялся в определенных релизах ветки 8.3.15 (особенно в версии 8.3.15.1700). Суть ошибки заключается в некорректной передаче фокуса и обработки модальных окон выбора типа данных внутри ячеек табличного поля. Когда мы выбираем тип «Перечисление» в системном окне, платформа должна мгновенно инициализировать выпадающий список значений этого перечисления. Однако в проблемных сборках контекст выбора теряется, и вместо списка значений пользователь снова видит окно выбора типа или вовсе пустую реакцию интерфейса.

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

Решение №1: Программный вызов списка выбора через событие изменения

Самый быстрый способ заставить систему работать — это перехватить момент, когда пользователь уже выбрал тип «Перечисление», и принудительно показать ему список доступных значений. Для этого мы воспользуемся событием ПриИзменении для элемента управления в колонке таблицы.

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


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

&НаСервереБезКонтекста
Функция ПолучитьСписокЗначенийПеречисления()
    Список = Новый СписокЗначений;
    // Обходим метаданные перечисления для автоматизации
    Для Каждого ЗначениеИзМетаданных Из Метаданные.Перечисления.СостоянияЗаказов.ЗначенияПеречисления Цикл
        ИмяЗначения = ЗначениеИзМетаданных.Имя;
        Список.Добавить(Перечисления.СостоянияЗаказов[ИмяЗначения]);
    КонецЦикла;
    Возврат Список;
КонецФункции

Важный нюанс: использование события ПриИзменении может привести к тому, что пользователю придется нажимать лишний раз. Однако это гарантированно «проталкивает» выбор в тех версиях платформы, где стандартный механизм сломан.

Решение №2: Перехват в событии «НачалоВыбора»

Более элегантный и «чистый» способ с точки зрения UX — использование события НачалоВыбора (StartChoice). Этот метод позволяет нам вмешаться в процесс еще до того, как платформа попытается открыть стандартное окно выбора типа. Проанализируем ситуацию: если мы знаем, что пользователю чаще всего нужно именно перечисление, или мы хотим полностью контролировать процесс выбора типов, мы можем установить параметр СтандартнаяОбработка = Ложь.

Давайте посмотрим, как можно реализовать этот механизм:


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

Использование НачалоВыбора предотвращает появление бажного системного диалога и делает интерфейс более предсказуемым для конечного пользователя.

Решение №3: Настройка свойств колонки «Быстрый выбор» и «Кнопка списка выбора»

Иногда проблему удается решить без написания сложного программного кода, просто изменив настройки отображения элемента в конфигураторе или программно при создании формы. Проанализируем влияние свойств БыстрыйВыбор (QuickChoice) и КнопкаСпискаВыбора (ChoiceListButton).

Рассмотрим пошагово, что нужно сделать:

  1. Откройте управляемую форму в конфигураторе.
  2. Найдите нужный реквизит (колонку) в табличной части.
  3. В палитре свойств установите флаг «Кнопка списка выбора» в значение Да.
  4. Установите свойство «Режим выбора из списка».
  5. Попробуйте активировать свойство «Быстрый выбор».

Почему это помогает? Когда включен «Быстрый выбор», платформа пытается сразу подгрузить доступные значения, минуя сложные модальные переходы. Для составного типа это может работать нестабильно, но в сочетании с перечислением часто исправляет ошибку отрисовки выпадающего списка в ячейке таблицы.

Решение №4: Архитектурный обход (Разделение реквизитов)

Если ни один из программных методов не дает 100% стабильности на вашем релизе платформы, рекомендуем рассмотреть вариант изменения структуры данных. Вместо одного реквизита с составным типом (Документ + Перечисление) можно использовать два отдельных поля, визуально объединенных для пользователя.

Разберем этот подход подробнее:

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

Пример программной настройки типа:


&НаКлиенте
Процедура ТипДанныхПриИзменении(Элемент)
    ТекущаяСтрока = Элементы.ТабличнаяЧасть1.ТекущиеДанные;
    
    // Очищаем старое значение при смене типа
    ТекущаяСтрока.Значение = Неопределено;
    
    // Устанавливаем доступные типы для выбора в соседней колонке
    НовыйМассив = Новый Массив;
    Если ТекущаяСтрока.ТипДанных = "Документ" Тогда
        НовыйМассив.Добавить(Тип("ДокументСсылка.РеализацияТоваровУслуг"));
    Иначе
        НовыйМассив.Добавить(Тип("ПеречислениеСсылка.СостоянияЗаказов"));
    КонецЕсли;
    
    ОписаниеТипов = Новый ОписаниеТипов(НовыйМассив);
    // Теперь при нажатии кнопки выбора в колонке "Значение" 
    // платформа не будет спрашивать тип, а сразу откроет нужное окно
    Элементы.ТабличнаяЧасть1Значение.ОграничениеТипа = ОписаниеТипов;
КонецПроцедуры

Этот метод является наиболее надежным, так как он полностью исключает использование «проблемного» диалога выбора типа платформы 8.3.15, заменяя его логичным и понятным бизнес-процессом.

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

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

← На главную