Постараюсь построить повествование в виде: реализация решений вопросов по ходу разработки.
Иногда мы сталкиваемся с необходимостью использовать динамические списки, лично я их стараюсь использовать по возможности и намедни столкнулся с такой задачей:
У нас есть форма с динамическим списком, куда подтягиваются запросом документы нескольких типов (видов ведомостей, не суть) за все года. Пускай их сейчас не так уж и много, период эксплуатации программы у нас пока небольшой, но через пару лет список пополнится парой сотен-тысяч документов и искать вручную уже будет не удобно от слова очень. Я решил, что неплохо было бы перед вызовом формы задать период, который я потом смогу передать в этот динамический список и тем самым произведу нужный мне отбор.
Далее встал вопрос реализации:
1) Штудируя синтаксис-помощник и саму конфигурацию я наткнулся на такую функцию:
//// Необходимая функция
Новый ДиалогРедактированияСтандартногоПериода()
//// Что нам говорит СП
ДиалогРедактированияСтандартногоПериода (StandardPeriodEditDialog)
Свойства:
Период (Period)
Методы:
Показать (Show)
Редактировать (Edit) ///Как раз то, что нам нужно для интерактивной работы на клиенте
Конструкторы:
По умолчанию
Описание:
Предназначен для интерактивного редактирования объекта СтандартныйПериод.
Доступность:
Тонкий клиент, веб-клиент, мобильный клиент, толстый клиент, внешнее соединение, мобильное приложение(клиент).
//// Синтаксис-помощник засыпает, просыпаются программисты
Добавляем кнопку на форму (которую в последствии будем использовать для открытия другой формы с динамическим списком), далее её функционал:
&НаКлиенте
Процедура ОткрытьСписокПодбора(Команда)
Диалог = Новый ДиалогРедактированияСтандартногоПериода();
Диалог.Период = Новый СтандартныйПериод(Объект.ДатаН, Объект.ДатаК); //Указываем, что дата начала и дата конца стандартного периода будут с пустыми значениями
Диалог.Показать(Новый ОписаниеОповещения("ВыборПериодаЗавершение", ЭтотОбъект, Новый Структура("Диалог", Диалог))); //Вызываем форму подбора периода
КонецПроцедуры
Объект.ДатаН и Объект.ДатаК - реквизиты внешней обработки, в которых будут хранится значения, полученные с формы подбора периода.
При обработке данной команды появляется следующая форма (так хорошо знакомая нам и наиболее встречающаяся в отчётах)
Здесь каких только вариантов нет, поэтому считаю этот вариант наиболее удобным в применении.
Добавим ещё одну функцию, чтобы обработать наш выбор:
&НаКлиенте
Процедура ВыборПериодаЗавершение(Период, ДополнительныеПараметры) Экспорт
Диалог = ДополнительныеПараметры.Диалог;
ДатаНачала = Дата("20130724"); //Зададим дату, чтобы подстраховаться, вдруг пользователь не выберет ничего
//(это примерная дата ,когда документов ещё никаких не было, что бы отобразить весь список)
Если ЗначениеЗаполнено(Период) Тогда //Проверяем, заданы ли даты начала и конца, для отбора
Объект.ДатаН = Период.ДатаНачала; // Присваиваем значения
Объект.ДатаК = Период.ДатаОкончания; //
Иначе
Объект.ДатаН = ДатаНачала;
Объект.ДатаК = КонецДня(ТекущаяДата());
КонецЕсли;
ПараметрыФормы = Новый Структура("ДатаН, ДатаК", Объект.ДатаН,Объект.ДатаК); //заполняем структуру передаваемых параметров
Форма = ОткрытьФорму("ВнешняяОбработка.Обработка.Форма.ФормаСпискаДокументов",ПараметрыФормы,ЭтаФорма); // Открываем форму с передачей параметров, которые используем при создании на сервере
КонецПроцедуры
В модуле второй формы-приемника параметров, пропишем следующую функцию "ПриСозданииНаСервере" (используется сервером при создании формы) - это стандартная процедура, в ней мы будем описывать присвоение параметров в динамический список.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
СписокДокументов.Параметры.УстановитьЗначениеПараметра("ДатаН", Параметры.ДатаН);
СписокДокументов.Параметры.УстановитьЗначениеПараметра("ДатаК", Параметры.ДатаК);
КонецПроцедуры
Готово. Теперь данные появляются в разрезе указанного периода, который мы интерактивно выбрали и передали.
Следующий вопрос, который появился при разработке:
А как из открытой формы мне передать выбранные данные из динамического списка обратно, на форму родителя?
Ответ пришёл как всегда из нашего любимого и всеми уважаемого СП:
ОповеститьОВыборе (NotifyChoice)
Синтаксис:
ОповеститьОВыборе(<ЗначениеВыбора>)
Параметры:
<ЗначениеВыбора> (обязательный)
Тип: Произвольный.
Результат выбора.
Описание:
Посылает оповещение владельцу формы о выполнении выбора или подбора, передает ему выбранное значение. Закрывает форму в соответствии со значением свойства ЗакрыватьПриВыборе. Данное действие аналогично выполнению выбора в форме, открытой для выбора в поле ввода или ячейке табличного поля.
Доступность:
Тонкий клиент, веб-клиент, мобильный клиент, толстый клиент, мобильное приложение(клиент).
Примечание:
Может применяться в случае, когда открытие формы выбора или подбора выполнено средствами языка
Добавим соответствующую кнопочку "Отправить данные" и опишем её
&НаКлиенте
Процедура ОтправитьДокументы(Команда)
Данные = Элементы.СписокДокументов.ВыделенныеСтроки; //ловим выделенные строки
СписокДляОтправки = Новый Массив;
Для Каждого Строка из Данные Цикл
СписокДляОтправки.Добавить(Элементы.СписокДокументов.ДанныеСтроки(Строка).Ссылка); // записываем данные выбора в массив
КонецЦикла;
ОповеститьОВыборе(СписокДляОтправки); //
КонецПроцедуры
// а на клиенте в модуле формы-родителя уже добавляем такую процедурку
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
ЗаполнитьТаблицу(ВыбранноеЗначение); // вызывается функция заполнения ТЧ формы-родителя
КонецПроцедуры
Фукнция ЗаполнитьТаблицу (ДанныеДляЗаполнения)
Для Каждого Стр Из ДанныеДляЗаполнения
НоваяСтрока = НашаОбработка.ТаблицаНаФорме.Добавить(); //Добавляем новую строку
ЗаполнитьЗначенияСвойств(НоваяСтрока, Стр); // заполняем новую строку данными
КонецЦикла;
КонецФункции
Возвращаясь к отборам в динамических списках, при выполнении задач, приходит на ум идея, а вдруг пользователь не все документы перенёс с первого раза и ему вдруг захотелось снова открыть форму подбора. Что это может значить? Необходимо теперь исключить из выводимого списка перенесённые документы, зачем ему видеть снова те документы, убрав тем самым возможность дублирования строк. Как один из вариантов, это доработать произвольный запрос в динамическом списке условиями и передать туда соответствующий параметр типа "Массив". В нём будет содержаться список уже выгруженных документов.
Тогда добавим следующий функционал:
//После выбора периода допишем вызов функции
Функция ЗаписатьВыгруженные()
Таб = НашаОбработка.ТаблицаНаФорме.Выгрузить(); // Выгружаем ТЧ в переменную
Таб.Свернуть("Документ"); //Избавляемся от дублей, если таковые имеются
Объект.Адрес = ПоместитьВоВременноеХранилище(Таб.ВыгрузитьКолонку("Документ"),ЭтаФорма.УникальныйИдентификатор); //Помещаем информацию во временное хранилище
КонецФункции
//Временное хранилище будет доступно, пока открыта форма-родитель, перезапись будет осуществляться после каждого нового открытия формы-подбора
Дописав функцию, где мы передаём параметры периода, включив в неё адрес временного хранилища, можем уже исключить при создании на сервере ненужные уже нам документы.
//Модификация записи во временное хранилище заключается в том, что мы во-первых, избавляемся от повторяющихся.
//Во-вторых, если тч была ошибочно очищена, мы не запишем пустую таблицу и не заменим ею ту, где у нас хранятся данные
Функция ЗаписатьВыгруженные()
Таб = Объект.ТаблицаНаФорме.Выгрузить();
Таб.Свернуть("Документ");
Массив = Таб.ВыгрузитьКолонку("Документ");
Если ЗначениеЗаполнено(Объект.Адрес) Тогда
МассивДляСверки = ПолучитьИзВременногоХранилища(Объект.Адрес);
МассивДляСверки = ПроверкаПовторяющихся(Массив, МассивДляСверки);
Объект.Адрес = ПоместитьВоВременноеХранилище(МассивДляСверки,ЭтаФорма.УникальныйИдентификатор);
Иначе
Объект.Адрес = ПоместитьВоВременноеХранилище(Массив,ЭтаФорма.УникальныйИдентификатор);
КонецЕсли;
КонецФункции
//Не бросайтесь камнями в меня :), не эталонное сравнение, знаю
Функция ПроверкаПовторяющихся(Массив1, Массив2)
Для Каждого Стр Из Массив1 Цикл
Если Массив2.Найти(Стр)=Неопределено Тогда
Массив2.Добавить(Стр);
КонецЕсли;
КонецЦикла;
Возврат Массив2
КонецФункции
//Заменим 2 последние строки в функции ВыборПериодаЗавершение()
&НаКлиенте
Процедура ВыборПериодаЗавершение(Период, ДополнительныеПараметры) Экспорт
Диалог = ДополнительныеПараметры.Диалог;
ДатаНачала = Дата("20130724"); //Зададим дату, чтобы подстраховаться, вдруг пользователь не выберет ничего
//(это примерная дата ,когда документов ещё никаких не было, что бы отобразить весь список)
Если ЗначениеЗаполнено(Период) Тогда //Проверяем, заданы ли даты начала и конца, для отбора
Объект.ДатаН = Период.ДатаНачала; // Присваиваем значения
Объект.ДатаК = Период.ДатаОкончания; //
Иначе
Объект.ДатаН = ДатаНачала;
Объект.ДатаК = КонецДня(ТекущаяДата());
КонецЕсли;
ПараметрыФормы = Новый Структура("ДатаН, ДатаК, Адрес", Объект.ДатаН,Объект.ДатаК, Объект.Адрес);
Форма = ОткрытьФорму("НашаОбработка.ТаблицаНаФорме.Форма.ФормаСпискаДокументов",ПараметрыФормы,ЭтаФорма);
КонецПроцедуры
//
А в модуле формы-приёмника изменим Процедуру "ПриСозданииНаСервере" дописав:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
СписокДокументов.Параметры.УстановитьЗначениеПараметра("ДатаН", Параметры.ДатаН);
СписокДокументов.Параметры.УстановитьЗначениеПараметра("ДатаК", Параметры.ДатаК);
//Получаем массив из хранилища
Попытка
МассивИзХранилища = ПолучитьИзВременногоХранилища(Параметры.Адрес);
Исключение
Сообщить("Ошибка получения данных из хранилища!",СтатусСообщения.Важное);
КонецПопытки;
//Проверяем заполнение его
Если МассивИзХранилища.Количество() = 0 Тогда
СписокДокументов.Параметры.УстановитьЗначениеПараметра("Ссылка", Документы.МоиДокументы.ПустаяСсылка());
Иначе
СписокДокументов.Параметры.УстановитьЗначениеПараметра("Ссылка",МассивИзХранилища);
КонецЕсли;
КонецПроцедуры
Тестировалось всё на платформе 8.3.13.1513
Всем спасибо за уделённое время.
Надеюсь, что информация окажется Вам полезной.