В процессе разработки прикладных решений на платформе 1С:Предприятие 8.3 часто возникает задача предоставить пользователю удобный интерфейс для выбора определенного месяца и года. По умолчанию стандартный календарь ориентирован на выбор конкретного числа (даты), что часто приводит к ошибкам ввода при ведении периодического учета (например, при начислении зарплаты, планировании бюджета или формировании ежемесячной отчетности). Пользователю приходится совершать лишние клики, а разработчику — писать код для принудительного приведения выбранной даты к началу месяца.
В рамках данной статьи мы подробно рассмотрим, как решить эту задачу изящно и профессионально. Мы разберем четыре различных сценария реализации: от простейшего стандартного механизма платформы до динамических выпадающих списков и интеграции со стандартными библиотеками (БСП).
Если перед нами стоит задача выбрать период в рамках месяца (или просто указать рабочий месяц), самым быстрым решением без написания сложного программного кода будет использование стандартного платформенного типа данных СтандартныйПериод.
Разберем этот процесс по шагам:
ПериодРегистрации) и укажем для него тип данных СтандартныйПериод.При использовании этого элемента управления пользователь получает удобное поле ввода. При нажатии на кнопку выбора откроется стандартное платформенное окно, в котором сетка выбора представлена не днями, а месяцами, кварталами и годами. Пользователю достаточно сделать один клик по нужному месяцу, чтобы система зафиксировала период с первого по последнее число выбранного месяца. В коде мы сможем легко получить дату начала этого месяца через обращение к свойству реквизита ПериодРегистрации.ДатаНачала.
В типовых конфигурациях, содержащих подсистему расчета зарплаты и кадров (например, 1С:Зарплата и управление персоналом, 1С:ERP или 1С:Комплексная автоматизация), уже существует идеальный с точки зрения юзабилити механизм выбора месяца. Он выглядит как поле с кнопками регулирования (стрелками «вперед» и «назад») и иконкой календаря, при клике на которую открывается лаконичная форма выбора месяца и года.
Давайте проанализируем, как внедрить это решение в свою форму:
Для реализации нам понадобятся два реквизита формы:
Период (тип Дата) — здесь мы будем хранить реальное значение (всегда первое число выбранного месяца).ПериодПредставление (тип Строка, длина 15-20 символов) — этот реквизит будет отображаться на форме для пользователя (например, "Сентябрь 2026").Выведем строковый реквизит ПериодПредставление на форму и настроим его свойства в панели свойств:
Теперь перейдем в модуль управляемой формы и свяжем элементы с логикой БСП. Нам понадобится обработать событие начала выбора текстового поля и событие создания формы на сервере для первоначального заполнения:
&НаКлиенте
Процедура ПериодПредставлениеНачалоВыбора(Элемент, ДанныеВыбора, ВыборДобавлением, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Вызываем штатный интерактивный выбор месяца БСП
ЗарплатаКадрыКлиент.ВводМесяцаНачалоВыбора(ЭтотОбъект, ЭтотОбъект, "Период", "ПериодПредставление", Ложь);
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Если дата периода уже заполнена (например, при открытии существующего документа),
// нам необходимо сформировать его красивое текстовое представление
Если ЗначениеЗаполнено(Период) Тогда
ЗарплатаКадрыКлиентСервер.ЗаполнитьМесяцПоДате(ЭтотОбъект, "Период", "ПериодПредставление");
КонецЕсли;
КонецПроцедуры
Этот метод гарантирует полное соответствие интерфейса вашей разработки общим стандартам конфигураций "1С:Совместимо" и не требует изобретения велосипедов.
Что делать, если мы ведем разработку в самописной конфигурации или на "пустой" базе, где нет библиотек БСП? Нам отлично подойдет решение с динамическим списком выбора и умной навигацией по годам непосредственно внутри выпадающего списка. Суть метода заключается в том, что при открытии списка выбора пользователю показываются 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;
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораГодаИзСписка(РезультатВыбора, ДополнительныеПараметры) Экспорт
Если РезультатВыбора <> Неопределено Тогда
// Рекурсивно отправляем результат на обработку выбора
МесяцВыбораСтрокаОбработкаВыбора(Элементы.МесяцВыбораСтрока, РезультатВыбора.Значение, Ложь);
КонецЕсли;
КонецПроцедуры
Проанализировав данное решение, мы видим, что оно полностью автономно, не зависит от наличия БСП в конфигурации и предоставляет превосходный пользовательский опыт на любых устройствах и экранах.
Если в вашей конфигурации присутствует базовая БСП, но вы не хотите усложнять форму дополнительными текстовыми реквизитами-представлениями, вы можете вызывать общую форму выбора периода программно напрямую при нажатии кнопки выбора у реквизита типа Дата.
Посмотрим на пример реализации данного подхода:
&НаКлиенте
Процедура ПолеДатыНачалоВыбора(Элемент, ДанныеВыбора, ВыборДобавлением, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Подготовим параметры для открытия стандартной мини-формы выбора периода
ПараметрыВыбора = Новый Структура;
ПараметрыВыбора.Вставить("НачалоПериода", НачалоМесяца(Объект.ПериодРегистрации));
ПараметрыВыбора.Вставить("КонецПериода", КонецМесяца(Объект.ПериодРегистрации));
Контекст = Новый Структура;
Контекст.Вставить("ИмяРеквизита", "Объект.ПериодРегистрации");
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьВыборМесяцаЗавершение", ЭтотОбъект, Контекст);
// Открываем специализированную общую форму БСП
ОткрытьФорму("ОбщаяФорма.ВыборСтандартногоПериодаМесяц", ПараметрыВыбора, Элемент, , , , ОписаниеОповещения);
КонецПроцедуры
&НаКлиенте
Процедура ОбработатьВыборМесяцаЗавершение(РезультатВыбора, ДополнительныеПараметры) Экспорт
Если РезультатВыбора <> Неопределено Тогда
// Записываем дату начала выбранного интервала в наш реквизит
Объект.ПериодРегистрации = РезультатВыбора.ДатаНачала;
КонецЕсли;
КонецПроцедуры
Этот способ отличается своей компактностью и избавляет от необходимости дублировать реквизиты на форме. При этом пользователю открывается привычное и красивое диалоговое окно выбора месяцев и лет.
Выясним причину, почему разработчики часто пытаются писать сложный код там, где платформа умеет справляться своими силами. Если ваша задача — ограничить выбор месяца для параметра в отчете на базе схемы компоновки данных (СКД), вам вообще не нужно писать программный код.
Выполните следующие настройки на вкладке Параметры в СКД:
Дата (например, ПериодОтчета) в колонке Выражение пропишите: НачалоПериода(&ПериодОтчета, "Месяц"). Это гарантирует, что даже если пользователь выберет произвольное число, система автоматически сдвинет его на первое число месяца при расчете запроса.ДФ='ММММ yyyy'. В этом случае платформа скроет отображение дней в поле ввода отчета, оставив только название месяца и год.Таким образом, мы рассмотрели пять отличных способов организации выбора месяца и года в интерфейсе 1С. Выбирайте тот метод, который наилучшим образом подходит под архитектуру вашей конфигурации и требования конечных пользователей к удобству интерфейса.