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