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