Как правильно работать с реквизитами формы и выводить таблицу значений в 1С?

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

Проанализируем задачу и типичные ошибки

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

В исходном коде часто допускаются две фундаментальные архитектурные ошибки при работе с управляемыми формами:

  1. Использование модалеподобных окон вместо элементов интерфейса. Метод ПоказатьВводЗначения заставляет пользователя вводить данные в отдельном всплывающем окне. Для ввода параметров, которые напрямую влияют на отображение данных формы, необходимо использовать реквизиты самой формы (поля ввода).
  2. Игнорирование визуального конструирования. Программное создание объекта ТаблицаЗначений в памяти на сервере без привязки к реквизитам формы не позволит отобразить эту таблицу пользователю. Объект ТаблицаЗначений существует только в момент выполнения серверной процедуры, после чего уничтожается платформой.

Разберем ограничения платформы: Клиент и Сервер

В управляемых формах 1С четко разделены клиентский и серверный контексты. Программный объект ТаблицаЗначений доступен только на сервере (и в толстом клиенте). На тонком клиенте данные таблицы преобразуются платформой в специальный тип ДанныеФормыКоллекция.

Из-за этого нельзя просто создать ТаблицуЗначений на сервере и вернуть ее на тонкий клиент через оператор Возврат. Чтобы пользователь увидел таблицу на экране, мы должны работать с ней как с реквизитом формы. Платформа 1С берет на себя всю работу по автоматической синхронизации этого реквизита между клиентом и сервером.

Разберем по шагам правильное решение

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

Шаг 1: Визуальное создание реквизитов формы

  1. Откроем редактор формы. В окне "Реквизиты" создадим новый реквизит с именем Год. Установим ему тип Число, длину 4, точность 0. В свойствах элемента на форме обязательно укажем формат ЧГ=0, чтобы год отображался слитно (например, "2025", а не "2 025").
  2. Создадим второй реквизит с именем ТаблицаМесяцев и выберем для него тип ТаблицаЗначений.
  3. Добавим в ТаблицаМесяцев две колонки: Месяц (тип Строка) и КоличествоДней (тип Число). Крайне важно указывать точные типы колонок, иначе они станут составного типа, что приведет к ошибкам при дальнейшей работе.
  4. Перетащим оба реквизита в окно элементов формы, чтобы они стали видны пользователю.

Шаг 2: Программная реализация

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Устанавливаем текущий год по умолчанию
    Год = Год(ТекущаяДатаСеанса());
    // Первичное заполнение таблицы
    ЗаполнитьТаблицуНаСервере();
КонецПроцедуры

&НаКлиенте
Процедура ГодПриИзменении(Элемент)
    // Обновляем таблицу при вводе нового года
    ЗаполнитьТаблицуНаСервере();
    ПоказатьИтогиПоГоду();
КонецПроцедуры

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

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

Альтернативный способ вычисления количества дней в году

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

Можно просто узнать номер последнего дня года с помощью стандартных функций для работы с датами:


&НаКлиенте
Функция ПолучитьДнейВГодуБыстро(ЗначениеГода)
    // Получаем 31 декабря указанного года и берем номер дня от начала года
    ПоследняяДатаГода = КонецГода(Дата(ЗначениеГода, 1, 1));
    Возврат ДеньГода(ПоследняяДатаГода); // Вернет 365 или 366
КонецФункции

Этот подход делает код чище и избавляет от необходимости производить лишние математические расчеты в цикле.

← На главную