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