Динамический список 1С — основной способ показать в форме данные из базы: он сам читает порции строк, применяет отборы, поиск и сортировку. Но стоит выйти за рамки стандартного поведения — распечатать список, показать один товар в нескольких ячейках, поставить флажки или иконки, — и начинаются вопросы. Ниже пять приемов, которые я регулярно применяю на проектах, с кодом и подводными камнями.
Коротко по сути: печать делается через исполняемую схему и настройки компоновки самого списка; уникальность строк — через ПоляКлюча и ВидКлюча; пометки — через параметр запроса и событие активизации ячейки; иконки — через картинку строки, поле картинки или ПриПолученииДанныхНаСервере; программная правка запроса — через СхемаЗапроса с РежимКомпоновкиДанных = Истина.
Печать динамического списка с отборами и поиском
Пользователь настроил отбор, ввел строку поиска, скрыл колонки и просит «распечатать, что вижу». Стандартная команда «Вывести список» есть, но часто нужен свой макет, заголовок, итог или выгрузка в файл.
У реквизита типа ДинамическийСписок есть два серверных метода:
| Метод | Что возвращает |
|---|---|
ПолучитьИсполняемуюСхемуКомпоновкиДанных() | Готовую схему компоновки, построенную по запросу списка |
ПолучитьИсполняемыеНастройкиКомпоновкиДанных() | Настройки со всеми отборами, поиском, видимыми колонками, сортировкой и оформлением |
Анализировать текст запроса, основную таблицу и пользовательские настройки вручную больше не нужно.
&НаКлиенте
Процедура ПечатьСписка(Команда)
ТабличныйДокумент = ПечатьСпискаНаСервере();
ТабличныйДокумент.Показать(НСтр("ru = 'Список документов'"));
КонецПроцедуры
&НаСервере
Функция ПечатьСпискаНаСервере()
Схема = Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
Настройки = Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ТабличныйДокумент = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Возврат ТабличныйДокумент;
КонецФункцииВместо табличного документа результат можно вывести в таблицу значений (генератор макета для коллекции значений и ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений) — так удобно делать выгрузку в Excel или отправку по API ровно тех строк, что видит пользователь.
Учтите: печать выбирает все строки по отбору, а не только видимую порцию. На списке без отбора по журналу документов за несколько лет это может быть очень долго. Я в таких командах проверяю наличие отбора по периоду и предупреждаю пользователя.

Уникальность строк по нескольким полям
Типичная ситуация: в форму подбора номенклатуры добавили колонку «Ячейка хранения» соединением с остатками. Товар лежит в двух ячейках — список перестает строиться с ошибкой о повторении ключевых полей.
Причина: при заполненном свойстве ОсновнаяТаблица ключом строки считается ссылка основной таблицы, и она должна быть уникальной. Решение в современных версиях платформы — составной ключ:
- Задать
ПоляКлюча— фиксированный массив имен полей, которые вместе уникальны. - Установить
ВидКлюча = ВидКлючаДинамическогоСписка.КлючСтроки. - Очистить
ОсновнаяТаблица: пока она заполнена,ПоляКлючаигнорируется. - Гарантировать, что ни одно ключевое поле не возвращает
NULLилиНеопределено. Для левых соединений используйтеЕСТЬNULLс пустой ссылкой.
&НаСервере
Процедура НастроитьСписокСЯчейками()
СвойстваСписка = ОбщегоНазначения.СтруктураСвойствДинамическогоСписка();
СвойстваСписка.ТекстЗапроса = ТекстЗапросаСОстаткамиПоЯчейкам(СписокНоменклатуры.ТекстЗапроса);
СвойстваСписка.ОсновнаяТаблица = "";
СвойстваСписка.ДинамическоеСчитываниеДанных = Истина;
ОбщегоНазначения.УстановитьСвойстваДинамическогоСписка(Элементы.СписокНоменклатуры, СвойстваСписка);
ПоляКлюча = Новый Массив;
ПоляКлюча.Добавить("Ссылка");
ПоляКлюча.Добавить("Ячейка");
СписокНоменклатуры.ПоляКлюча = Новый ФиксированныйМассив(ПоляКлюча);
СписокНоменклатуры.ВидКлюча = ВидКлючаДинамическогоСписка.КлючСтроки;
ПолеЯчейка = Элементы.Добавить("СписокНоменклатурыЯчейка", Тип("ПолеФормы"), Элементы.СписокНоменклатуры);
ПолеЯчейка.Вид = ВидПоляФормы.ПолеВвода;
ПолеЯчейка.ПутьКДанным = "СписокНоменклатуры.Ячейка";
ПолеОстаток = Элементы.Добавить("СписокНоменклатурыОстатокВЯчейке", Тип("ПолеФормы"), Элементы.СписокНоменклатуры);
ПолеОстаток.Вид = ВидПоляФормы.ПолеВвода;
ПолеОстаток.ПутьКДанным = "СписокНоменклатуры.ОстатокВЯчейке";
ПолеОстаток.Заголовок = НСтр("ru = 'Остаток'");
КонецПроцедурыБез основной таблицы теряются некоторые автоматические возможности: текущая строка уже не ссылка, а ключ строки, поэтому код вида Элементы.Список.ТекущаяСтрока нужно заменить на чтение ТекущиеДанные.Ссылка. Проверьте команды формы после переделки.

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




