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