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