При разработке отчетов на базе Системы компоновки данных (СКД) разработчики часто сталкиваются со следующей проблемой: пользователю необходимо получить движения по регистру (накопления или бухгалтерии) для конкретного документа, выбранного на форме в качестве параметра. Казалось бы, простейшим решением является наложение условия в секции ГДЕ, например, ГДЕ Регистратор = &Регистратор.
Однако такое решение таит в себе серьезную опасность для производительности всей системы. На больших базах данных подобный подход заставляет СУБД сначала агрегировать и вычислять виртуальную таблицу по всему объему записей регистра за все время его существования, и лишь затем отфильтровывать результат по конкретному документу. Это гарантированно приводит к зависанию отчета и колоссальной нагрузке на сервер.
Чтобы отчет формировался мгновенно, необходимо жестко ограничить выборку на уровне параметров самой виртуальной таблицы, передав в НачалоПериода и КонецПериода точные временные границы. Для конкретного документа идеальным ограничителем является его МоментВремени. Но как получить этот момент времени из выбранного пользователем документа непосредственно внутри СКД, не прибегая к написанию кода в модуле объекта (в процедуре ПриКомпоновкеРезультата)?
В этой статье мы подробно разберем два эффективных и практичных способа решения данной задачи штатными средствами платформы 1С.
---
Если в вашей конфигурации используется Библиотека стандартных подсистем (БСП), то у вас есть доступ к богатому инструментарию готовых общих модулей. Вы можете динамически вычислить момент времени выбранного документа прямо в настройках параметров схемы компоновки данных.
Давайте разберем этот процесс по шагам:
НачалоПериода и КонецПериода.МоментВремени из выбранного пользователем документа:
ОбщегоНазначения.ЗначениеРеквизитаОбъекта(&ОперацияЗакрытия, "МоментВремени")
В данном примере &ОперацияЗакрытия — это имя параметра СКД, в который пользователь выбирает свой документ-регистратор.
Важное условие: Чтобы СКД могла выполнять внешние функции из общих модулей конфигурации, в настройках схемы компоновки данных или при программном выводе отчета обязательно должно быть разрешено использование системных функций. Убедитесь, что флаг Разрешить использовать внешние функции активен.
Преимущества метода:
Ограничения метода:
ОбщегоНазначения с функцией ЗначениеРеквизитаОбъекта, этот способ не сработает.---
Рассмотрим более надежный, архитектурно "чистый" и безопасный способ, который работает абсолютно в любой конфигурации 1С, включая решения на базе платформы 1С:Элемент, облачные инсталляции и безопасные режимы. Этот метод не требует написания кода и вызова внешних функций, а базируется на механизме связей наборов данных самой СКД.
Рассмотрим пошагово, как настроить данный механизм:
Шаг 1. Создание НабораДанных1 (запрос к документу)
Первым делом мы создадим вспомогательный набор данных, цель которого — быстро получить системные реквизиты выбранного пользователем документа.
НаборДанныхДокумент.
ВЫБРАТЬ
Ссылка КАК ДокументСсылка,
МоментВремени КАК МоментВремениДокумента
ИЗ
Документ.ИмяВашегоДокумента КАК ДокументИсточника
ГДЕ
Ссылка = &ВыбранныйДокумент
В этом запросе &ВыбранныйДокумент — это стандартный параметр-ссылка, который мы предоставим пользователю для выбора на форме отчета.
Шаг 2. Создание НабораДанных2 (основной запрос к регистру)
Теперь создадим основной набор данных, который будет выбирать данные из виртуальной таблицы регистра.
НаборДанныхРегистр.Хозрасчетный.ОборотыДтКт). Параметры виртуальной таблицы (Начало периода и Конец периода) оставим стандартными — например, &НачалоПериода и &КонецПериода.Шаг 3. Настройка связей наборов данных
Связующим звеном, которое передаст полученный из первого набора данных МоментВремени во второй набор данных в качестве параметров виртуальной таблицы, является вкладка Связи наборов данных.
НаборДанныхДокументНаборДанныхРегистрДокументСсылка (или любое другое ключевое поле, если требуется сопоставление аналитики).МоментВремениДокумента из источника должно передаваться в параметры приемника.НачалоПериода и/или КонецПериода (в зависимости от логики вашего отчета).При таком подходе СКД сначала выполнит легкий и быстрый запрос первого набора данных, получит МоментВремени конкретного документа, а затем передаст его напрямую в качестве параметров виртуальной таблицы во второй запрос. Выборка в базе данных произойдет мгновенно.
---
Давайте проанализируем поведение СУБД в обоих случаях, чтобы понять причины колоссальной разницы в скорости работы отчета.
Когда вы используете конструкцию вида ГДЕ Регистратор = &Регистратор, платформа делает следующее:
Когда вы передаете МоментВремени в параметры виртуальной таблицы:
---
Проанализируем еще один важнейший нюанс работы с временными точками в платформе 1С. Существует принципиальное различие между объектами МоментВремени и Граница, о котором необходимо помнить при проектировании отчетов по остаткам и оборотам:
МоментВремени в качестве параметров начала или конца периода корректно захватывает все движения, включая движения самого документа-регистратора.МоментВремени документа в параметр Период таблицы остатков, то остатки будут рассчитаны на момент времени непосредственно ПЕРЕД документом. Это означает, что движения, сделанные самим этим документом, учтены не будут!Чтобы получить остатки ПОСЛЕ проведения документа (то есть с учетом его собственных движений), в параметрах запроса необходимо использовать объект Граница с видом ВидГраницы.Включая.
Поскольку СКД не поддерживает создание новых объектов типа Граница непосредственно внутри выражений параметров схемы (оператор Новый недоступен в выражениях СКД), в ситуациях, когда вам требуются остатки после документа без написания программного кода, вы можете применить небольшую хитрость:
В выражении параметра к дате документа можно прибавить одну секунду с помощью встроенной функции СКД:
ДобавитьКДате(&ВыбраннаяДата, "СЕКУНДА", 1)
Однако помните, что данный обходной путь методически не всегда верен, если в одну и ту же секунду в системе записано и проведено несколько документов. Для абсолютно точного получения остатков "включая движения документа" на крупных базах данных рекомендуется использовать программную установку параметров типа Граница в модуле отчета.