При написании конфигурации с нуля, я столкнулся с задачей организации подборов в документах. Все что я накопал по этому вопросу, сводилось либо к совсем простеньким подборам, в рамках задачи по управляемым формам на экзамене на Спеца по платформе, что было недостаточно, либо к сложным обработкам, обширный функционал которых был явно избыточен для моей задачи. В итоге, посидев и немного подумав, я сделал свой вариант, который, не претендуя ни на что особенное, устроил меня в рамках выполняемой задачи. Может, кому-то пригодится и сэкономит время.
В МодулеФормы документа из которого осуществляется подбор разместил две процедуры:
&НаКлиенте
Процедура Подобрать(Команда)
//Проверка заполнение ревизитов ВидЦены и Склад
Если НЕ ЗначениеЗаполнено(Объект.ВидЦены) Тогда
Предупреждение("Заполните Вид цены!");
ИначеЕсли НЕ ЗначениеЗаполнено(Объект.Склад) Тогда
Предупреждение("Заполните Склад!");
Иначе
//Создадим и заполним структуру передаваемых параметров
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("ВидЦены", Объект.ВидЦены);
ПараметрыОтбора.Вставить("Склад",Объект.Склад);
Если РасчетыНаСервере.ЗначениеКонстанты() = Истина Тогда
//Откроем форму подбора справочника Номенклатура
ФормаПодбора = ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаПодбораСХарактеристиками", ПараметрыОтбора, Элементы.Товары);
Иначе
ФормаПодбора = ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаВыбораТовБезХарактеристик", ПараметрыОтбора, Элементы.Товары);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ТоварыОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
Для Каждого СтрокаТЧ из ВыбранноеЗначение Цикл
ТекСтрока = Объект.Товары.Добавить();
ТекСтрока.Номенклатура = СтрокаТЧ.Номенклатура;
Если РасчетыНаСервере.ЗначениеКонстанты() = Истина Тогда
ТекСтрока.Характеристика = СтрокаТЧ.Характеристика;
Иначе
ТекСтрока.Характеристика = "";
КонецЕсли;
ТекСтрока.Количество = СтрокаТЧ.Количество;
ДанныеСтруктура = Новый Структура("СтавкаНДС, ВидНоменклатуры, ЕденицаИзмерения",,,,);
Структура = РасчетыНаСервере.ПолучитьДанныеНоменклатуры(ДанныеСтруктура, ТекСтрока.Номенклатура);
ТекСтрока.СтавкаНДС = Структура.СтавкаНДС;
ТекСтрока.ВидНоменклатуры = Структура.ВидНоменклатуры;
ТекСтрока.ЕденицаИзмерения = Структура.ЕденицаИзмерения;
РасчетыНаКлиенте.ОбработкаЦены(ТекСтрока, ТекСтрока.Характеристика, Объект);
РасчетыНаКлиенте.ПересчитатьСтроку(ТекСтрока, Объект);
КонецЦикла;
КонецПроцедуры
Создал ФормуПодбора, в ней разместил реквизиты формы ИерархияНоменклатуры(ДинамическийСписок: Основная таблица - СправочникНоменклатура), Список(ТаблицаЗначений ) и ОтобранныеТовары(ТаблицаЗначений) в модуле формы разместил несколько процедур
&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)//Выбор номенклатуры кликом
ТекСтрока = Элементы.Список.ТекущиеДанные;
Структура = Новый Структура("Номенклатура, Характеристика, Цена", ТекСтрока.Номенклатура,ТекСтрока.Характеристика, ТекСтрока.Цена);
СтандартнаяОбработка = ЛОЖЬ;
//Поиск идентичной номенклатуры в ТаблицеЗначений
Строка = ОтобранныеТовары.НайтиСтроки(Новый Структура("Номенклатура, Характеристика, Цена", Структура.Номенклатура, Структура.Характеристика, Структура.Цена));
//Если Номенклатура уже записана то просто добавляем 1 к Количеству
Если Строка.Количество() > 0 Тогда
Строка[0].Количество = Строка[0].Количество+1;
Строка[0].Сумма = Строка[0].Количество * Строка[0].Цена;
Иначе//Создаем новый элемент
НовСтр = ОтобранныеТовары.Добавить();
НовСтр.Номенклатура = ТекСтрока.Номенклатура;
НовСтр.Характеристика = ТекСтрока.Характеристика;
НовСтр.Количество = 1;
НовСтр.Цена = ТекСтрока.Цена;
НовСтр.Сумма = ТекСтрока.Цена;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура СписокНачалоПеретаскивания(Элемент, ПараметрыПеретаскивания, Выполнение)//Выбор номенклатуры перетаскиванием
ТекСтрока = Элементы.Список.ТекущиеДанные;
Структура = Новый Структура("Номенклатура, Характеристика, Цена", ТекСтрока.Номенклатура,ТекСтрока.Характеристика, ТекСтрока.Цена);
СтандартнаяОбработка = ЛОЖЬ;
//Поиск идентичной номенклатуры в ТаблицеЗначений
Строка = ОтобранныеТовары.НайтиСтроки(Новый Структура("Номенклатура, Характеристика", Структура.Номенклатура, Структура.Характеристика));
//Если Номенклатура уже записана то просто добавляем 1 к Количеству
Если Строка.Количество() > 0 Тогда
Строка[0].Количество = Строка[0].Количество+1;
Строка[0].Сумма = Строка[0].Количество * Строка[0].Цена;
Иначе//Создаем новый элемент
НовСтр = ОтобранныеТовары.Добавить();
НовСтр.Номенклатура = ТекСтрока.Номенклатура;
НовСтр.Характеристика = ТекСтрока.Характеристика;
НовСтр.Количество = 1;
НовСтр.Цена = ТекСтрока.Цена;
НовСтр.Сумма = ТекСтрока.Цена;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)//Параметры передаваемые из Документа для запроса
ВидЦены = Параметры.ВидЦены;
Склад =Параметры.Склад;
Дата = Параметры.Дата;
КонецПроцедуры
&НаКлиенте
Процедура ПеренестиВДокумент(Команда)
ОповеститьОВыборе(ОтобранныеТовары);
КонецПроцедуры
&НаСервере
Функция ЗаполнитьСписокНаСервере(Родитель)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| ЕСТЬNULL(ОстаткиНаСкладахОстатки.Характеристика, ЦеныНоменклатурыСрезПоследних.Характеристика) КАК Характеристика,
| ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.ВидЦены, """") КАК ВидЦены,
| ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
| ЕСТЬNULL(ОстаткиНаСкладахОстатки.Склад, """") КАК Склад,
| ЕСТЬNULL(ОстаткиНаСкладахОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток,
| ОстаткиНаСкладахОстатки.Номенклатура КАК Номенклатура
|ПОМЕСТИТЬ ВТ
|ИЗ
| РегистрНакопления.ОстаткиНаСкладах.Остатки(&Дата, Склад = &Склад) КАК ОстаткиНаСкладахОстатки
| ПОЛНОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ВидЦены = &ВидЦены) КАК ЦеныНоменклатурыСрезПоследних
| ПО ОстаткиНаСкладахОстатки.Номенклатура = ЦеныНоменклатурыСрезПоследних.Номенклатура
| И ОстаткиНаСкладахОстатки.Характеристика = ЦеныНоменклатурыСрезПоследних.Характеристика
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| СпрНоменклатура.Ссылка КАК Номенклатура,
| ВТ.Характеристика КАК Характеристика,
| ВТ.ВидЦены КАК ВидЦены,
| ВТ.Цена КАК Цена,
| ВТ.Склад КАК Склад,
| ВТ.КоличествоОстаток КАК КоличествоОстаток
|ИЗ
| Справочник.Номенклатура КАК СпрНоменклатура
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ КАК ВТ
| ПО СпрНоменклатура.Ссылка = ВТ.Номенклатура
|ГДЕ
| СпрНоменклатура.Родитель = &Родитель
| И СпрНоменклатура.ВидНоменклатуры = ЗНАЧЕНИЕ(Справочник.ВидыНоменклатуры.Товар)";
Запрос.УстановитьПараметр("ВидЦены", ВидЦены);
Запрос.УстановитьПараметр("Дата", Дата);
Запрос.УстановитьПараметр("Склад", Склад);
Запрос.УстановитьПараметр("Родитель", Родитель);
РезультатЗапроса = Запрос.Выполнить();
ВДЗ = РезультатЗапроса.Выбрать();
Список.Очистить();
Пока ВДЗ.Следующий() Цикл
Строка = Список.Добавить();
Строка.Номенклатура = ВДЗ.Номенклатура;
Строка.Характеристика = ВДЗ.Характеристика;
Строка.Склад = ВДЗ.Склад;
Строка.Цена = ВДЗ.Цена;
Строка.ВидЦены = ВДЗ.ВидЦены;
Строка.КоличествоОстаток = ВДЗ.КоличествоОстаток;
КонецЦикла;
КонецФункции
&НаКлиенте
Процедура ИерархияНоменклатурыВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
Родитель = Элементы.ИерархияНоменклатуры.ТекущаяСтрока;
ЗаполнитьСписокНаСервере(Родитель);
КонецПроцедуры
Вот собственно и все.
Чуть чуть улучшил функционал обработки, сделав аналог полнотекстового поиска при большом количестве номенклатуры. Для этого добавил реквизит формы ОтборНаименование с типом Строка. Код разместил в модуле ФормыПодбора
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
ПеречитатьТабЧасть();
КонецПроцедуры
&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
ПеречитатьТабЧасть();
КонецПроцедуры
Процедура ПеречитатьТабЧасть()
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Таб.НомерСтроки КАК НомерСтроки,
| Таб.Номенклатура КАК Номенклатура
|ПОМЕСТИТЬ ВР_НоменклатураДокумента
|ИЗ
| &Таб КАК Таб
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ПОМЕСТИТЬ ВР_Номенклатура
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В
| (ВЫБРАТЬ
| ВР_НоменклатураДокумента.Номенклатура КАК Номенклатура
| ИЗ
| ВР_НоменклатураДокумента КАК ВР_НоменклатураДокумента)
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВР_НоменклатураДокумента.Номенклатура КАК Номенклатура,
| ВР_Номенклатура.Наименование КАК Наименование
|ИЗ
| ВР_НоменклатураДокумента КАК ВР_НоменклатураДокумента
| ЛЕВОЕ СОЕДИНЕНИЕ ВР_Номенклатура КАК ВР_Номенклатура
| ПО ВР_НоменклатураДокумента.Номенклатура = ВР_Номенклатура.Ссылка
|
|СГРУППИРОВАТЬ ПО
| ВР_НоменклатураДокумента.Номенклатура,
| ВР_Номенклатура.Наименование";
Запрос.УстановитьПараметр("Таб", Список.Выгрузить());
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
СтруктураПоиска = Новый Структура;
СтруктураПоиска.Вставить("Номенклатура");
Пока Выборка.Следующий() Цикл
СтруктураПоиска.Номенклатура = Выборка.Номенклатура;
МассивСтрок = Список.НайтиСтроки(СтруктураПоиска);
Для Каждого СтрМассива ИЗ МассивСтрок Цикл
СтрМассива.НаименованиеНоменклатуры = Выборка.Наименование;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ОтборНаименованиеОчистка(Элемент, СтандартнаяОбработка)
УстановитьОтбор("НаименованиеНоменклатуры","");
КонецПроцедуры
&НаКлиенте
Процедура ОтборНаименованиеИзменениеТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
УстановитьОтбор("НаименованиеНоменклатуры",Текст);
КонецПроцедуры
&НаКлиенте
Процедура УстановитьОтбор (ТекЭлементОтбора,ТекЗначениеОтбора)
СтруктураПоиска = Новый Структура;
Если ТекЗначениеОтбора <> "" Тогда
СтруктураПоиска.Вставить(ТекЭлементОтбора,ТекЗначениеОтбора);
КонецЕсли;
Элементы.Список.ОтборСтрок = Новый ФиксированнаяСтруктура(СтруктураПоиска);
КонецПроцедуры