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