При разработке отчетов в системе 1С:Предприятие программисты часто сталкиваются с необходимостью динамического изменения логики расчета в зависимости от вида начисления. Типичная ошибка начинающих разработчиков — попытка сравнить ссылочный тип данных (например, ВидРасчета) со строковым литералом напрямую в тексте запроса. Разберем подробно, почему так делать нельзя и какие существуют правильные способы решения этой задачи.
Рассмотрим ситуацию: нам необходимо в одном запросе вывести количество дней. Если это «Отпуск», нужно брать календарные дни, в остальных случаях — фактически отработанные дни. Попытка написать условие так:
ВЫБОР КОГДА ВидРасчета = "Отпуск" ТОГДА ... КОНЕЦ
приведет к ошибке или некорректной работе отчета. Это происходит потому, что поле ВидРасчета в регистре расчета содержит Ссылку (уникальный идентификатор записи в таблице плана видов расчета), а "Отпуск" — это просто Строка. Система не может сравнить эти два разных типа данных.
Выясним, как реализовать эту логику правильно, используя три основных подхода.
Проанализируем самый эффективный и быстрый способ — использование функции ЗНАЧЕНИЕ(). Этот метод идеально подходит, если вид расчета является предопределенным (то есть созданным в конфигураторе).
Рассмотрим пример кода в запросе:
ВЫБРАТЬ
ОсновныеНачисления.Сотрудник КАК Сотрудник,
ВЫБОР
КОГДА ОсновныеНачисления.ВидРасчета = ЗНАЧЕНИЕ(ПланВидовРасчета.Начисления.Отпуск)
ТОГДА ОсновныеНачисления.КалендарныеДниФактическийПериодДействия
ИНАЧЕ ОсновныеНачисления.ЗначениеДниФактическийПериодДействия
КОНЕЦ КАК Дни
ИЗ
РегистрРасчета.ОсновныеНачисления.ДанныеГрафика(&ПараметрыПериода) КАК ОсновныеНачисления
Преимущества этого метода:
Если вид расчета не является предопределенным или он выбирается пользователем на форме отчета, нам необходимо использовать параметры. Посмотрим, как это реализовать по шагам.
Сначала в тексте запроса мы указываем имя параметра через символ &:
ВЫБОР
КОГДА ОсновныеНачисления.ВидРасчета = &НужныйВидРасчета
ТОГДА ОсновныеНачисления.КалендарныеДниФактическийПериодДействия
ИНАЧЕ ОсновныеНачисления.ЗначениеДниФактическийПериодДействия
КОНЕЦ КАК Дни
Затем во встроенном языке (в модуле обработки или отчета) мы должны установить этот параметр. Рассмотрим пример поиска ссылки по наименованию (хотя это не самый рекомендуемый метод, он часто используется):
СсылкаНаОтпуск = ПланыВидовРасчета.Начисления.НайтиПоНаименованию("Отпуск");
Запрос.УстановитьПараметр("НужныйВидРасчета", СсылкаНаОтпуск);
Важный нюанс: Если вы используете Систему компоновки данных (СКД), параметр &НужныйВидРасчета появится в настройках отчета автоматически, и пользователь сможет выбрать конкретный элемент из справочника самостоятельно.
Иногда разработчики используют конструкцию ВидРасчета.Наименование = "Отпуск". Разберем, почему этот вариант считается «плохим тоном».
При обращении через точку в языке запросов 1С происходит неявное левое соединение (LEFT JOIN) с таблицей Плана видов расчета. Если записей в регистре миллионы, это существенно замедляет выполнение отчета. Кроме того, сравнение строк всегда медленнее, чем сравнение ссылок. Используйте этот метод только в крайнем случае, если нет возможности получить ссылку напрямую.
Посмотрим на исходный запрос автора и проанализируем возможности оптимизации. В тексте используются объединения (ОБЪЕДИНИТЬ ВСЕ) из разных таблиц. При работе с виртуальными таблицами (ДанныеГрафика) крайне важно накладывать фильтры в параметрах виртуальной таблицы, а не в секции ГДЕ.
Сравним два подхода:
Плохо: ИЗ РегистрРасчета.Начисления КАК Таблица ГДЕ Таблица.ПериодРегистрации = &Период
Хорошо: ИЗ РегистрРасчета.Начисления(&Период) КАК Таблица
Во втором случае платформа отсекает лишние данные на уровне базы данных еще до того, как они попадут в оперативную память для обработки запросом.
В запросе автора при объединении данных из ДополнительныеНачисления и Удержания в поле «Дни» подставляется NULL. Проанализируем последствия: если этот отчет будет использоваться в СКД для расчета итогов, NULL может вызвать ошибки при суммировании или привести к пустому результату.
Рекомендация: Для числовых показателей в объединяемых запросах лучше использовать 0 вместо NULL. Это обеспечит корректное приведение типов данных:
ВЫБРАТЬ Сотрудник, Результат, 0 КАК Дни ИЗ РегистрРасчета.Удержания ГДЕ ...
Для корректной работы условия ВЫБОР в запросах 1С необходимо придерживаться следующих правил:
ВидРасчета = "Строка".КалендарныеДниФактическийПериодДействия будут заполнены только в том случае, если у вида расчета в конфигураторе включена настройка «Использовать период действия».Соблюдение этих принципов позволит вам создавать стабильные и быстрые отчеты, которые не «сломаются» при обновлении базы или переименовании элементов пользователями.