Как реализовать выбор только месяца и года на управляемой форме в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки прикладных решений на платформе 1С:Предприятие 8.3 часто возникает задача предоставить пользователю удобный интерфейс для выбора определенного месяца и года. По умолчанию стандартный календарь ориентирован на выбор конкретного числа (даты), что часто приводит к ошибкам ввода при ведении периодического учета (например, при начислении зарплаты, планировании бюджета или формировании ежемесячной отчетности). Пользователю приходится совершать лишние клики, а разработчику — писать код для принудительного приведения выбранной даты к началу месяца.

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

Способ №1. Использование стандартного реквизита типа "СтандартныйПериод"

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

Разберем этот процесс по шагам:

  1. Создадим реквизит формы (например, с именем ПериодРегистрации) и укажем для него тип данных СтандартныйПериод.
  2. Перетащим этот реквизит на рабочую область управляемой формы.
  3. В свойствах созданного элемента формы в поле Вид выберем значение Поле периода.

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

Способ №2. Использование механизмов БСП (для ЗУП, ERP, Комплексной автоматизации)

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

Давайте проанализируем, как внедрить это решение в свою форму:

Для реализации нам понадобятся два реквизита формы:

Выведем строковый реквизит ПериодПредставление на форму и настроим его свойства в панели свойств:

Теперь перейдем в модуль управляемой формы и свяжем элементы с логикой БСП. Нам понадобится обработать событие начала выбора текстового поля и событие создания формы на сервере для первоначального заполнения:


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

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

Этот метод гарантирует полное соответствие интерфейса вашей разработки общим стандартам конфигураций "1С:Совместимо" и не требует изобретения велосипедов.

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

Что делать, если мы ведем разработку в самописной конфигурации или на "пустой" базе, где нет библиотек БСП? Нам отлично подойдет решение с динамическим списком выбора и умной навигацией по годам непосредственно внутри выпадающего списка. Суть метода заключается в том, что при открытии списка выбора пользователю показываются 12 месяцев текущего года, а также две сервисные строки: "Предыдущий год" и "Следующий год". Если пользователь нажимает на год, список мгновенно перестраивается без закрытия меню.

Рассмотрим по шагам реализацию этого элегантного алгоритма:

Шаг 1. Создадим реквизит формы МесяцВыбораСтрока (тип Строка) и выведем его на форму. Настроим свойства элемента управления на форме:

Шаг 2. Нам потребуется вспомогательный реквизит формы для хранения текущего редактируемого года. Создадим реквизит формы ТекущийГодВыбора (тип Число, длина 4, без знака).

Шаг 3. В модуле формы опишем процедуру генерации списка месяцев для конкретного года:


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

Шаг 4. Напишем код инициализации при открытии формы на сервере и клиенте:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // По умолчанию устанавливаем текущий год
    ТекущийГодВыбора = Год(ТекущаяДата());
    
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    // Заполняем список выбора при старте работы с формой
    СформироватьСписокВыбораМесяцев(ТекущийГодВыбора);
    
КонецПроцедуры

Шаг 5. Теперь запрограммируем интерактивную обработку выбора элемента пользователем. Нам нужно отловить момент, когда пользователь нажимает на строку перехода к другому году, перестроить список выбора и принудительно открыть его снова:


&НаКлиенте
Процедура МесяцВыбораСтрокаОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    Если ВыбранноеЗначение = Неопределено Или ПустаяСтрока(ВыбранноеЗначение) Тогда
        Возврат;
    КонецЕсли;
    
    // Проверяем, выбрал ли пользователь навигационную строку года (длина строки года равна 4 символам)
    Если СтрДлина(СокрЛП(ВыбранноеЗначение)) = 4 Тогда
        
        // Меняем рабочий год и перестраиваем список
        ТекущийГодВыбора = Число(ВыбранноеЗначение);
        СформироватьСписокВыбораМесяцев(ТекущийГодВыбора);
        
        // Снова принудительно раскрываем список выбора для пользователя
        Оповещение = Новый ОписаниеОповещения("ПослеВыбораГодаИзСписка", ЭтотОбъект);
        ПоказатьВыборИзСписка(Оповещение, Элементы.МесяцВыбораСтрока.СписокВыбора, Элементы.МесяцВыбораСтрока);
        
    Иначе
        
        // Пользователь выбрал конкретный месяц конкретного года
        МесяцВыбораСтрока = ВыбранноеЗначение;
        
        // Выполним синтаксический разбор строки "Месяц Год" для получения реальной даты начала месяца
        ЧастиВыбора = СтрРазделить(ВыбранноеЗначение, " ");
        Если ЧастиВыбора.Количество() = 2 Тогда
            
            ВыбрГод = Число(ЧастиВыбора[1]);
            ИмяМесяца = НРег(Лев(ЧастиВыбора[0], 3)); // берем первые 3 буквы названия месяца
            
            // Находим порядковый номер месяца по его текстовому сокращению
            СтрокаПоиска = "янвфевмарапрмайиюниюлавгсеноктноядек";
            ИндексПоиска = Найти(СтрокаПоиска, ИмяМесяца);
            НомМесяца = (ИндексПоиска + 2) / 3;
            
            // Записываем дату (первый день выбранного месяца) в рабочий реквизит объекта/формы
            ТекущаяДатаМесяца = Дата(ВыбрГод, НомМесяца, 1);
            
            // Здесь вы можете присвоить дату вашему реквизиту объекта:
            // Объект.ПериодРегистрации = ТекущаяДатаМесяца;
            
        КонецЕсли;
        
    EndIf;
    
КонецПроцедуры

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

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

Способ №4. Ручной вызов диалога выбора периода БСП через описание оповещения

Если в вашей конфигурации присутствует базовая БСП, но вы не хотите усложнять форму дополнительными текстовыми реквизитами-представлениями, вы можете вызывать общую форму выбора периода программно напрямую при нажатии кнопки выбора у реквизита типа Дата.

Посмотрим на пример реализации данного подхода:


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

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

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

Способ №5. Тонкости настройки параметров выбора в отчетах СКД без программирования

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

Выполните следующие настройки на вкладке Параметры в СКД:

  1. Для параметра с типом Дата (например, ПериодОтчета) в колонке Выражение пропишите: НачалоПериода(&ПериодОтчета, "Месяц"). Это гарантирует, что даже если пользователь выберет произвольное число, система автоматически сдвинет его на первое число месяца при расчете запроса.
  2. В панели свойств параметра найдите поле Формат редактирования и задайте маску: ДФ='ММММ yyyy'. В этом случае платформа скроет отображение дней в поле ввода отчета, оставив только название месяца и год.

Таким образом, мы рассмотрели пять отличных способов организации выбора месяца и года в интерфейсе 1С. Выбирайте тот метод, который наилучшим образом подходит под архитектуру вашей конфигурации и требования конечных пользователей к удобству интерфейса.

← На главную