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

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

Как получить данные из формы в 1С

Как получить данные из формы в 1С: работа с реквизитами формы, Элементы, ДанныеФормыВЗначение, обращение к форме из другой формы. Примеры кода и типичные ошибки.

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

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

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

Чтение реквизитов формы в модуле формы

Самый простой случай — получить значение внутри модуля самой формы. Реквизиты формы доступны напрямую по имени, без обращения к коллекции. Если на форме документа есть основной реквизит Объект, то его поля читаются через точку: Объект.Номенклатура, Объект.СуммаДокумента.

Для дополнительных реквизитов формы (тех, что вы добавили в дереве реквизитов в редакторе формы) обращение такое же — просто по имени. Например, если создан реквизит ВыбранныйСклад, то в коде модуля формы пишется: ТекущийСклад = ВыбранныйСклад; или ЭтаФорма.ВыбранныйСклад.

Когда имя реквизита заранее неизвестно и хранится в переменной, используйте квадратные скобки: ЭтаФорма[ИмяРеквизита]. Это удобно для универсальных обработчиков, которые обходят несколько реквизитов по списку имён.

&НаКлиенте

Процедура КомандаРассчитать(Команда)

// Чтение полей основного реквизита

Сумма = Объект.СуммаДокумента;

Склад = Объект.Склад;

// Чтение дополнительного реквизита формы

Коэффициент = ЭтаФорма.КоэффициентПересчета;

// Чтение по имени из переменной

ИмяРеквизита = "СуммаДокумента";

Значение = Объект[ИмяРеквизита];

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

Элементы формы: когда читать через Элементы нельзя

Частая ошибка начинающих — пытаться получить данные через коллекцию Элементы: Элементы.СуммаДокумента.??? У элемента формы нет свойства со значением данных в привычном смысле. У поля ввода есть свойство ТекстРедактирования, но оно возвращает текст, который пользователь ввёл прямо сейчас, ещё до окончания редактирования, и может не совпадать с реальным значением реквизита.

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

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

Передача данных между клиентом и сервером

В управляемой форме код делится на клиентский и серверный. На клиенте недоступны запросы к базе и прикладные объекты, поэтому данные формы часто нужно передать на сервер для обработки. Директивы &НаКлиенте, &НаСервере, &НаСервереБезКонтекста определяют, где выполняется процедура.

Простые значения (числа, строки, даты, ссылки) передаются на сервер как параметры процедуры без ограничений. А вот реквизит типа ДанныеФормыСтруктура (например, Объект документа) нельзя просто взять и использовать на сервере как прикладной объект — его нужно преобразовать.

&НаКлиенте

Процедура ЗаполнитьНаСервере(Команда)

ЗаполнитьНаСервереСервер(Объект.Организация, Объект.Дата);

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

&НаСервере

Процедура ЗаполнитьНаСервереСервер(Организация, Дата)

// Здесь доступны запросы и менеджеры объектов

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ ...";

Запрос.УстановитьПараметр("Организация", Организация);

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

В процедуре &НаСервереБезКонтекста реквизиты формы недоступны напрямую — такой метод не «видит» форму. Всё нужное передавайте параметрами. Это ускоряет вызов, так как на сервер не пересылается весь контекст формы.

ДанныеФормыВЗначение и ЗначениеВДанныеФормы

Основной реквизит формы документа или справочника имеет тип ДанныеФормыСтруктура — это не прикладной объект, а его представление в форме. Чтобы на сервере получить полноценный объект (ДокументОбъект, СправочникОбъект) с методами Записать(), используется метод РеквизитФормыВЗначение.

&НаСервере

Процедура ПровестиДокументНаСервере()

ДокОбъект = РеквизитФормыВЗначение("Объект");

ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

ЗначениеВРеквизитФормы(ДокОбъект, "Объект");

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

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

Учтите, что РеквизитФормыВЗначение — затратная операция: весь объект сериализуется и пересоздаётся. Если нужно только прочитать пару полей или ссылку, преобразование не требуется — ссылка доступна прямо на клиенте через Объект.Ссылка.

Получение данных из таблицы и табличной части на форме

Табличная часть объекта доступна как коллекция: Объект.Товары. Строки перебираются циклом, значения колонок читаются по имени. Текущую строку, которую выделил пользователь, дают Элементы.Товары.ТекущиеДанные (на клиенте) и Элементы.Товары.ТекущаяСтрока (идентификатор строки).

&НаКлиенте

Процедура ТоварыПриИзменении(Элемент)

Строка = Элементы.Товары.ТекущиеДанные;

Если Строка = Неопределено Тогда

Возврат;

КонецЕсли;

Строка.Сумма = Строка.Количество * Строка.Цена;

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

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

Типичные ошибки
01
Обращение к ТекущиеДанные без проверки на Неопределено — падает, когда таблица пустая или строка не выбрана
02
Изменение строки на сервере по индексу вместо идентификатора строки — после отбора или сортировки индексы не совпадают
03
Чтение данных из динамического списка через Элементы.Список — данные списка читаются запросом, а не через элемент формы

Получение данных из другой формы

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

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

&НаКлиенте

Процедура ВыбратьКонтрагента(Команда)

ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораКонтрагента", ЭтотОбъект);

ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", , ЭтаФорма, , , ,

ОписаниеОповещения, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

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

&НаКлиенте

Процедура ПослеВыбораКонтрагента(Результат, ДопПараметры) Экспорт

Если Результат <> Неопределено Тогда

Объект.Контрагент = Результат;

КонецЕсли;

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

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

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

Как выбрать способ

Нужно выбрать значение из другой формы и получить результатОткрытьФорму с ОписаниеОповещения и ОповеститьОВыборе в форме выбора
Нужно передать данные в открываемую формуСтруктура параметров в ОткрытьФорму, чтение в ПриСозданииНаСервере через Параметры
Нужно уведомить несколько открытых форм об измененииОповестить с именем события и ОбработкаОповещения в формах-подписчиках
Нужно прочитать данные формы-владельцаЭтаФорма.ВладелецФормы.ИмяРеквизита, но только если форма гарантированно открыта

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

После получения данных проверяйте их перед использованием. Ссылочные значения проверяйте на пустую ссылку через ЗначениеЗаполнено(), строки таблиц — на Неопределено, числовые поля — на допустимые диапазоны. Не полагайтесь на то, что пользователь заполнил всё корректно.

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

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

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

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

Значение реквизита после чтения
Норма

Совпадает с отображаемым на форме, тип значения корректный

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

Пустое значение или строка вместо ожидаемого типа

Данные после серверной обработки
Норма

Форма показывает обновлённые значения

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

Объект изменён, но форма показывает старое — нет ЗначениеВРеквизитФормы

Результат выбора из другой формы
Норма

Обработчик оповещения срабатывает, значение записано

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

Оповещение не приходит — форма не вызвала ОповеститьОВыборе

Итог

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

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

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

Как получить значение поля ввода, которое пользователь ещё редактирует?

Через Элементы.ИмяПоля.ТекстРедактирования — это строка текущего ввода. Учтите, что значение ещё не приведено к типу реквизита: число придёт текстом, и его нужно преобразовывать самостоятельно. Для завершённого ввода используйте событие ПриИзменении и читайте реквизит.

Почему на сервере недоступен реквизит формы?

Скорее всего, процедура объявлена с директивой &НаСервереБезКонтекста — такой метод не имеет доступа к данным формы. Либо смените директиву на &НаСервере, либо передайте нужные значения параметрами из клиентской процедуры.

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

Ссылка доступна на клиенте напрямую: Объект.Ссылка. Преобразование РеквизитФормыВЗначение для этого не требуется — оно нужно только когда требуется сам объект с методами записи и проведения.

Как прочитать данные строки динамического списка?

Через Элементы.Список.ТекущиеДанные вы получите значения видимых колонок текущей строки. Если нужны поля, не выведенные в список, получите ссылку из ТекущиеДанные.Ссылка и прочитайте объект запросом на сервере.

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

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

Почему после Записать() на форме старые данные?

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