Работа с динамическими интерфейсами в 1С — это мощный инструмент, который позволяет адаптировать форму под конкретные задачи пользователя «на лету». Однако программисты часто сталкиваются с трудностями при попытке программно добавить ТаблицуЗначений на форму и наполнить её данными. В этой статье мы подробно разберем, как правильно реализовать этот механизм, проанализируем типичные ошибки «Поле объекта не обнаружено» и выясним, почему метод ЗначениеВРеквизитФормы может выдавать исключение — для этих целей пригодится консоль разработчика для управляемых форм 1С.
Представим ситуацию: нам необходимо при выборе документа (например, приходной накладной) вывести на форму список его запасов, при этом состав колонок таблицы может определяться программно. Основная сложность заключается в том, что в управляемом приложении существует четкое разделение между данными формы (реквизитами) и визуальными элементами (элементами формы).
Для решения задачи мы пройдем через три обязательных этапа:
ТаблицаЗначений с нужным набором колонок.Рассмотрим ситуацию, когда в процедуре ПриСозданииНаСервере нам нужно объявить структуру будущей таблицы. Важно понимать, что просто создать объект Новая ТаблицаЗначений в коде недостаточно — форма «не знает» о его существовании как о части своих данных.
Для добавления реквизита используем метод ИзменитьРеквизиты. Разберем правильный код:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// 1. Описываем массив добавляемых реквизитов
МассивДобавляемыхРеквизитов = Новый Массив;
// Добавляем саму таблицу. "ТЗ_Данные" — это внутреннее имя реквизита на форме
МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ТЗ_Данные", Новый ОписаниеТипов("ТаблицаЗначений"), , "Список товаров"));
// Добавляем колонки для этой таблицы.
// Обратите внимание на путь к данным: "ИмяТаблицы.ИмяКолонки"
МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Код", Новый ОписаниеТипов("Строка"), "ТЗ_Данные"));
МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"), "ТЗ_Данные"));
МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)), "ТЗ_Данные"));
// Применяем изменения на форме
ЭтаФорма.ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
КонецПроцедуры
Важный момент: Если вы планируете пересоздавать колонки динамически при изменении каких-либо параметров, не забывайте удалять старые реквизиты перед добавлением новых, иначе система выдаст ошибку о дублировании имен.
После того как данные (реквизиты) созданы, мы должны создать элементы управления, чтобы пользователь их увидел. Проанализируем, как связать программный реквизит с элементом формы Таблица — настроить видимость и поведение полей без программирования поможет настройка интерфейса и поведения управляемых форм без кода.
&НаСервере
Процедура СоздатьВизуальныеЭлементы()
// Добавляем саму таблицу на форму
ТаблицаФормы = Элементы.Добавить("ТЗ_Вид", Тип("ТаблицаФормы"), ЭтаФорма);
ТаблицаФормы.ПутьКДанным = "ТЗ_Данные"; // Связываем с созданным ранее реквизитом
// Добавляем колонку "Код"
НоваяКолонка = Элементы.Добавить("ТЗ_Код", Тип("ПолеФормы"), ТаблицаФормы);
НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
НоваяКолонка.ПутьКДанным = "ТЗ_Данные.Код";
НоваяКолонка.Заголовок = "Код товара";
// Добавляем колонку "Номенклатура"
НоваяКолонка = Элементы.Добавить("ТЗ_Номенклатура", Тип("ПолеФормы"), ТаблицаФормы);
НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
НоваяКолонка.ПутьКДанным = "ТЗ_Данные.Номенклатура";
НоваяКолонка.Заголовок = "Товар";
КонецПроцедуры
Теперь выясним причину распространенной ошибки: Поле объекта не обнаружено (Код). Эта ошибка возникает, когда вы создаете новую локальную переменную типа ТаблицаЗначений, но забываете добавить в неё колонки методом Колонки.Добавить(), прежде чем обращаться к строкам этой таблицы — быстро найти причину поможет обработка для отладки кода 1С в режиме Предприятия.
Рассмотрим правильный алгоритм заполнения в обработчике изменения документа:
&НаСервере
Процедура пнПриИзмененииНаСервере()
Если Объект.пн.Пустая() Тогда
Возврат;
КонецЕсли;
// Рекомендуемый способ: Работаем сразу через реквизит формы
// Преобразуем реквизит формы в объект ТаблицаЗначений
ТаблицаОбъект = РеквизитФормыВЗначение("ТЗ_Данные");
ТаблицаОбъект.Очистить();
// Подготовим запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПриходнаяНакладнаяЗапасы.Номенклатура КАК Номенклатура,
| ПриходнаяНакладнаяЗапасы.Номенклатура.Код КАК Код,
| ПриходнаяНакладнаяЗапасы.Цена КАК Цена
|ИЗ
| Документ.ПриходнаяНакладная.Запасы КАК ПриходнаяНакладнаяЗапасы
|ГДЕ
| ПриходнаяНакладнаяЗапасы.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Объект.пн);
// Выгружаем результат напрямую в таблицу
ТаблицаОбъект = Запрос.Выполнить().Выгрузить();
// Важно! Имена колонок в запросе (псевдонимы) ДОЛЖНЫ совпадать
// с именами реквизитов, добавленных в Этапе 1.
// Возвращаем данные на форму
ЗначениеВРеквизитФормы(ТаблицаОбъект, "ТЗ_Данные");
КонецПроцедуры
Проанализируем ситуацию из сообщения автора, где возникла ошибка «Недопустимое значение параметра (параметр номер '2')» при вызове ЗначениеВРеквизитФормы(ТДп, "Тп").
Причина 1: Неверное имя реквизита. Во втором параметре метода ЗначениеВРеквизитФормы нужно указывать строковое имя реквизита, который был добавлен через ИзменитьРеквизиты. Если вы назвали его "ТЗ_Данные", а пытаетесь записать в "Тп", система закономерно выдаст ошибку, так как реквизита "Тп" не существует в контексте формы.
Причина 2: Несоответствие типов. Если в локальной таблице значений ТДп колонка «Цена» имеет тип Число, а в реквизите формы она была объявлена как Строка, метод конвертации данных завершится ошибкой. Всегда следите за строгим соответствием типов данных.
Причина 3: Использование пустой таблицы. Ошибка Поле объекта не обнаружено (Код) при выполнении кода Строка.Код = ... означает, что в объекте ТаблицаЗначений, к которому вы обращаетесь, нет колонки с таким именем. Если вы создаете таблицу через Новый ТаблицаЗначений, вы обязаны явно прописать все колонки через ТЗ.Колонки.Добавить("Код").
Рассмотрим несколько советов, которые помогут сделать ваш код надежнее:
Строка = ТЗ.Добавить()), используйте РезультатЗапроса.Выгрузить(). Это работает значительно быстрее на больших объемах данных.ЕСТЬNULL(). Если запрос вернет NULL в колонку, которая на форме строго типизирована как СправочникСсылка или Число, возникнет ошибка при передаче данных на форму.ТЗ.Колонки. Это самый быстрый способ увидеть реальную структуру объекта в памяти.Таким образом, правильная работа с программными таблицами требует синхронного управления тремя сущностями: описанием реквизитов, структурой объекта ТаблицаЗначений и элементами интерфейса. Соблюдение этой последовательности гарантирует стабильную работу вашей обработки.