Как получить Момент Времени в СКД через документ из параметров без написания кода?

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

При разработке отчетов на базе Системы компоновки данных (СКД) разработчики часто сталкиваются со следующей проблемой: пользователю необходимо получить движения по регистру (накопления или бухгалтерии) для конкретного документа, выбранного на форме в качестве параметра. Казалось бы, простейшим решением является наложение условия в секции ГДЕ, например, ГДЕ Регистратор = &Регистратор.

Однако такое решение таит в себе серьезную опасность для производительности всей системы. На больших базах данных подобный подход заставляет СУБД сначала агрегировать и вычислять виртуальную таблицу по всему объему записей регистра за все время его существования, и лишь затем отфильтровывать результат по конкретному документу. Это гарантированно приводит к зависанию отчета и колоссальной нагрузке на сервер.

Чтобы отчет формировался мгновенно, необходимо жестко ограничить выборку на уровне параметров самой виртуальной таблицы, передав в НачалоПериода и КонецПериода точные временные границы. Для конкретного документа идеальным ограничителем является его МоментВремени. Но как получить этот момент времени из выбранного пользователем документа непосредственно внутри СКД, не прибегая к написанию кода в модуле объекта (в процедуре ПриКомпоновкеРезультата)?

В этой статье мы подробно разберем два эффективных и практичных способа решения данной задачи штатными средствами платформы 1С.

---

Способ 1. Использование функций общего назначения БСП в выражениях параметров

Если в вашей конфигурации используется Библиотека стандартных подсистем (БСП), то у вас есть доступ к богатому инструментарию готовых общих модулей. Вы можете динамически вычислить момент времени выбранного документа прямо в настройках параметров схемы компоновки данных.

Давайте разберем этот процесс по шагам:

  1. Откроем схему компоновки данных нашего отчета и перейдем на вкладку Параметры.
  2. Найдем параметры виртуальной таблицы, отвечающие за период. Обычно это стандартные параметры НачалоПериода и КонецПериода.
  3. В поле Выражение для параметров начала и конца периода пропишем вызов функции общего назначения, которая получит МоментВремени из выбранного пользователем документа:

ОбщегоНазначения.ЗначениеРеквизитаОбъекта(&ОперацияЗакрытия, "МоментВремени")

В данном примере &ОперацияЗакрытия — это имя параметра СКД, в который пользователь выбирает свой документ-регистратор.

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

Преимущества метода:

Ограничения метода:

---

Способ 2. Связи наборов данных (Native-метод СКД)

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

Рассмотрим пошагово, как настроить данный механизм:

Шаг 1. Создание НабораДанных1 (запрос к документу)

Первым делом мы создадим вспомогательный набор данных, цель которого — быстро получить системные реквизиты выбранного пользователем документа.

  1. Добавим в схему СКД новый Набор данных - запрос и назовем его, например, НаборДанныхДокумент.
  2. Напишем простой запрос для получения момента времени:

ВЫБРАТЬ
    Ссылка КАК ДокументСсылка,
    МоментВремени КАК МоментВремениДокумента
ИЗ
    Документ.ИмяВашегоДокумента КАК ДокументИсточника
ГДЕ
    Ссылка = &ВыбранныйДокумент

В этом запросе &ВыбранныйДокумент — это стандартный параметр-ссылка, который мы предоставим пользователю для выбора на форме отчета.

Шаг 2. Создание НабораДанных2 (основной запрос к регистру)

Теперь создадим основной набор данных, который будет выбирать данные из виртуальной таблицы регистра.

  1. Добавим второй Набор данных - запрос с именем НаборДанныхРегистр.
  2. В качестве источника выберем нужную виртуальную таблицу (например, Хозрасчетный.ОборотыДтКт). Параметры виртуальной таблицы (Начало периода и Конец периода) оставим стандартными — например, &НачалоПериода и &КонецПериода.

Шаг 3. Настройка связей наборов данных

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

  1. Перейдем на вкладку Связи наборов данных в СКД.
  2. Добавим новую строку связи:
    • Источник связи: НаборДанныхДокумент
    • Приемник связи: НаборДанныхРегистр
    • Выражение источника: ДокументСсылка (или любое другое ключевое поле, если требуется сопоставление аналитики).
    • Выражение приемника: Соответствующее поле из приемника.
  3. Самое главное — заполняем колонку Параметры для нашей связи:
    • Укажем, что поле МоментВремениДокумента из источника должно передаваться в параметры приемника.
    • Свяжем его с параметром НачалоПериода и/или КонецПериода (в зависимости от логики вашего отчета).

При таком подходе СКД сначала выполнит легкий и быстрый запрос первого набора данных, получит МоментВремени конкретного документа, а затем передаст его напрямую в качестве параметров виртуальной таблицы во второй запрос. Выборка в базе данных произойдет мгновенно.

---

Почему фильтрация в параметрах ВТ работает быстрее, чем "ГДЕ Регистратор = &Регистратор"?

Давайте проанализируем поведение СУБД в обоих случаях, чтобы понять причины колоссальной разницы в скорости работы отчета.

Когда вы используете конструкцию вида ГДЕ Регистратор = &Регистратор, платформа делает следующее:

Когда вы передаете МоментВремени в параметры виртуальной таблицы:

---

Важная методическая тонкость: "Момент Времени" против "Границы"

Проанализируем еще один важнейший нюанс работы с временными точками в платформе 1С. Существует принципиальное различие между объектами МоментВремени и Граница, о котором необходимо помнить при проектировании отчетов по остаткам и оборотам:

Чтобы получить остатки ПОСЛЕ проведения документа (то есть с учетом его собственных движений), в параметрах запроса необходимо использовать объект Граница с видом ВидГраницы.Включая.

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

В выражении параметра к дате документа можно прибавить одну секунду с помощью встроенной функции СКД:

ДобавитьКДате(&ВыбраннаяДата, "СЕКУНДА", 1)

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

← На главную