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