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

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

В данной статье мы детально разберем основные способы получения реквизитов справочника, их синтаксис и особенности применения в коде. Мы рассмотрим как стандартные методы платформы, так и оптимизированные подходы для работы с табличными частями.

Прямое получение объекта по ссылке

Наиболее интуитивным и часто используемым способом является прямое получение объекта метаданных по его ссылке. Этот метод идеально подходит для ситуаций, когда необходимо получить данные одного или нескольких элементов справочника в единичных случаях, например, при заполнении шапки документа или проверке одного конкретного товара.

Для реализации этого подхода используется метод ПолучитьОбъект() глобального контекста. Он принимает ссылку на объект и возвращает полноценный объект конфигурации, к реквизитам которого можно обращаться точечно.

Рассмотрим пример кода, где из документа "ЗаказКлиента" мы получаем значение реквизита "ВалютаЦены" из справочника "Номенклатура".

ЭлементНоменклатуры = СсылкаНаНоменклатуру.ПолучитьОбъект();

Если ЭлементНоменклатуры <> Неопределено Тогда

ТекущаяВалюта = ЭлементНоменклатуры.ВалютаЦены;

КонецЕсли;

Использование этого метода в циклах по строкам табличной части является грубой ошибкой проектирования. Если в документе 100 строк, система выполнит 100 отдельных SQL-запросов, что вызовет ощутимые задержки для пользователя. Поэтому данный подход следует применять только для единичных обращений вне циклов.

💡

Используйте метод ПолучитьОбъект() только для шапки документа или единичных проверок. Никогда не вызывайте его внутри цикла обхода строк табличной части.

Использование объекта выбора для пакетной обработки

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

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

  • 🚀 Значительно повышает скорость работы при обработке списков.
  • 💾 Снижает нагрузку на сервер СУБД за счет группировки запросов.
  • ⚙️ Позволяет выбирать только конкретные необходимые поля, экономя трафик.

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

Выборка = Справочники.Номенклатура.Выбрать();

Выборка.Инициализировать(МассивСсылок); // Массив ссылок из строк документа

Пока Выборка.Следующий() Цикл

// Обработка данных из выборки

НайденнаяСтавкаНДС = Выборка.СтавкаНДС;

КонецЦикла;

☑️ Алгоритм работы с выборкой

Выполнено: 0 / 4

Доступ к данным в модуле формы документа

При разработке пользовательского интерфейса часто возникает задача подставлять значения из справочника сразу при выборе номенклатуры в поле ввода формы. В модуле формы документа данные справочника доступны через событие изменения поля или через команду заполнения.

Здесь важно различать контекст выполнения. Если вы находитесь в обработчике события ПриИзменении поля табличной части, у вас уже есть ссылка на выбранный элемент. Вы можете использовать её для быстрого получения данных, но опять же, стоит учитывать производительность. Для форм с большим количеством строк лучше использовать фоновые задания или отложенное обновление.

Частой ошибкой является попытка обратиться к реквизиту справочника, который еще не записан в базу (новый элемент). В этом случае метод ПолучитьОбъект() вернет пустое значение или объект с незаполненными данными. Всегда проверяйте, является ли ссылка ссылкой на существующий объект.

⚠️ Внимание: Если справочник имеет иерархию, убедитесь, что вы обращаетесь к нужному уровню вложенности. Реквизиты могут быть определены только для элементов, а не для групп.

📊 Какой метод вы чаще используете в коде?
ПолучитьОбъект()
ВыборкаДанных
Запрос
Конструктор запроса

Применение запросов для сложных выборок

В ситуациях, когда требуется не просто получить реквизит, а выполнить фильтрацию, агрегацию или соединение данных из нескольких справочников, наиболее мощным инструментом остается язык запросов . Запросы позволяют получить данные в виде виртуальной таблицы, которую удобно обрабатывать в коде.

Использование запроса особенно оправдано, когда данные справочника нужны для аналитики или формирования печатных форм, где требуется объединить информацию из документа, справочника номенклатуры и справочника единиц измерения. Запрос выполняется на стороне сервера баз данных, что максимально эффективно.

Пример запроса, получающего наименование и артикул номенклатуры для строк документа:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| ДокументЗаказКлиентаТовары.Номенклатура,

| СправочникНоменклатура.Наименование,

| СправочникНоменклатура.Артикул

|ИЗ

| Документ.ЗаказКлиента.Товары КАК ДокументЗаказКлиентаТовары

| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СправочникНоменклатура

| ПО ДокументЗаказКлиентаТовары.Номенклатура = СправочникНоменклатура.Ссылка";

Результат = Запрос.Выполнить();

ВыборкаДетальныеЗаписи = Результат.Выбрать();

Главное преимущество запросов — возможность получить данные одним обращением, даже если они разбросаны по разным таблицам. Однако для простых задач, таких как получение одного поля по известной ссылке, запрос может быть избыточным по объему кода по сравнению с объектом выбора.

Оптимизация запросов

Используйте индексы по полям соединения и избегайте функций в условиях соединения (ГДЕ), чтобы сервер баз данных мог эффективно использовать план выполнения запроса.

Особенности работы с табличными частями

Табличные части документов представляют собой коллекции строк, и доступ к реквизитам справочников внутри них требует особого внимания к циклам. Основная проблема здесь — Avoid N+1 query problem (проблема N+1 запроса), когда система делает один запрос для получения списка строк и N запросов для получения данных по каждой строке.

Для решения этой проблемы в платформе 1С:Предприятие 8 существует механизм "Заполнение значений". Вы можете собрать все ссылки в массив и заполнить ими значения реквизитов строк табличной части за один проход. Это делается через временную таблицу или выборку, о которой мы говорили ранее.

Метод Производительность Сложность кода Рекомендуемое применение
ПолучитьОбъект() Низкая Низкая Шапка документа, единичные проверки
ВыборкаДанных Высокая Средняя Заполнение табличных частей
Запрос Очень высокая Высокая Отчеты, сложные выборки, аналитика
Конструктор запроса Высокая Низкая Быстрая разработка стандартных выборок

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

⚠️ Внимание: Интерфейс платформы и методы доступа могут обновляться с выходом новых релизов. Всегда сверяйте синтаксис с официальной документацией или справкой по объектам метаданных в вашей версии конфигуратора.

💡

Золотое правило оптимизации: минимизируйте количество обращений к базе данных. Один сложный запрос всегда лучше сотни простых.

Обработка ошибок и несуществующих ссылок

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

Всегда используйте проверку на Неопределено перед обращением к свойствам объекта. Если вы используете метод ПолучитьОбъект(), он вернет Неопределено, если объект не найден. Попытка прочитать свойство у неопределенного значения вызовет исключение.

Кроме того, стоит учитывать права доступа. У пользователя может не быть прав на чтение конкретного элемента справочника, даже если у него есть права на запись документа. В таком случае попытка получения объекта также может вернуть пустое значение или вызвать ошибку прав доступа в зависимости от настроек РЛС (Ролевой модели безопасности).

  • 🛡️ Всегда проверяйте ссылку на значение Неопределено.
  • 🔐 Учитывайте права доступа пользователя к объектам справочника.
  • 🔄 Обрабатывайте исключения в блоках Попытка..Исключение для критических участков кода.

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

Часто задаваемые вопросы (FAQ)

Можно ли обратиться к реквизиту справочника без получения объекта?

Нет, для доступа к произвольному реквизиту необходимо получить объект (через ПолучитьОбъект или выборку). Однако, если реквизит является предопределенным свойством ссылки (например, Наименование или Код), к нему можно обратиться напрямую через ссылку без получения полного объекта, что работает быстрее.

Почему метод ПолучитьОбъект() тормозит в цикле?

Каждый вызов ПолучитьОбъект() инициирует отдельный сетевой запрос к серверу баз данных. В цикле из 100 итераций это означает 100 запросов. Использование выборки или запроса объединяет эти обращения в один пакет, что ускоряет работу в десятки раз.

Как получить реквизиты табличной части справочника?

Схема аналогична работе с обычными реквизитами. После получения объекта справочника вы обращаетесь к его табличной части как к коллекции (например, Объект.ДополнительныеРеквизиты) и обходите её в цикле или используете запрос с соединением по владельцу.

Что делать, если справочник находится в другой базе данных?

Для доступа к данным в другой информационной базе используется механизм HTTP-сервисов, веб-сервисов или прямое подключение через ПодключениеВнешнейИсточникиДанных (для SQL), в зависимости от архитектуры вашего решения и требований к производительности.