Работа с динамическими списками в управляемых формах 1С часто требует гибкости, выходящей за рамки стандартных настроек в конфигураторе. Одна из наиболее сложных задач — добавление колонки, данные для которой нельзя получить простым соединением таблиц в запросе (например, когда нужно агрегировать несколько строк в одну или выполнить сложные вычисления на стороне сервера). Рассмотрим подробные механизмы реализации этой задачи, проанализируем ограничения и выберем оптимальный подход.
Прежде чем приступать к написанию кода, важно понимать природу объекта ДинамическийСписок. В отличие от ТаблицыЗначений, он не хранит в себе все данные целиком. Это «окно» в базу данных, работающее на движке системы компоновки данных (СКД). Поэтому мы не можем просто «пробежать» циклом по списку и заполнить ячейки. Любое программное добавление поля требует либо изменения текста запроса, либо использования специальных событий отрисовки формы.
Это наиболее «визуальный» способ добавления данных. Рассмотрим ситуацию: у вас уже есть колонка в таблице формы, но вы хотите заполнить её вычисляемыми значениями. Начиная с версии платформы 8.3.10 (и при условии, что режим совместимости конфигурации установлен не ниже этой версии), у таблицы формы доступно событие ПриПолученииДанныхНаСервере.
Проанализируем основные моменты работы с этим событием:
&НаСервереБезКонтекста), что обеспечивает высокую скорость работы.Пример реализации алгоритма в обработчике:
&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
// Получаем массив ключей (идентификаторов) строк, которые сейчас отрисовываются
МассивКлючей = Строки.ПолучитьКлючи();
// Выполняем ОДИН запрос для получения данных по всем строкам сразу
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка, ПредставлениеДопДанных ИЗ Справочник.Контрагенты ГДЕ Ссылка В (&МассивКлючей)";
Запрос.УстановитьПараметр("МассивКлючей", МассивКлючей);
РезультатЗапроса = Запрос.Выполнить().Выбрать();
// Заполняем оформление строк данными
Пока РезультатЗапроса.Следующий() Цикл
ТекущаяСтрока = Строки[РезультатЗапроса.Ссылка];
ТекущаяСтрока.Данные.ДополнительноеПоле = РезультатЗапроса.ПредставлениеДопДанных;
КонецЦикла;
КонецПроцедуры
Важное ограничение: Поскольку данные в этом случае «рисуются» поверх списка, по таким полям невозможен поиск, отбор или сортировка встроенными средствами платформы. Если пользователю критически важна сортировка по этой колонке, данный метод не подходит.
Если нам нужно добавить колонку полностью программно (например, в зависимости от прав пользователя или параметров запуска), мы должны выполнить ряд шагов по модификации структуры формы. Рассмотрим по шагам, как создать реквизит типа ДинамическийСписок, задать ему запрос и вывести на форму.
Рассмотрим универсальную процедуру, которая позволяет инициализировать список «с нуля»:
&НаСервере
Процедура СоздатьДинамическийСписокНаФорме(ИмяСписка, ТекстЗапроса, ТаблицаСписка)
// 1. Создаем реквизит формы
ДобавляемыеРеквизиты = Новый Массив;
ТипыРеквизита = Новый ОписаниеТипов("ДинамическийСписок");
НовыйРеквизит = Новый РеквизитФормы(ИмяСписка, ТипыРеквизита, , , Ложь);
ДобавляемыеРеквизиты.Добавить(НовыйРеквизит);
// Применяем изменения к форме
ИзменитьРеквизиты(ДобавляемыеРеквизиты);
// 2. Настраиваем свойства созданного списка
СписокОбъект = ЭтаФорма[ИмяСписка];
СписокОбъект.ПроизвольныйЗапрос = Истина;
СписокОбъект.ТекстЗапроса = ТекстЗапроса;
СписокОбъект.ОсновнаяТаблица = ТаблицаСписка;
// 3. Создаем элемент формы (таблицу)
ТаблицаФормы = Элементы.Добавить(ИмяСписка, Тип("ТаблицаФормы"), ЭтаФорма);
ТаблицаФормы.ПутьКДанным = ИмяСписка;
// 4. Добавляем колонки в таблицу
НовоеПоле = Элементы.Добавить(ИмяСписка + "Наименование", Тип("ПолеФормы"), ТаблицаФормы);
НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
НовоеПоле.ПутьКДанным = ИмяСписка + ".Наименование";
КонецПроцедуры
Проанализируем ситуацию, описанную в сообщениях форума: автору нужно преобразовать несколько записей в одну строку. Поскольку в языке запросов 1С нет прямого аналога функции агрегации строк, мы можем пойти двумя путями:
"" КАК СводныеДанные) и заполнять его через описанный выше метод ПриПолученииДанныхНаСервере.Выясним причину, почему программное заполнение колонки часто считается «корявым» способом. Основная проблема — нагрузка на сервер и невозможность работы с данными (поиск/сортировка). Если задача стоит остро, лучшим решением будет подготовка данных заранее.
Разберем, как это реализовать:
СводныеДанные.ПередЗаписью пишется код, который собирает нужные данные из подчиненных таблиц/регистров и записывает их в эту строку.Этот метод гарантирует максимально быструю работу интерфейса и сохраняет все стандартные функции платформы по работе со списками.
Если вы решили использовать метод изменения свойства ТекстЗапроса у уже существующего списка, помните о следующих правилах:
Вызов метода ИзменитьРеквизиты является тяжелой операцией, так как он заставляет сервер полностью пересобрать структуру формы. Рекомендуется выполнять такие действия один раз при открытии формы (в обработчике ПриСозданииНаСервере), а не в процессе интерактивной работы пользователя.
Если дополнительные данные представляют собой набор дополнительных сведений или свойств, рассмотрим возможность использования механизма Характеристик. В настройках динамического списка (через запрос или свойства основной таблицы) можно указать источник характеристик. В этом случае новые колонки появятся у пользователя в меню «Изменить форму» или в настройках списка автоматически. Это наиболее «чистый» способ с точки зрения архитектуры 1С, так как он не требует написания сложного программного кода по созданию элементов формы и при этом поддерживает полноценные отборы.