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