Динамическое создание элементов управляемой формы в платформе «1С:Предприятие 8» — мощный инструмент, который позволяет разработчикам строить гибкие, адаптирующиеся под конкретные данные интерфейсы. Однако при написании подобного кода легко столкнуться с неочевидными ошибками платформы. Самая частая и наименее информативная из них — «Недопустимое значение параметров» (Invalid parameter value).
В этой статье мы подробно разберем, почему возникает эта ошибка при попытке вложить один динамический элемент в другой, как правильно инициализировать контейнеры на форме и как избежать скрытой ловушки форматирования чисел при генерации уникальных имен элементов.
Рассмотрим по шагам логику работы платформы, выясним причины сбоев и напишем надежный, отказоустойчивый код.
---
Типичный сценарий: разработчик пытается программно создать группу, а затем добавить внутрь нее элемент (например, декорацию-надпись или поле ввода). На этапе добавления дочернего элемента платформа выбрасывает исключение.
Проанализируем проблемный участок кода на английском синтаксисе, с которым столкнулся автор темы:
Counter = 1;
For Each Item in Array Do
GroupItem = ThisForm.Items.Add("Groups" + String(Counter), Type("FormGroup"), ThisForm.Items.Tiles);
DescriptionItem = ThisForm.Items.Add("Desc" + String(Counter), Type("FormDecoration"), GroupItem);
DescriptionItem.Title = Item.Get("Description");
DescriptionItem.Type = FormDecorationType.Label;
Counter = Counter + 1;
EndDo;
В этой конструкции метод Items.Add аварийно завершает работу на строке создания декорации DescriptionItem, указывая на неверный третий параметр (родительскую группу GroupItem). При этом, если в качестве родителя указать статическую группу ThisForm.Items.Tiles, созданную в конфигураторе, код отрабатывает без ошибок.
Почему так происходит?
Класс ГруппаФормы (в англ. локализации FormGroup) является универсальным контейнером. Он может принимать самые разные формы: обычная группа, страницы, страница панели, командная панель или группа кнопок. Пока у динамически добавленного объекта GroupItem не заполнено свойство Вид (Type), платформа считает инициализацию объекта незавершенной. Она не может определить правила отрисовки и валидации вложенных элементов, поэтому запрещает передавать такую «незавершенную» группу в качестве родителя для других элементов.
Чтобы решить эту проблему, необходимо строго до добавления подчиненных элементов явно назначить вид создаваемой группы:
// Для русскоязычного кода:
НоваяГруппа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
// Для англоязычного кода:
GroupItem.Type = FormGroupType.UsualGroup;
---
Даже если вид группы указан корректно, при больших объемах данных код может внезапно начать падать на определенных итерациях цикла. Если количество создаваемых элементов превысит 999, простая конвертация счетчика в строку через Строка(Счетчик) или String(Counter) приведет к ошибке.
В чем кроется опасность?
По умолчанию стандартное преобразование числа в строку в 1С происходит с учетом региональных установок. В русской локализации при превышении порога в 999 платформа автоматически группирует разряды числа и разделяет их неразрывным пробелом (символ с кодом 160).
Например, число 1000 преобразуется в строковое значение "1 000".
Поскольку имя элемента формы формируется сложением префикса и строкового счетчика:
ИмяГруппы = "Groups" + Строка(Counter); // При Counter = 1000 вернет "Groups1 000"
В метод Элементы.Добавить() передается имя, содержащее пробел. Правила платформы строго запрещают использование пробелов и спецсимволов в идентификаторах элементов управляемой формы. Как результат — платформа возвращает все ту же неинформативную ошибку «Недопустимое значение параметров».
Чтобы гарантированно избежать этой проблемы, для формирования уникальных имен необходимо всегда использовать функцию Формат() с отключением группировки разрядов:
// Правильное формирование имени (на русском языке):
ИмяГруппы = "Groups" + Формат(Счетчик, "ЧГ=0");
// Правильное формирование имени (на английском языке):
GroupName = "Groups" + Format(Counter, "NG=0");
Параметр форматирования ЧГ=0 (в английской версии NG=0) полностью убирает группировку разрядов, гарантируя получение сплошной строки из цифр (например, "Groups1000" вместо "Groups1 000").
---
На основе выявленных правил составим эталонный шаблон кода для динамического создания групп и декораций на управляемой форме. Напишем его на русском языке в соответствии со стандартами разработки фирмы «1С».
Предположим, что код выполняется в серверном контексте формы (например, в процедуре ПриСозданииНаСервере):
&НаСервере
Процедура СоздатьЭлементыИнтерфейсаНаСервере(МассивДанных)
Счетчик = 1;
РодительскаяГруппа = Элементы.Tiles; // Предположим, группа Tiles уже есть на форме
Для Каждого СтрокаДанных Из МассивДанных Цикл
// 1. Формируем гарантированно уникальные имена без пробелов
ИмяГруппы = "ГруппаСтроки_" + Формат(Счетчик, "ЧГ=0");
ИмяДекорации = "ОписаниеСтроки_" + Формат(Счетчик, "ЧГ=0");
// 2. Создаем и инициализируем контейнер (группу)
НоваяГруппа = Элементы.Добавить(ИмяГруппы, Тип("ГруппаФормы"), РодительскаяГруппа);
// КРИТИЧЕСКИ ВАЖНО: Указываем вид группы сразу после добавления
НоваяГруппа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
НоваяГруппа.ОтображатьЗаголовок = Ложь;
// 3. Создаем подчиненный элемент внутри новой группы
НоваяДекорация = Элементы.Добавить(ИмяДекорации, Тип("ДекорацияФормы"), НоваяГруппа);
// Настраиваем свойства созданной декорации
НоваяДекорация.Вид = ВидДекорацииФормы.Надпись;
НоваяДекорация.Заголовок = СтрокаДанных.Description;
// Увеличиваем счетчик для следующей итерации
Счетчик = Счетчик + 1;
КонецЦикла;
КонецПроцедуры
---
Для того чтобы ваш код динамического построения интерфейса всегда работал стабильно, рекомендуем придерживаться следующих правил:
Элементы) и реквизитами формы выполняются исключительно на сервере. Попытка вызвать метод Добавить() на клиенте вызовет синтаксическую ошибку еще на этапе компиляции модуля.Добавить() вторым параметром всегда передается базовый тип метаданных формы: Тип("ПолеФормы"), Тип("ГруппаФормы"), Тип("ТаблицаФормы") или Тип("ДекорацияФормы"). Конкретное поведение (будет ли это поле ввода, флажок, переключатель или картинка) определяется исключительно через свойство Вид созданного объекта после его добавления.ВидПоляФормы.ПолеВвода), одного создания элемента на форме недостаточно. Вам потребуется связать его с данными формы. Для этого необходимо сначала программно создать реквизит формы через объект РеквизитФормы, добавить его в структуру формы методом ИзменитьРеквизиты(), и только после этого привязать к элементу через свойство ПутьКДанным.Применение этих простых правил убережет вас от трудночитаемых системных ошибок платформы 1С и сделает ваш программный код лаконичным, производительным и надежным.