При работе с управляемыми формами в 1С:Предприятии 8.3 разработчики часто сталкиваются с необходимостью кастомизации данных, отображаемых в динамическом списке. Если стандартных настроек основной таблицы недостаточно и требуется добавить специфические соединения с другими таблицами (например, регистрами сведений или дополнительными справочниками), встает вопрос: как сделать это грамотно, не превращая код в «заплатку»?
Рассмотрим, как реализовать формирование запроса программно с использованием объекта СхемаЗапроса, что позволяет гибко управлять структурой данных и поддерживать код в актуальном состоянии при изменениях метаданных.
Когда свойство динамического списка ПроизвольныйЗапрос установлено в значение Ложь, платформа 1С автоматически генерирует SQL-запрос к СУБД. Этот механизм анализирует метаданные основной таблицы и автоматически включает в выборку:
Ссылка, Номер, Дата, МоментВремени, ПометкаУдаления, Проведен.Важно помнить, что платформа также берет на себя управление пейджингом (постраничным выводом), что критически важно для производительности при работе с большими объемами данных.
Если вам необходимо добавить в список данные из других таблиц, вы можете перевести список в режим ПроизвольныйЗапрос = Истина и программно сформировать текст запроса. Использование СхемаЗапроса является более современным и удобным подходом, чем простое конкатенирование строк запроса.
Разберем по шагам, как собрать такой запрос:
СхемаЗапроса.Рассмотрим пример реализации для документа ЗаказКлиента с присоединением данных из регистра сведений:
СхемаЗапроса = Новый СхемаЗапроса;
ЗапросСписка = СхемаЗапроса.ПакетЗапросов.Добавить();
ОператорЗаказов = ЗапросСписка.Операторы[0];
// Добавляем основные источники
ИсточникЗаказы = ОператорЗаказов.Источники.Добавить("Документ.ЗаказКлиента", "ЗаказКлиента");
ИсточникАдресаДоставки = ОператорЗаказов.Источники.Добавить("РегистрСведений.Адр1_АдресаДокументов", "АдресаДокументов");
// Настраиваем соединение
СоединениеАдресаДоставки = ИсточникАдресаДоставки.Соединения[0];
СоединениеАдресаДоставки.ТипСоединения = ТипСоединенияСхемыЗапроса.ПравоеВнешнее;
СоединениеАдресаДоставки.Условие = Новый ВыражениеСхемыЗапроса("ЗаказКлиента.Ссылка = АдресаДокументов.Документ");
// Добавляем стандартные поля
ОператорЗаказов.ВыбираемыеПоля.Добавить("ЗаказКлиента.Ссылка");
ОператорЗаказов.ВыбираемыеПоля.Добавить("ЗаказКлиента.Номер");
ОператорЗаказов.ВыбираемыеПоля.Добавить("ЗаказКлиента.Дата");
ОператорЗаказов.ВыбираемыеПоля.Добавить("ЗаказКлиента.ПометкаУдаления");
ОператорЗаказов.ВыбираемыеПоля.Добавить("ЗаказКлиента.Проведен");
ОператорЗаказов.ВыбираемыеПоля.Добавить("ЗаказКлиента.МоментВремени");
// Автоматический перебор реквизитов документа
РеквизитыЗаказа = Метаданные.Документы.ЗаказКлиента.Реквизиты;
Для Каждого РеквизитЗаказа Из РеквизитыЗаказа Цикл
ОператорЗаказов.ВыбираемыеПоля.Добавить("ЗаказКлиента." + РеквизитЗаказа.Имя);
КонецЦикла;
// Добавление специфических полей с псевдонимами
ОператорЗаказов.ВыбираемыеПоля.Добавить("ЗаказКлиента.Партнер.ГруппаДоступа");
КоличествоКолонок = ЗапросСписка.Колонки.Количество();
ЗапросСписка.Колонки[КоличествоКолонок].Псевдоним = "Адр1_ГруппаДоступа";
ОператорЗаказов.ВыбираемыеПоля.Добавить("ЕСТЬNULL(АдресаДокументов.АдресДоставки, ЗНАЧЕНИЕ(Справочник.Адр1_АдресаДоставки.ПустаяСсылка))");
ЗапросСписка.Колонки[КоличествоКолонок + 1].Псевдоним = "Адр1_АдресДоставки";
// Применяем запрос к динамическому списку
Список.ПроизвольныйЗапрос = Истина;
Список.ТекстЗапроса = СхемаЗапроса.ПолучитьТекстЗапроса();
При использовании данного подхода важно учитывать следующие аспекты:
Метаданные позволяет динамически подхватывать новые реквизиты, добавленные в конфигуратор, что избавляет вас от необходимости постоянно править текст запроса.JOIN в произвольном запросе может замедлить работу списка. Всегда анализируйте планы запросов, если список работает медленно.Ссылка и т.д.), так как без них платформа не сможет корректно отрисовать список, обеспечить отборы и работу стандартных команд.Используя предложенный алгоритм, вы обеспечите гибкость и «чистоту» реализации динамических списков, сохраняя при этом контроль над тем, какие данные попадают в интерфейс пользователя.