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