Как обработать незаполненную дату начала в параметре «СтандартныйПериод» в СКД?

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

При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с неприятной особенностью платформы 1С: если в параметре типа СтандартныйПериод пользователь оставляет дату начала или дату окончания незаполненной, система может передать в запрос значение Неопределено вместо ожидаемой пустой даты (01.01.0001). Это приводит к ошибкам при выполнении запроса, особенно если этот параметр используется в виртуальных таблицах, таких как СрезПоследних, или в арифметических операциях с датами.

В рамках данной статьи мы разберем, почему это происходит, проанализируем различные способы решения и выберем наиболее эффективные методы «нормализации» данных в СКД.

Почему возникает ошибка при обращении к &Период.ДатаНачала

Разберем ситуацию подробнее. Когда мы объявляем параметр с типом СтандартныйПериод, СКД автоматически создает два вложенных значения: &Период.ДатаНачала и &Период.ДатаОкончания. На уровне встроенного языка объект СтандартныйПериод при пустых полях ввода возвращает именно Неопределено.

Проблема заключается в том, что язык запросов 1С, который выполняется на стороне СУБД (SQL Server, PostgreSQL и др.), не знает типа данных Неопределено в контексте полей типа «Дата». Если в СКД не настроено принудительное приведение типов, параметр передается «как есть», и движок базы данных выдает ошибку несовместимости типов или некорректного значения.

Решение 1: Использование выражения в параметрах СКД (Метод «Выбор Истина»)

Рассмотрим самый быстрый и, как ни странно, надежный способ, найденный опытным путем. Чтобы заставить СКД принудительно типизировать значение как «Дата», мы можем использовать вычисляемое выражение в колонке «Выражение» на закладке «Параметры» в конструкторе схемы компоновки.

Посмотрим на пример выражения, которое решает проблему:

ВЫБОР КОГДА Истина ТОГДА &Период.ДатаНачала ИНАЧЕ &Период.ДатаНачала КОНЕЦ

Почему это работает? Проанализируем логику: когда СКД видит конструкцию ВЫБОР в поле выражения параметра, она запускает внутренний вычислитель выражений. Этот вычислитель обязан привести результат условия к типу, который указан для данного параметра (в нашем случае — Дата). В процессе этого преобразования Неопределено превращается в стандартную пустую дату 1С (01.01.0001), которая уже корректно воспринимается запросом.

Решение 2: Применение встроенных функций работы с датами

Рассмотрим более «красивый» с точки зрения оформления кода вариант. Вместо логических условий можно использовать функции, которые по своей сути ожидают на вход дату и возвращают дату. Это также заставляет СКД выполнить приведение типов.

В колонке «Выражение» для параметра &ДатаНачала (если вы вынесли её в отдельный скрытый параметр) можно прописать:

НачалоПериода(&Период.ДатаНачала, "День")

Или просто:

&Период.ДатаНачала

Важно помнить: само наличие любого текста в колонке «Выражение» заставляет систему вычислять этот параметр программно перед выполнением запроса. Если же колонка пуста, СКД просто пытается «пробросить» значение из объекта СтандартныйПериод напрямую, что и приводит к попаданию Неопределено в запрос.

Решение 3: Программная обработка в модуле отчета

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

Проанализируем пример кода:


Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Получаем настройки отчета
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // Находим наш параметр Период
    ПараметрПериод = Настройки.ПараметрыДанных.Элементы.Найти("Период");
    
    Если ПараметрПериод <> Неопределено И ПараметрПериод.Использование Тогда
        ЗначениеПериода = ПараметрПериод.Значение;
        
        // Проверяем ДатуНачала на Неопределено
        Если ЗначениеПериода.ДатаНачала = Неопределено Или ЗначениеПериода.ДатаНачала = Дата(1, 1, 1) Тогда
            // Если дата не заполнена, можем установить её в глубокое прошлое или пустую дату
            // Однако в объекте СтандартныйПериод лучше оставить как есть, 
            // а корректировать именно значения, передаваемые в запрос.
        КонецЕсли;
    КонецЕсли;
    
    // Для надежности лучше использовать отдельные параметры ДатаНачала и ДатаОкончания в запросе,
    // и устанавливать их значения явно:
    НачалоДаты = ?(ЗначениеПериода.ДатаНачала = Неопределено, Дата(1, 1, 1), ЗначениеПериода.ДатаНачала);
    КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("ДатаНачала", НачалоДаты);

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

Этот метод считается наиболее «прозрачным», так как программист полностью контролирует, какие значения уходят в движок компоновки.

Решение 4: Проверка состава типов параметра

Иногда проблема кроется в автоматическом определении типов. Посмотрим на настройки параметров в схеме:

  1. Откройте закладку Параметры в СКД.
  2. Найдите ваш параметр (или вложенные параметры даты).
  3. Убедитесь, что в колонке Тип явно указано Дата, а не составной тип, включающий Неопределено.
  4. Снимите галочку Доступные значения, если она установлена ошибочно.
  5. Проверьте флаг Ограничение доступности. Часто бывает полезно скрыть автоматические параметры ДатаНачала и ДатаОкончания от пользователя, оставив доступным только основной параметр Период, а в выражениях скрытых параметров уже делать проверку.

Важные нюансы при работе со Срезом Последних

Рассмотрим ситуацию, когда &Период.ДатаНачала используется для получения данных на момент времени «до» начала отчета (например, остатки на начало). Если пользователь не выбрал дату начала, и система подставила Неопределено, запрос к виртуальной таблице СрезПоследних упадет с ошибкой.

В таких случаях рекомендуется в запросе использовать функцию ДОБАВИТЬКДАТЕ или КОНЕЦПЕРИОДА, но только после того, как вы применили один из вышеперечисленных способов нормализации в параметрах. Попытка написать ВЫБОР КОГДА &ДатаНачала = НЕОПРЕДЕЛЕНО... непосредственно в тексте запроса чаще всего не помогает, так как ошибка типизации возникает на этапе передачи параметров в SQL.

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

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

  1. Всегда заполняйте колонку Выражение для параметров дат, связанных с периодом.
  2. Используйте простую функцию &Период.ДатаНачала в выражении — этого достаточно, чтобы включить типизацию СКД.
  3. Если требуется гарантированная пустая дата вместо Неопределено, используйте конструкцию ВЫБОР КОГДА Истина ТОГДА &Период.ДатаНачала ИНАЧЕ &Период.ДатаНачала КОНЕЦ.
  4. Если вы используете параметр в виртуальных таблицах, убедитесь, что параметр является обязательным или имеет значение по умолчанию.

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

← На главную