Как программно установить отбор свободных документов в форме выбора на обычной форме 1С 8.3?

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

Разберем распространенную задачу разработки в 1С 8.3 на обычных формах: как при выборе документа из списка отобразить только те объекты, которые еще не были привязаны к другим документам системы. Например, когда необходимо выбрать автономно созданный документ Взвешивание, на который еще нет ссылки в реквизите СсылкаНаДокументВзвешивания документа Отгрузка.

Анализ задачи и подход к решению

Рассмотрим структуру данных: у нас есть основной документ Отгрузка с реквизитом СсылкаНаДокументВзвешивания и документ Взвешивание. Наша цель — по кнопке из формы документа Отгрузка вызывать форму выбора документа Взвешивание, в которой отображаются только незанятые (автономные) документы.

Для решения этой задачи выполним следующий порядок действий:

  1. Сформируем запрос, который выберет все документы Взвешивание, отсутствующие в качестве ссылок в документах Отгрузка.
  2. Выгрузим результат запроса в СписокЗначений.
  3. Программно откроем форму выбора документа Взвешивание и установим отбор по полю Ссылка с видом сравнения ВидСравнения.ВСписке.

Шаг 1. Формирование запроса для поиска свободных документов

Выясним, как правильно составить запрос к базе данных. Чтобы найти документы без ссылок-связей, наилучшим решением с точки зрения производительности является использование левого соединения с проверкой на NULL.


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Взвешивание.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.Взвешивание КАК Взвешивание
    |	ЛЕВОЕ СОЕДИНЕНИЕ Документ.Отгрузка КАК Отгрузка
    |	ПО (Отгрузка.СсылкаНаДокументВзвешивания = Взвешивание.Ссылка)
    |ГДЕ
    |	Отгрузка.Ссылка ЕСТЬ NULL";

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

  1. Из таблицы Документ.Взвешивание выбираются все существующие документы.
  2. К ним с помощью ЛЕВОЕ СОЕДИНЕНИЕ присоединяется таблица Документ.Отгрузка по условию равенства ссылки на документ взвешивания.
  3. Для тех документов Взвешивание, на которые еще не ссылается ни одна Отгрузка, поля присоединенной таблицы содержат значение NULL.
  4. Условие ГДЕ Отгрузка.Ссылка ЕСТЬ NULL отсекает уже занятые документы и оставляет только свободной выборку.

Важное замечание по производительности: Чтобы данный запрос выполнялся быстро, для реквизита СсылкаНаДокументВзвешивания в конфигураторе рекомендуем установить свойство Индексировать. Также при работе с большими объемами данных желательно ограничивать период выборки документов в запросе.

Шаг 2. Программная настройка отбора и открытие формы выборки

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


СписокДляОтбора = Новый СписокЗначений;

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Взвешивание.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.Взвешивание КАК Взвешивание
    |	ЛЕВОЕ СОЕДИНЕНИЕ Документ.Отгрузка КАК Отгрузка
    |	ПО (Отгрузка.СсылкаНаДокументВзвешивания = Взвешивание.Ссылка)
    |ГДЕ
    |	Отгрузка.Ссылка ЕСТЬ NULL";

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл
    СписокДляОтбора.Добавить(Выборка.Ссылка);
КонецЦикла;

Форма = Документы.Взвешивание.ПолучитьФормуВыбора();
Форма.Заголовок = "Выбор документа (Взвешивание) для закрепления за документом (Отгрузка)";

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

Форма.Открыть();

Критически важный нюанс: На обычных формах порядок присвоения свойств объекту Отбор имеет строгое значение. Сначала необходимо установить свойство ВидСравнения = ВидСравнения.ВСписке, и только после этого присваивать подготовленный СписокЗначений в свойство Значение. Если записать список значений при виде сравнения по умолчанию (Равно), платформа выдаст ошибку несоответствия типов данных.

Сравнение подходов к запросу: ЛЕВОЕ СОЕДИНЕНИЕ против НЕ В (...)

Рассмотрим альтернативный вариант написания запроса с помощью вложенного запроса и конструкции НЕ Ссылка В (...):


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Взвешивание.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.Взвешивание КАК Взвешивание
    |ГДЕ
    |	НЕ Взвешивание.Ссылка В (
    |		ВЫБРАТЬ
    |			Отгрузка.СсылкаНаДокументВзвешивания КАК СсылкаНаДокументВзвешивания
    |		ИЗ
    |			Документ.Отгрузка КАК Отгрузка
    |		ГДЕ
    |			Отгрузка.СсылкаНаДокументВзвешивания <> ЗНАЧЕНИЕ(Документ.Взвешивание.ПустаяСсылка)
    |	)";

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

  1. Запрос с использованием условий В или НЕ В менее эффективен на стороне СУБД и может вызывать замедление работы при количестве записей более нескольких сотен.
  2. В подзапросе обязательно нужно отфильтровывать пустые ссылки, иначе логика проверки значений может сработать некорректно.

Именно поэтому вариант с ЛЕВОЕ СОЕДИНЕНИЕ и проверкой на ЕСТЬ NULL является наиболее предпочтительным и быстрым.

Альтернативный вариант установки одиночного отбора

Если в будущем потребуется установить простой отбор по конкретному значению (например, отобразить документы по определенному владельцу или контрагенту), код настройки элемента отбора на обычной форме выглядит еще проще:


ФормаВыбора = Документы.Взвешивание.ПолучитьФормуВыбора();
ФормаВыбора.Отбор.Организация.ВидСравнения = ВидСравнения.Равно;
ФормаВыбора.Отбор.Организация.Значение = ИскомаяОрганизация;
ФормаВыбора.Отбор.Организация.Использование = Истина;
ФормаВыбора.Открыть();

Таким образом, комбинируя возможности запросов платформы 1С и программную настройку объекта Отбор, можно гибко управлять списками документов, показывая пользователю только актуальные данные для выбора.

← На главную