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

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

Как записать реквизит формы в 1С

Как записать реквизит формы в 1С: программное создание через ИзменитьРеквизиты, присвоение значений, работа с динамическими списками и типичные ошибки.

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

Основная сложность работы с реквизитами формы — разделение контекстов клиента и сервера. Простое присвоение вида РеквизитФормы = Значение работает в любом контексте, но создание новых реквизитов и изменение их состава возможно только на сервере через метод ИзменитьРеквизиты(). Игнорирование этого правила — самая частая причина ошибок «Метод объекта не обнаружен» у начинающих разработчиков.

Материал рассчитан на разработчиков и внедренцев, работающих с управляемыми формами в платформе 1С:Предприятие 8.3. Рассмотрены оба сценария: запись в существующий реквизит и динамическое создание реквизитов программно, а также особенности работы с таблицами значений и динамическими списками на форме.

Что такое реквизит формы и чем он отличается от реквизита объекта

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

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

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

Если реквизит создан в конфигураторе через панель «Реквизиты» формы, запись значения выполняется обычным присвоением по имени. Имя реквизита становится свойством объекта формы:

&НаКлиенте

Процедура УстановитьПризнак(Команда)

ПоказыватьДетали = Истина;

ТекстСтатуса = "Загружено строк: " + Формат(ТаблицаСтрок.Количество(), "ЧГ=");

КонецПроцедуры

Здесь ПоказыватьДетали и ТекстСтатуса — реквизиты формы, объявленные в конфигураторе. Присвоение выполняется на клиенте без обращения к серверу, если тип значения простой (строка, число, булево, дата) или является сериализуемой ссылкой.

Обращаться к реквизиту можно и через коллекцию ЭтаФорма["ИмяРеквизита"], что удобно, когда имя формируется динамически. Этот приём используется в универсальных механизмах, где имена реквизитов генерируются по шаблону:

ЭтаФорма["Настройка_" + ИмяКлюча] = НовоеЗначение;

Как программно создать реквизит формы через ИзменитьРеквизиты

Когда реквизит нужен только в определённых условиях или его состав зависит от данных (например, колонки динамического отчёта), реквизиты создают программно. Это делается методом ИзменитьРеквизиты(), который доступен только в серверном контексте формы.

Метод принимает два параметра: массив добавляемых реквизитов (объекты типа ОписаниеРеквизитаФормы) и массив имён удаляемых реквизитов. Типичный сценарий — создать реквизит и сразу записать в него значение:

&НаСервере

Процедура СоздатьРеквизитИЗаписать()

Добавляемые = Новый Массив;

Описание = Новый ОписаниеРеквизитаФормы(

"РезультатРасчета",

Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));

Добавляемые.Добавить(Описание);

ИзменитьРеквизиты(Добавляемые);

// Теперь реквизит существует — можно записать значение

ЭтаФорма["РезультатРасчета"] = 1250.75;

КонецПроцедуры

Конструктор ОписаниеРеквизитаФормы принимает имя, описание типов, путь к данным (для вложенных реквизитов), заголовок и признак сохраняемости. После вызова ИзменитьРеквизиты() реквизит доступен по имени как обычное свойство формы.

Порядок программного создания реквизита
  1. 1
    Сформируйте массив объектов ОписаниеРеквизитаФормы с именами и типами
  2. 2
    Вызовите ИзменитьРеквизиты() в серверной процедуре формы
  3. 3
    Проверьте, что реквизит с таким именем не существовал ранее — иначе будет ошибка
  4. 4
    Запишите значение присвоением по имени реквизита
  5. 5
    При необходимости создайте элемент формы и свяжите его с реквизитом через ПутьКДанным

Как записать данные в таблицу значений на форме

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

&НаКлиенте

Процедура ДобавитьСтроку(Команда)

НоваяСтрока = ТоварыКОтгрузке.Добавить();

НоваяСтрока.Номенклатура = ТекущаяНоменклатура;

НоваяСтрока.Количество = 1;

КонецПроцедуры

Если нужно загрузить в таблицу результат запроса, потребуется серверная процедура, потому что запросы выполняются только на сервере. Результат передаётся через ЗначениеВДанныеФормы() или загружается методом Загрузить():

&НаСервере

Процедура ЗагрузитьДанные()

РезультатЗапроса = ВыполнитьЗапросКДанным();

ТоварыКОтгрузке.Загрузить(РезультатЗапроса.Выгрузить());

КонецПроцедуры

Добавление новых колонок в таблицу значений формы выполняется тем же ИзменитьРеквизиты(): в описании реквизита указывается путь к таблице, а имя — это имя новой колонки.

Особенности записи в реквизит типа «Динамический список»

Динамический список — особый реквизит формы, содержимое которого платформа формирует автоматически по запросу. Напрямую записать строки в динамический список нельзя: он не хранит данные, а отображает результат запроса. Изменить можно только параметры, отбор, порядок и текст запроса:

&НаСервере

Процедура УстановитьОтборСписка()

Список.Параметры.УстановитьЗначениеПараметра("Организация", ТекущаяОрганизация);

ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Проведен");

ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;

ЭлементОтбора.ПравоеЗначение = Истина;

ЭлементОтбора.Использование = Истина;

КонецПроцедуры

Если требуется показать произвольные данные, которых нет в одной таблице базы, динамический список не подходит — используйте реквизит типа «ТаблицаЗначений» и заполняйте его программно.

Типичные ошибки
01
Вызов ИзменитьРеквизиты() на клиенте — метод доступен только на сервере, получите ошибку исполнения
02
Повторное создание реквизита с тем же именем без проверки — платформа выдаст ошибку дублирования
03
Попытка записать строки в динамический список — он отображает результат запроса и не хранит данные напрямую
04
Ожидание, что реквизит формы сохранится в базе — данные формы теряются при закрытии, для сохранения нужна запись объекта
05
Передача несериализуемых типов (например, объекта запроса) в реквизит формы — используйте только допустимые для формы типы

Как проверить, что значение записано корректно

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

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

Функция РеквизитСуществует(ИмяРеквизита)

Для Каждого Реквизит Из ПолучитьРеквизиты() Цикл

Если Реквизит.Имя = ИмяРеквизита Тогда

Возврат Истина;

КонецЕсли;

КонецЦикла;

Возврат Ложь;

КонецФункции

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

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

Значение отображается в связанном элементе формы
Норма

Элемент показывает новое значение сразу после присвоения

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

Элемент пуст или показывает старое значение — проверьте ПутьКДанным и имя реквизита

Динамически созданный реквизит
Норма

ПолучитьРеквизиты() возвращает реквизит с нужным именем и типом

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

Реквизита нет в списке — ИзменитьРеквизиты() не выполнился или вызван в другом экземпляре формы

Таблица значений после загрузки
Норма

Количество строк соответствует источнику, типы колонок корректны

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

Строки есть, но значения пустые — не совпадают имена колонок источника и реквизита

Ограничения и когда выбрать другой подход

Реквизиты формы не подходят для хранения больших объёмов данных: значения передаются между клиентом и сервером при каждом серверном вызове, что замедляет форму. Таблицы на тысячи строк лучше заменить динамическим списком с запросом к базе или временным хранилищем.

Для передачи данных между формами реквизиты формы тоже не лучший инструмент — используйте параметры формы при открытии (Параметры.ПередатьЗначение), оповещения (Оповестить) или временное хранилище (ПоместитьВоВременноеХранилище).

Если значение должно сохраняться между сеансами пользователя, рассмотрите хранение в регистре сведений, константе или настройках пользователя через ХранилищеОбщихНастроек.

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

Как выбрать подход

Нужно просто показать или хранить значение в открытой формеСоздайте реквизит в конфигураторе и записывайте простым присвоением
Состав реквизитов зависит от данных и заранее неизвестенСоздавайте реквизиты программно через ИзменитьРеквизиты() на сервере
Нужно показать данные из базы с отбором и сортировкойИспользуйте динамический список и управляйте его параметрами и отбором
Значение должно пережить закрытие формыСохраняйте его в базе данных или в хранилище настроек, а не в реквизите формы

Часто задаваемые вопросы

Можно ли вызвать ИзменитьРеквизиты() в клиентской процедуре?

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

Почему после ИзменитьРеквизиты() присвоение по имени выдаёт ошибку?

Чаще всего присвоение выполняется в другом контексте или до фактического создания реквизита. Убедитесь, что присвоение идёт после вызова ИзменитьРеквизиты() в той же серверной процедуре, либо обращайтесь через ЭтаФорма["ИмяРеквизита"] из последующих серверных вызовов. Также проверьте, что имя не содержит опечаток и не конфликтует с существующими свойствами формы.

Как записать значение в реквизит формы из модуля объекта?

Напрямую из модуля объекта к реквизитам формы обратиться нельзя — у объекта нет ссылки на открытую форму. Передайте нужные данные в форму через параметры при открытии, через оповещение Оповестить() с обработчиком ОбработкаОповещения в форме, либо выполните логику в серверной процедуре самой формы, обратившись к объекту через РеквизитФормыВЗначение().

Сохранится ли реквизит формы при переоткрытии формы?

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

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

Вызовите ИзменитьРеквизиты() со вторым параметром — массивом строк с именами удаляемых реквизитов: ИзменитьРеквизиты(Новый Массив, МассивИменДляУдаления). Удалять можно только реквизиты, созданные программно; реквизиты, добавленные в конфигураторе, удалить в режиме выполнения нельзя.

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

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

Итог

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

Запись в существующий реквизит формы — простое присвоение по имени в любом контексте. Создание новых реквизитов выполняется только на сервере через ИзменитьРеквизиты() с массивом ОписаниеРеквизитаФормы. Динамический список заполнить напрямую нельзя — управляйте его запросом и отбором. Реквизиты формы не сохраняются в базе: для долговременного хранения записывайте данные объекта или используйте хранилища настроек.