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