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