Поле «Месяц» на форме 1С 8.3: ввод, листание и отбор данных за период

· 9 мин

Содержание

Чтобы пользователь выбирал месяц, а не конкретную дату, заведите на форме реквизит типа Дата (состав даты — «Дата»), задайте полю формат ДФ='ММММ гггг' и в обработчике ПриИзменении приводите значение к первому числу через НачалоМесяца(). Для отбора в запросе передавайте две границы: НачалоМесяца(Месяц) и КонецМесяца(Месяц).

Дальше всё сводится к деталям: как показать удобный диалог, как листать месяцы стрелками, как не потерять последний день периода в запросе и почему выборка по месяцу иногда работает медленно. Всё ниже — для управляемых форм платформы 8.3 в интерфейсе «Такси».

Как выбор месяца устроен в типовых конфигурациях

В типовых решениях встречаются три подхода. Полезно знать их, прежде чем писать своё: пользователи уже привыкли к этим паттернам.

  • 📅 Месяц как дата на первое число. Так хранят «Месяц начисления» в зарплатных документах и период регламентных операций. В базе лежит 01.10.2026 0:00:00, на форме видно «Октябрь 2026».
  • ⬅️➡️ Строка с представлением и кнопками листания. В ЗУП поле месяца выглядит как текст «Октябрь 2026» со стрелками по бокам. Стрелки сдвигают месяц на один вперёд или назад, кнопка выбора открывает подбор.
  • 🗓️ Стандартный период. В отчётах на СКД и в журналах используется тип СтандартныйПериод с вариантами «Этот месяц», «Прошлый месяц» и произвольным интервалом. Пользователь выбирает месяц в стандартном диалоге настройки периода.

Первый вариант — основа. Второй — его удобная оболочка. Третий нужен, когда пользователь может выбрать не только месяц, но и квартал, год или произвольные даты.

ПодходЧто хранитсяКогда брать
Дата на первое числоДатаДокументы, регистры, параметры обработок
Строка + листаниеДата + строковое представлениеЧастое переключение соседних месяцев
Стандартный периодСтандартныйПериодОтчёты, где месяц — лишь один из вариантов

ВыборДаты, ВвестиДату и ПоказатьВводДаты: получаем месяц из диалога

Глобального метода ВыборДаты в синтаксис-помощнике платформы нет. Под этим названием обычно ищут штатный диалог ввода даты. В 8.3 их два.

  • ВвестиДату(Дата, Подсказка, ЧастьДаты) — модальный вызов. При режиме использования модальности «Не использовать» он вызывает ошибку, поэтому в новых разработках его не применяют.
  • ПоказатьВводДаты(ОписаниеОповещения, Дата, Подсказка, ЧастьДаты) — немодальный аналог. Результат приходит в процедуру-обработчик оповещения.

Диалог отдаёт полную дату, а не месяц. Месяц из неё получают функцией НачалоМесяца():

&НаКлиенте
Процедура ВыбратьМесяц(Команда)

    Оповещение = Новый ОписаниеОповещения("ВыбратьМесяцЗавершение", ЭтотОбъект);
    ПоказатьВводДаты(Оповещение, Месяц, "Укажите любой день нужного месяца", ЧастиДаты.Дата);

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

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

    Если ВыбраннаяДата = Неопределено Тогда
        Возврат; // пользователь закрыл диалог
    КонецЕсли;

    Месяц = НачалоМесяца(ВыбраннаяДата);

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

Обработчик оповещения обязательно объявляйте с Экспорт. Без этого платформа не сможет его вызвать, и выбор молча не сработает.

Выбор из списка двенадцати месяцев

Календарь заставляет щёлкать по дню, хотя день не нужен. Если месяцы ограничены одним годом, удобнее список. Его собирают в СписокЗначений и показывают методом ПоказатьВыборЭлемента:

&НаКлиенте
Процедура ПоказатьСписокМесяцев()

    Список = Новый СписокЗначений;
    НачалоГодаВыбора = НачалоГода(?(ЗначениеЗаполнено(Месяц), Месяц, ТекущаяДата()));

    Для Номер = 0 По 11 Цикл
        ДатаМесяца = ДобавитьМесяц(НачалоГодаВыбора, Номер);
        Список.Добавить(ДатаМесяца, Формат(ДатаМесяца, "ДФ='ММММ гггг'"));
    КонецЦикла;

    Текущий = Список.НайтиПоЗначению(НачалоМесяца(Месяц));
    Оповещение = Новый ОписаниеОповещения("СписокМесяцевЗавершение", ЭтотОбъект);
    Список.ПоказатьВыборЭлемента(Оповещение, "Выберите месяц", Текущий);

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

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

    Если ВыбранныйЭлемент <> Неопределено Тогда
        Месяц = ВыбранныйЭлемент.Значение;
    КонецЕсли;

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

Цикл даёт ровно 12 элементов: от 0 до 11 включительно. ДобавитьМесяц к первому января сдвигает дату на нужное число месяцев без проблем с короткими месяцами, потому что исходный день — первое число.

Стандартный диалог периода

Если нужен именно СтандартныйПериод, используйте ДиалогРедактированияСтандартногоПериода. В нём есть готовые варианты, включая «Этот месяц» и «Прошлый месяц»:

&НаКлиенте
Процедура НастроитьПериод(Команда)

    Диалог = Новый ДиалогРедактированияСтандартногоПериода;
    Диалог.Период = Период;
    Диалог.Показать(Новый ОписаниеОповещения("НастроитьПериодЗавершение", ЭтотОбъект));

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

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

    Если НовыйПериод <> Неопределено Тогда
        Период = НовыйПериод;
    КонецЕсли;

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

Своё поле выбора месяца на управляемой форме

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

Шаг 1. Реквизит и формат отображения

  1. Добавьте реквизит формы Месяц с типом Дата, в квалификаторах выберите состав даты «Дата».
  2. Перетащите реквизит на форму, откройте свойства элемента.
  3. В свойстве «Формат» задайте ДФ='ММММ гггг' — поле покажет «Октябрь 2026».
  4. В свойстве «Формат редактирования» задайте ДФ=ММ.гггг. Пользователь вводит с клавиатуры «10.2026», день платформа подставит сама.
  5. Включите свойство «Кнопка регулирования» — у поля появятся стрелки.

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

Шаг 2. Нормализация и листание

Пользователь всё равно может выбрать в календаре 17-е число. Приводим значение к началу месяца при каждом изменении и обрабатываем стрелки:

&НаКлиенте
Процедура МесяцПриИзменении(Элемент)

    Если ЗначениеЗаполнено(Месяц) Тогда
        Месяц = НачалоМесяца(Месяц);
    КонецЕсли;

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

&НаКлиенте
Процедура МесяцРегулирование(Элемент, Направление, СтандартнаяОбработка)

    СтандартнаяОбработка = Ложь;
    Если Не ЗначениеЗаполнено(Месяц) Тогда
        Месяц = НачалоМесяца(ТекущаяДата());
    КонецЕсли;
    Месяц = ДобавитьМесяц(НачалоМесяца(Месяц), Направление);

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

Без СтандартнаяОбработка = Ложь стрелка сдвинет дату на день, а не на месяц: это поведение регулирования поля даты по умолчанию. Направление приходит как 1 или -1, его можно сразу передавать в ДобавитьМесяц.

Шаг 3. Подмена кнопки выбора

Если вместо календаря нужен список месяцев из предыдущего раздела, перехватите событие НачалоВыбора:

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

    СтандартнаяОбработка = Ложь;
    ПоказатьСписокМесяцев();

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

Изменение реквизита из кода не вызывает событие ПриИзменении элемента. Если после выбора месяца нужно перезаполнить таблицу или обновить отбор, вызовите эту логику явно в обработчике оповещения.

Строковое представление, как в ЗУП

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

&НаКлиенте
Процедура ОбновитьПредставлениеМесяца()

    МесяцСтрокой = Формат(Месяц, "ДФ='ММММ гггг'");

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

Плюс подхода — полный контроль над видом поля. Минус — ручной ввод с клавиатуры придётся разбирать самостоятельно, например в событии ОкончаниеВводаТекста. Если ручной ввод не нужен, отключите редактирование текста в свойствах поля.

Границы месяца в запросах 1С

Самая частая ошибка — передать в запрос одну дату и сравнить с ней поле Дата. Документ от 15.10.2026 14:30:00 не равен 01.10.2026, и выборка вернётся пустой.

Правильно передавать две границы:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|    Реализация.Ссылка,
|    Реализация.Дата
|ИЗ
|    Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
|    Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(Месяц));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(Месяц));

КонецМесяца() возвращает последний день месяца со временем 23:59:59. Поэтому документы последнего дня попадают в выборку. Если вместо этого подставить ДобавитьМесяц(Месяц, 1) - 1, получите то же значение, но код читается хуже.

Группировка по месяцам внутри запроса

Когда нужен свод по нескольким месяцам, используйте функцию языка запросов НАЧАЛОПЕРИОДА(Поле, МЕСЯЦ) в секции ВЫБРАТЬ и СГРУППИРОВАТЬ ПО:

ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(Реализация.Дата, МЕСЯЦ) КАК Месяц,
    КОЛИЧЕСТВО(Реализация.Ссылка) КАК Документов
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
    НАЧАЛОПЕРИОДА(Реализация.Дата, МЕСЯЦ)

Регистры: обороты и остатки на конец месяца

У виртуальной таблицы оборотов есть параметр периодичности. Указав Месяц, вы получите поле Период с первым числом каждого месяца:

ВЫБРАТЬ
    Обороты.Период,
    Обороты.Номенклатура,
    Обороты.КоличествоОборот
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Обороты(&НачалоПериода, &КонецПериода, Месяц, ) КАК Обороты

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

Запрос.УстановитьПараметр("НаДату", Новый Граница(КонецМесяца(Месяц), ВидГраницы.Включая));

Для периодического регистра сведений срез на месяц берут через СрезПоследних(&НаДату), где в параметр передают КонецМесяца(Месяц).

Месяц как параметр отчёта на СКД

В отчёте на системе компоновки поле месяца на форме часто делают отдельным реквизитом, а в схему передают уже границы. Так пользователь видит одно поле «Октябрь 2026», а запрос получает привычные &НачалоПериода и &КонецПериода.

Параметры передают через настройки компоновщика перед формированием:

&НаСервере
Процедура ПередатьМесяцВОтчет()

    Параметры = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных;
    Параметры.УстановитьЗначениеПараметра("НачалоПериода", НачалоМесяца(Месяц));
    Параметры.УстановитьЗначениеПараметра("КонецПериода", КонецМесяца(Месяц));

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

Имена параметров должны совпадать с именами в схеме компоновки. Если в схеме параметр не найден, значение просто не установится, а отчёт выведет данные за пустой период. Поэтому после переименования параметров в схеме проверьте и этот код.

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

Проверка выбранного месяца

Пустой месяц или месяц не с первого числа ломают расчёты тихо: отчёт просто покажет нули. Проверяйте значение до записи.

Обязательность и сообщение у поля

Для реквизита объекта проще всего включить свойство «Проверка заполнения» → «Выдавать ошибку». Если правила сложнее, проверяйте в модуле объекта:

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

    Если ЗначениеЗаполнено(Месяц) И Месяц <> НачалоМесяца(Месяц) Тогда
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Месяц должен быть указан на первое число";
        Сообщение.Поле = "Месяц";
        Сообщение.УстановитьДанные(ЭтотОбъект);
        Сообщение.Сообщить();
        Отказ = Истина;
    КонецЕсли;

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

Привязка через Поле и УстановитьДанные подсветит именно поле месяца на форме.

Защита от будущих и закрытых периодов

  • 🚫 Месяц в будущем. Сравнивайте с НачалоМесяца(ТекущаяДатаСеанса()) на сервере, а не с датой компьютера пользователя.
  • 🔒 Закрытый период. В типовых конфигурациях на БСП для этого есть механизм дат запрета изменения. Не дублируйте его своей проверкой, а настройте дату запрета.
  • 🧹 Нормализация при записи. Даже если форма приводит значение к первому числу, данные могут прийти через обмен или загрузку. Добавьте Месяц = НачалоМесяца(Месяц) в ПередЗаписью объекта.

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

Как ускорить выборку данных за месяц

Месяц — удобная единица для итогов, и платформа этим пользуется. Важно не мешать ей.

ПриёмПочему работает
Условие Дата МЕЖДУ &Начало И &КонецИспользуется индекс по полю даты
Отбор в параметрах виртуальной таблицы, а не в ГДЕОтбор применяется до соединений и расчёта
Периодичность Месяц у таблицы оборотовДанные берутся из итогов, а не из всех движений
Остатки на границу месяца, а не расчёт по движениямМеньше строк для обработки

Чего избегать:

  • ❌ ГДЕ МЕСЯЦ(Дата) = 10 И ГОД(Дата) = 2026 — функция над полем не даёт использовать индекс, СУБД перебирает таблицу целиком.
  • ❌ ГДЕ НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ) = &Месяц — та же проблема.
  • ❌ Запрос в цикле по месяцам. Двенадцать запросов за год медленнее одного с группировкой по НАЧАЛОПЕРИОДА.
  • ❌ Отбор по Период после получения всей виртуальной таблицы вместо её параметров.

Если отчёт за месяц по регистру накопления строится долго, проверьте в Конфигураторе, включены ли итоги регистра. Пересчёт итогов выполняйте вне рабочего времени: он нагружает базу и замедляет работу пользователей.

Частые вопросы

Как вывести месяц в родительном падеже, например «октября»?
Добавьте в формат день: ДФ='д ММММ гггг' выведет «1 октября 2026». Без дня ММММ даёт именительный падеж.
Можно ли хранить месяц числом от 1 до 12?
Можно, но тогда отдельно хранится год, а запросы усложняются. Дата на первое число удобнее: её сразу можно передать в параметры виртуальных таблиц.
Как по умолчанию подставить прошлый месяц?
В ПриСозданииНаСервере присвойте Месяц = ДобавитьМесяц(НачалоМесяца(ТекущаяДатаСеанса()), -1).
Почему в отчёте на СКД нет выбора одного месяца?
Задайте параметру тип СтандартныйПериод и вариант по умолчанию «Этот месяц» или «Прошлый месяц». Пользователь переключит его в диалоге периода.
Работает ли ПоказатьВводДаты в веб-клиенте?
Да, метод немодальный и поддерживается тонким и веб-клиентом. Модальный ВвестиДату в веб-клиенте лучше не использовать.