Как в расширении конфигурации 1С использовать тип "СтандартныйПериод"?

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

Часто при доработке конфигураций через расширения возникает задача добавить на форму удобный элемент для выбора периода. Вместо двух полей «Дата начала» и «Дата окончания» хочется использовать стандартный и привычный для пользователей элемент с типом СтандартныйПериод. Однако при попытке добавить реквизит такого типа к объекту метаданных (например, к справочнику или документу) в расширении, разработчики сталкиваются с тем, что этого типа просто нет в списке доступных. Давайте разберемся, почему так происходит и как правильно решить эту задачу.

Ключевое различие: Реквизит Объекта и Реквизит Формы

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

Реквизит объекта — это, по сути, поле в таблице базы данных. Когда мы добавляем реквизит к справочнику, документу или любому другому объекту метаданных, мы описываем структуру данных, которые будут физически храниться в БД. Соответственно, типы данных для таких реквизитов ограничены теми, которые платформа умеет сохранять: Число, Строка, Дата, Булево, ссылки на другие объекты и т.д. Это примитивные, хранимые типы.

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

Природа типа «СтандартныйПериод»

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

Внутри себя этот объект содержит два ключевых свойства:

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

Правильный подход: решение задачи по шагам

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

Рассмотрим на примере: допустим, нам нужно в расширении добавить к справочнику «Договоры контрагентов» период действия.

  1. Создаем реквизиты для хранения данных в базе

    В расширении найдем нужный нам справочник («Договоры контрагентов») и добавим к нему два новых реквизита с типом Дата. Назовем их, например, ПериодДействияНачало и ПериодДействияОкончание. Именно в этих полях и будут храниться даты нашего периода.

  2. Добавляем удобный элемент на форму

    Теперь откроем основную форму элемента этого справочника (или создадим свою в расширении). В дереве реквизитов формы (не объекта!) добавим новый реквизит. Назовем его, например, ПериодНаФорме. Вот для него мы уже можем спокойно выбрать тип СтандартныйПериод, так как это реквизит формы.

    После этого перетащим новый реквизит формы на саму форму. Платформа автоматически создаст красивый и удобный элемент для выбора периода.

  3. Настраиваем логику связи

    Самый важный шаг — связать наш интерфейсный реквизит ПериодНаФорме с реквизитами объекта, которые хранятся в БД. Делается это программно.

    Во-первых, при открытии формы нам нужно заполнить наш элемент выбора периода данными из объекта. Для этого создадим обработчик события формы ПриСозданииНаСервере.

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

    Во-вторых, нам нужно отследить, когда пользователь меняет период, и записать новые даты в реквизиты объекта. Для этого у поля ввода на форме, связанного с реквизитом ПериодНаФорме, создадим обработчик события ПриИзменении.

    
    &НаКлиенте
    Процедура ПериодНаФормеПриИзменении(Элемент)
        
        // Вызываем серверную процедуру для обновления данных объекта
        УстановитьДатыПериодаВОбъекте();
        
    КонецПроцедуры
    
    &НаСервереБезКонтекста
    Процедура УстановитьДатыПериодаВОбъекте()
        
        // Копируем даты из реквизита формы в реквизиты объекта
        Объект.ПериодДействияНачало = ПериодНаФорме.ДатаНачала;
        Объект.ПериодДействияОкончание = ПериодНаФорме.ДатаОкончания;
        
    КонецПроцедуры
    

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

Подведем итог

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

Правильный подход всегда заключается в разделении:

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

← На главную