Часто при разработке отчетов, обработок или различных форм в 1С:Предприятии возникает задача предоставить пользователю возможность выбора периода, но с ограничением до месяца и года, без необходимости указывать конкретный день. Это полезно для аналитики по месяцам, сводных данных, формирования документов по определенным периодам и других сценариев, где детализация до дня избыточна или нежелательна. Цель состоит в том, чтобы обеспечить удобный и интуитивно понятный интерфейс, где пользователь видит и выбирает только месяц и год. Мы рассмотрим несколько эффективных подходов к решению этой задачи в управляемых формах 1С, начиная от использования стандартных механизмов платформы до разработки собственных, более гибких решений, которые позволят вам точно настроить поведение.
Платформа 1С:Предприятие предлагает разработчикам мощный и универсальный объект СтандартныйПериод, который специально предназначен для работы с временными интервалами. Этот объект является фундаментом для многих типовых механизмов выбора периода в конфигурациях 1С, таких как отчеты, журналы документов и обработки. Он позволяет гибко настраивать выбор периода по различным вариантам: день, неделя, месяц, квартал, полугодие или год. Для нашей задачи – выбора только месяца и года – СтандартныйПериод подходит идеально.
Когда мы настраиваем СтандартныйПериод на выбор месяца, система автоматически устанавливает период с первого по последнее число выбранного месяца и года включительно. Таким образом, вне зависимости от того, какой день выберет пользователь в календаре (если он будет доступен), или каким образом будет изменен период, объект всегда будет "знать" о начале и конце соответствующего месяца. Это существенно упрощает получение корректных граничных дат.
Давайте разберем, как мы можем реализовать этот подход в управляемой форме:
ВыбранныйСтандартныйПериод. Его тип должен быть установлен как СтандартныйПериод.ПолеСтандартногоПериода. Это активирует специализированный диалог выбора периода, который поддерживает различные варианты (день, месяц, год и т.д.).ВыбранныйСтандартныйПериод в обработчике формы ПриСозданииНаСервере. Это задаст начальное состояние и предпочтительный вариант периода.
// В обработчике события формы ПриСозданииНаСервере
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если ВыбранныйСтандартныйПериод = Неопределено Тогда
ВыбранныйСтандартныйПериод = Новый СтандартныйПериод;
// Устанавливаем текущий месяц как значение по умолчанию
ВыбранныйСтандартныйПериод.УстановитьПериод(НачалоМесяца(ТекущаяДата()), КонецМесяца(ТекущаяДата()));
// Задаем вариант периода по умолчанию как "Месяц"
ВыбранныйСтандартныйПериод.ВариантПериода = ВариантСтандартногоПериода.Месяц;
КонецЕсли;
КонецПроцедуры
После этой настройки, когда пользователь откроет форму и нажмет кнопку выбора в поле, ему будет предложен диалог, где по умолчанию будет выбран текущий месяц, и он сможет легко перейти к выбору другого месяца или года. Для быстрой отладки алгоритмов формирования дат удобно использовать встраиваемую консоль кода — для этого подойдёт встраиваемая консоль отладки кода прямо в Предприятии.
ВыбранныйСтандартныйПериод в любом серверном или клиентском обработчике (например, в обработчике кнопки "Сформировать").
// Например, в обработчике команды "СформироватьОтчет"
&НаКлиенте
Процедура СформироватьОтчет(Команда)
// При необходимости можно перенести на сервер для получения дат
// или использовать уже доступные значения на клиенте
СформироватьОтчетНаСервере();
КонецПроцедуры
&НаСервере
Процедура СформироватьОтчетНаСервере()
ДатаНачалаМесяца = ВыбранныйСтандартныйПериод.ДатаНачала; // Получаем первое число выбранного месяца
ДатаОкончанияМесяца = ВыбранныйСтандартныйПериод.ДатаОкончания; // Получаем последнее число выбранного месяца
// Далее используем ДатаНачалаМесяца и ДатаОкончанияМесяца
// для формирования запроса или других операций
Сообщить("Выбран период: с " + Формат(ДатаНачалаМесяца, "ДФ='дд.ММ.гггг'") +
" по " + Формат(ДатаОкончанияМесяца, "ДФ='дд.ММ.гггг'"));
КонецПроцедуры
Если ваша конфигурация использует Библиотеку Стандартных Подсистем (БСП), у вас есть еще более удобные и готовые к использованию инструменты. БСП предоставляет ряд общих форм и модулей, которые уже реализовали логику выбора стандартных периодов, включая специализированные варианты для месяцев, а найти нужные функции поможет справочник по методам БСП — в этом поможет набор инструментов разработчика со справочником методов БСП.
Одной из наиболее часто используемых функций является вызов формы выбора стандартного периода через общие модули или формы БСП. Например, вы можете встретить такие объекты, как ОбщийМодуль.ОтчетыКлиент.ВыбратьПериод или общая форма ОбщаяФорма.ВыборПериодаИС, а также специфические функции вроде ВыборСтандартногоПериодаМесяц.
Для использования этого подхода нам понадобится:
МесяцГодСтрокой.МесяцГодСтрокой.НачалоВыбора: В этом событии мы отменяем стандартную обработку и вызываем функцию БСП, которая откроет диалог выбора периода.Пример вызова функции БСП в управляемой форме:
Предположим, у нас есть строковый реквизит МесяцГодСтрокой. В событии НачалоВыбора поля, связанного с этим реквизитом, мы можем вызвать функцию БСП:
&НаКлиенте
Процедура МесяцГодСтрокойНачалоВыбора(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Отменяем стандартную обработку
// Пример вызова формы выбора периода из БСП
// (Точные параметры и имя функции могут отличаться в вашей версии БСП)
ПередаваемыеПараметры = Новый Структура;
// Можно передать текущий выбранный период для инициализации формы
// Например, если вы храните дату первого дня месяца в другом реквизите:
// ПередаваемыеПараметры.ВключатьПериоды = Истина;
// ПередаваемыеПараметры.НачалоПериода = НачалоМесяца(ДатаМесяца);
// ПередаваемыеПараметры.КонецПериода = КонецМесяца(ДатаМесяца);
// ПередаваемыеПараметры.ДоступныеВидыПериода = "Месяц,Квартал,Год"; // Ограничиваем выбор
ОткрытьФорму("ОбщаяФорма.ВыборПериода", ПередаваемыеПараметры, Элемент, , , ,
Новый ОписаниеОповещения("ПослеВыбораПериодаБСП", ЭтотОбъект));
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораПериодаБСП(РезультатВыбора, ДополнительныеПараметры) Экспорт
Если РезультатВыбора <> Неопределено Тогда
// РезультатВыбора, как правило, является объектом СтандартныйПериод
МесяцГодСтрокой = Формат(РезультатВыбора.ДатаНачала, "ДФ='ММММ гггг'");
// Если необходимо получить сами даты начала и конца месяца:
// ДатаНачалаВыбранногоМесяца = РезультатВыбора.ДатаНачала;
// ДатаОкончанияВыбранногоМесяца = РезультатВыбора.ДатаОкончания;
КонецЕсли;
КонецПроцедуры
Данный подход позволяет использовать уже протестированный и стандартизированный функционал БСП, что значительно ускоряет разработку и повышает надежность. Мы получаем не только строковое представление выбранного месяца и года, но и объект СтандартныйПериод, из которого легко извлечь граничные даты для дальнейшей работы.
Этот подход является одним из самых элегантных и минималистичных, поскольку он использует стандартный элемент "Поле ввода" для даты, но с интеллектуальной настройкой форматирования и обработкой событий. Мы можем настроить это поле таким образом, чтобы оно отображало только месяц и год, при этом внутренне храня полноценную дату, которая всегда будет корректироваться на начало месяца.
Давайте подробно разберем шаги:
ДатаВыбранногоМесяца, с типом Дата. Для него установим свойство ВидДаты в ДатаВремя и СоставДаты в Дата (чтобы исключить время). Инициализируем его, например, текущей датой в обработчике ПриСозданииНаСервере:
// В обработчике события формы ПриСозданииНаСервере
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если ДатаВыбранногоМесяца = Неопределено Тогда
ДатаВыбранногоМесяца = НачалоМесяца(ТекущаяДата());
КонецЕсли;
КонецПроцедуры
ДатаВыбранногоМесяца на форму. Платформа создаст элемент "Поле ввода". Ключевой момент здесь — это настройка свойства Формат для этого элемента формы. Мы должны установить его в значение, которое будет отображать только месяц и год, игнорируя день.Примеры значений для свойства Формат:
"ДФ='ММММ гггг'": Отображает полное название месяца и год (например, "Январь 2023")."ДФ='ММ.гггг'": Отображает месяц числом и год (например, "01.2023")."ДФ='МММ гггг'": Отображает сокращенное название месяца и год (например, "Янв 2023").Важно: Используйте именно свойство Формат, а не ФорматРедактирования. Свойство Формат определяет, как значение отображается для пользователя, тогда как ФорматРедактирования влияет только на вид поля при активном редактировании.
ПриИзменении для нашего поля ввода.
&НаКлиенте
Процедура ДатаВыбранногоМесяцаПриИзменении(Элемент)
Если ЗначениеЗаполнено(ДатаВыбранногоМесяца) Тогда
// Всегда устанавливаем дату на первое число выбранного месяца
ДатаВыбранногоМесяца = НачалоМесяца(ДатаВыбранногоМесяца);
КонецЕсли;
КонецПроцедуры
Этот код гарантирует, что даже если пользователь случайно или намеренно изменит день (например, введет "15.02.2023" или прокрутит до "15"), после активации обработчика значение реквизита будет автоматически скорректировано на "01.02.2023". Визуально пользователь по-прежнему будет видеть только месяц и год, но внутренняя логика будет работать с корректной датой начала месяца.
Этот метод является очень эффективным и не требует создания дополнительных форм или сложной логики. Он прекрасно интегрируется со стандартными механизмами платформы и обеспечивает чистый, функциональный интерфейс для выбора месяца и года, а для визуального выделения таких полей можно использовать условное оформление.
Данный подход предоставляет более явный и детализированный контроль над выбором периода для пользователя. Вместо одного поля даты мы создаем два независимых элемента управления на форме: одно для выбора номера или названия месяца, и другое для выбора года. Это может быть полезно, когда требуется максимально наглядное представление выбора или когда нужно обеспечить специфические ограничения по диапазону месяцев или годов.
Давайте рассмотрим процесс реализации:
ВыбранныйМесяцЧислом: Тип Число, Длина 2. Будет хранить номер месяца (1-12).ВыбранныйГод: Тип Число, Длина 4. Будет хранить год (например, 2023).Инициализируем эти реквизиты текущими значениями в обработчике ПриСозданииНаСервере:
// В обработчике события формы ПриСозданииНаСервере
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если ВыбранныйМесяцЧислом = Неопределено Тогда
ВыбранныйМесяцЧислом = Месяц(ТекущаяДата());
КонецЕсли;
Если ВыбранныйГод = Неопределено Тогда
ВыбранныйГод = Год(ТекущаяДата());
КонецЕсли;
КонецПроцедуры
ВыбранныйМесяцЧислом, нам необходимо настроить СписокВыбора, чтобы пользователь мог выбирать месяц по названию, а не по числу.Настройка списка выбора для месяца (программно): В обработчике ПриСозданииНаСервере мы можем заполнить список выбора для поля месяца. Установим также свойство РежимВыбораИзСписка в Истина, чтобы активировать выпадающий список.
// В обработчике события формы ПриСозданииНаСервере
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Инициализация месяца и года (как показано выше)
// ...
// Настройка списка выбора для месяца
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Очистить();
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(1, "Январь");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(2, "Февраль");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(3, "Март");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(4, "Апрель");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(5, "Май");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(6, "Июнь");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(7, "Июль");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(8, "Август");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(9, "Сентябрь");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(10, "Октябрь");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(11, "Ноябрь");
Элементы.ВыбранныйМесяцЧислом.СписокВыбора.Добавить(12, "Декабрь");
Элементы.ВыбранныйМесяцЧислом.РежимВыбораИзСписка = Истина;
Элементы.ВыбранныйМесяцЧислом.КнопкаВыбора = Истина; // Показать кнопку выбора
КонецПроцедуры
Для поля года мы можем оставить его как обычное числовое поле или, если необходимо, также настроить список выбора для определенного диапазона лет (например, для последних 5 лет и следующих 2 лет).
ПриИзменении для полей месяца и года, или же в обработчике команды "Сформировать", "ОК" и т.п.
&НаКлиенте
Процедура ВыбранныйМесяцЧисломПриИзменении(Элемент)
// При изменении месяца можно сразу сформировать дату
СформироватьИтоговуюДату();
КонецПроцедуры
&НаКлиенте
Процедура ВыбранныйГодПриИзменении(Элемент)
// При изменении года также формируем дату
СформироватьИтоговуюДату();
КонецПроцедуры
&НаКлиенте
Процедура СформироватьИтоговуюДату()
Если ЗначениеЗаполнено(ВыбранныйМесяцЧислом) И ЗначениеЗаполнено(ВыбранныйГод) Тогда
Попытка
// Создаем дату первого числа выбранного месяца и года
ДатаРезультат = Дата(ВыбранныйГод, ВыбранныйМесяцЧислом, 1);
// Теперь ДатаРезультат содержит 01.MM.YYYY
Сообщить("Сформированная дата: " + Формат(ДатаРезультат, "ДФ='дд.ММ.гггг'"));
// Далее можно использовать эту дату для других операций
Исключение
Сообщить("Введены некорректные значения месяца или года. Проверьте правильность ввода.");
КонецПопытки;
Иначе
Сообщить("Пожалуйста, выберите и месяц, и год.");
КонецЕсли;
КонецПроцедуры
Этот подход обеспечивает высокую наглядность для пользователя, так как месяц и год представлены явно. Он также дает разработчику полный контроль над диапазонами выбора и логикой формирования итоговой даты, что может быть важно для специфических бизнес-требований.
В тех случаях, когда стандартные механизмы или комбинации полей не предоставляют достаточной гибкости или не соответствуют уникальным требованиям к пользовательскому интерфейсу (UX), мы можем разработать собственную, специализированную управляемую форму для выбора только месяца и года. Этот подход дает нам максимальный контроль над внешним видом, логикой и поведением элемента выбора.
Давайте подробно разберем шаги по созданию такой формы:
ОбщаяФорма.ФормаВыбораМесяцаГода) или форму для конкретного объекта, если она привязана к определенному модулю.Например, создадим два реквизита формы на нашей новой форме: МесяцВыбора (Тип: Число) и ГодВыбора (Тип: Число). Также добавим кнопку "Выбрать" и "Отмена".
Инициализируем эти реквизиты при создании формы, возможно, принимая начальные значения из параметров:
// В модуле формы ФормаВыбораМесяцаГода
// Реквизиты формы: МесяцВыбора (Число), ГодВыбора (Число)
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("ДатаИнициализации") Тогда
МесяцВыбора = Месяц(Параметры.ДатаИнициализации);
ГодВыбора = Год(Параметры.ДатаИнициализации);
Иначе
МесяцВыбора = Месяц(ТекущаяДата());
ГодВыбора = Год(ТекущаяДата());
КонецЕсли;
// Настроить список выбора для месяца, как в Решении 3
Элементы.МесяцВыбора.СписокВыбора.Добавить(1, "Январь");
// ... и так далее до Декабря
КонецПроцедуры
Закрыть() с параметром.
&НаКлиенте
Процедура КомандаВыбрать(Команда)
Если ЗначениеЗаполнено(МесяцВыбора) И ЗначениеЗаполнено(ГодВыбора) Тогда
Попытка
// Формируем дату первого числа выбранного месяца и года
ВыбраннаяДата = Дата(ГодВыбора, МесяцВыбора, 1);
Закрыть(ВыбраннаяДата); // Закрываем форму, передавая результат
Исключение
Сообщить("Не удалось сформировать дату. Проверьте корректность месяца и года.");
КонецПопытки;
Иначе
Сообщить("Пожалуйста, выберите и месяц, и год.");
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура КомандаОтмена(Команда)
Закрыть(Неопределено); // Если пользователь отменил выбор
КонецПроцедуры
НачалоВыбора вызываем нашу пользовательскую форму асинхронно, используя метод ОткрытьФорму.
// В модуле основной формы
// Реквизит формы: МойРеквизитДляМесяцаГода (Тип Дата)
&НаКлиенте
Процедура ПолеВыбораМесяцаГодаНачалоВыбора(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Отменяем стандартную обработку выбора
// Передаем текущее значение для инициализации нашей формы выбора
ПараметрыОткрытия = Новый Структура("ДатаИнициализации", МойРеквизитДляМесяцаГода);
// Открываем нашу пользовательскую форму асинхронно
ОткрытьФорму("ОбщаяФорма.ФормаВыбораМесяцаГода", ПараметрыОткрытия, Элемент, , , ,
Новый ОписаниеОповещения("ПослеВыбораМесяцаГодаВПользовательскойФорме", ЭтотОбъект));
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораМесяцаГодаВПользовательскойФорме(ВыбраннаяДата, ДополнительныеПараметры) Экспорт
// Эта процедура будет вызвана после закрытия формы ФормаВыбораМесяцаГода
Если ВыбраннаяДата <> Неопределено Тогда
МойРеквизитДляМесяцаГода = ВыбраннаяДата; // Обновляем реквизит основной формы
// Если реквизит отображается как строка, его нужно обновить
// Элементы.ПолеВыбораМесяцаГода.Текст = Формат(ВыбраннаяДата, "ДФ='ММММ гггг'");
КонецЕсли;
КонецПроцедуры
Этот метод является наиболее трудозатратным, так как требует создания и отладки новой формы. Однако он предоставляет полную свободу в реализации требуемого функционала и дизайна, позволяя создать максимально специализированный и удобный для пользователя элемент выбора месяца и года, который может быть настроен под любые, даже самые нетривиальные требования.
Мы подробно рассмотрели различные подходы к реализации выбора только месяца и года в управляемых формах 1С, обеспечивая при этом невозможность выбора конкретного дня. Каждый из методов имеет свои преимущества и может быть оптимален в зависимости от конкретной ситуации и требований к проекту.
СтандартныйПериод и БСП: Это наиболее рекомендуемый подход для большинства случаев, так как он использует встроенные, проверенные механизмы платформы и БСП, обеспечивая при этом высокую функциональность и относительно простую реализацию. Он подходит, когда стандартный диалог выбора периода БСП или объект СтандартныйПериод удовлетворяет требованиям к пользовательскому интерфейсу.ПриИзменении для корректной работы с датой начала месяца. Идеально подходит, когда нужна простота и компактность.При выборе подходящего решения мы всегда должны анализировать объем работ, удобство для конечного пользователя, а также наличие и версию Библиотеки Стандартных Подсистем в вашей конфигурации. Правильный выбор подхода позволит вам создать эффективное, надежное и интуитивно понятное решение для работы с периодами в 1С:Предприятии.