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

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

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

Как получить значение реквизита объекта на клиенте в 1С: чтение реквизитов формы, текущей строки таблицы, вызов сервера и обмен данными с клиентом.

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

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

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

Что вообще доступно на клиенте в управляемой форме

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

Ключевое следствие: если реквизит объекта выведен в данные формы (есть в дереве реквизитов формы), его значение уже находится на клиенте, и читать его можно без всяких серверных вызовов. Если реквизита в форме нет, его нужно либо добавить в данные формы, либо получать на сервере.

Как прочитать реквизит объекта, уже загруженного в форму

Самый частый случай: форма документа или элемента справочника. Основной реквизит такой формы обычно называется Объект, и все реквизиты объекта, добавленные в форму, доступны через него напрямую:

&НаКлиенте

Процедура КонтрагентПриИзменении(Элемент)

ТекущийКонтрагент = Объект.Контрагент;

Комментарий = Объект.Комментарий;

Сообщить("Выбран контрагент: " + ТекущийКонтрагент);

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

Здесь Объект.Контрагент — это уже значение на клиенте. Никаких дополнительных вызовов не требуется. То же относится к реквизитам формы, добавленным вручную: они читаются по имени напрямую, например ЭтаФорма.ИтоговаяСумма или просто ИтоговаяСумма.

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

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

Табличные части и динамические списки на клиенте читаются через свойство ТекущиеДанные элемента формы. Это стандартный приём для обработчиков событий таблиц:

&НаКлиенте

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

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

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

Возврат;

КонецЕсли;

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

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

Обязательно проверяйте ТекущиеДанные на Неопределено: когда таблица пуста или фокус не установлен, свойство возвращает Неопределено, и обращение к полю приведёт к ошибке.

Если нужна строка не текущая, а по индексу, используйте коллекцию данных формы: Объект.Товары[0] для первой строки табличной части. Для обхода всех строк подходит цикл Для Каждого Строка Из Объект.Товары Цикл.

Чтение значения из строки таблицы
  1. 1
    Получите строку: Строка = Элементы.Товары.ТекущиеДанные
  2. 2
    Проверьте, что Строка <> Неопределено
  3. 3
    Обратитесь к полю: Строка.Цена или Строка["Цена"]
  4. 4
    Проверьте результат в отладчике или через Сообщить()

Как получить реквизит по ссылке через серверный вызов

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

&НаКлиенте

Процедура КонтрагентПриИзменении(Элемент)

ИНН = ПолучитьИННКонтрагента(Объект.Контрагент);

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

&НаСервереБезКонтекста

Функция ПолучитьИННКонтрагента(КонтрагентСсылка)

Возврат КонтрагентСсылка.ИНН;

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

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

Если нужно несколько реквизитов одного объекта, возвращайте их одним вызовом — структурой. Десять отдельных вызовов по одному реквизиту создадут десять обращений к серверу и заметно замедлят форму, особенно на веб-клиенте.

&НаСервереБезКонтекста

Функция РеквизитыКонтрагента(Ссылка)

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

"ВЫБРАТЬ Контрагенты.ИНН, Контрагенты.КПП

|ИЗ Справочник.Контрагенты КАК Контрагенты

|ГДЕ Контрагенты.Ссылка = &Ссылка");

Запрос.УстановитьПараметр("Ссылка", Ссылка);

Выборка = Запрос.Выполнить().Выбрать();

Результат = Новый Структура("ИНН, КПП", "", "");

Если Выборка.Следующий() Тогда

ЗаполнитьЗначенияСвойств(Результат, Выборка);

КонецЕсли;

Возврат Результат;

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

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

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

Ограничения: нельзя передавать на клиент объекты типа СправочникОбъект, Запрос, РезультатЗапроса и другие серверные сущности. Для передачи таблиц используют Массив структур или ТаблицаЗначений, помещённая в реквизит формы, либо ДанныеФормыКоллекция.

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

Способы получить значение

Прямое чтение из данных формы

Мгновенно и без нагрузки, но только для реквизитов, добавленных в форму

Серверный вызов с контекстом

Доступны данные формы на сервере, но передаётся весь контекст — медленнее

Серверный вызов без контекста

Быстрый и лёгкий, подходит для чтения реквизитов по ссылке, но данные формы недоступны

Добавление реквизита в форму

Значение всегда на клиенте без вызовов, но увеличивает объём передаваемых данных

Частые ошибки и как их исправить

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

Ошибка «Процедура или функция с указанным именем не определена» при серверном вызове возникает, когда функция объявлена с директивой &НаКлиенте, а вызывается из серверного контекста, или наоборот. Проверьте директивы компиляции.

Отдельная группа проблем — попытка выполнить запрос на клиенте: конструктор Новый Запрос недоступен в клиентском коде управляемого приложения. Запросы выполняются только на сервере, а на клиент возвращается готовый результат.

Типичные ошибки
01
Обращение к реквизиту через ссылку на клиенте (Ссылка.ИНН) — ошибка компиляции, нужен серверный вызов
02
Чтение ТекущиеДанные без проверки на Неопределено — падение при пустой таблице
03
Серверный вызов в цикле по строкам — резкое падение производительности формы
04
Использование контекстного вызова там, где хватит БезКонтекста — лишний трафик данных формы
05
Ожидание, что реквизит объекта доступен, хотя он не добавлен в данные формы

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

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

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

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

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

Значение переменной в отладчике
Норма

Содержит ожидаемое значение нужного типа

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

Неопределено или пустая ссылка

Тип значения через ТипЗнч()
Норма

Совпадает с ожидаемым (СправочникСсылка, Число и т.д.)

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

Неопределено — значит, данные не были получены

Скорость работы формы
Норма

Один серверный вызов на действие пользователя

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

Форма «подвисает» — вероятны вызовы в цикле

FAQ

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

Нет. В управляемом приложении объект «Запрос» доступен только на сервере. Клиент вызывает серверную функцию, которая выполняет запрос и возвращает результат в виде структуры, массива или таблицы значений.

Чем отличается &НаСервере от &НаСервереБезКонтекста?

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

Почему Объект.МойРеквизит выдаёт «Поле объекта не обнаружено»?

Реквизит не добавлен в данные формы. Откройте редактор формы, перейдите на вкладку реквизитов и проверьте состав. Если реквизита там нет, добавьте его или получайте значение серверным вызовом.

Как получить реквизиты сразу нескольких строк таблицы?

Соберите ссылки из строк в массив на клиенте, передайте его одним серверным вызовом, на сервере выполните запрос с условием «Ссылка В (&МассивСсылок)» и верните результат. Это исключает множественные обращения к серверу.

Можно ли изменить реквизит объекта на клиенте?

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

Что делать, если серверный вызов недоступен в обработчике ожидания?

Серверные вызовы из обработчиков ожидания разрешены, но их следует использовать осторожно из-за нагрузки. Если платформа или настройки запрещают вызов, перенесите логику в явное действие пользователя — нажатие кнопки или обработчик изменения поля.

Итог

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

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