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