В помощь начинающим: настройка динамических списков на УФ

Использование динамических списков в управляемых формах на примере простейшей формы подбора номенклатуры. В помощь осваивающим платформу 1с 8.2 с нуля или тем, кто переходит с 7.7.

Многие из тех, кто программировал на платформе 7.7, сталкивались с задачей доработки стандартных форм подбора номенклатуры, например, в ТиС. Пользователи часто желали видеть в одной таблице и остатки, и цены, да чтобы еще можно было отфильтровать список, например, по ненулевым остаткам. Создать произвольную форму списка стандартными средствами, которая бы при этом еще и не тормозила при листании и поиске на списках приличного размера, было не так-то просто. Честно говоря, именно такого рода задачи привели меня в свое время к использованию известных внешних компонент, которые позволяли семерке более эффективно получать данные запросами и отображать списки в альтернативных контролах. Ну а когда я начал осваивать платформу 8.2 и познакомился в общих чертах с ее базовыми механизмами, мне захотелось проверить, насолько проще можно решить подобные задачи теперь.

Итак, на управляемых формах попробуем создать простейшую форму для подбора номенклатуры, так, чтобы в списке отображался остаток и цена, и можно было выводить только те строчки, по которым есть остаток. Предполагаем что у нас уже есть справочник Номенклатура, документ Реализация, регистр накопления ОстаткиНоменклатуры и регистр сведений ЦеныНоменклатуры.

Создаем новую управляемую форму списка для справочника Номенклатура. Если созданная форма прописалась, как основная форма списка справочника, очистим это поле, дабы наша новая форма подбора открывалась только в нужном нам месте, а не везде, где предусмотрено открытие формы списка по умолчанию. Указываем мастеру, какие реквизиты справочника мы желаем видеть в списке, пусть это будут Код и Наименование. Выбираем детищу имя, например ФормаПодбора.

Теперь нас будет интересовать основной реквизит этой формы, имеющий тип ДинамическийСписок и имя ему — просто Список. В списке реквизитов формы основной реквизит отображается жирным шрифтом, я выделил его на картинке. Заглянем в его свойства, система автоматом установила для него основную таблицу, данные из которой и будут помещаться в список и отображаться на форме. Именно установка в качестве основной таблицы справочника позволит списку выглядеть и функционировать именно как список справочника, со всеми присущими ему иконками и командами. Так же установлен флажок «Динамическое считывание данных», это свойство позволяет отображать на лету изменения, происходящие с номенклатурой, например, в сеансах других пользователей — добавление новых записей, например.

Новая форма

 

Нас же больше всего интересует флажок «Произвольный запрос». Именно его установка позволит нам изменить набор данных, который окажется в нашем списке. Устанавливаем флажок и переходим по появившейся снизу ссылке  «Настройка списка — открыть».

Начальный запрос

 

  Видим, что платформа любезно подготовила для нас текст запроса, который пока что позволяет нам получит все тот же обычный список номенклатуры с наименованием, кодом и другими реквизитами справочника. Но теперь у нас есть возможность отредактировать этот запрос! Можем воспользоваться конструктором запроса или написать текст вручную, кто как привык.

Быстренько добавляем левые соединения с виртуальными таблицами остатков и цен, задаем нужные параметры, нам пока достаточно даты получения остатков и цен, и типа цены (конечно, такое измерение уже должно быть в нашем регистре сведений). Запрос готов.

Готовый запрос

 

Любопытства ради переходим на закладку настройки — и вот оно, счастье вчерашнего семерочника! Без всякого программирования, в самой первой закладке имеем возможность задавать любые интересуюшие нас отборы по полям, отбираемым в запросе! И главное — ровно все то же самое будет доступно и в пользовательском режиме! Выбрав в стандартных действиях пункт «Настроить список», пользователь увидит точно такое же окно настроек. Немного облегчим ему жизнь, заранее добавив отбор по полю Количество. Пользователю останется лишь установить флажок активности созданного нами отбора, когда это потребуется.

Настройки списка

 

Закрываем форму настройки списка и продолжаем облагораживание нашей формы подбора. Добавляем булевский реквизит ЗапрашиватьКоличество и таблицу значений Корзина, в ней мы будем отображать уже выбранную номенклатуру с количеством, ждущую переноса в документ. Перетаскиваем созданные реквизиты на форму, располагаем, как нам нравится. Кстати, нужно не забыть, что у реквизита Список, благодаря нашему новому запросу, появились новые доступные поля — Количество и Цена, перетаскиваем на форму и их тоже:

Готовая форма

 

Теперь вспоминаем, что запрос у нас содержит два параметра, которые мы должны получить из формы документа, в которой будем вызывать подбор, и передать в запрос. Для этой цели неплохо подойдут параметры формы, создаем два параметра нужных типов:

Параметры формы

 

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

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Список.Параметры.УстановитьЗначениеПараметра("Период", Параметры.Дата);
    Список.Параметры.УстановитьЗначениеПараметра("ТипЦен", Параметры.ТипЦен);
КонецПроцедуры

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

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

&НаСервере
Процедура ДобавитьВПодбор(Номенклатура, Количество)

    ТЗ = ДанныеФормыВЗначение(Корзина, Тип("ТаблицаЗначений"));
    
    Строка = ТЗ.Найти(Номенклатура, "Номенклатура");
    Если Строка = Неопределено Тогда
        Строка = ТЗ.Добавить();
        Строка.Номенклатура = Номенклатура;
    КонецЕсли;
    Строка.Количество = Строка.Количество + Количество;
    
    ЗначениеВДанныеФормы(ТЗ, Корзина);

КонецПроцедуры // ДобавитьВПодбор()

 Теперь корзина у нас заполняется выбранной номенклатурой и количеством. Остается организовать передачу корзины в вызывающий документ. Добавляем команду формы ПеренестиВДокумент, перетаскиваем ее на форму, получаем связанную с командой кнопку. Создаем обработчик команды. Поскольку форму мы изначально создавали как форму списка, а не форму выбора, нам придется принудительно оповестить вызывающую форму о том, что выбор завершен:

&НаКлиенте
Процедура ПеренестиВДокумент(Команда)
    Результат = Новый Структура;
    Результат.Вставить("Корзина", Корзина);
    ОповеститьОВыборе(Результат);
КонецПроцедуры

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

По нажатию на кнопку Подбор вызываем созданную форму и передаем параметры. Обращаю внимание на обязательную передачу в открываемую форму параметра ЭтаФорма (третий параметр в вызове формы, форма-владелец). Если этот параметр не передать, то событие ОбработкаПодбора() не возникнет в контесте формы вызывающего документа.

&НаКлиенте
Процедура Подбор(Команда)
    ДатаПодбора = ?(ЗначениеЗаполнено(Объект.Ссылка), Объект.Дата, '00010101');
    ПараметрыПодбора = Новый Структура;
    ПараметрыПодбора.Вставить("Дата", ДатаПодбора);
    ПараметрыПодбора.Вставить("ТипЦен", Объект.ТипЦен);
    ФормаВыбора = ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаПодбора", ПараметрыПодбора, ЭтаФорма);
КонецПроцедуры

  Ну и, собственно, то, ради чего все затевалось — разбираем «корзину» и добавляем новые строки в табличную часть Товары нашего документа. На всякий случай, не забываем, что Корзина у нас не настоящая ТЗ, а служебная коллекция ДанныеФормыКоллекция:

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

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

 

 Подбор в работе

Вот и все. Надеюсь, моя скромная заметка кому-то поможет побыстрее разобраться с динамическими списками и управляемыми формами.

34 Comments

  1. turboatom

    Спасибо, очень доступно и наглядно, побольше бы таких публикаций!

    Reply
  2. TrinitronOTV

    Огромное спасибо автору за данную публикацию о динамических списках. Очень пригодится для освоения платформы 8.2

    Reply
  3. a.terentev

    Как лучше делать возврат значений:

    1 вариант: В процедуре, которая открывает форму делать

    СтруктураВозврата = ОткрытьФормуМодально(«Справочник.Номенклатура.Форма.ФормаПодбора», ПараметрыПодбора, ЭтаФорма)

    и следующей строкой

    Если СтруктураВозврата <> Неопределено Тогда

    ……

    тут обработка возвращенных значений

    ……

    КонецЕсли;

    А в форме подбора делать

    Результат = Новый Структура;

    Результат.Вставить(«Корзина», Корзина);

    Закрыть(Результат);

    2 вариант, как у вас:

    ФормаВыбора = ОткрытьФорму(«Справочник.Номенклатура.Форма.ФормаПодбора», ПараметрыПодбора, ЭтаФорма)

    В форме подбора:

    Результат = Новый Структура;

    Результат.Вставить(«Корзина», Корзина);

    ОповеститьОВыборе(Результат);

    И потом в форме вызова:

    Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)

    ……

    тут обработка возвращенных значений

    ……

    КонецПроцедуры

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

    Reply
  4. viddik

    (3) Спасибо. Наверное, вариант 1 действительно попроще при анализе кода. Вообще, чем больше вариантов, тем лучше.

    Кстати, добавлю, что необязательно открывать форму подбора модально. Как вариант, может хватить установки свойства формы РежимОткрытияОкна в значение «Блокировать окно владельца». Тогда окно вызывающей формы будет недоступно до закрытия подбора, но можно будет работать в других формах.

    Reply
  5. a.terentev

    (4) ОткрытьФормуМодально() возвращает произвольное значение, которые передали в Закрыть(<ВозвращаемоеЗначение>). ОткрытьФорму() возвращает форму или управляемую форму. Поэтому вариант 1 работает только с ОткрытьФормуМодально(). В этом есть небольшой минус…

    Reply
  6. viddik

    (5) Вы правы. Вариант с модальной формой более «железобетонный». Вариант с Обработкой выбора выглядит гибче. Хорошо, когда есть выбор 🙂

    Reply
  7. nataon

    Спасибо автору )))

    Reply
  8. Andry.Boris

    Спасибо автору за статью…

    Reply
  9. Ksu

    Спасибо автору за интересную статью!

    Reply
  10. belochkaNN

    Очень доступно! +!

    Reply
  11. Aleskey_K

    Спасибо за статью!

    Reply
  12. kenza

    Спасибо! Долго правда мучился, никак остатки не хотели отображаться. В итоге переделал код запроса как в примере и все получилось, через конструктор запросов код запроса выходил почему то другой и поэтому не работал.

    Reply
  13. Agema

    Спасибо! полезная информация и статья.

    Reply
  14. candy_sk

    Очень полезная статья!!! спасибо тебе!

    Reply
  15. kenza

    Подскажите пожалуйста как можно организовать отображение остатков по разным складам. Т.е. например в столбце «остаток» видим остатки по фирме, а в нижней области идет что то вроде таблички со складами и остатками напротив них. Видел подобное на 8.1 «Управление торговлей». Больше нигде не встречалось. Может хотя бы как сделать, чтобы просто отображались остатки по определенному складу?

    Reply
  16. С.Беляков_Калининград

    Огромное спасибо за простоту и доступность изложения материала.

    Reply
  17. artspeed

    Отличная статья. Долго не понимал, как УФ открывать с предустановленными параметрами (отбором)

    Рекомендую.

    Reply
  18. cccp82

    спасибо за стать

    Reply
  19. rayastar

    Огромное спасибо. Научили работать с отборами

    Reply
  20. wowkai

    Спасибо. в статье нашел ответ на то что искал!

    Reply
  21. sergos3331

    Очень хорошая статья. Все подробно и четко расписано.

    Reply
  22. grrus

    Всё это конечно хорошо, отобрали показали, а вот кто может сказать как узнать количество найденных позиций в Динамическом списке, полученный через вид сравнения(Элемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит)?

    Reply
  23. user_2010

    (16) kenza, Тоже столкнулась с тем, что конструктором результат запроса отображался верно. А вот при открытии формы с этим запросом — данные вообще отсутствовали. В чем суть не поняла. В запросе было объединение справочника и РегСв.ДополнительныеСведения — для записей справочника. Нужно было показывать для выбора записи справочника с определенным значением дополнительного сведения.

    Получилось запустить только когда установила брать ВСЕ из таблицы справочника и добавила отбор по доп сведению на закладке Настройка.

    Если автор, или кто-то еще знает — в чем тут соль — объясните, плз!

    Автору спасибо — молодец! Полезно и доступно!

    Reply
  24. slawanix

    Приветствую.

    Сейчас как раз работаю над похожей задачей. Ну и как начинающий 1с программер, столкнулся с тем, что в параметр формы подбора «Дата» передается не интервал дат, а именно дата. На практике лично у меня это приводит к тому, что в отбор попадают записи из регистра накопления не только по этой дате, но и те, период у которых раньше этой даты. Т.е. если у меня в документе стоит 28 июня, то в отбор попадают записи по этому числу. Но если в документе установить 27 июня, то записи от 28 июня из регистра все равно попадают в отбор. Вопрос, как установить именно границы интервала. Чтобы в отбор попадали только записи в пределах текущих суток (ну или рабочей смены как вариант)? Я думаю, что и в запросе можно установить интервал дат. Тогад вообще не надо будет мутить тему с параметрами и упростит отладку. Надо вот только придумать, как именно это сделать) Не силен в этом, налету сделать не получится. Надо будет завтра подумать над этим…

    &НаКлиенте

    Процедура Подбор(Команда)

    ДатаПодбора = ?(ЗначениеЗаполнено(Объект.Ссылка), Объект.Дата, ‘00010101’);

    ПараметрыПодбора = Новый Структура;

    ПараметрыПодбора.Вставить(«Дата», ДатаПодбора);

    ПараметрыПодбора.Вставить(«ТипЦен», Объект.ТипЦен);

    ФормаВыбора = ОткрытьФорму(«Справочник.Номенклатура.Форма.ФормаПодбора», ПараметрыПодбора, ЭтаФорма);

    КонецПроцедуры
    Reply
  25. miralisssa

    А я вот не поняла как работает закладка отбор. У меня есть документ с полем Партнер. Добавила это поле в качестве отбора в закладке, указала использование, включить в пользовательские настройки и т. д. При обычной работе все норм, но я не могу понять, как мне передать значение в этот отбор при открытии списка.

    Как программно добавить элементы отбора, я знаю. Хочу сделать так, чтобы и пользователь видел настройки отбора с заполненным значением и мог потом изменить.

    Reply
  26. golod

    Спасибо за хорошую статью

    Reply
  27. stranger2014

    подскажите, плз, а можно как-то добавить строку в динамический список? что-то не могу найти ни одного метода для этого. пример для чего это нужно. в ут есть справочник видцен. в заказе можно на все позиции выбрать какой-нибудь вид цен. есть еще произвольный видцен, который является пустой ссылкой, так вот его на список строк не выбрать. хотелось бы его добавить в окне выбора видов цен отдельной строкой.

    Reply
  28. titilon

    Спасибо, очень доступно , побольше бы таких публикаций! Спасибо

    Reply
  29. baracuda

    1) А как будет правильно заполняться Цену и прочие реквизиты ТЧ.Товары в Документе в который переносятся товары из корзины?

    Заполнять эти данные в корзине и передавать все также структурой?

    2) При публикации базы на вебсервере если включить показывать количество выдается: «Использование модальных окон запрещено», возможно ли обойти как нибудь модальность?

    Reply
  30. baracuda

    (4) viddik, Модальность платформы можно обойти вот так

    
    &НаКлиенте
    Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    Если ЗапрашиватьКоличество Тогда
    ДобавитьКоличество = 0;
    Коэффициент = 1;
    Оповещение = Новый ОписаниеОповещения(«ДобавитьВПодборнаКлиенте», ЭтаФорма, ВыбраннаяСтрока);
    ПоказатьВводЧисла(Оповещение, Коэффициент, «Введите количество», 10, 2);
    
    // Если ВвестиЧисло(ДобавитьКоличество, «Введите количество единиц», 15, 3) Тогда
    //        ДобавитьВПодбор(ВыбраннаяСтрока, ДобавитьКоличество);
    //    КонецЕсли;
    Иначе
    ДобавитьВПодбор(1,ВыбраннаяСтрока);
    КонецЕсли;
    КонецПроцедуры
    
    &НаКлиенте
    Процедура ДобавитьВПодборнаКлиенте(Количество, ВыбраннаяСтрока)  Экспорт
    ДобавитьВПодбор(Количество, ВыбраннаяСтрока);
    КонецПроцедуры
    
    

    Показать

    Reply
  31. jobkostya1c8

    Тут пришлось экстренно к «старой» технологии вернуться с выгрузкой в таблицу значений на форме. Увы, нет объединений и еще кое-чего в произвольном запросе динамического списка.

    А минус такой, что в списке по F9 можно сразу скопировать по текущему. Да и вообще работа удобнее (и сама платформа во всем помогает в т.ч. окошком поиска по строке, отборами, настройками.

    Reply
  32. IrinaKostroma

    Спасибо!!! Побольше бы таких публикаций!!!

    Reply
  33. FLYka

    Подскажите, вылетает вот такая ошибка

    {Справочник.Номенклатура.Форма.ФормаСписка2.Форма(892,41)}: Переменная не определена (Объект)

    ПараметрыПодбора.Вставить(«ВидЦены»,<<?>>Объект.ВидыЦен); (Проверка: Тонкий клиент)

    Reply
  34. baracuda

    Топовая статья!0

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *