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