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