Кнопка подбора в 1С: добавляем и программируем своими руками

· 10 мин

Содержание

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

Разберём, как создать такую кнопку с нуля: добавить команду на форму, написать обработчик нажатия, принять выбранные значения и заполнить строки. Отдельно — когда своя кнопка не нужна, потому что в типовой конфигурации подбор уже встроен, и как настроить отбор в форме выбора.

Весь код ниже — для управляемых форм (платформа 8.3). На обычных формах принцип похож, но методы другие; если вы ведёте разработку на старой платформе, ориентируйтесь на свою версию.

Готовим форму и размещаем команду подбора

Сначала решите, куда подбор будет складывать значения. Чаще всего это табличная часть документа — например, Товары или Номенклатура. Кнопку логично повесить на командную панель этой таблицы.

Порядок действий в конфигураторе:

  1. Откройте форму объекта (документа или обработки) на закладке Форма.
  2. В дереве элементов слева выделите узел Команды → Команды формы и добавьте новую команду, назовите её, например, Подбор.
  3. В палитре свойств команды в поле Действие нажмите на лупу — платформа создаст пустой обработчик Подбор(Команда) в модуле формы.
  4. Перетащите команду на командную панель нужной табличной части либо добавьте кнопку вручную: выделите КоманднаяПанель таблицы, добавьте элемент Кнопка и в свойстве ИмяКоманды выберите Подбор.
  5. Задайте кнопке заголовок «Подбор» и, при желании, картинку из библиотеки (ВыбратьИзСписка, ПодборИзСписка).

Если подбор нужен в нескольких формах одного объекта, команду удобнее создавать в каждой форме отдельно — общего места для команд формы нет, они живут в модуле конкретной формы.

После этого в модуле формы появится заготовка обработчика. Её мы и заполним на следующем шаге.

Пишем обработчик нажатия кнопки

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

&НаКлиенте
Процедура Подбор(Команда)
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("МножественныйВыбор", Истина);
    ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Ложь);
    
    Оповещение = Новый ОписаниеОповещения("ПодборЗавершение", ЭтотОбъект);
    
    ОткрытьФорму(
        "Справочник.Номенклатура.ФормаВыбора",
        ПараметрыФормы,
        ЭтотОбъект,
        ,
        ,
        ,
        Оповещение);
    
КонецПроцедуры

Что здесь происходит по пунктам:

  • МножественныйВыбор = Истина — в форме выбора появляются флажки, можно отметить несколько строк.
  • ЗакрыватьПриВыборе = Ложь — форма не закрывается после каждого клика, пользователь сначала отмечает всё нужное, потом нажимает «Выбрать».
  • ОписаниеОповещения связывает открытие формы с процедурой ПодборЗавершение — именно туда вернётся результат.
  • Третий параметр ЭтотОбъект делает текущую форму владельцем открываемой. Это нужно, чтобы отбор и контекст работали корректно.

Не пытайтесь получить выбранные значения сразу после ОткрытьФорму — на этой строке форма ещё не закрыта, и никакого результата в переменной не будет. Результат придёт только в процедуру оповещения.

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

Обрабатываем выбранные значения

Теперь напишем процедуру, которая получит выбранное и заполнит табличную часть. Её имя должно совпадать с первым параметром ОписаниеОповещения — в примере это ПодборЗавершение.

&НаКлиенте
Процедура ПодборЗавершение(РезультатВыбора, ДополнительныеПараметры) Экспорт
    
    Если РезультатВыбора = Неопределено Тогда
        Возврат; // пользователь закрыл форму без выбора
    КонецЕсли;
    
    ЗаполнитьТоварыНаСервере(РезультатВыбора);
    
КонецПроцедуры

При множественном выборе в РезультатВыбора приходит Массив ссылок. При одиночном — одна ссылка. Поэтому заполнение строк выносим на сервер, где удобно работать с реквизитами объекта и остатками.

&НаСервере
Процедура ЗаполнитьТоварыНаСервере(ВыбранныеЭлементы)
    
    МассивНоменклатуры = Новый Массив;
    Если ТипЗнч(ВыбранныеЭлементы) = Тип("Массив") Тогда
        МассивНоменклатуры = ВыбранныеЭлементы;
    Иначе
        МассивНоменклатуры.Добавить(ВыбранныеЭлементы);
    КонецЕсли;
    
    Для Каждого ТекНоменклатура Из МассивНоменклатуры Цикл
        НоваяСтрока = Объект.Товары.Добавить();
        НоваяСтрока.Номенклатура = ТекНоменклатура;
        НоваяСтрока.Количество   = 1;
    КонецЦикла;
    
КонецПроцедуры

Несколько практических деталей:

  • Проверка ТипЗнч спасает код от падения, если режим выбора поменяется: он одинаково работает и с массивом, и с одиночной ссылкой.
  • Объект.Товары — путь к табличной части через реквизит формы Объект. Имя Товары замените на своё.
  • Количество по умолчанию поставили 1. Здесь же можно подтянуть цену, единицу измерения, ставку НДС — через запрос к регистрам.

Серверную процедуру вызывайте только для реального заполнения. Не гоняйте на сервер каждую строку в цикле на клиенте — один вызов с массивом работает в разы быстрее.

Чтобы не плодить дубли, перед добавлением можно проверять, нет ли уже такой номенклатуры в таблице, и вместо новой строки увеличивать количество в существующей.

Альтернатива: обработчик события ОбработкаВыбора

ОписаниеОповещения — не единственный способ принять результат. У формы есть встроенное событие ОбработкаВыбора, которое срабатывает, когда подчинённая форма возвращает выбор своему владельцу. Если открыть форму выбора без оповещения, но с владельцем ЭтотОбъект, результат придёт именно сюда.

&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора, СтандартнаяОбработка)
    
    Если ИсточникВыбора.ИмяФормы = "Справочник.Номенклатура.ФормаВыбора" Тогда
        СтандартнаяОбработка = Ложь;
        ЗаполнитьТоварыНаСервере(ВыбранноеЗначение);
    КонецЕсли;
    
КонецПроцедуры

Разница в том, что ОбработкаВыбора ловит выбор от любой подчинённой формы, поэтому внутри нужно проверять ИсточникВыбора, иначе один обработчик смешает результаты разных кнопок. Оповещение же адресное — оно привязано к конкретному вызову ОткрытьФорму. Для одной кнопки удобнее оповещение, для нескольких разнотипных подборов на одной форме — общее событие с проверкой источника.

Подтягиваем цену и остатки при подборе

Простое добавление ссылки редко устраивает пользователя — обычно в строку сразу нужны цена и остаток на складе. Это делается тем же серверным методом, только с запросом.

&НаСервере
Процедура ЗаполнитьЦеныНаСервере(НоваяСтрока)
    
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |   ЦеныСрезПоследних.Цена КАК Цена
    |ИЗ
    |   РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, Номенклатура = &Номенклатура) КАК ЦеныСрезПоследних";
    Запрос.УстановитьПараметр("Дата", Объект.Дата);
    Запрос.УстановитьПараметр("Номенклатура", НоваяСтрока.Номенклатура);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        НоваяСтрока.Цена = Выборка.Цена;
    КонецЕсли;
    
КонецПроцедуры

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

Если строк подбирается много, собирайте все цены одним запросом с условием Номенклатура В (&МассивНоменклатуры), а не по одному запросу на каждую строку. На подборе из сотни позиций разница в скорости заметна сразу.

Иногда количество удобнее запрашивать прямо в момент подбора, а не ставить 1 по умолчанию. Тогда в форме выбора включают режим ввода количества: при выборе строки платформа запрашивает число, и оно приходит в результат вместе со ссылкой. Это задаётся параметром формы выбора РежимВыбора в связке с настройкой самой формы списка; если типовая форма такого не умеет, проще оставить количество 1, а правку оставить пользователю в самой табличной части — так меньше кода и меньше мест для ошибки.

Когда своя кнопка не нужна: встроенный подбор

Прежде чем писать код, загляните в типовую конфигурацию . В «1С:Управление торговлей», «1С:Бухгалтерии», «1С:ERP» и других решениях на БСП подбор номенклатуры в документы продаж и поступления уже реализован — это отдельная полноценная форма с остатками, ценами, фильтрами и историей.

В готовом документе, например «Реализация товаров и услуг», кнопка «Подбор» стоит над табличной частью Товары. Она открывает рабочее место подбора, где видно:

  • остаток по складу и свободный остаток;
  • актуальную цену по выбранному виду цен;
  • характеристики и серии, если они включены;
  • строку поиска по наименованию и артикулу.

Переписывать это своим кодом смысла нет. Своя кнопка подбора оправдана в трёх случаях:

  1. Вы делаете собственный документ или обработку, где типового подбора нет.
  2. Нужен нестандартный отбор — например, только товары одного поставщика.
  3. Подбор идёт не по номенклатуре, а по другому справочнику (контрагенты, сотрудники, договоры).

Если дорабатываете типовую конфигурацию, не меняйте форму документа напрямую — используйте расширение конфигурации. Так доработка переживёт обновление.

Встроенный подбор в типовых решениях — это обычно общая форма или обработка (в «Управлении торговлей» её называют рабочим местом подбора). Она хранит уже отмеченные позиции, пока пользователь ходит по группам справочника, и переносит их в документ одной кнопкой «Перенести в документ». Повторить такое поведение своим кодом можно, но трудоёмко: нужно самому держать таблицу отмеченного и переносить её по команде. Для нетиповых документов чаще достаточно простого множественного выбора, который мы собрали выше.

Настраиваем форму выбора и отбор

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

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

Ключ структуры Отбор — это имя реквизита справочника, а значение — то, по чему фильтруем. Платформа применит отбор при открытии формы, и пользователь увидит только подходящие элементы.

Другие полезные параметры формы выбора:

ПараметрЧто делает
ТекущаяСтрокассылка, на которой встанет курсор при открытии
ВыборГруппИЭлементовразрешить или запретить выбор групп справочника
РежимВыборавключает режим выбора для обычной формы списка
Отборструктура фильтров, накладываемых на список

Если готовой формы выбора у справочника нет, платформа сгенерирует её автоматически — отдельно создавать её не обязательно. Но когда нужен особый внешний вид (колонки с остатками, свой поиск), создайте собственную форму выбора и укажите её имя в ОткрытьФорму.

Производительность и типичные ошибки

Подбор — операция массовая, поэтому мелкие огрехи в коде превращаются в заметные тормоза. Самое частое: вызов сервера в цикле. Открыли форму, на каждый выбранный элемент дёргаете &НаСервере — и на пятидесяти позициях пользователь ждёт несколько секунд. Передавайте весь массив одним вызовом.

Второй момент — цены и остатки. Один запрос на строку создаёт десятки обращений к базе. Соберите нужные ссылки в массив и возьмите данные одним запросом с условием В (&Массив).

Третье — повторный подбор. Если пользователь открывает форму дважды, строки могут задвоиться. Либо проверяйте дубли перед добавлением, либо суммируйте количество в существующей строке.

Разберём, что идёт не так чаще всего:

Диагностика: выберите симптом

Перед сдачей доработки пройдитесь по короткому списку проверки:

Проверка кнопки подбора перед сдачей
Выполнено: 0 / 7

Частые вопросы

Чем отличается подбор от обычного выбора по кнопке ссылки?
Обычный выбор возвращает одно значение в поле ввода. Подбор открывает форму списка в режиме множественного выбора и позволяет отметить сразу несколько элементов, которые затем переносятся в табличную часть.
Можно ли сделать подбор не по номенклатуре, а по другому справочнику?
Да. В методе ОткрытьФорму укажите имя формы выбора нужного справочника, например "Справочник.Контрагенты.ФормаВыбора". Логика обработчика результата при этом не меняется.
Почему результат подбора приходит в отдельную процедуру, а не сразу?
На управляемых формах открытие формы асинхронное: клиент не блокируется, пока открыта форма выбора. Поэтому результат возвращается через ОписаниеОповещения в указанную процедуру после закрытия формы.
Как при подборе сразу подставить количество и цену?
Заполняйте эти реквизиты в серверной процедуре после добавления строки: количество ставьте значением по умолчанию, цену берите запросом к регистру сведений с ценами на дату документа.
Нужно ли создавать форму выбора справочника вручную?
Нет. Если собственной формы выбора у справочника нет, платформа сгенерирует её автоматически. Своя форма нужна, только когда требуется особый вид списка — например, колонки с остатками и ценами.