Полезности при работе с динамическими списками

27.03.19

Разработка - Механизмы платформы 1С

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

Постараюсь построить повествование в виде: реализация решений вопросов по ходу разработки. 

Иногда мы сталкиваемся с необходимостью использовать динамические списки, лично я их стараюсь использовать по возможности и намедни столкнулся с такой задачей: 

У нас есть форма с динамическим списком, куда подтягиваются запросом документы нескольких типов (видов ведомостей, не суть) за все года. Пускай их сейчас не так уж и много, период эксплуатации программы у нас пока небольшой, но через пару лет список пополнится парой сотен-тысяч документов и искать вручную уже будет не удобно от слова очень. Я решил, что неплохо было бы перед вызовом формы задать период, который я потом смогу передать в этот динамический список и тем самым произведу нужный мне отбор. 

Далее встал вопрос реализации:

1) Штудируя синтаксис-помощник и саму конфигурацию я наткнулся на такую функцию:

//// Необходимая функция

Новый ДиалогРедактированияСтандартногоПериода()

//// Что нам говорит СП


ДиалогРедактированияСтандартногоПериода (StandardPeriodEditDialog)
Свойства:
Период (Period)
Методы:
Показать (Show)
Редактировать (Edit)   ///Как раз то, что нам нужно для интерактивной работы на клиенте
Конструкторы:
По умолчанию
Описание:
Предназначен для интерактивного редактирования объекта СтандартныйПериод.
Доступность:
Тонкий клиент, веб-клиент, мобильный клиент, толстый клиент, внешнее соединение, мобильное приложение(клиент).

//// Синтаксис-помощник засыпает, просыпаются программисты

 

Добавляем кнопку на форму (которую в последствии будем использовать для открытия другой формы с динамическим списком), далее её функционал:

&НаКлиенте
Процедура ОткрытьСписокПодбора(Команда)
	Диалог = Новый ДиалогРедактированияСтандартногоПериода(); 
	Диалог.Период = Новый СтандартныйПериод(Объект.ДатаН, Объект.ДатаК); //Указываем, что дата начала и дата конца стандартного периода будут с пустыми значениями
	Диалог.Показать(Новый ОписаниеОповещения("ВыборПериодаЗавершение", ЭтотОбъект, Новый Структура("Диалог", Диалог))); //Вызываем форму подбора периода
КонецПроцедуры

Объект.ДатаН и Объект.ДатаК - реквизиты внешней обработки, в которых будут хранится значения, полученные с формы подбора периода. 

При обработке данной команды появляется следующая форма (так хорошо знакомая нам и наиболее встречающаяся в отчётах)

Здесь каких только вариантов нет, поэтому считаю этот вариант наиболее удобным в применении. 

Добавим ещё одну функцию, чтобы обработать наш выбор:

&НаКлиенте
Процедура ВыборПериодаЗавершение(Период, ДополнительныеПараметры) Экспорт

    Диалог = ДополнительныеПараметры.Диалог;
    ДатаНачала = Дата("20130724"); //Зададим дату, чтобы подстраховаться, вдруг пользователь не выберет ничего  
                                   //(это примерная дата ,когда документов ещё никаких не было, что бы отобразить весь список)  
     
    Если ЗначениеЗаполнено(Период) Тогда //Проверяем, заданы ли даты начала и конца, для отбора 
        Объект.ДатаН = Период.ДатаНачала; // Присваиваем значения
		Объект.ДатаК = Период.ДатаОкончания; //		
    Иначе
		Объект.ДатаН = ДатаНачала;  
        Объект.ДатаК = КонецДня(ТекущаяДата());
	КонецЕсли;

	ПараметрыФормы = Новый Структура("ДатаН, ДатаК", Объект.ДатаН,Объект.ДатаК); //заполняем структуру передаваемых параметров
	Форма = ОткрытьФорму("ВнешняяОбработка.Обработка.Форма.ФормаСпискаДокументов",ПараметрыФормы,ЭтаФорма); // Открываем форму с передачей параметров, которые используем при создании на сервере

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

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

 

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

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

Следующий вопрос, который появился при разработке:

А как из открытой формы мне передать выбранные данные из динамического списка обратно, на форму родителя?  

Ответ пришёл как всегда из нашего любимого и всеми уважаемого СП:

ОповеститьОВыборе (NotifyChoice)
Синтаксис:
ОповеститьОВыборе(<ЗначениеВыбора>) 
Параметры:
<ЗначениеВыбора> (обязательный)
Тип: Произвольный. 
Результат выбора. 
Описание:
Посылает оповещение владельцу формы о выполнении выбора или подбора, передает ему выбранное значение. Закрывает форму в соответствии со значением свойства ЗакрыватьПриВыборе. Данное действие аналогично выполнению выбора в форме, открытой для выбора в поле ввода или ячейке табличного поля.
Доступность: 
Тонкий клиент, веб-клиент, мобильный клиент, толстый клиент, мобильное приложение(клиент). 
Примечание:
Может применяться в случае, когда открытие формы выбора или подбора выполнено средствами языка

Добавим соответствующую кнопочку "Отправить данные" и опишем её

&НаКлиенте
Процедура ОтправитьДокументы(Команда)
	
Данные = Элементы.СписокДокументов.ВыделенныеСтроки; //ловим выделенные строки
СписокДляОтправки = Новый Массив;	
	
Для Каждого Строка из Данные Цикл 
	СписокДляОтправки.Добавить(Элементы.СписокДокументов.ДанныеСтроки(Строка).Ссылка); // записываем данные выбора в массив
КонецЦикла;

ОповеститьОВыборе(СписокДляОтправки); //

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

// а на клиенте в модуле формы-родителя уже добавляем такую процедурку 

&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
	
	ЗаполнитьТаблицу(ВыбранноеЗначение); // вызывается функция заполнения ТЧ формы-родителя
	
КонецПроцедуры

Фукнция ЗаполнитьТаблицу (ДанныеДляЗаполнения)
    
    Для Каждого Стр Из ДанныеДляЗаполнения
        НоваяСтрока = НашаОбработка.ТаблицаНаФорме.Добавить();  //Добавляем новую строку
        ЗаполнитьЗначенияСвойств(НоваяСтрока, Стр); // заполняем новую строку данными
    КонецЦикла;

КонецФункции

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

Тогда добавим следующий функционал:

//После выбора периода допишем вызов функции

Функция ЗаписатьВыгруженные()

Таб = НашаОбработка.ТаблицаНаФорме.Выгрузить();	// Выгружаем ТЧ в переменную
Таб.Свернуть("Документ"); //Избавляемся от дублей, если таковые имеются
Объект.Адрес = ПоместитьВоВременноеХранилище(Таб.ВыгрузитьКолонку("Документ"),ЭтаФорма.УникальныйИдентификатор); //Помещаем информацию во временное хранилище

КонецФункции

//Временное хранилище будет доступно, пока открыта форма-родитель, перезапись будет осуществляться после каждого нового открытия формы-подбора

Дописав функцию, где мы передаём параметры периода, включив в неё адрес временного хранилища, можем уже исключить при создании на сервере ненужные уже нам документы. 

//Модификация записи во временное хранилище заключается в том, что мы во-первых, избавляемся от повторяющихся. 
//Во-вторых, если тч была ошибочно очищена, мы не запишем пустую таблицу и не заменим ею ту, где у нас хранятся данные 
Функция ЗаписатьВыгруженные()
		
	    Таб = Объект.ТаблицаНаФорме.Выгрузить();	
		Таб.Свернуть("Документ");
		Массив = Таб.ВыгрузитьКолонку("Документ");
		Если ЗначениеЗаполнено(Объект.Адрес) Тогда
		    МассивДляСверки = ПолучитьИзВременногоХранилища(Объект.Адрес);
			МассивДляСверки = ПроверкаПовторяющихся(Массив, МассивДляСверки);
			Объект.Адрес = ПоместитьВоВременноеХранилище(МассивДляСверки,ЭтаФорма.УникальныйИдентификатор);
		Иначе
			Объект.Адрес = ПоместитьВоВременноеХранилище(Массив,ЭтаФорма.УникальныйИдентификатор);
		КонецЕсли;
		
КонецФункции

//Не бросайтесь камнями в меня :), не эталонное сравнение, знаю 
Функция ПроверкаПовторяющихся(Массив1, Массив2)
	
	Для Каждого Стр Из Массив1 Цикл
		Если Массив2.Найти(Стр)=Неопределено Тогда
			Массив2.Добавить(Стр);
		КонецЕсли;
	КонецЦикла;
	Возврат Массив2
	
КонецФункции

//Заменим 2 последние строки в функции ВыборПериодаЗавершение()
&НаКлиенте
Процедура ВыборПериодаЗавершение(Период, ДополнительныеПараметры) Экспорт

    Диалог = ДополнительныеПараметры.Диалог;
    ДатаНачала = Дата("20130724"); //Зададим дату, чтобы подстраховаться, вдруг пользователь не выберет ничего  
                                   //(это примерная дата ,когда документов ещё никаких не было, что бы отобразить весь список)  
     
    Если ЗначениеЗаполнено(Период) Тогда //Проверяем, заданы ли даты начала и конца, для отбора 
        Объект.ДатаН = Период.ДатаНачала; // Присваиваем значения
		Объект.ДатаК = Период.ДатаОкончания; //		
    Иначе
		Объект.ДатаН = ДатаНачала;  
        Объект.ДатаК = КонецДня(ТекущаяДата());
	КонецЕсли;

	ПараметрыФормы = Новый Структура("ДатаН, ДатаК, Адрес", Объект.ДатаН,Объект.ДатаК, Объект.Адрес);
Форма = ОткрытьФорму("НашаОбработка.ТаблицаНаФорме.Форма.ФормаСпискаДокументов",ПараметрыФормы,ЭтаФорма);

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

//

 

А в модуле формы-приёмника изменим Процедуру "ПриСозданииНаСервере" дописав:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	СписокДокументов.Параметры.УстановитьЗначениеПараметра("ДатаН", Параметры.ДатаН);
	СписокДокументов.Параметры.УстановитьЗначениеПараметра("ДатаК",  Параметры.ДатаК);
	//Получаем массив из хранилища
    Попытка
		МассивИзХранилища = ПолучитьИзВременногоХранилища(Параметры.Адрес);
	Исключение
	    Сообщить("Ошибка получения данных из хранилища!",СтатусСообщения.Важное);
	КонецПопытки;
    //Проверяем заполнение его
	Если МассивИзХранилища.Количество() = 0 Тогда
		СписокДокументов.Параметры.УстановитьЗначениеПараметра("Ссылка", Документы.МоиДокументы.ПустаяСсылка());   
	Иначе
		СписокДокументов.Параметры.УстановитьЗначениеПараметра("Ссылка",МассивИзХранилища);   
	КонецЕсли;
	
КонецПроцедуры

 

Тестировалось всё на платформе 8.3.13.1513

Всем спасибо за уделённое время.

Надеюсь, что информация окажется Вам полезной.  

Списки ДинамическийСписок Dev

См. также

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.

23.06.2024    7451    bayselonarrend    20    

154

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пример использования «Сервисов интеграции» без подключения к Шине и без обменов.

13.03.2024    5943    dsdred    16    

80

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Бесплатно (free)

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

24.01.2024    17672    YA_418728146    26    

71

Перенос данных 1C Механизмы платформы 1С Системный администратор Программист Стажер Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    11224    dsdred    44    

130

Механизмы платформы 1С Программист Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    23761    SeiOkami    48    

135

Механизмы платформы 1С Системный администратор Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    18831    human_new    27    

80

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    14732    YA_418728146    7    

166
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. andryandry 100 28.03.19 10:30 Сейчас в теме
а что мешает через параметры формы передать все не использую хранилище?
3. nestokay 62 28.03.19 11:35 Сейчас в теме
(1) Можно и параметром конечно, Вы правы, если объём данных будет небольшой.
2. user1011897 28.03.19 10:40 Сейчас в теме
Все, конечно, круто! Но где здесь полезности? При всем уважении к автору, я бы назвал все это "стандартности". Но кому-то это будет, конечно полезно прочитать.
WellMaster; dabu-dabu; nestokay; mbalyukin; insurgut; bulpi; noprogrammer; Дмитрий74Чел; qwinter; mr.Kot; Xershi; mvxyz; cefew; for_sale; androgin; maksa2005; +16 Ответить
7. Дмитрий74Чел 239 29.03.19 10:12 Сейчас в теме
(2) Очередная (какая там по счету) копипаста синтаксис-помощника. Ну ладно, хоть пара примеров своего кода есть.
Вот на хабре есть "песочница". Как раз для совсем юных подаванов статья.
4. androgin 28.03.19 13:22 Сейчас в теме
выбор периода - вообще стандартная функция дин списков)
5. nestokay 62 28.03.19 13:37 Сейчас в теме
(4) Не мне Вам рассказывать, как пользователи не любят изучать состав вкладки "Ещё" и т.д. :) а так, конечно, отбор по дате там организовать ручками можно. Здесь идёт установка более привычная и удобная для конечного пользователя на мой взгляд.
6. androgin 28.03.19 20:25 Сейчас в теме
(5) если пользователь что-то не любит - он всегда может вернуться к журналам на столе. Это не значит, что нужна дублирующая функция. Вам, как программисту, ничего не мешает вынести кнопку периода на видное место.
insurgut; +1 Ответить
8. bulpi 217 29.03.19 15:49 Сейчас в теме
Замечание:
Не стоит называть переменную СписокДляОтправки и помещать туда не список, а массив.
9. nestokay 62 29.03.19 15:56 Сейчас в теме
(8) Спасибо за замечание. Буду внимательнее.
10. ixijixi 1913 02.08.21 09:19 Сейчас в теме
Данные = Элементы.СписокДокументов.ВыделенныеСтроки; //ловим выделенные строки
СписокДляОтправки = Новый Массив;	
	
Для Каждого Строка из Данные Цикл 
	СписокДляОтправки.Добавить(Элементы.СписокДокументов.ДанныеСтроки(Строка).Ссылка); // записываем данные выбора в массив
КонецЦикла;


ВыделенныеСтроки динамического списка УЖЕ содержит массив ссылок, зачем повторно его перегонять в другой массив?
Прикрепленные файлы:
11. Yashazz 4790 18.08.21 15:24 Сейчас в теме
(10) Далеко не всегда. Это если основная таблица указана, и вид ключа "Авто", тогда да. И если мы говорим о дин.списке, работающем со ссылками. А если это, например, ключи регистров сведений, или иные виды ключа, или если просто группировка попала в выделенное, то вовсе даже и не будет ссылок. И потребуется именно обход выделенных.
12. ixijixi 1913 22.08.21 16:44 Сейчас в теме
(11) Разговор про конкретный случай
Элементы.СписокДокументов.ДанныеСтроки(Строка).Ссылка
13. Yashazz 4790 22.08.21 22:38 Сейчас в теме
Оставьте свое сообщение