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