Рассмотрим частую задачу, с которой сталкиваются начинающие разработчики 1С: необходимо создать форму, на которой пользователь вводит год, а система автоматически формирует таблицу с месяцами и количеством дней в них. При этом результат должен отображаться прямо на форме, а пользователю должно выдаваться сообщение с общим количеством дней в году.
В исходном коде часто допускаются две фундаментальные архитектурные ошибки при работе с управляемыми формами:
ПоказатьВводЗначения заставляет пользователя вводить данные в отдельном всплывающем окне. Для ввода параметров, которые напрямую влияют на отображение данных формы, необходимо использовать реквизиты самой формы (поля ввода).ТаблицаЗначений в памяти на сервере без привязки к реквизитам формы не позволит отобразить эту таблицу пользователю. Объект ТаблицаЗначений существует только в момент выполнения серверной процедуры, после чего уничтожается платформой.В управляемых формах 1С четко разделены клиентский и серверный контексты. Программный объект ТаблицаЗначений доступен только на сервере (и в толстом клиенте). На тонком клиенте данные таблицы преобразуются платформой в специальный тип ДанныеФормыКоллекция.
Из-за этого нельзя просто создать ТаблицуЗначений на сервере и вернуть ее на тонкий клиент через оператор Возврат. Чтобы пользователь увидел таблицу на экране, мы должны работать с ней как с реквизитом формы. Платформа 1С берет на себя всю работу по автоматической синхронизации этого реквизита между клиентом и сервером.
Чтобы реализовать функционал корректно, выполним следующие действия визуально в Конфигураторе, а затем напишем обработчики событий.
Шаг 1: Визуальное создание реквизитов формы
Год. Установим ему тип Число, длину 4, точность 0. В свойствах элемента на форме обязательно укажем формат ЧГ=0, чтобы год отображался слитно (например, "2025", а не "2 025").ТаблицаМесяцев и выберем для него тип ТаблицаЗначений.ТаблицаМесяцев две колонки: Месяц (тип Строка) и КоличествоДней (тип Число). Крайне важно указывать точные типы колонок, иначе они станут составного типа, что приведет к ошибкам при дальнейшей работе.Шаг 2: Программная реализация
Теперь напишем код, который будет инициализировать данные при открытии и обновлять таблицу при ручном изменении года пользователем.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Устанавливаем текущий год по умолчанию
Год = Год(ТекущаяДатаСеанса());
// Первичное заполнение таблицы
ЗаполнитьТаблицуНаСервере();
КонецПроцедуры
&НаКлиенте
Процедура ГодПриИзменении(Элемент)
// Обновляем таблицу при вводе нового года
ЗаполнитьТаблицуНаСервере();
ПоказатьИтогиПоГоду();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьТаблицуНаСервере()
// Очищаем реквизит формы перед новым заполнением
ТаблицаМесяцев.Очистить();
Для к = 1 По 12 Цикл
// Добавляем строку напрямую в реквизит формы
НоваяСтрока = ТаблицаМесяцев.Добавить();
// Вычисляем последний день месяца
ДатаОтсчета = КонецМесяца(Дата(Год, к, 1));
// Заполняем данные
НоваяСтрока.КоличествоДней = День(ДатаОтсчета);
НоваяСтрока.Месяц = Формат(ДатаОтсчета, "ДФ=ММММ");
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ПоказатьИтогиПоГоду()
КоличествоДнейВГоду = 0;
// Перебираем коллекцию данных формы на клиенте
Для Каждого СтрокаТаблицы Из ТаблицаМесяцев Цикл
КоличествоДнейВГоду = КоличествоДнейВГоду + СтрокаТаблицы.КоличествоДней;
КонецЦикла;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "В " + Формат(Год, "ЧГ=0") + " году " + КоличествоДнейВГоду + " дней";
Сообщение.Сообщить();
КонецПроцедуры
В нашем коде мы подсчитываем дни, складывая значения каждой строки таблицы в цикле. Однако, выясним, как получить количество дней в году гораздо проще и эффективнее без перебора массива месяцев.
Можно просто узнать номер последнего дня года с помощью стандартных функций для работы с датами:
&НаКлиенте
Функция ПолучитьДнейВГодуБыстро(ЗначениеГода)
// Получаем 31 декабря указанного года и берем номер дня от начала года
ПоследняяДатаГода = КонецГода(Дата(ЗначениеГода, 1, 1));
Возврат ДеньГода(ПоследняяДатаГода); // Вернет 365 или 366
КонецФункции
Этот подход делает код чище и избавляет от необходимости производить лишние математические расчеты в цикле.