Как правильно получать реквизиты выбранного элемента справочника в управляемых формах 1С?

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

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

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

В чем заключается проблема производительности при чтении реквизитов?

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


&НаСервереБезКонтекста
Функция ПолучитьРеквизит(Ссылка)
	Возврат Ссылка.Комментарий;
КонецФункции

Или при обращении через квадратные скобки: Ссылка["Комментарий"]. В обоих случаях платформа 1С производит неявное считывание всего объекта из базы данных. Если справочник или документ содержит большое количество реквизитов и тяжелые табличные части, СУБД считывает полностью весь объект в оперативную память сервера приложений. Это создает ненужную нагрузку на базу данных и существенно замедляет выполнение кода, особенно при работе в циклах или многопользовательском режиме.

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

Если ваша конфигурация создана на базе БСП (например, «Управление торговлей», «ERP», «Бухгалтерия предприятия» и др.), рекомендуется использовать встроенные методы общих модулей. Они вызывают оптимизированные SQL-запросы, которые считывают исключительно необходимые поля, не загружая сам объект целиком.

  1. Получение одного реквизита:

    Для чтения отдельного реквизита применим функцию ОбщегоНазначения.ЗначениеРеквизитаОбъекта.

    
    // Вызов на сервере
    Комментарий = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаНоменклатуру, "Комментарий");
    

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

    
    // Вызов на клиенте
    Комментарий = ОбщегоНазначенияВызовСервера.ЗначениеРеквизитаОбъекта(СсылкаНаНоменклатуру, "Комментарий");
    
  2. Получение нескольких реквизитов за один вызов:

    Если необходимо получить сразу несколько реквизитов одного объекта, эффективнее считать их за один серверный вызов и один запрос к базе данных. Для этого используем метод ОбщегоНазначения.ЗначенияРеквизитовОбъекта, который возвращает структуру значений.

    
    // Передаем имена реквизитов через запятую
    Реквизиты = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СсылкаНаНоменклатуру, "Артикул, Комментарий, СтавкаНДС");
    
    Артикул = Реквизиты.Артикул;
    Комментарий = Реквизиты.Комментарий;
    КонецФункции
    
  3. Получение реквизитов для массива ссылок:

    Когда требуется собрать данные по нескольким объектам одновременно (например, для всех строк табличной части), используем метод ОбщегоНазначения.ЗначенияРеквизитовОбъектов. Это полностью исключает проблему массовых одиночных запросов к БД в цикле.

Способ 2. Вывод подчиненных реквизитов на форму без написания кода

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

Для реализации этого сценария программный код не требуется вовсе:

  1. Открываем управляемую форму в редакторе форм.
  2. В дереве реквизитов формы находим нужный реквизит ссылочного типа (например, Объект.Номенклатура) и раскрываем его список подчиненных реквизитов с помощью значка «+».
  3. Перетаскиваем нужный подчиненный реквизит (например, Комментарий) в левое дерево элементов формы.

В данном случае платформа 1С берет на себя всю работу: при изменении основного реквизита на клиенте подчиненное поле автоматически запрашивается и обновляется без выполнения лишнего кода на сервере.

Способ 3. Использование языка запросов на сервере без контекста

Если конфигурация разрабатывается с нуля без использования БСП, наилучшим решением будет написание легкого запроса внутри серверной функции. При этом важно передавать вызов с клиента на сервер с директивой &НаСервереБезКонтекста, чтобы не передавать по сети тяжелый контекст всей формы.


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

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

← На главную