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

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

Данные формы в 1С: что это и как устроена структура

Что такое данные формы в 1С: структура реквизитов, типы ДанныеФормыСтруктура и ДанныеФормыКоллекция, преобразование в объект и обратно, типичные ошибки.

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

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

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

Из чего состоит структура данных формы

Структура данных формы определяется составом её реквизитов. Каждый реквизит формы имеет имя, тип и, для главного реквизита, связь с объектом конфигурации. В форме документа главный реквизит обычно называется «Объект» и содержит данные редактируемого документа; в форме списка главный реквизит — «Список» типа ДинамическийСписок.

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

Просмотреть фактическую структуру в режиме отладки можно через табло: вычислите выражение ЭтаФорма и раскройте состав — вы увидите все реквизиты с их текущими типами и значениями. Это самый быстрый способ понять, с каким типом данных вы работаете в конкретной точке кода.

Типы данных формы: какой тип у какого реквизита

Платформа автоматически подбирает тип данных формы в зависимости от типа реквизита. Знание соответствия избавляет от путаницы при программной работе.

Тип реквизита формыТип данных формыОсобенности
Объект (документ, справочник)ДанныеФормыСтруктураСвойства соответствуют реквизитам объекта
Табличная часть объектаДанныеФормыКоллекцияСтроки — ДанныеФормыЭлементКоллекции
ТаблицаЗначений (реквизит формы)ДанныеФормыКоллекцияЕсть метод НайтиСтроки
ДеревоЗначений (реквизит формы)ДанныеФормыДеревоЭлементы — ДанныеФормыЭлементДерева с методом ПолучитьЭлементы()
ДинамическийСписокДанныеФормыСтруктура (список)Доступ только на чтение через форму
Примитивные типы, ссылкиХранятся как естьПреобразование не требуется

Важное следствие: обращение к реквизиту документа через данные формы выглядит как Объект.Номенклатура, но «Объект» здесь — не ДокументОбъект, а ДанныеФормыСтруктура. У неё нет методов объекта (Записать(), Провести() и т.п.), только свойства-данные.

Как преобразовать данные формы в объект и обратно

Главная пара методов для работы с основным реквизитом формы — РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы(). Оба доступны только в серверном контексте формы (директивы &НаСервере), потому что объектные типы недоступны на тонком и веб-клиенте.

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

1c
&НаСервере
Процедура ЗаполнитьПоОснованиюНаСервере()
    ДокОбъект = РеквизитФормыВЗначение("Объект");
    ДокОбъект.Заполнить(ДокОбъект.Основание);
    ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры

Обратите внимание: после ЗначениеВРеквизитФормы форма считает данные изменёнными — у пользователя появится признак модифицированности. Если вы вызываете преобразование только для чтения (например, чтобы получить результат метода объекта), модифицированность придётся сбросить вручную через ЭтаФорма.Модифицированность = Ложь либо работать с копией.

Работа с табличными частями и коллекциями формы

Табличная часть в данных формы — это ДанныеФормыКоллекция. С ней работают привычными методами: Добавить(), Найти(), НайтиСтроки(Отбор), Удалить(), Итог("Колонка"). Строка коллекции — ДанныеФормыЭлементКоллекции, доступ к полям идёт через точку.

На клиенте доступен ограниченный набор операций: добавление, удаление, обход строк, чтение и запись полей. Методы вроде Выгрузить() на клиенте недоступны — если нужна таблица значений для сложной обработки, делайте это на сервере. Для передачи отобранных строк с клиента на сервер используйте массивы идентификаторов строк (Элементы.Товары.ВыделенныеСтроки) и метод НайтиПоИдентификатору() коллекции формы.

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

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

Контекст выполнения: клиент, сервер и границы передачи

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

Отсюда практическое правило размещения кода. Чтение и правка отдельных полей, реакция на ввод пользователя — клиентские обработчики. Запросы к базе, вызовы объектных методов, заполнение по алгоритмам — серверные процедуры формы. Вызов сервера из обработчика события элемента формы — нормальная практика, но избегайте серверных вызовов в циклах по строкам: каждый вызов — сетевой обмен.

Типичные ошибки и как их диагностировать

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

Отдельная группа проблем — динамическое изменение структуры формы. Если вы программно добавляете реквизит методом ИзменитьРеквизиты(), помните: после вызова старые пути к данным могут стать недействительными, а элементы формы, привязанные к удалённым реквизитам, вызовут ошибку. Всегда добавляйте реквизит до создания связанного элемента формы и не удаляйте реквизиты, на которые есть привязки.

Как проверить, что всё работает правильно

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

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

Тип реквизита в отладчике
Норма

Табло показывает ДанныеФормыСтруктура или ДанныеФормыКоллекция с ожидаемыми полями

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

Тип не соответствует ожиданию или значение Неопределено — проверьте имя реквизита и контекст

Сохранение изменений
Норма

После Записать() формы изменения попадают в базу и видны при повторном открытии

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

Изменения теряются — вероятно, меняли объект после ЗначениеВРеквизитФормы без обратного возврата

Модифицированность формы
Норма

Флаг появляется только при реальных правках пользователя или осознанных изменениях кода

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

Форма всегда «модифицирована» при открытии — где-то в ПриСозданииНаСервере меняются данные формы

Производительность
Норма

Заполнение большой табличной части занимает приемлемое время, один серверный вызов

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

Каждая строка тянет серверный вызов — перенесите обработку целиком на сервер

Для проверки состава данных формы в отладке удобно вычислять выражение ЭлементыФормы... нет, в управляемой форме — ЭтаФорма с раскрытием реквизитов, а также смотреть свойство ЭтаФорма.Параметры для понимания, с какими параметрами форма открыта. Если данные формы «не совпадают» с данными базы, первым делом проверьте, не работаете ли вы с кэшированной копией после РеквизитФормыВЗначение.

FAQ

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

Реквизит формы — это описание (имя, тип, назначение) в структуре формы, а данные формы — фактические значения этих реквизитов в конкретном экземпляре открытой формы. Один реквизит в каждый момент времени хранит одно значение соответствующего типа.

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

Да, если у вас есть ссылка на объект формы. Например, форма-владелец доступна через свойство Владелец или передаётся в параметрах. Обращение выглядит как ФормаВладелец.Объект.Реквизит. Однако такая связь делает формы зависимыми — предпочтительнее передавать данные через параметры открытия или оповещения (Оповестить/ОбработкаОповещения).

Почему изменения в табличной части не сохраняются при записи?

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

Как добавить реквизит формы программно?

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

Что такое ключевой реквизит формы и зачем он нужен?

Ключевой (основной) реквизит определяет, данные какого объекта форма редактирует: именно он сохраняется при команде Записать, участвует в стандартных обработчиках и определяет поведение при закрытии с вопросом о сохранении. У формы документа это реквизит «Объект» типа ДанныеФормыСтруктура на основе ДокументОбъект. Форма может иметь только один главный реквизит.

Как передать данные формы в фоновое задание?

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

Итог

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

Данные формы — это редактируемое представление реквизитов формы с типами ДанныеФормыСтруктура, ДанныеФормыКоллекция и ДанныеФормыДерево. Главный реквизит содержит объект, но это не объект базы: переход между ними выполняется только на сервере через РеквизитФормыВЗначение и ЗначениеВРеквизитФормы. Клиентский код работает с данными формы напрямую, объектные методы и запросы — только на сервере.