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