К статье
Практический материал

Разработка и Конфигурация · 13 мин

Структура как реквизит формы 1С: практическое руководство

Как добавить реквизит формы типа «Структура» в 1С: пошаговая инструкция, работа из кода, типичные ошибки, альтернативы и способы проверки результата.

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

Ключевая особенность: в конструкторе реквизитов формы тип «Структура» выбрать нельзя. Реквизит создаётся с произвольным типом, а собственно структура помещается в него программно — либо реквизит добавляется динамически через метод ИзменитьРеквизиты(). Оба подхода рабочие, но у каждого есть свои ограничения по сериализации, времени жизни и отображению.

Ниже разобраны оба способа создания, работа с реквизитом из кода, типичные ошибки (включая потерю данных при серверных вызовах) и критерии выбора между «Структурой», «Соответствием» и таблицей значений.

Что такое реквизит формы и почему «Структуры» нет в палитре типов

Реквизит формы — это данные, которые живут вместе с формой: они существуют, пока форма открыта, и доступны из её модулей на клиенте и на сервере. В конфигураторе реквизиты добавляются через панель «Реквизиты» в редакторе формы, где для каждого указывается имя, тип и признак основного реквизита.

В списке типов реквизита формы присутствуют примитивные типы (Строка, Число, Дата, Булево), ссылочные типы, а также универсальные коллекции: ТаблицаЗначений, ДеревоЗначений, ДинамическийСписок. Типа «Структура» в этом списке нет, потому что структура — это объект встроенного языка, а не самостоятельный тип данных формы с точки зрения платформы.

Обходной путь простой: реквизит объявляется с произвольным типом (без конкретизации) или с типом «Произвольный», а структура помещается в него при создании формы. Платформа спокойно хранит структуру в таком реквизите, пока не требуется её отображение на форме или передача между вызовами в специфических режимах.

Способ 1. Реквизит произвольного типа через конструктор формы

Это основной способ, когда состав реквизита известен на этапе разработки. Откройте форму в конфигураторе, в панели реквизитов добавьте новый реквизит, например «ПараметрыОтбора». В поле типа снимите все флажки конкретных типов либо оставьте составной тип без выбора — реквизит станет произвольным.

Далее в модуле формы, обычно в обработчике ПриСозданииНаСервере, реквизит инициализируется структурой:

1c
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ЭтаФорма.ПараметрыОтбора = Новый Структура;
    ЭтаФорма.ПараметрыОтбора.Вставить("Организация", Неопределено);
    ЭтаФорма.ПараметрыОтбора.Вставить("ДатаНачала", НачалоМесяца(ТекущаяДатаСеанса()));
    ЭтаФорма.ПараметрыОтбора.Вставить("ТолькоАктивные", Истина);
КонецПроцедуры

После инициализации обращение к элементам структуры выполняется через точку: ЭтаФорма.ПараметрыОтбора.Организация. Проверка наличия ключа делается через Свойство(): ЭтаФорма.ПараметрыОтбора.Свойство("Склад", НайденноеЗначение) — так безопаснее, чем прямое обращение, которое вызовет ошибку при отсутствии ключа.

Порядок действий
  1. 1
    Откройте форму в конфигураторе, добавьте реквизит без конкретного типа
  2. 2
    В ПриСозданииНаСервере присвойте реквизиту Новый Структура с нужными ключами
  3. 3
    Обращайтесь к значениям через ЭтаФорма.ИмяРеквизита.ИмяКлюча
  4. 4
    Проверяйте наличие ключа методом Свойство() перед обращением
  5. 5
    Проверьте работу: откройте форму, убедитесь, что значения читаются и на клиенте, и на сервере

Способ 2. Динамическое добавление через ИзменитьРеквизиты

Если реквизит нужен только в определённых сценариях или его состав зависит от параметров открытия, используется программное добавление. Метод ИзменитьРеквизиты() доступен только на сервере и только до того, как форма показана пользователю в финальном виде — чаще всего в ПриСозданииНаСервере.

1c
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Добавляемые = Новый Массив;
    Добавляемые.Добавить(Новый РеквизитФормы("НастройкиОбмена", Новый ОписаниеТипов()));
    ИзменитьРеквизиты(Добавляемые);
    ЭтаФорма.НастройкиОбмена = Новый Структура("Узел, Режим", Неопределено, "Ручной");
КонецПроцедуры

Пустой конструктор Новый ОписаниеТипов() создаёт описание произвольного типа — именно это позволяет затем поместить в реквизит структуру. Если указать конкретный тип, присвоение структуры вызовет ошибку несоответствия типов.

Работа со структурой на клиенте и сервере

Реквизит формы доступен и в клиентских, и в серверных процедурах модуля формы через ЭтаФорма.ИмяРеквизита. Чтение и изменение отдельных ключей структуры допустимо на клиенте без серверного вызова — это удобно для накопления настроек пользователя перед выполнением «тяжёлой» операции.

Типичный сценарий: пользователь заполняет несколько полей, значения складываются в структуру, затем структура целиком передаётся в серверную процедуру как параметр. Это сокращает число серверных вызовов и упрощает сигнатуры процедур — вместо десяти параметров передаётся одна структура.

1c
&НаКлиенте
Процедура СформироватьОтчет(Команда)
    ЭтаФорма.ПараметрыОтбора.Вставить("Организация", Организация);
    Результат = СформироватьНаСервере(ЭтаФорма.ПараметрыОтбора);
КонецПроцедуры

&НаСервереБезКонтекста
Функция СформироватьНаСервере(ПараметрыОтбора)
    // работа с переданной структурой
КонецФункции

Обратите внимание: при передаче структуры как параметра серверной процедуры ограничений почти нет. Проблемы возникают именно при хранении структуры в реквизите формы между серверными вызовами в некоторых режимах работы — об этом ниже.

Ограничения и подводные камни

Главное ограничение — сериализация. Данные формы между серверными вызовами проходят через механизм передачи данных формы, и не все значения переживают этот цикл. Структура, содержащая только простые типы (строки, числа, даты, булево, ссылки), обычно переносится корректно. Но вложенные объекты — например, таблица значений внутри структуры, COM-объекты, результаты запросов — могут быть утрачены или вызвать ошибку.

Вторая ловушка — невозможность отобразить структуру на форме напрямую. Элемент формы «Поле» требует конкретного пути к данным с известным типом. Если нужно показать содержимое структуры пользователю, её преобразуют в таблицу значений (две колонки: «Ключ» и «Значение») или выводят отдельные элементы в поля с примитивными реквизитами.

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

Что выбрать вместо структуры: сравнение альтернатив

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

Сравнение вариантов

Структура (реквизит произвольного типа)

Набор именованных настроек, параметры отбора, передача параметров на сервер. Ограничение: не отображается на форме, риск с сериализацией сложных значений.

ТаблицаЗначений

Однотипные строки данных, которые нужно показать пользователю или редактировать. Полностью сериализуется, отображается таблицей формы. Избыточна для пары «ключ-значение».

Соответствие

Частый поиск по произвольным ключам (не только строкам-идентификаторам). Нет обращения через точку, те же ограничения по отображению.

Отдельные реквизиты формы

Небольшое фиксированное число параметров, каждый из которых привязан к элементу формы. Самый прозрачный вариант для сопровождения.

ХранилищеЗначения

Сложные несериализуемые объекты, которые нужно сохранить между сеансами. Требует упаковки/распаковки, не работает как оперативный кэш формы.

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

Маршрут решения

Как выбрать действие

Нужно передать набор параметров из клиентской процедуры в сервернуюСоберите структуру и передайте её параметром — реквизит формы для этого не обязателен
Параметры должны жить всё время, пока открыта формаСоздайте реквизит произвольного типа и инициализируйте его структурой в ПриСозданииНаСервере
Данные нужно показать пользователю в виде таблицыИспользуйте реквизит типа ТаблицаЗначений вместо структуры
Состав реквизитов зависит от параметров открытия формыДобавляйте реквизит динамически через ИзменитьРеквизиты в ПриСозданииНаСервере

Типичные ошибки и как их избежать

Типичные ошибки
01
Попытка выбрать тип «Структура» в конструкторе реквизита — его там нет; реквизит создаётся с произвольным типом, структура присваивается кодом
02
Обращение к несуществующему ключу через точку — возникает ошибка «Поле объекта не обнаружено»; используйте Свойство() с проверкой результата
03
Хранение таблицы значений внутри структуры-реквизита — после серверного вызова вложенная таблица может быть потеряна; выносите таблицы в отдельные реквизиты
04
Вызов ИзменитьРеквизиты в клиентском обработчике — метод доступен только на сервере; переносите добавление реквизитов в ПриСозданииНаСервере
05
Присвоение структуры реквизиту с конкретным типом (например, Строка) — ошибка несоответствия типов; очищайте состав типов у реквизита

Ещё одна распространённая ситуация — путаница между реквизитом формы и параметром формы. Параметры передаются при открытии и доступны через коллекцию Параметры, реквизиты создаются разработчиком и живут в данных формы. Если значение нужно только в момент открытия, достаточно параметра; если оно изменяется в процессе работы — нужен реквизит.

Проверка результата

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

Контрольные точки

Как проверить результат

Инициализация при открытии
Норма

В отладчике реквизит содержит структуру со всеми ожидаемыми ключами

Тревожный признак

Реквизит равен Неопределено — проверьте ПриСозданииНаСервере

Сохранность после серверного вызова
Норма

После вызова серверной процедуры все ключи и значения на месте

Тревожный признак

Часть значений потеряна — в структуре есть несериализуемые объекты

Обращение к ключам
Норма

Свойство() возвращает Истина, значение читается без ошибок

Тревожный признак

Ошибка «Поле объекта не обнаружено» — ключ не добавлен или опечатка в имени

Для форм, где структура критична для бизнес-логики, полезно добавить защитное программирование: в начале серверных процедур проверять наличие обязательных ключей и вызывать понятное исключение, если структура не инициализирована. Это ускоряет диагностику при доработках.

Удобный приём — централизованная функция инициализации структуры с полным списком ключей и значениями по умолчанию. Она вызывается и в ПриСозданииНаСервере, и перед каждым «тяжёлым» серверным вызовом: если часть данных потерялась при сериализации, структура восстанавливается до рабочего состояния, а текущие значения переносятся поверх значений по умолчанию.
ПЗ
Практическое замечание

Частые вопросы

Можно ли отобразить структуру на форме, чтобы пользователь видел её содержимое?

Напрямую — нет, элементы формы не привязываются к структуре. Варианты обхода: преобразовать структуру в таблицу значений с колонками «Параметр» и «Значение» и вывести её таблицей формы, либо создать отдельные реквизиты с примитивными типами под каждый отображаемый ключ.

Почему после серверного вызова часть значений структуры пропала?

Наиболее вероятная причина — внутри структуры лежат несериализуемые объекты: таблица значений, дерево значений, COM-объект, результат запроса. Оставляйте в структуре только простые типы и ссылки, а сложные данные храните в отдельных реквизитах подходящего типа.

Чем структура отличается от соответствия в роли реквизита формы?

Структура позволяет обращаться к значениям через точку и требует, чтобы ключи были допустимыми идентификаторами. Соответствие принимает ключи любого типа и быстрее ищет по большому числу элементов, но обращение идёт только через квадратные скобки. Для настроек обычно удобнее структура, для кэша поиска — соответствие.

Можно ли добавить реквизит формы программно уже после открытия формы?

Нет, метод ИзменитьРеквизиты корректно работает только на сервере до финального формирования формы — практически всегда это ПриСозданииНаСервере. Если состав данных меняется в процессе работы, заранее создайте реквизит произвольного типа и меняйте содержимое структуры, а не набор реквизитов.

Как передать структуру из одной формы в другую?

Через параметры открытия: при вызове ОткрытьФорму() передайте структуру в параметре, а в открываемой форме прочитайте её в ПриСозданииНаСервере из коллекции Параметры и скопируйте в собственный реквизит. Копирование предпочтительнее прямого использования параметра, так как параметры формы имеют ограниченное время жизни.

Влияет ли структура-реквизит на производительность формы?

При разумном размере (десятки ключей с простыми значениями) влияние незаметно. Накладные расходы растут, если структура содержит сотни элементов или тяжёлые вложенные объекты и передаётся между клиентом и сервером при каждом вызове. В таких случаях сокращайте состав передаваемых данных или пересоздавайте объект на сервере вместо хранения.

Итог

Что важно запомнить

Типа «Структура» в конструкторе реквизитов формы нет: создавайте реквизит произвольного типа и присваивайте структуру кодом в ПриСозданииНаСервере, либо добавляйте реквизит динамически через ИзменитьРеквизиты. Храните в структуре только простые сериализуемые значения, проверяйте ключи через Свойство(), а для отображаемых и табличных данных используйте таблицу значений.