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