Как сделать отбор в форме списка документов по вычисляемой колонке в 1С

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При работе с документами в 1С часто возникает необходимость вывести в форму списка дополнительную информацию, которой нет в реквизитах самого документа. Например, проверить наличие связанного документа (налоговой накладной, счет-фактуры или документа оплаты). Если такая колонка рассчитывается динамически в событии формы, стандартный отбор платформы по ней не работает. Разберем, почему возникает эта проблема и как ее правильно решить.

Выясним причину: почему нельзя поставить стандартный отбор

В обычных формах источник данных динамического списка (объект ДокументСписок) выполняет запрос непосредственно к базе данных на уровне СУБД. Значения, которые формируются визуально в событиях оформления интерфейса (например, в событии ПриВыводеСтроки), существуют только на клиенте в момент отрисовки текущей строки.

Так как вычисляемого поля нет в таблице базы данных и в составе реквизитов объекта, платформа 1С не может применить к нему стандартное условие отбора. Попытка установить отбор прямо внутри события ПриВыводеСтроки приведет к зацикливанию: установка отбора вызовет обновленное получение данных, которое снова запустит вывод строк.

Решение 1. Программный отбор по массиву ссылок (для обычных форм)

Рассмотрим основной способ решения задачи без изменения структуры базы данных. Если необходимо отфильтровать список документов по какому-либо признаку (например, показать только счета, по которым выписана налоговая накладная), мы можем выполнить отдельный запрос к базе данных и передать полученный список ссылок в элемент отбора.

Проанализируем алгоритм реализации по шагам:

  1. Добавим на форму кнопку или команду (например, «Показать счета с НН»).
  2. В обработчике нажатия кнопки выполним запрос к базе данных, чтобы найти все ссылки на документы, удовлетворяющие условию.
  3. Выгрузим результаты запроса в массив или список значений.
  4. Установим отбор для ДокументСписок по полю Ссылка с типом сравнения В Списке.

Посмотрим на пример кода обработки нажатия кнопки:


// Выполняем запрос для поиска счетов, имеющих налоговую накладную
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	СчетНаОплату.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.НалоговаяНакладная КАК НалоговаяНакладная
    |ГДЕ
    |	НалоговаяНакладная.ДокументОснование ССЫЛКА Документ.СчетНаОплатуПокупателю
    |	И НЕ НалоговаяНакладная.ПометкаУдаления";

РезультатЗапроса = Запрос.Выполнить();
МассивСсылок = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка");

// Устанавливаем отбор в списке документов
ЭлементОтбора = ДокументСписок.Отбор.Ссылка;
ЭлементОтбора.ВидСравнения = ВидСравнения.ВСписке;
ЭлементОтбора.Значение.ЗагрузитьЗначения(МассивСсылок);
ЭлементОтбора.Использование = Истина;

Важная деталь по производительности: данный способ отлично подходит для небольших и средних выборок. Однако если запрос возвращает десятки тысяч счетов, передача огромного массива ссылок в отбор может вызвать повышенную нагрузку на СУБД. В таких случаях рекомендуются архитектурные изменения.

Решение 2. Использование динамического списка с произвольным запросом (для управляемых форм)

Если разработка ведется на управляемых формах, лучшим решением является настройка динамического списка. В этом случае вычисляемое поле переносится прямо в запрос источника данных.

Разберем по шагам, как настроить такой отбор:

  1. В свойствах динамического списка установим флаг ПроизвольныйЗапрос в значение Истина.
  2. В тексте запроса свяжем таблицу документов с таблицей налоговых накладных через ЛЕВОЕ СОЕДИНЕНИЕ.
  3. Добавим вычисляемое поле с помощью инструкции ВЫБОР КОГДА ... ТОГДА.

Рассмотрим пример текста запроса для динамического списка:


ВЫБРАТЬ
	ДокСчет.Ссылка КАК Ссылка,
	ДокСчет.Дата КАК Дата,
	ДокСчет.Номер КАК Номер,
	ДокСчет.Контрагент КАК Контрагент,
	ВЫБОР
		КОГДА Налоговые.Ссылка ЕСТЬ НЕ NULL ТОГДА Истина
		ИНАЧЕ Ложь
	КОНЕЦ КАК ЕстьНН
ИЗ
	Документ.СчетНаОплатуПокупателю КАК ДокСчет
	ЛЕВОЕ СОЕДИНЕНИЕ Документ.НалоговаяНакладная КАК Налоговые
		ПО Налоговые.ДокументОснование = ДокСчет.Ссылка
		И НЕ Налоговые.ПометкаУдаления

После добавления поля ЕстьНН в запрос списка пользователь сможет настраивать стандартный отбор по этому полю через меню «Настроить список» без написания дополнительного кода.

Решение 3. Архитектурный подход через регистр сведений

Если в системе требуется мгновенный отбор и высокая скорость работы при миллионах записей, создают специальный независимый РегистрСведений (например, НаличиеНалоговыхНакладных).

Проанализируем схему работы данного подходы:

  1. Измерением регистра выступает документ СчетНаОплатуПокупателю, а ресурсом — флаг ЕстьНН (тип Булево) или ссылка на созданную накладную.
  2. При проведении, отмене проведения или записи подчиненного документа (налоговой накладной) через подписку на событие данные в регистре автоматически обновляются.
  3. В результате для отбора достаточно выполнить простое соединение с таблицей регистра сведений, что работает максимально быстро.

Оптимизация отображения данных в обычных формах

Если отбор не требуется делать постоянным, а ключевая задача — избавиться от зависаний при открытии списка, обратите внимание на событие вывода данных. Выполнение запросов внутри события ПриВыводеСтроки создает проблему «запроса в цикле», так как запрос отправляется к базе данных для каждой отдельной строки.

Для ускорения визуального вывода в обычных формах следует заменять событие ПриВыводеСтроки на событие ПриПолученииДанных. В него передается параметр ОформленияСтрок, содержащий массив всех видимых на экране строк. Это позволяет выполнить один пакетный запрос сразу по всей видимой области и быстро расставить значения в вычисляемой колонке.

← На главную