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