Как программно установить тип ячейки и ограничить выбор в табличном поле обычных форм?

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

При разработке сложных интерфейсов в обычных формах 1С часто возникает задача динамического управления типами данных. Типичный сценарий: есть таблица для загрузки данных (например, через COM-соединение или из Excel), где одна колонка описывает тип объекта (строкой, например, "Справочник.Сотрудники"), а соседняя колонка предназначена для выбора конкретного значения (ссылки).

Проблема заключается в том, что если колонка имеет составной тип данных (включающий множество справочников и документов), то при начале редактирования платформа по умолчанию предлагает пользователю сначала выбрать тип данных (в этом поможет универсальная форма выбора типа; список "Документ", "Справочник" и т.д.). Это замедляет работу оператора. Наша задача — настроить интерфейс так, чтобы при клике на ячейку система сама "понимала", какой тип нужен, устанавливала его и сразу открывала список выбора конкретного элемента.

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

Этап 1: Подготовка данных и колонки таблицы значений

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

Самая распространенная ошибка — попытка присвоить ячейке значение типа, который не предусмотрен в описании типов колонки этой таблицы. Рассмотрим этот момент внимательнее.

Если мы хотим, чтобы в колонке "ЗначениеПриемника" могли храниться ссылки и на "Справочник.Сотрудники", и на "Документ.ПриемНаРаботу", эта колонка изначально должна быть создана с составным типом, включающим все эти варианты. Если таблица формируется программно (например, при загрузке), код создания колонок должен выглядеть примерно так:


// Формируем массив всех возможных типов, которые могут встретиться
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Сотрудники"));
МассивТипов.Добавить(Тип("СправочникСсылка.Должности"));
МассивТипов.Добавить(Тип("ДокументСсылка.ПриемНаРаботу"));
// ... добавляем остальные типы

// Создаем описание типов на основе массива
ОписаниеВсехТипов = Новый ОписаниеТипов(МассивТипов);

// Добавляем колонку в Таблицу Значений с этим описанием
ТЗ_Данные.Колонки.Добавить("ЗначениеПриемника", ОписаниеВсехТипов);

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

Этап 2: Использование события "ПередНачаломИзменения"

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

В этом событии мы имеем доступ к текущей строке данных и к элементу управления редактируемой колонки. Рассмотрим алгоритм действий:

  1. Определяем, какую колонку начал редактировать пользователь.
  2. Считываем значение из соседней колонки, где указан требуемый тип (в виде строки).
  3. Преобразуем строковое название типа в реальный объект ОписаниеТипов.
  4. Настраиваем свойство ОграничениеТипа у элемента управления активной ячейки.
  5. Отключаем выбор типа пользователем через свойство ВыбиратьТип.

Разберем готовый пример кода реализации этого события.


Процедура ТабличноеПолеДанныеПередНачаломИзменения(Элемент, Отказ)
    
    // Проверяем, что редактируется именно целевая колонка
    Если Элемент.ТекущаяКолонка.Имя = "ЗначениеПриемника" Тогда
        
        // Получаем текущую строку данных
        ТекущиеДанные = Элемент.ТекущиеДанные;
        Если ТекущиеДанные = Неопределено Тогда
            Возврат;
        КонецЕсли;
        
        // 1. Получаем строковое описание типа из соседней колонки
        // Предположим, там записано "СправочникСсылка.Сотрудники"
        СтрокаТипа = ТекущиеДанные.ТипИсточника; 
        
        // Важно: Строка должна содержать полное имя типа ссылки, например "СправочникСсылка.Номенклатура"
        // Если у вас там просто "Справочник.Номенклатура", нужно будет выполнить преобразование строк.
        
        Попытка
            // 2. Создаем ОписаниеТипов для конкретного нужного типа
            НужныйТип = Тип(СтрокаТипа);
            Ограничение = Новый ОписаниеТипов(НужныйТип);
            
            // Получаем доступ к элементу управления внутри ячейки
            ЭлементУпр = Элемент.Колонки.ЗначениеПриемника.ЭлементУправления;
            
            // 3. Устанавливаем ограничение типа
            // Теперь в этом поле можно выбрать только значения указанного типа
            ЭлементУпр.ОграничениеТипа = Ограничение;
            
            // 4. Отключаем диалог выбора типа (кнопка "Т")
            // Так как тип остался всего один, платформа сразу перейдет к выбору из справочника
            ЭлементУпр.ВыбиратьТип = Ложь;
            
            // 5. Приведение значения (опционально, но рекомендуется)
            // Если в ячейке было значение другого типа ("мусор"), его лучше очистить или привести
            Если ЗначениеЗаполнено(ЭлементУпр.Значение) 
               И НЕ Ограничение.СодержитТип(ТипЗнч(ЭлементУпр.Значение)) Тогда
                
                // Если старое значение не подходит под новый тип - очищаем
                ЭлементУпр.Значение = Ограничение.ПривестиЗначение(ЭлементУпр.Значение);
                
                // Также обновляем данные в самой строке таблицы
                ТекущиеДанные.ЗначениеПриемника = ЭлементУпр.Значение;
            КонецЕсли;
            
        Исключение
            // Обработка ситуации, если тип указан некорректно
            Сообщить("Ошибка определения типа: " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЕсли;

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

Важные нюансы работы с типами

Рассмотрим подробнее работу с конструктором ОписаниеТипов. В коде выше мы использовали конструкцию Новый ОписаниеТипов(Тип(СтрокаТипа)). Это критически важный момент.

Многие разработчики совершают ошибку, пытаясь передать строку с именем типа (например, "СправочникСсылка.Сотрудники") напрямую в конструктор ОписаниеТипов. В платформе 1С:

Если в вашей колонке "ТипИсточника" хранятся имена метаданных (например, "Справочник.Сотрудники"), то перед использованием их нужно преобразовать в имена типов ссылок. Обычно это делается заменой: "Справочник." -> "СправочникСсылка.", "Документ." -> "ДокументСсылка.".

Альтернативный вариант: Событие "НачалоВыбора"

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

В такой ситуации проанализируем альтернативный подход через событие НачалоВыбора (StartChoice). Этот метод позволяет полностью переопределить стандартное поведение системы при нажатии на кнопку "..." (три точки).


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

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

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

Резюме решения

Для реализации удобного выбора разнородных объектов в одной колонке обычных форм выполним следующие шаги:

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

Такой подход обеспечивает пользователю комфортную работу: система "сама" подставляет контекст, избавляя от лишних кликов, при этом сохраняя гибкость составного типа данных.

← На главную