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