При написании запросов в платформе 1С:Предприятие часто возникает задача смещения даты на определенный интервал — дни, месяцы или годы. Для этого используется встроенная функция языка запросов ДОБАВИТЬКДАТЕ. Однако при передаче реквизита или поля временной таблицы в качестве смещения разработчики нередко сталкиваются с ошибкой «Неверные параметры» или получают пустое значение (NULL) в результате.
Разберем подробно, почему возникает такое поведение, как устроена типизация в запросах 1С и какими способами можно корректно прибавить количество месяцев к дате.
Рассмотрим синтаксис системной функции языка запросов:
ДОБАВИТЬКДАТЕ(Дата, ТипУвеличения, Количество)
К параметрам функции предъявляются строгие требования:
Дата.СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД).Число, указывающее, на сколько единиц смещается дата.Если вместо числа в третий параметр передается строка, составной тип или нетипизированное значение, платформа возвращает ошибку «Неверные параметры».
Частая попытка исправить ситуацию с помощью оператора ВЫРАЗИТЬ(Поле КАК Число) приводит либо к ошибке несовместимости типов, либо к результату NULL. Выясним причину такого поведения: в языке запросов 1С оператор ВЫРАЗИТЬ не выполняет конвертацию значений (как оператор CAST в классическом SQL), а лишь сужает (уточняет) составной тип данных до конкретного. Если поле в исходной таблице или регистре изначально сохранено с типом Строка, попытка применить к нему ВЫРАЗИТЬ(... КАК Число) вернет NULL.
Кроме того, если реквизит смещения содержит значение NULL (например, при левом соединении таблиц), функция ДОБАВИТЬКДАТЕ также вернет NULL.
Проанализируем структуру источника данных. Если реквизит (например, СрокИспользования в регистре или документе) хранит числовое количество месяцев, наиболее правильным решением будет изменение типа данных реквизита в дереве метаданных конфигуратора с типа Строка на тип Число.
После изменения типа данных в запросе можно напрямую использовать поле со смещением, обязательно обработав возможное значение NULL:
ВЫБРАТЬ
ВТ_Осн.Сотрудник,
ВТ_Осн.ДатаДокумента,
ДОБАВИТЬКДАТЕ(ВТ_Осн.ДатаДокумента, МЕСЯЦ, ЕСТЬNULL(ВТ_Осн.СрокИспользования, 0)) КАК ДатаКонецИспользования
ИЗ
ВТ_Осн КАК ВТ_Осн
Если изменить структуру метаданных невозможно, а список возможных строковых значений срока ограничен (например, фиксированные периоды: 1, 3, 6, 12 месяцев), выполним явную подмену строк на числа внутри запроса.
Посмотрим на пример реализации с конструкцией ВЫБОР:
ВЫБРАТЬ
ВТ_Осн.Сотрудник,
ВТ_Осн.ДатаДокумента,
ДОБАВИТЬКДАТЕ(
ВТ_Осн.ДатаДокумента,
МЕСЯЦ,
ВЫБОР
КОГДА ВТ_Осн.СрокИспользования = "1" ТОГДА 1
КОГДА ВТ_Осн.СрокИспользования = "3" ТОГДА 3
КОГДА ВТ_Осн.СрокИспользования = "6" ТОГДА 6
КОГДА ВТ_Осн.СрокИспользования = "12" ТОГДА 12
КОГДА ВТ_Осн.СрокИспользования = "24" ТОГДА 24
ИНАЧЕ 0
КОНЕЦ
) КАК ДатаКонецИспользования
ИЗ
ВТ_Осн КАК ВТ_Осн
В этом случае конструкция ВЫБОР гарантированно возвращает числовой результат, что исключает возникновение ошибки «Неверные параметры».
Если строковые значения могут быть произвольными и их невозможно перебрать в запросе через ВЫБОР, разберем вычисление итоговой даты после выполнения запроса с помощью средств встроенного языка 1С.
Для этого в запросе выбираем исходные строковые поля и дату, а расчет выполняем при обходе выборки с помощью функций Число() и ДобавитьМесяц():
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Преобразуем строку в числовое значение
ЧислоМесяцев = Число(Выборка.СрокИспользования);
// Рассчитываем дату окончания
ДатаОкончания = ДобавитьМесяц(Выборка.ДатаДокумента, ЧислоМесяцев);
// Дальнейшая обработка полученных данных
КонецЦикла;
Если расчет даты обязательно должен быть промежуточным звеном сложного пакетного запроса, выполним предварительную подготовку данных в коде:
ТаблицаЗначений.Число().МенеджерВременныхТаблиц и выполняем функцию ДОБАВИТЬКДАТЕ уже по числовой колонке.