Почему не удается задать ТипЗначения для реквизита табличной части в 1С и как это исправить?

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

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

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

Выясняем причину: почему возникает ошибка «Поле объекта не обнаружено»?

Для начала проанализируем, к какому именно объекту мы обращаемся в коде. Ошибка обращения к свойству ТипЗначения чаще всего происходит по двум причинам:

  1. Попытка обратиться к свойству значения, а не объекта. Если реквизит табличной части имеет стандартный тип (например, СправочникСсылка.Номенклатура), то при обращении к нему через точку платформой возвращается конкретное ссылочное значение (или пустая ссылка). У типа данных СправочникСсылка в принципе отсутствует свойство ТипЗначения. Задать его напрямую для конкретной строки невозможно.
  2. Конфликт имен (дублирование реквизитов) на форме. Это классическая архитектурная ловушка. На форме могут одновременно существовать два реквизита с одинаковым или схожим наименованием в разных коллекциях (например, реквизит самой табличной части объекта и программно добавленный реквизит формы в той же таблице). Если один из них имеет тип обычного справочника, а второй — СписокЗначений, платформа при обращении через Элемент[ИмяРеквизита] может вернуть обычную ссылку вместо списка. Как результат — свойство ТипЗначения не будет обнаружено.

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

Различие поведения реквизитов типа «СписокЗначений» и стандартных типов

Если реквизит колонки табличной части определен как СписокЗначений (что часто используется для множественного выбора), то в ячейке строки хранится полноценный объект. У объекта СписокЗначений действительно есть доступное как для чтения, так и для записи свойство ТипЗначения, имеющее тип ОписаниеТипов.

Рассмотрим пример правильной инициализации и ограничения типов для реквизита типа СписокЗначений на сервере:


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

Если же мы имеем дело с обычным реквизитом (например, составного типа), то изменять его ТипЗначения напрямую у строки данных ДанныеФормыЭлементКоллекции нельзя. Вместо этого необходимо управлять свойствами элемента формы (визуального поля ввода), который отображает эти данные.

Решение проблемы дублирования имен реквизитов

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

В такой ситуации отладчик 1С может вести себя непредсказуемо, показывая в табло то один тип, то другой. Для решения этой проблемы выполните следующие шаги:

  1. Проверьте состав реквизитов вашей табличной части в дереве метаданных конфигурации.
  2. Проверьте состав реквизитов формы на вкладке "Реквизиты" в правом верхнем углу конструктора формы.
  3. Если вы обнаружили совпадение имен, обязательно переименуйте реквизит формы, добавив к нему понятный префикс, характеризующий тип данных. Например, переименуйте реквизит типа СписокЗначений в СЗ_НарушенноеТребование.
  4. Обновите путь к данным (свойство ПутьКДанным) у соответствующего элемента формы (колонки таблицы).

После устранения конфликта имен обращение к свойству ТипЗначения у корректного объекта СписокЗначений начнет отрабатывать стабильно и без ошибок.

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

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

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


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

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

Резюме и рекомендации

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

← На главную