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

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

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

Анализ типовой ошибки: время жизни переменных модуля формы

Посмотрим на исходный пример кода, который приводит к ошибке:


Перем Таб;

&НаСервере
Процедура ТаблицаТоваровТЗ()
    Таб = Новый ТаблицаЗначений;
    Таб.Колонки.Добавить("ИнвентарныйНомерПолеВвода");
    Таб.Колонки.Добавить("НоменклатурныйНомерПолеВвода");
    // ... добавление остальных колонок
КонецПроцедуры

&НаСервере
Процедура ТаблицаТоваровПриАктивизацииСтроки(Элемент)
    Стр = Таб.Добавить();
КонецПроцедуры

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

Когда срабатывает обработчик ТаблицаТоваровПриАктивизацииСтроки, инициируется новый серверный вызов. В этом новом вызове переменная Таб инициализируется заново со значением Неопределено. В результате обращение Таб.Добавить() вызывает исключение времени выполнения, так как у значения Неопределено нет метода Добавить.

Кроме того, обратим внимание на синтаксис: вызов процедур и функций без параметров в платформе 1С обязательно должен сопровождаться круглыми скобками (Таб.Добавить(), а не Таб.Добавить), иначе платформа интерпретирует это как обращение к свойству объекта.

Опасность серверных вызовов в событии ПриАктивизацииСтроки

Проанализируем работу события ПриАктивизацииСтроки таблицы формы. Данное событие возникает:

  1. При первичном открытии формы и инициализации таблицы;
  2. При любом перемещении курсора по строкам (стрелками клавиатуры, колесом мыши или кликом);
  3. При смене фокуса ввода между элементами формы.

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

Способ 1. Хранение данных в реквизитах формы (ДанныеФормыКоллекция)

Чтобы данные сохранялись между вызовами сервера в течение всего жизненного цикла формы, их необходимо объявлять не в коде модуля через Перем, а на вкладке Реквизиты редактора формы.

Разберем по шагам, как правильно настроить реквизит:

  1. В окне редактирования формы перейдем на вкладку Реквизиты.
  2. Добавим новый реквизит (например, ХарактеристикиТоваров) и укажем ему тип ТаблицаЗначений.
  3. Раскроем созданный реквизит и добавим необходимые колонки (ИнвентарныйНомер, НоменклатурныйНомер, ИдентификаторСтроки и т.д.).

Важно понимать: на сервере этот реквизит доступен для алгоритмов как типизированная коллекция, а при передаче на клиент платформа автоматически преобразует его в объект ДанныеФормыКоллекция. Это позволяет считывать и записывать значения напрямую на клиенте.

Если на сервере требуется выполнить сложные групповые операции с таблицей, используются методы трансформации данных:


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

Способ 2. Реализация связи «Товары — Характеристики» на клиенте

Рассмотрим распространенную задачу: на первой вкладке расположен список добавленных товаров, а на второй вкладке — 30 полей ввода для детальных характеристик текущего товара.

Чтобы характеристики отображались корректно при переключении между товарами без обращения к серверу, свяжем поля формы с текущей строкой основной таблицы через реквизиты объекта или напрямую через данные строки.

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


&НаКлиенте
Процедура ТаблицаТоваровПриАктивизацииСтроки(Элемент)
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        // Строка не выбрана (таблица пуста) - очищаем поля на второй вкладке
        ОчиститьПоляХарактеристик();
        Возврат;
    КонецЕсли;

    // Заполняем поля ввода значениями из текущей строки таблицы товаров
    ПолеИнвентарныйНомер = ТекущиеДанные.ИнвентарныйНомер;
    ПолеНоменклатурныйНомер = ТекущиеДанные.НоменклатурныйНомер;
    ПолеНаименованиеОбъекта = ТекущиеДанные.НаименованиеОбъекта;
    ПолеТипУстройства = ТекущиеДанные.ТипУстройства;
КонецПроцедуры

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

Способ 3. Связь двух табличных частей по ключу связи (Архитектурный подход)

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

  1. Табличная часть Товары с числовым реквизитом КлючСвязи;
  2. Табличная часть ХарактеристикиТоваров с реквизитом КлючСвязи.

При добавлении нового товара ему присваивается уникальный номер (например, через УникальныйИдентификатор или инкрементный счетчик). На форме во второй таблице устанавливается отбор по КлючуСвязи текущей строки первой таблицы. Это гарантирует целостность структуры данных и позволяет автоматически сохранять всю информацию стандартными механизмами платформы 1С.

← На главную