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