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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Суть проблемы: Ссылка против Строки

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


&НаСервере
Процедура ОрганизацияПриИзменении(Элемент)
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
                   |    Организации.ДолжностьРуководителя
                   |ИЗ
                   |    Справочник.Организации КАК Организации
                   |ГДЕ
                   |    Организации.Наименование = &Организация";
    Запрос.УстановитьПараметр("Организация", Объект.Организация);    
    // ... дальнейшая обработка
КонецПроцедуры

В этом примере кроется фундаментальная ошибка: поле Наименование в базе данных является строкой, а в параметр &Организация передается ссылка (Уникальный идентификатор объекта). Система 1С не может приравнять строку к ссылке, поэтому запрос всегда возвращает пустой результат. Если изменить тип реквизита на «Строка» и вписать название вручную, запрос сработает, но это лишит нас всех преимуществ работы с объектами (контроль целостности, типизация, связи).

Решение №1: Прямое сравнение ссылок в запросе

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


Запрос.Текст = "ВЫБРАТЬ
               |    Организации.ДолжностьРуководителя,
               |    Организации.ФамилияРуководителя
               |ИЗ
               |    Справочник.Организации КАК Организации
               |ГДЕ
               |    Организации.Ссылка = &ОрганизацияСсылка";

Запрос.УстановитьПараметр("ОрганизацияСсылка", Объект.Организация);
Результат = Запрос.Выполнить().Выбрать();

Важный нюанс: В языке запросов 1С допустимо сокращение. Вместо Организации.Ссылка = &Организация можно написать просто Организации = &Организация. Система поймет, что сравнение идет по внутреннему идентификатору объекта.

Решение №2: Использование функций БСП (Библиотеки стандартных подсистем)

Если ваша конфигурация построена на базе современных типовых решений (УТ 11, БП 3.0, ERP), то писать запрос вручную для получения пары реквизитов — избыточно. Для этого существуют оптимизированные функции в общем модуле ОбщегоНазначения. Проанализируем, как это упрощает код:


// Получаем структуру с нужными данными в одну строку
НужныеДанные = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Объект.Организация, "ДолжностьРуководителя, ФамилияРуководителя, ИмяРуководителя");

// Обращаемся к результату
Если ЗначениеЗаполнено(НужныеДанные.ДолжностьРуководителя) Тогда
    НовСтр = Объект.ТЧДолжностьФИО.Добавить();
    ЗаполнитьЗначенияСвойств(НовСтр, НужныеДанные);
КонецЕсли;

Почему это лучше? Во-первых, код становится чище и читабельнее. Во-вторых, функции БСП часто содержат механизмы кэширования и проверки на «пустые ссылки», что делает решение более отказоустойчивым.

Почему нельзя обращаться «через точку»?

Часто возникает соблазн получить данные еще проще: Должность = Объект.Организация.ДолжностьРуководителя. С точки зрения синтаксиса это верно, но с точки зрения производительности — это «плохой тон».

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

Работа с «битыми» ссылками и пустыми значениями

Проанализируем ситуацию, когда пользователь еще не выбрал организацию в поле, а процедура ПриИзменении уже сработала. Если передать пустую ссылку в запрос, ошибки не будет, но и результат будет пустым. Однако при работе с БСП или сложной логикой рекомендуется всегда проверять ссылку перед использованием:

  1. Проверка на заполненность: Используйте функцию ЗначениеЗаполнено(Объект.Организация). Если результат Ложь, выполнение кода следует прервать.
  2. Проверка на существование (битая ссылка): Если объект был удален из базы, ссылка может остаться в реквизите, но превратиться в надпись «Объект не найден». Запрос к такой ссылке вернет пустоту. Чтобы проверить ссылку на «битость», можно использовать метод Ссылка.ПолучитьОбъект() = Неопределено (но помните про производительность!).

Продвинутые техники: Получение представления

Иногда в запросе нам нужно не только значение конкретного реквизита, но и то, как организация называется для пользователя. Вместо обращения к полю Наименование, рекомендуется использовать функцию ПРЕДСТАВЛЕНИЕ.


Запрос.Текст = "ВЫБРАТЬ
               |    ПРЕДСТАВЛЕНИЕ(Организации.Ссылка) КАК ИмяОрганизации,
               |    Организации.ИНН КАК ИНН
               |ИЗ
               |    Справочник.Организации КАК Организации
               |ГДЕ
               |    Организации.Ссылка = &Ссылка";

Функция ПРЕДСТАВЛЕНИЕ работает очень быстро и автоматически учитывает настройки программы (например, если в конфигурации установлено выводить в качестве представления не наименование, а код).

Итоги и рекомендации

Подводя итог нашему разбору, выделим основные правила работы со ссылочными типами данных:

Соблюдение этих простых принципов позволит вам писать код, который не только работает правильно, но и не замедляет работу всей системы 1С.

← На главную