Как задать разные периоды для виртуальных таблиц в одном отчете СКД

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

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

Метод 1: Использование нескольких наборов данных с отключенным автозаполнением

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

Разберем этот процесс по шагам:

  1. Создадим в схеме компоновки данных два набора данных — типа «Запрос».
  2. В первом наборе данных напишем запрос к виртуальной таблице оборотов. В параметрах таблицы укажем уникальные имена, например, &НачалоПериодаОборотов и &КонецПериодаОборотов.
  3. Во втором наборе данных обратимся к таблице остатков. Здесь укажем параметр &ДатаОстатков.
  4. Важный момент: на вкладке «Наборы данных» для каждого запроса необходимо снять галочку «Автозаполнение». Это предотвратит попытки СКД автоматически добавить стандартные параметры периода, которые могли бы конфликтовать с нашими ручными настройками.
  5. Перейдем на закладку «Компоновка данных» внутри конструктора запроса и вручную добавим поля, которые должны быть доступны в отчете (Номенклатура, Склад, КоличествоОборот, КоличествоОстаток).
  6. Настроим связь наборов данных на соответствующей вкладке по ключевым полям (например, по Номенклатура).

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

Метод 2: Объединение (UNION ALL) и расширение языка запросов

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

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


ВЫБРАТЬ
    Обороты.Номенклатура КАК Номенклатура,
    Обороты.КоличествоРасход КАК Расход,
    0 КАК Остаток
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Обороты({&НачалоГода}, {&КонецГода}, , ) КАК Обороты

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Остатки.Номенклатура,
    0,
    Остатки.КоличествоОстаток
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки({&КонецПрошлогоМесяца}, ) КАК Остатки

Почему ОБЪЕДИНИТЬ ВСЕ эффективнее соединения? При соединении (особенно ПОЛНОЕ СОЕДИНЕНИЕ) двух виртуальных таблиц база данных строит сложный план выполнения, который может привести к значительному потреблению памяти при больших объемах данных. При объединении данные просто «склеиваются» в один поток, а последующая группировка ресурсами СКД происходит гораздо быстрее.

Метод 3: Использование выражений в параметрах СКД

Выясним, как сделать отчет удобным для пользователя. Если мы заставим пользователя вводить три разные даты (начало года, конец года, конец месяца), это повысит риск ошибки. Мы можем автоматизировать расчет зависимых периодов.

Посмотрим на пример настройки на вкладке «Параметры» в СКД:

  1. Оставим доступным для пользователя только один стандартный параметр &ПериодОтчета (типа СтандартныйПериод).
  2. Для параметра &ДатаОстатков снимем галочку «Включать в доступные поля».
  3. В колонке «Выражение» для &ДатаОстатков пропишем формулу на языке выражений СКД:

ДобавитьКДате(КонецПериода(&ПериодОтчета.ДатаОкончания, "Месяц"), "Секунда", -1)

Или, если нужно получить именно конец прошлого месяца относительно текущей даты:

ДобавитьКДате(НачалоПериода(&ТекущаяДата, "Месяц"), "Секунда", -1)

Это позволит системе самостоятельно вычислять нужные моменты времени, оставляя интерфейс отчета лаконичным.

Важные нюансы настройки ролей полей

При использовании сложных объединений или нескольких наборов данных критически важно правильно настроить Роли полей на вкладке «Наборы данных». Если мы просто выведем остаток как обычное числовое поле, СКД при группировке (например, по иерархии номенклатуры) начнет его суммировать как ресурс. В итоге вы получите неверные данные.

Что нужно сделать:

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

Метод 4: Использование периодичности виртуальной таблицы

Существует еще один подход, упомянутый в обсуждении — задать в виртуальной таблице ОстаткиИОбороты периодичность Месяц. В этом случае запрос вернет остатки на начало и конец каждого месяца внутри выбранного периода. Однако, как верно заметили участники форума, этот метод имеет существенный недостаток: если по товару не было движений в конкретном месяце, запись по нему может отсутствовать в выборке (в зависимости от настроек дополнения периодов), и вы потеряете остаток, который «висит» мертвым грузом на складе.

Поэтому для задач, где требуется гарантированный остаток на произвольную дату и обороты за широкий интервал, связка двух разных виртуальных таблиц через ОБЪЕДИНИТЬ ВСЕ или через разные наборы данных остается «золотым стандартом» разработки в 1С.

← На главную