Как в 1С разделить выбор номенклатуры на товары и услуги в разных табличных частях

Программист 1С v8.3 (Управляемые формы)
← На главную

В процессе разработки или доработки конфигураций 1С часто возникает задача упростить интерфейс для конечного пользователя. Одной из таких задач является разделение справочника Номенклатура при выборе в документы. Например, если в документе есть две отдельные вкладки (табличные части) — одна для товаров, а другая для услуг, — логично настроить систему так, чтобы пользователь не мог ошибочно выбрать услугу в список товаров и наоборот. Рассмотрим подробнее, какими способами можно реализовать это ограничение, проанализируем технические нюансы для разных типов приложений и разберем конкретные примеры кода.

Метод 1. Использование параметров выбора в метаданных (без программирования)

Прежде чем приступать к написанию кода, проанализируем стандартные возможности платформы 1С 8.3. Если в вашем документе товары и услуги разнесены по разным табличным частям, самым простым и правильным решением будет настройка свойства Параметры выбора непосредственно в конфигураторе.

Разберем этот процесс по шагам:

  1. Откроем нужный документ в конфигураторе и перейдем на вкладку Данные.
  2. Найдем табличную часть (например, Товары) и выберем реквизит Номенклатура.
  3. В палитре свойств найдем пункт Параметры выбора.
  4. Нажмем на кнопку выбора (три точки) и добавим новый параметр.
  5. В колонке «Имя параметра» выберем Отбор.ТипНоменклатуры (предполагается, что в справочнике есть реквизит ТипНоменклатуры).
  6. В колонке «Значение» укажем конкретное значение из перечисления, например, Товар.

Аналогичную операцию проделаем для табличной части Услуги, установив отбор по значению Услуга. Этот метод хорош тем, что он работает на уровне платформы и не требует поддержки кода при обновлении конфигурации. Однако, как отмечалось в обсуждении, иногда этот способ «не срабатывает», если форма документа сильно кастомизирована или используются динамические списки с переопределенным выбором. В таких случаях мы переходим к программным методам.

Метод 2. Программная установка параметров выбора в Управляемых формах

Если нам необходимо динамически управлять отбором или если настройки в метаданных по какой-то причине не применяются, мы можем установить параметры выбора программно. Рассмотрим ситуацию, когда нам нужно сделать это при создании формы или при изменении каких-либо условий.

Проанализируем пример кода, который устанавливает отбор для элемента формы (поля табличной части):


&НаСервере
Процедура УстановитьОтборыНаФорме()
    // Устанавливаем отбор для колонки Номенклатура в таблице Товары
    НовыйПараметр = Новый ПараметрВыбора("Отбор.ТипНоменклатуры", Перечисления.ТипыНоменклатуры.Товар);
    
    МассивПараметров = Новый Массив;
    МассивПараметров.Добавить(НовыйПараметр);
    
    // Элементы.ТоварыНоменклатура - это путь к полю в табличной части на форме
    Элементы.ТоварыНоменклатура.ПараметрыВыбора = Новый ФиксированныйМассив(МассивПараметров);
КонецПроцедуры

Важно помнить, что свойство ПараметрыВыбора имеет тип ФиксированныйМассив, поэтому мы сначала формируем обычный массив, а затем преобразуем его. Этот код лучше всего вызывать в обработчике ПриСозданииНаСервере.

Метод 3. Реализация в Обычном приложении (Толстый клиент)

Как справедливо заметили участники обсуждения, в старых конфигурациях (на обычных формах) механизм ПараметрыВыбора может отсутствовать или работать иначе. В этом случае мы используем событие НачалоВыбора. Выясним, как это реализовать правильно, чтобы подменялась форма выбора с уже установленным фильтром.

Рассмотрим пример кода для модуля формы документа:


Процедура ТоварыНоменклатураНачалоВыбора(Элемент, СтандартнаяОбработка)
    // Отключаем стандартное открытие формы, чтобы открыть её программно с нашими настройками
    СтандартнаяОбработка = Ложь;
    
    // Получаем форму выбора справочника Номенклатура
    ФормаВыбора = Справочники.Номенклатура.ПолучитьФормуВыбора("ФормаВыбора", Элемент, ЭтаФорма);
    
    // Устанавливаем жесткий отбор по типу номенклатуры
    ФормаВыбора.Отбор.ТипНоменклатуры.Значение = Перечисления.ТипыНоменклатуры.Товар;
    ФормаВыбора.Отбор.ТипНоменклатуры.Использование = Истина;
    
    // Открываем настроенную форму
    ФормаВыбора.Открыть();
КонецПроцедуры

В этом сценарии мы полностью берем управление на себя. Пользователь при нажатии на кнопку выбора увидит только те элементы, которые соответствуют заданному типу. Помните, что если в справочнике используется иерархия, отбор будет действовать на все уровни, и пустые группы (в которых нет товаров) могут мешать навигации. В таких случаях можно дополнительно установить ФормаВыбора.ЭлементыФормы.СправочникСписок.ИерархическийПросмотр = Ложь;.

Метод 4. Использование механизма «Связи параметров выбора»

Иногда разделение на товары и услуги зависит не от табличной части, а от контекста документа, например, от выбранного «Вида операции». В 1С существует мощный механизм Связи параметров выбора. Разберем, как он работает.

Допустим, в шапке документа есть реквизит ВидДокумента (Товарный/Услуговый). Мы можем связать поле Номенклатура с этим реквизитом. В настройках связи мы указываем, что поле Отбор.ТипНоменклатуры в справочнике должно принимать значение из реквизита ВидДокумента на форме. В этом случае платформа сама будет обновлять список доступных элементов при изменении значения в шапке без единой строчки кода.

Метод 5. Обработка получения данных выбора (модуль менеджера)

Для современных систем на базе Управляемого приложения (УТ 11, БП 3.0, ERP) наиболее элегантным и быстрым способом является использование обработчика ОбработкаПолученияДанныхВыбора в модуле менеджера справочника Номенклатура. Это позволяет фильтровать данные даже при вводе по строке.

Проанализируем ситуацию: когда пользователь начинает набирать название в поле, система обращается к серверу. Мы можем перехватить этот запрос:


// В модуле менеджера справочника Номенклатура
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
    
    // Проверяем, пришел ли к нам специфический параметр отбора
    Если Параметры.Свойство("ТолькоТовары") Тогда
        СтандартнаяОбработка = Ложь;
        
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |   Ссылка
            |ИЗ
            |   Справочник.Номенклатура
            |ГДЕ
            |   ТипНоменклатуры = &ТипНоменклатуры
            |   И Наименование ПОДОБНО &ТекстПоиска";
            
        Запрос.УстановитьПараметр("ТипНоменклатуры", Перечисления.ТипыНоменклатуры.Товар);
        Запрос.УстановитьПараметр("ТекстПоиска", "%" + Параметры.СтрокаПоиска + "%");
        
        ДанныеВыбора = Новый СписокЗначений;
        ДанныеВыбора.ЗагрузитьЗначения(Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка"));
    КонецЕсли;
    
КонецПроцедуры

Метод 6. Организационное разделение через иерархию

Если задача стоит остро, а программирование по каким-то причинам ограничено, можно прибегнуть к административному методу. Выясним, как это реализовать через структуру справочника. Вы можете создать две корневые папки: «ТОВАРЫ» и «УСЛУГИ». В свойствах поля Номенклатура в конфигураторе (в параметрах выбора) можно указать родителя (конкретную папку). Это ограничит область поиска пользователя только одной веткой дерева справочника.

Важный нюанс: Услуги vs Работы

При настройке отборов обязательно проанализируйте, какие типы номенклатуры используются в вашей базе. В современных версиях 1С часто выделяют «Работы». Работы, в отличие от услуг, могут иметь себестоимость и учитываться в производстве. Если ваша задача — разделить материальные ценности и нематериальные операции, убедитесь, что в отбор для «Услуг» вы включили и «Работы» (используя вид сравнения В списке в параметрах выбора).

Контроль корректности данных

Ни один визуальный отбор не дает 100% гарантии отсутствия ошибок. Данные могут попасть в документ через копирование строк, обработки загрузки или групповое изменение реквизитов. Поэтому, завершая работу над разделением товаров и услуг, обязательно добавим проверку в модуле документа в процедуре ОбработкаПроведения или ПередЗаписью.

Пример проверки:


Для Каждого СтрокаТовара Из Товары Цикл
    Если СтрокаТовара.Номенклатура.ТипНоменклатуры = Перечисления.ТипыНоменклатуры.Услуга Тогда
        Отказ = Истина;
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "В табличной части 'Товары' найдена услуга: " + СтрокаТовара.Номенклатура;
        Сообщение.Сообщить();
    КонецЕсли;
КонецЦикла;

Таким образом, мы обеспечим комплексную защиту данных: пользователю будет удобно выбирать данные благодаря фильтрам на форме, а система сохранит целостность благодаря проверкам при проведении.

← На главную