При разработке интерфейсов в 1С часто возникает задача отобразить в списке справочника дополнительные данные, которые хранятся во внешнем источнике — например, в регистре сведений. Если в управляемых формах эта задача легко решается редактированием запроса динамического списка, то в обычных формах разработчики сталкиваются со специфическими ограничениями платформы.
В этой статье мы подробно разберем, как правильно вывести данные из регистра сведений в форму списка справочника на обычных формах, не потеряв при этом в производительности системы.
Если мы просто добавим новую колонку в табличное поле списка на обычной форме, то увидим, что ее свойство Данные невозможно связать с реквизитом регистра сведений напрямую. Попытка записать значение непосредственно в ячейку через данные строки вызовет ошибку, так как этого поля нет в исходном источнике данных (в таблице справочника).
Для решения этой задачи нам потребуется программно заполнять оформление ячеек при выводе данных на экран.
Для вывода дополнительных данных в обычных формах существует два основных события табличного поля: ПриВыводеСтроки и ПриПолученииДанных. Разберем, почему следует использовать именно второе.
Событие ПриВыводеСтроки вызывается отдельно для каждой строки, отображаемой на экране. Если внутри этого обработчика выполнять запрос к базе данных, система будет отправлять десятки запросов при каждом цикле отрисовки интерфейса (например, при обычной прокрутке списка). Это приведет к критическому падению производительности и зависанию программы.
Событие ПриПолученииДанных работает иначе. Оно вызывается один раз для всей порции строк, которые выводятся на экран (обычно это 20-30 строк). Это позволяет нам получить ссылки всех отображаемых элементов, выполнить один пакетный запрос к регистру сведений и быстро распределить полученные значения по ячейкам.
Шаг 1. Добавим на форму в табличное поле списка справочника новую колонку. Зададим ей уникальное имя (например, ИмяКолонки). Свойство Данные оставляем пустым.
Шаг 2. Создадим обработчик события ПриПолученииДанных для табличного поля списка справочника и напишем следующий код:
Процедура СписокПриПолученииДанных(Элемент, ОформленияСтрок)
// Проверяем видимость добавленной колонки.
// Если пользователь скрыл ее, не тратим ресурсы на запросы к базе данных.
Если Не Элемент.Колонки.ИмяКолонки.Видимость Тогда
Возврат;
КонецЕсли;
СоответствиеАдресации = Новый Соответствие;
МассивСсылок = Новый Массив;
// Обходим оформление строк, собирая ссылки отображаемых элементов
Для Каждого СтрокаОформления Из ОформленияСтрок Цикл
// Пропускаем группы, если данные регистра к ним не относятся
Если СтрокаОформления.ДанныеСтроки.ЭтоГруппа Тогда
Продолжить;
КонецЕсли;
СсылкаНаЭлемент = СтрокаОформления.ДанныеСтроки.Ссылка;
МассивСсылок.Добавить(СсылкаНаЭлемент);
// Запоминаем связь ссылки и оформления строки в Соответствии
СоответствиеАдресации.Вставить(СсылкаНаЭлемент, СтрокаОформления);
// Инициализируем пустое значение на случай, если данных в регистре нет
СтрокаОформления.Ячейки.ИмяКолонки.УстановитьТекст("");
КонецЦикла;
Если МассивСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Получаем данные из регистра сведений одним запросом
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Рег.Объект КАК Ссылка,
| Рег.РеквизитДляВывода КАК ЗначениеИзРегистра
|ИЗ
| РегистрСведений.ИмяРегистра КАК Рег
|ГДЕ
| Рег.Объект В(&МассивСсылок)";
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
Выборка = Запрос.Выполнить().Выбрать();
// Быстро заполняем ячейки сохраненных строк оформления
Пока Выборка.Следующий() Цикл
СтрокаОформления = СоответствиеАдресации.Получить(Выборка.Ссылка);
Если СтрокаОформления <> Неопределено Тогда
// Для отображения простого текста используем УстановитьТекст
СтрокаОформления.Ячейки.ИмяКолонки.УстановитьТекст(Выборка.ЗначениеИзРегистра);
// Если в ячейку нужно передать сам объект (например, ссылку на другой справочник):
// СтрокаОформления.Ячейки.ИмяКолонки.Значение = Выборка.ЗначениеИзРегистра;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Рассмотрим ситуации, когда стандартный подход может быть скорректирован ради оптимизации работы интерфейса:
ПриАктивизацииСтроки. При выборе конкретной строки пользователем выполняется один легкий запрос по текущей ссылке, а результат выводится в отдельное текстовое поле (декоративную надпись), расположенное внизу формы списка.ПриОткрытии формы и сохранить в переменную модуля (например, в Соответствие). Тогда в обработчике ПриПолученииДанных мы будем мгновенно сопоставлять данные из оперативной памяти без единого обращения к СУБД.Если в будущем планируется перевод решения на управляемые формы, полезно знать следующие нюансы работы с динамическими списками:
СрезПоследних) СУБД может строить неоптимальные планы запросов. Это приводит к замедлению при сортировках или полнотекстовом поиске по списку.ПриПолученииДанныхНаСервере. Оно позволяет выводить любые вычисляемые или внешние данные порционно для видимых строк динамического списка, сохраняя высокую скорость работы интерфейса и не перегружая основной запрос.