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

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

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

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

Способ 1. Использование встроенных возможностей платформы 1С для просмотра временных таблиц

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

Для этого установим точку останова в коде после того, как пакет запросов (или его часть) был выполнен, но менеджер временных таблиц еще не уничтожен. Откроем окно «Вычислить выражение» (сочетание клавиш Shift+F9) или воспользуемся панелью «Табло».

Вариант А. Получение данных по индексу таблицы

Если мы знаем порядковый номер временной таблицы в пакете, мы можем обратиться к ней напрямую по индексу. Введем следующее выражение:

Запрос.МенеджерВременныхТаблиц.Таблицы[0].ПолучитьДанные().Выгрузить()

После вычисления этого выражения платформа вернет объект ТаблицаЗначений. Чтобы детально рассмотреть ее строки и колонки, достаточно нажать клавишу F2 на клавиатуре — откроется удобное стандартное окно просмотра коллекций 1С.

Вариант Б. Получение данных по имени временной таблицы

Часто индексы таблиц могут меняться при изменении логики программы, поэтому гораздо надежнее обращаться к ним по имени. Используем метод поиска по имени:


Запрос.МенеджерВременныхТаблиц.Таблицы.Найти("ИмяВременнойТаблицы").ПолучитьДанные().Выгрузить()

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

Вариант В. Выполнение всего пакета запросов с промежуточными данными

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


Запрос.ВыполнитьПакетСПромежуточнымиДанными()[ИндексВременнойТаблицы].Выгрузить()

Этот метод выполняет весь пакет запросов и возвращает массив результатов, где для каждого запроса пакета (включая создание ВТ) содержится полноценная таблица с данными.

Хитрость: Подмена текста запроса прямо в отладчике

Представим ситуацию: нам нужно выполнить произвольный запрос к уже созданным в памяти временным таблицам. Мы можем сделать это прямо в окне вычисления выражений за несколько простых шагов:

  1. В окне «Вычислить выражение» временно подменим текст запроса:
    
    Запрос.Текст = "ВЫБРАТЬ * ИЗ ИмяВременнойТаблицы Где ВажноеПоле = &ЗначениеПараметра"
    
  2. Вычислим результат выполнения этого нового запроса: Запрос.Выполнить().Выгрузить()
  3. Проанализируем полученную таблицу значений через кнопку просмотра F2.
  4. Чтобы программа продолжила корректно работать дальше, вернем исходный текст запроса обратно в свойство Запрос.Текст.

Способ 2. Извлечение финального текста запроса и параметров из макета компоновки

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

Разберем по шагам, как перехватить этот макет:

  1. Найдем в коде отчета строку, где вызывается выполнение компоновщика макета:
    
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, НастройкиКомпоновки, ДанныеРасшифровки);
    
  2. Установим точку останова сразу после выполнения этой строки.
  3. В окне вычисления выражений обратимся к структуре макета.

Для получения реального текста запроса введем выражение:

МакетКомпоновки.НаборыДанных.НаборДанных1.Запрос

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

Для получения параметров запроса, которые СКД автоматически рассчитала и подготовила к передаче, выполним выражение:

МакетКомпоновки.ЗначенияПараметров

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

Способ 3. Использование "Инструментов разработчика" (ИР)

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

Разберем два сценария использования функции От() для отладки СКД.

Сценарий 1. Отладка схемы и настроек компоновки

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

От(СхемаКомпоновки, НастройкаКомпоновки, ВнешниеНаборыДанных)

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

Сценарий 2. Отладка готового макета компоновки

Если отчет формирует макет динамически, меняет его структуру "на лету" и только потом передает его процессору компоновки, нам нужно анализировать именно готовый макет. Для этого в точке останова вызовем функцию:

От(МакетКомпоновкиДанных)

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

Способ 4. Программный вывод временных таблиц (внедрение отладочного кода)

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

Рассмотрим пример такой процедуры:


Процедура ПоказатьВременнуюТаблицу(МенеджерВТ, ИмяТаблицы) Экспорт
    ЗапросОтладки = Новый Запрос;
    ЗапросОтладки.МенеджерВременныхТаблиц = МенеджерВТ;
    ЗапросОтладки.Текст = "ВЫБРАТЬ * ИЗ " + ИмяТаблицы;
    Попытка
        ТЗРезультат = ЗапросОтладки.Volnit().Выгрузить();
        
        // Запишем ее в XML для анализа в Журнале регистрации
        ЗаписьXML = Новый ЗаписьXML;
        ЗаписьXML.УстановитьСтроку();
        ЗаписатьXML(ЗаписьXML, ТЗРезультат);
        ТекстXML = ЗаписьXML.Закрыть();
        
        ЗаписьЖурналаРегистрации("ОтладкаСКД", 
            УровеньЖурналаРегистрации.Информация, 
            , 
            , 
            "Данные таблицы " + ИмяТаблицы + ": " + ТекстXML);
    Исключение
        ВызватьИсключение "Ошибка при выгрузке временной таблицы: " + ОписаниеОшибки();
    КонецПопытки;
КонецПроцедуры

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

ПоказатьВременнуюТаблицу(НашМенеджерВТ, "ВТ_ИтоговыеСуммы");

Этот метод особенно удобен при фоновом выполнении задач на сервере, когда мы не можем напрямую подключиться интерактивным отладчиком к сеансу. Мы просто заглядываем в Журнал регистрации и анализируем структуру нашей таблицы.

Способ 5. Менеджер временных таблиц как связующее звено

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

Если вы столкнулись с такой архитектурой, помните, что вы можете контролировать процесс на этапе инициализации процессора компоновки данных. Обратите внимание на метод Инициализировать() объекта ПроцессорКомпоновкиДанных:


ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки, Истина);

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

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

← На главную