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