Как в СКД передать дату из документа в параметр виртуальной таблицы остатков?

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

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

Проблема: Параметр виртуальной таблицы и динамические данные

Основная сложность заключается в том, что параметры виртуальных таблиц (таких как Остатки или ОстаткиИОбороты) в запросе СКД должны быть определены до того, как запрос будет выполнен. Если мы просто напишем в запросе РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаПлана, ), система будет ожидать, что значение &ДатаПлана будет заполнено в настройках отчета. Но как заставить систему взять это значение из выбранного пользователем документа ПланЗакупок?

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

Способ 1. Использование выражений в параметрах СКД

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

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

  1. В тексте запроса набора данных используйте стандартный параметр, например:
    
    ВЫБРАТЬ
        ПланЗакупокСоставПлана.Номенклатура,
        ПланЗакупокСоставПлана.Количество,
        ТоварыНаСкладахОстатки.КоличествоОстаток
    ИЗ
        Документ.ПланЗакупок.СоставПлана КАК ПланЗакупокСоставПлана
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаПлана, ) КАК ТоварыНаСкладахОстатки
        ПО ПланЗакупокСоставПлана.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура
    ГДЕ
        ПланЗакупокСоставПлана.Ссылка = &ВыбранныйПлан
    
  2. Перейдите на вкладку Параметры.
  3. Для параметра &ДатаПлана в колонке Выражение напишите: &ВыбранныйПлан.ДатаПланирования.
  4. Убедитесь, что для параметра &ВыбранныйПлан указан правильный тип (Ссылка на документ План закупок), а параметр &ДатаПлана отмечен как Ограничение доступности (чтобы пользователь не вводил его вручную).

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

Способ 2. Связи наборов данных (Параметрическая связь)

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

Для реализации этого метода нам потребуется два набора данных:

  1. НаборДанных1 (Запрос): Выбирает основные данные из документа.
    
    ВЫБРАТЬ
        ПланЗакупок.Ссылка КАК Ссылка,
        ПланЗакупок.ДатаПланирования КАК ДатаДляОстатков,
        ПланЗакупок.Номенклатура КАК Номенклатура
    ИЗ
        Документ.ПланЗакупок КАК ПланЗакупок
    
  2. НаборДанных2 (Запрос): Выбирает остатки с использованием параметра.
    
    ВЫБРАТЬ
        Остатки.Номенклатура КАК Номенклатура,
        Остатки.КоличествоОстаток КАК Остаток
    ИЗ
        РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаПлана, ) КАК Остатки
    

Теперь самое главное — настройка на вкладке Связи наборов данных:

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

Способ 3. Программная установка в модуле объекта

Иногда логика определения даты слишком сложна для простых выражений СКД. В таких случаях мы можем использовать обработчик события ПриКомпоновкеРезультата в модуле объекта отчета. Выясним, как это сделать правильно, чтобы не нарушить работу пользовательских настроек.

Пример кода для модуля объекта:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Истина;
    
    // Получаем значение документа из пользовательских настроек
    ПараметрСсылка = Новый ПараметрКомпоновкиДанных("ВыбранныйПлан");
    ЗначениеСсылки = Неопределено;
    
    Для Каждого Элемент Из КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
        Если ТипЗнч(Элемент) = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") 
            И Элемент.Параметр = ПараметрСсылка Тогда
            ЗначениеСсылки = Элемент.Значение;
        КонецЕсли;
    КонецЦикла;

    Если ЗначениеЗаполнено(ЗначениеСсылки) Тогда
        // Получаем дату из документа
        НужнаяДата = ЗначениеСсылки.ДатаПланирования;
        
        // Устанавливаем параметр ДатаПлана
        ПараметрДата = Новый ПараметрКомпоновкиДанных("ДатаПлана");
        Для Каждого Параметр Из КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы Цикл
            Если Параметр.Параметр = ПараметрДата Тогда
                Параметр.Значение = НужнаяДата;
                Параметр.Использование = Истина;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;

КонецПроцедуры

Обратите внимание, что мы работаем с КомпоновщикНастроек.Настройки.ПараметрыДанных. Если параметр выведен в пользовательские настройки, приоритет будет иметь значение из ПользовательскиеНастройки, поэтому программную установку нужно делать внимательно, учитывая структуру настроек компоновщика.

Типичные ошибки и способы их решения

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

  1. Несовпадение времени в дате: По умолчанию остатки в 1С считаются на начало указанной секунды. Если документ ПланЗакупок создан 01.11.2018 в 12:00:00, и вы передаете эту дату в параметр остатков, движения этого самого документа не попадут в остатки. Чтобы включить движения документа, используйте объект Граница:

    Новый Граница(НужнаяДата, ВидГраницы.Включая)

    В выражении параметра СКД это можно записать как: ДобавитьКДате(КонецПериода(&ДатаПлана, "День"), "Секунда", 1) (для остатков на конец дня).
  2. Автоматический параметр "Период": СКД автоматически добавляет параметр Период для всех виртуальных таблиц. Если в вашем запросе несколько таблиц (например, остатки на дату документа и текущие остатки), СКД может попытаться "подружить" их через один общий параметр. Чтобы этого избежать, используйте разные имена параметров в круглых скобках виртуальных таблиц и отключайте у них флаг Автозаполнение.
  3. Использование "ГДЕ" вместо параметров: Одной из критических ошибок производительности является получение остатков без параметров и последующая фильтрация в секции ГДЕ.

    Плохо: ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки ГДЕ Остатки.Период = &Дата

    Хорошо: ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата, ) КАК Остатки

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

Использование функций общих модулей

Еще один продвинутый способ — вызов экспортной функции из общего модуля прямо в выражении параметра. Рассмотрим пример:

В выражении параметра &ДатаПлана пишем: МойОбщийМодуль.ПолучитьДатуДляОтчета(&ВыбранныйПлан).

В общем модуле (с флагами Сервер, Вызов сервера):


Функция ПолучитьДатуДляОтчета(СсылкаНаДокумент) Экспорт
    Если ТипЗнч(СсылкаНаДокумент) = Тип("ДокументСсылка.ПланЗакупок") Тогда
        Возврат СсылкаНаДокумент.ДатаПланирования;
    КонецЕсли;
    Возврат ТекущаяДата();
КонецФункции

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

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

← На главную