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

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

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

Выбор типа данных для хранения года: Дата, Число или Перечисление?

Первое, с чем сталкивается разработчик — это выбор типа реквизита ГодПоставки или ГодПланирования. Рассмотрим три основных варианта:

  1. Тип "Дата": Самый гибкий вариант. Чтобы пользователь видел только 4 цифры года, мы используем форматную строку ДФ=yyyy.
    • Плюсы: Легко использовать в стандартных функциях работы с датами (НачалоГода, ДобавитьМесяц), встроенный календарь.
    • Нюанс: По умолчанию календарь предлагает выбрать день, что может быть лишним кликом для пользователя.
  2. Тип "Число": Часто используется в профессиональной разработке (Число 4, 0).
    • Плюсы: Максимально простая визуализация (просто 4 цифры), высокая скорость работы в запросах.
    • Нюанс: Требуется ручная проверка диапазона (например, чтобы не ввели 1024 год или 3000-й). Для скрытия разделителя разрядов (чтобы не было "2 024") нужно установить параметр Группировка в значение "0".
  3. Тип "Перечисление": Создание объекта метаданных со значениями "Год2024", "Год2025" и т.д.
    • Плюсы: Жестко заданный список значений.
    • Минусы: Крайне не рекомендуется. Список лет придется постоянно обновлять в конфигураторе, что делает систему негибкой.

Рекомендация: Оптимальным вариантом является использование типа Дата с правильной настройкой интерфейса на форме.

Настройка интерфейса для удобного выбора года

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

  1. Установите свойство Формат (и ФорматРедактирования) в значение ДФ=yyyy. Теперь в поле будут отображаться только четыре цифры года.
  2. В свойстве КнопкаВыбора установите "Нет". Это отключит стандартный календарь, который может путать при выборе только года.
  3. Установите свойство КнопкаРегулирования в значение "Да". Это добавит стрелочки "вверх-вниз", позволяя пользователю быстро переключать года.
  4. Для нового документа в процедуре ПриСозданииНаСервере установите текущий год по умолчанию:

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

Работа с перечислениями на клиенте: получение текстового представления

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

В 1С для получения строкового представления любого ссылочного значения (включая перечисления) на клиенте достаточно использовать функцию Строка(). Рассмотрим пример:


&НаКлиенте
Процедура ГодПоставкиПриИзменении(Элемент)
    ТекстВыбранногоГода = Строка(Объект.ГодПоставки);
    Сообщить("Выбран период: " + ТекстВыбранногоГода);
КонецПроцедуры

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

Алгоритм автоматического заполнения табличной части месяцами

Теперь разберем самую важную часть: программное заполнение табличной части (ТЧ) в зависимости от выбранного года. Представим ситуацию: если выбран текущий год, мы заполняем ТЧ только оставшимися месяцами до конца года. Если выбран будущий год — заполняем всеми 12-ю месяцами.

Рассмотрим по шагам, как реализовать эту логику в обработчике изменения года:


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

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

Использование запроса для распределения сумм

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

Посмотрим на пример кода, который вычисляет количество оставшихся месяцев и распределяет сумму:


&НаСервере
Процедура РаспределитьСуммуПоМесяцам()
    
    ДатаНачала = ?(НачалоГода(Объект.ГодПоставки) = НачалоГода(ТекущаяДатаСеанса()), 
                   НачалоМесяца(ТекущаяДатаСеанса()), 
                   НачалоГода(Объект.ГодПоставки));
                   
    ДатаОкончания = КонецГода(Объект.ГодПоставки);
    
    // Вычисляем количество месяцев между датами
    КоличествоМесяцев = РазностьДат(ДатаНачала, ДатаОкончания, "МЕСЯЦ") + 1;
    
    Если КоличествоМесяцев > 0 Тогда
        РаспределеннаяСумма = Объект.ОбщаяСумма / КоличествоМесяцев;
        
        Для Счетчик = 0 По КоличествоМесяцев - 1 Цикл
            НоваяСтрока = Объект.Бюджет.Добавить();
            НоваяСтрока.Период = ДобавитьМесяц(ДатаНачала, Счетчик);
            НоваяСтрока.Сумма = РаспределеннаяСумма;
        КонецЦикла;
    КонецЕсли;
    
КонецПроцедуры

Дополнительные советы по юзабилити

Для того чтобы ваша форма выглядела профессионально, воспользуйтесь следующими приемами:

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

← На главную