IE2017

Организация выбора месяца из списка

Программирование - Работа с интерфейсом

Пришлось столкнуться с такой проблемой, как выбор месяца из ниспадающего списка (с элементами вида "НазваниеМесяца Год") с возможностью изменения года. Хочу предложить вариант реализации данного механизма, может кому и пригодится)

Итак, мы имеем некий объект с реквизитом "Месяц" с типом "Строка", который находится у нас на управляемой форме, куда и будет вписываться название месяца и год. Прежде всего, при открытии формы необходимо сформировать список выбора (например, на текущий год):

&НаКлиенте
Процедура ПриОткрытии(Отказ)


    СформироватьСписокВыбораМесяца(Год(ТекущаяДата()));


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

Сама процедура формирования будет следующей:

Процедура СформироватьСписокВыбораМесяца(Год)
    
    Элементы.Месяц.СписокВыбора.Очистить();
    Элементы.Месяц.СписокВыбора.Добавить(Формат(Год-1, "ЧГ=0")); //для смены года
    Для к = 1 По 12  Цикл
        СформДата = Дата(Год, к, 1);
        Наим = Формат(СформДата, "ДФ = ММММ_гггг");
        Наим = СтрЗаменить(Наим, "_", " ");
        Элементы.Месяц.СписокВыбора.Добавить(Наим);    
    КонецЦикла;
    Элементы.Месяц.СписокВыбора.Добавить(Формат(Год+1, "ЧГ=0")); //для смены года
    

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

Далее организуем выбор из списка. Для этого нам понадобится событие нашего элемента "НачалоВыбораИзСписка":

&НаКлиенте
Процедура МесяцНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)


    Если Объект.Месяц  "" Тогда

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

            //выбрано значение, которое соответствует смене года в списке
            Пока СтрДлина(ВыбранноеЗначение) = 4 Цикл

                //цикл продолжается до тех пор, пока мы не выберем месяц
                ВыбрГод = Число(ВыбранноеЗначение);
                СформироватьСписокВыбораМесяца(ВыбрГод);
                ВыбранноеЗначение = Строка(ЭтаФорма.ВыбратьИзСписка(Элемент.СписокВыбора, Элемент));                    
            КонецЦикла;
        КонецЕсли;
        Если ВыбранноеЗначение  "" Тогда

             //выбрали месяц, а не пустое значение, запишем его

            //если выбрали пустое значение, то в реквизите месяц сохранится значение, которое было до выбора
            Объект.Месяц = ВыбранноеЗначение;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
  
    Если ЗначениеЗаполнено(Объект.КонецМесяца) Тогда
        Месяц = Формат(Объект.КонецМесяца, "ДФ = ММММ");

        //формируем список на год, соответствующий заполненному реквизиту

        СформироватьСписокВыбораМесяца(Год(Объект.КонецМесяца));
    Иначе
        Месяц = ""; 

        //формируем список на текущий год

        СформироватьСписокВыбораМесяца(Год(ТекущаяДата()));
    КонецЕсли;
    

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


Событие "НачалоВыбораИзСписка" изменяем так, чтобы заполнялся реквизит "КонецМесяца". Помним, что "Месяц" - реквизит формы, а не объекта, поэтому убираем перед ним "Объект." и заполняем реквизит "КонецМесяца":

&НаКлиенте
Процедура МесяцНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)


    Если Месяц  "" Тогда

        //реквизит уже заполнен, нужно формировать список для года, соответствующего заполнению
        ВыбрГод = Число(Прав(Месяц, 4));
        СформироватьСписокВыбораМесяца(ВыбрГод);
    КонецЕсли;
    
    СтандартнаяОбработка = Ложь;
    ВыбранноеЗначение = Строка(ЭтаФорма.ВыбратьИзСписка(Элемент.СписокВыбора, Элемент));
    Если ВыбранноеЗначение  "" Тогда
        Если СтрДлина(ВыбранноеЗначение)=4 Тогда

            //выбрано значение, которое соответствует смене года в списке
            Пока СтрДлина(ВыбранноеЗначение) = 4 Цикл

                //цикл продолжается до тех пор, пока мы не выберем месяц
                ВыбрГод = Число(ВыбранноеЗначение);
                СформироватьСписокВыбораМесяца(ВыбрГод);
                ВыбранноеЗначение = Строка(ЭтаФорма.ВыбратьИзСписка(Элемент.СписокВыбора, Элемент));                    
            КонецЦикла;
        КонецЕсли;
        Если ВыбранноеЗначение  "" Тогда

             //выбрали месяц, а не пустое значение, запишем его

            //если выбрали пустое значение, то в реквизите месяц сохранится значение, которое было до выбора
            Месяц = ВыбранноеЗначение;

            НомМесяца = (Найти("янвфевмарапрмайиюниюлавгсеноктноядек",Нрег(Лев(ВыбранноеЗначение,3)))+2)/3; //получаем номер месяца
            ВыбрГод = Число(Прав(ВыбранноеЗначение, 4));
            Объект.КонецМесяца = КонецМесяца(Дата(ВыбрГод, НомМесяца, 1));


        КонецЕсли;
    КонецЕсли;
КонецПроцедуры


Собственно вот и все) Вы также можете скачать обработку с примером: //infostart.ru/public/download.php?file=167551

Скачать файлы

Наименование Файл Версия Размер
Выбор месяца из списка (модальный режим)
.epf 6,56Kb
07.02.17
112
.epf 6,56Kb 112 Скачать
Выбор месяца из списка (немодальный режим)
.epf 6,96Kb
07.02.17
8
.epf 6,96Kb 8 Скачать

См. также

Комментарии
1. ghj ghjh (vipq7) 05.02.14 16:00 Сейчас в теме
Спасибо, удобная штука...
2. Алексей Харламов (RocKeR_13) 240 06.02.14 12:42 Сейчас в теме
(1) vipq7, рад, что пригодилось)
3. Александр Куклин (alexandr851c) 21 06.03.14 14:00 Сейчас в теме
Очень выручили. Огромное спасибо !!!
4. Алексей Харламов (RocKeR_13) 240 06.03.14 14:18 Сейчас в теме
(3) alexandr851c, честно говоря, когда публиковал, не думал, что многих заинтересует)) На здоровье)
5. Кирилл Бондаренко (karapuzzzz) 59 30.08.14 01:36 Сейчас в теме
Спасибо. Идея с переходом между годами мне понравилась. Реализовал у себя с адаптированием под обычное приложение.

Единственное замечание в том, что обычно за период принимают не конец месяца, а начало.
6. Алексей Харламов (RocKeR_13) 240 31.08.14 21:43 Сейчас в теме
(5) karapuzzzz, пожалуйста) ну как у вас не знаю, сколько ни делал доработок отчетов - везде нужен был именно конец месяца в качестве конца периода
7. Александр Синиченко (nytlenc) 86 03.09.15 08:27 Сейчас в теме
Спасибо! Респект. Очень пригодилось!
8. Алексей Харламов (RocKeR_13) 240 03.09.15 16:57 Сейчас в теме
(7) nytlenc, рад, что пригодилось! Успехов вам)
9. Денис Сытый (Orlanxxx) 38 17.02.16 17:03 Сейчас в теме
А при нажатии на строчку с годом ничего не должно происходить?
Я думал откроются месяца с предыдущим годом.
10. Михаил Кончаренко (Anchoret) 19 16.03.16 17:10 Сейчас в теме
Спасибо за пример, очень помог.

(9) Orlanxxx, происходит, если сделать все правильно.
Я в условиях сначала поставил равенство (=) и у меня тоже ничего не происходило при выборе года.
Изменил на (<>) и все в порядке стало.
11. Максим Кузнецов (Makushimo) 151 17.03.16 15:58 Сейчас в теме
Если выбрать год, потом еще раз год
то вылетает с ошибкой
надо в рекурсию заворачивать

однозначно плюс
12. Юрий (Yuriy.MW) 20 02.02.17 16:07 Сейчас в теме
Чуток подкорректировал процедуры.
Месяц - строка, реквизит формы
ПериодРегистрации - Дата, реквизит объекта

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	
	 Месяц = Формат(Объект.ПериодРегистрации, "ДФ='MMMM yyyy'");
	
КонецПроцедуры

&НаКлиенте
Процедура СформироватьСписокВыбораМесяца(Год)
    
    Элементы.Месяц.СписокВыбора.Очистить();
    Элементы.Месяц.СписокВыбора.Добавить(Дата(Год-1, 1, 1), Формат(Год-1, "ЧГ=0")); //для смены года
    Для к = 1 По 12  Цикл
        СформДата = Дата(Год, к, 1);
        Элементы.Месяц.СписокВыбора.Добавить(СформДата, Формат(СформДата, "ДФ='MMMM yyyy'"));    
    КонецЦикла;
    Элементы.Месяц.СписокВыбора.Добавить(Дата(Год+1, 1, 1), Формат(Год+1, "ЧГ=0")); //для смены года    

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

&НаКлиенте
Процедура МесяцНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)
	
	Если ЗначениеЗаполнено(Объект.ПериодРегистрации) Тогда
		текМесяц = Объект.ПериодРегистрации;
	Иначе
		текМесяц = ТекущаяДата();
	КонецЕсли;
	СформироватьСписокВыбораМесяца(Год(текМесяц));
	
	СтандартнаяОбработка = Ложь;
	ВыбранноеЗначение = ЭтаФорма.ВыбратьИзСписка(Элемент.СписокВыбора, Элемент, Элемент.СписокВыбора.НайтиПоЗначению(текМесяц));
	Пока ВыбранноеЗначение <> Неопределено И СтрДлина(ВыбранноеЗначение.Представление) = 4 Цикл
		//цикл продолжается до тех пор, пока мы не выберем месяц
		СформироватьСписокВыбораМесяца(Год(ВыбранноеЗначение.Значение));
		ВыбранноеЗначение = ЭтаФорма.ВыбратьИзСписка(Элемент.СписокВыбора, Элемент);                    
	КонецЦикла;
	
	Если ВыбранноеЗначение <> Неопределено Тогда
		Месяц = ВыбранноеЗначение.Представление;
		Объект.ПериодРегистрации = ВыбранноеЗначение.Значение;
	КонецЕсли;
	
КонецПроцедуры
...Показать Скрыть
13. Антон Гвоздикин (Ганс) 07.02.17 12:57 Сейчас в теме
УТ11.3 не работает что-то! ((
14. Алексей Харламов (RocKeR_13) 240 07.02.17 13:27 Сейчас в теме
(13) да теперь модальные окна запрещены, выложу позже исправленный вариант.
Примерный код реализации теперь будет такой:

&НаКлиенте
Процедура МесяцНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)
	
    СтандартнаяОбработка = Ложь;
	Если Месяц <> "" Тогда

        //реквизит уже заполнен, нужно формировать список для года, соответствующего заполнению
        ВыбрГод = Число(Прав(Месяц, 4));
        СформироватьСписокВыбораМесяца(ВыбрГод);
    КонецЕсли;
    
    СтандартнаяОбработка = Ложь;
    ВыбранноеЗначение = Строка(ЭтаФорма.ВыбратьИзСписка(Элемент.СписокВыбора, Элемент));
    Если ВыбранноеЗначение <> "" Тогда
        Если СтрДлина(ВыбранноеЗначение)=4 Тогда

            //выбрано значение, которое соответствует смене года в списке
            Пока СтрДлина(ВыбранноеЗначение) = 4 Цикл

                //цикл продолжается до тех пор, пока мы не выберем месяц
                ВыбрГод = Число(ВыбранноеЗначение);
                СформироватьСписокВыбораМесяца(ВыбрГод);
                ВыбранноеЗначение = Строка(ЭтаФорма.ВыбратьИзСписка(Элемент.СписокВыбора, Элемент));                    
            КонецЦикла;
        КонецЕсли;
        Если ВыбранноеЗначение <> "" Тогда

             //выбрали месяц, а не пустое значение, запишем его

            //если выбрали пустое значение, то в реквизите месяц сохранится значение, которое было до выбора
            Месяц = ВыбранноеЗначение;

            НомМесяца = (Найти("янвфевмарапрмайиюниюлавгсеноктноядек",Нрег(Лев(ВыбранноеЗначение,3)))+2)/3; //получаем номер месяца
            ВыбрГод = Число(Прав(ВыбранноеЗначение, 4));
            Объект.КонецМесяца = КонецМесяца(Дата(ВыбрГод, НомМесяца, 1));


        КонецЕсли;
    КонецЕсли;	
КонецПроцедуры

&НаКлиенте
Процедура МесяцНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	
    СтандартнаяОбработка = Ложь;
	Если Месяц <> "" Тогда

        //реквизит уже заполнен, нужно формировать список для года, соответствующего заполнению
        ВыбрГод = Число(Прав(Месяц, 4));
        СформироватьСписокВыбораМесяца(ВыбрГод);
    КонецЕсли;
    
	Оповещение = Новый ОписаниеОповещения("ПослеВыбораМесяцаИзСписка", ЭтотОбъект);
	ПоказатьВыборИзСписка(Оповещение, Элементы.Месяц.СписокВыбора, Элементы.Месяц);
	
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораМесяцаИзСписка(Результат, ДП) Экспорт
	
	ВыбранноеЗначение = Результат.Значение;
	
    Если ВыбранноеЗначение <> "" Тогда
        Если СтрДлина(ВыбранноеЗначение)=4 Тогда

            //выбрано значение, которое соответствует смене года в списке
			//Пока СтрДлина(ВыбранноеЗначение) = 4 Цикл

                //цикл продолжается до тех пор, пока мы не выберем месяц
                ВыбрГод = Число(ВыбранноеЗначение);
                СформироватьСписокВыбораМесяца(ВыбрГод);
				Оповещение = Новый ОписаниеОповещения("ПослеВыбораМесяцаИзСписка", ЭтотОбъект);
				ПоказатьВыборИзСписка(Оповещение, Элементы.Месяц.СписокВыбора, Элементы.Месяц);
				Возврат;
			//КонецЦикла;
        ИначеЕсли ВыбранноеЗначение <> "" Тогда

             //выбрали месяц, а не пустое значение, запишем его

            //если выбрали пустое значение, то в реквизите месяц сохранится значение, которое было до выбора
            Месяц = ВыбранноеЗначение;

            НомМесяца = (Найти("янвфевмарапрмайиюниюлавгсеноктноядек",Нрег(Лев(ВыбранноеЗначение,3)))+2)/3; //получаем номер месяца
            ВыбрГод = Число(Прав(ВыбранноеЗначение, 4));
            Объект.КонецМесяца = КонецМесяца(Дата(ВыбрГод, НомМесяца, 1));


        КонецЕсли;
    КонецЕсли;		
	
КонецПроцедуры

Процедура СформироватьСписокВыбораМесяца(Год)
	
	Элементы.Месяц.СписокВыбора.Очистить();
	Элементы.Месяц.СписокВыбора.Добавить(Формат(Год-1, "ЧГ=0"));
	Для к = 1 По 12  Цикл
		СформДата = Дата(Год, к, 1);
		Наим = Формат(СформДата, "ДФ = ММММ_гггг");
		Наим = СтрЗаменить(Наим, "_", " ");
		Элементы.Месяц.СписокВыбора.Добавить(Наим);	
	КонецЦикла; 
	Элементы.Месяц.СписокВыбора.Добавить(Формат(Год+1, "ЧГ=0"));
	

КонецПроцедуры
...Показать Скрыть


И при открытии:
    Если ЗначениеЗаполнено(Объект.КонецМесяца) Тогда
        Месяц = Формат(Объект.КонецМесяца, "ДФ = ММММ");

        //формируем список на год, соответствующий заполненному реквизиту

        СформироватьСписокВыбораМесяца(Год(Объект.КонецМесяца));
    Иначе
        Месяц = ""; 

        //формируем список на текущий год

        СформироватьСписокВыбораМесяца(Год(ТекущаяДата()));
    КонецЕсли;
...Показать Скрыть
15. vn agapov (vnagapov) 28.06.17 10:38 Сейчас в теме
Я думаю, что так еще проще

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	Месяц = Формат(Объект.ПериодРегистрации, "ДФ='MMMM yyyy'");
	СформироватьСписокВыбораМесяца(Год(Объект.ПериодРегистрации));
КонецПроцедуры

Процедура СформироватьСписокВыбораМесяца(Год)
    
    Элементы.Месяц.СписокВыбора.Очистить();
    Элементы.Месяц.СписокВыбора.Добавить(Формат(Год-1, "ЧГ=0"));
    Для к = 1 По 12  Цикл
        СформДата = Дата(Год, к, 1);
        Наим = Формат(СформДата, "ДФ = ММММ_гггг");
        Наим = СтрЗаменить(Наим, "_", " ");
        Элементы.Месяц.СписокВыбора.Добавить(Наим);    
    КонецЦикла; 
    Элементы.Месяц.СписокВыбора.Добавить(Формат(Год+1, "ЧГ=0"));
КонецПроцедуры


&НаКлиенте
Процедура МесяцПриИзменении(Элемент)
	Если Месяц <> "" Тогда
		Если СтрДлина(Месяц)=4 Тогда 
			СформироватьСписокВыбораМесяца(Число(Месяц));
			Объект.ПериодРегистрации = НачалоМесяца(Дата(Число(Месяц), 1, 1));
			Месяц = Формат(Объект.ПериодРегистрации, "ДФ='MMMM yyyy'");
		Иначе
			НомМесяца = (Найти("янвфевмарапрмайиюниюлавгсеноктноядек",Нрег(Лев(Месяц,3)))+2)/3; //получаем номер месяца
			ВыбрГод = Число(Прав(Месяц, 4));
			Объект.ПериодРегистрации = НачалоМесяца(Дата(ВыбрГод, НомМесяца, 1));
		КонецЕсли;	
	КонецЕсли;
КонецПроцедуры
...Показать Скрыть
Оставьте свое сообщение