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

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

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

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

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

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

Выполним следующие шаги для настройки формы:

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

Теперь при нажатии на кнопку выбора в режиме «1С:Предприятие» перед пользователем откроется стандартное системное окно, где он сможет в один клик выбрать нужный месяц или указать даты вручную. Чтобы использовать выбранные границы периода в коде (например, для заполнения табличной части документа затратами за этот интервал), мы можем обратиться к свойствам нашего реквизита на сервере:


ДатаНачала = Интервал.ДатаНачала;
ДатаОкончания = Интервал.ДатаОкончания;

Этот метод чрезвычайно прост, надежен и не требует написания сложного программного кода.

Способ 2. Выбор конкретного месяца через форматирование даты

Зачастую для расчета себестоимости или закрытия месяца нам не нужен произвольный интервал с точностью до дней — требуется выбрать строго определенный месяц. Рассмотрим, как сделать так, чтобы стандартное поле даты отображало только месяц и год, например: «Апрель 2015 г.».

Для этого мы воспользуемся механизмом форматирования элементов формы:

  1. Добавим в документ реквизит объекта с именем ПериодРегистрации и типом Дата.
  2. Вынесем это поле на управляемую форму.
  3. Выделим элемент формы ПериодРегистрации и откроем его палитру свойств.
  4. Найдем свойство Формат. Нажмем на кнопку с тремя точками для открытия конструктора формата.
  5. В поле «Локальный формат даты» или в строке «Формат» пропишем маску: ДФ='ММММ гггг'. Эта маска указывает платформе, что дату нужно выводить в виде полного названия месяца и четырехзначного года.
  6. Аналогичную маску ДФЛ='ММММ гггг' пропишем в свойстве Формат редактирования, чтобы при вводе значения представление даты не сбивалось.

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

Способ 3. Реализация быстрой «прокрутки» месяцев стрелками

Чтобы повысить юзабилити формы и избавить пользователя от необходимости каждый раз открывать календарь для изменения месяца, мы можем настроить так называемые кнопки регулирования («стрелочки»). Это позволит перелистывать периоды одним кликом.

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

  1. Откроем свойства элемента формы, отображающего нашу дату (ПериодРегистрации).
  2. Установим флаг в свойстве Кнопка регулирования в значение Истина. После этого у поля ввода справа появятся маленькие стрелки «вверх» и «вниз».
  3. Перейдем к событиям элемента формы и найдем событие Регулирование. Нажмем на лупу для создания обработчика на клиенте.
  4. Пропишем в созданном обработчике следующий код, который будет перехватывать стандартное изменение даты на 1 день и менять ее ровно на 1 месяц вперед или назад:

&НаКлиенте
Процедура ПериодРегистрацииРегулирование(Элемент, Направление, СтандартнаяОбработка)
    
    // Отменяем стандартное поведение платформы (изменение даты на 1 день)
    СтандартнаяОбработка = Ложь; 
    
    // Параметр "Направление" принимает значение 1 при нажатии "вверх" и -1 при нажатии "вниз"
    Объект.ПериодРегистрации = ДобавитьМесяц(Объект.PeriodРегистрации, Направление);
    
КонецПроцедуры

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

Способ 4. Выбор месяца из строго заданного выпадающего списка

Если мы хотим полностью застраховать пользователя от ввода некорректных дат и ограничить выбор только текущим рабочим годом, можно перевести поле ввода в режим выбора из фиксированного списка.

Выполним следующую последовательность действий:

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

Посмотрим на пример программного кода:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Определим текущий рабочий год
    ТекущийГод = Год(ТекущаяДата());
    
    // Очистим список на случай повторного вызова
    Элементы.ПериодРегистрации.СписокВыбора.Очистить();
    
    // Заполняем список выбора двенадцатью месяцами текущего года
    Для НомерМесяца = 1 По 12 Цикл
        // Формируем дату на первое число месяца
        ДатаМесяца = Дата(ТекущийГод, НомерМесяца, 1);
        
        // Создаем понятное представление, например: "Январь 2024"
        ПредставлениеМесяца = Формат(ДатаМесяца, "ДФ='ММММ гггг'");
        
        // Добавляем значение в выпадающий список элемента формы
        Элементы.ПериодРегистрации.СписокВыбора.Добавить(ДатаМесяца, ПредставлениеМесяца);
    КонецЦикла;
    
КонецПроцедуры

В результате на форме появится классический выпадающий список (Drop-Down), содержащий только валидные месяцы. Пользователь физически не сможет ошибиться или выбрать некорректный день.

Способ 5. Использование общей формы выбора периода конфигурации

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

Разберем программный интерфейс для вызова этой формы из нашего документа. Для этого создадим на форме команду и привяжем к ней код:


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

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

Этот способ является стандартом разработки для профессиональных тиражируемых решений на платформе 1С.

Связывание выбранного периода с расчетом фактической себестоимости

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

Рассмотрим классический алгоритм реализации этой бизнес-логики:

  1. Создадим на форме документа команду ЗаполнитьЗатраты и вынесем её на форму в виде кнопки.
  2. Напишем серверный обработчик, который будет делать запрос к регистрам накопления за выбранный интервал времени.
  3. Принудительно приведем границы периода к началу и концу выбранного месяца, чтобы исключить ошибки, если пользователь указал середину месяца.

Пример серверной процедуры заполнения данных:


&НаСервере
Процедура ЗаполнитьЗатратыНаСервере()
    
    // Очищаем табличную часть перед заполнением
    Объект.Затраты.Очистить();
    
    // Определяем строгие границы месяца на основе выбранной даты
    ГраницаНачала = НачалоМесяца(Объект.ПериодРегистрации);
    ГраницаКонца  = КонецМесяца(Объект.ПериодРегистрации);
    
    // Инициализируем запрос к базе данных
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    ОборотыБюджета.СтатьяЗатрат КАК СтатьяЗатрат,
        |    ОборотыБюджета.СуммаОборот КАК Сумма
        |ИЗ
        |    РегистрНакопления.Закупки.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ОборотыБюджета";
    
    // Передаем границы периода в параметры запроса
    Запрос.УстановитьПараметр("НачалоПериода", ГраницаНачала);
    Запрос.УстановитьПараметр("КонецПериода",  ГраницаКонца);
    
    РезультатЗапроса = Запрос.Выполнить();
    
    // Если запрос вернул данные, загружаем их в табличную часть документа
    Если Не РезультатЗапроса.Пустой() Тогда
        Объект.Затраты.Загрузить(РезультатЗапроса.Выгрузить());
        
        // Рассчитываем итоговую сумму в подвале формы
        Объект.ВсегоЗатрат = Объект.Затраты.Итог("Сумма");
    КонецЕсли;
    
КонецПроцедуры

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

← На главную