Как правильно настроить расшифровку до документа-регистратора в отчетах СКД 1С?

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

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

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

Постановка задачи и базовый запрос

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


ВЫБРАТЬ
    ПродажиОбороты.Номенклатура,
    ПродажиОбороты.КоличествоОборот КАК Количество,
    ПродажиОбороты.СуммаОборот КАК Сумма
ИЗ
    РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты

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

Особенности работы с регистрами «Обороты» и «Остатки и обороты»

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

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

Для решения проблемы с пустыми регистраторами в регистрах остатков и оборотов применяется специальный "трюк" в запросе — преобразование значения НЕОПРЕДЕЛЕНО в NULL. Давайте посмотрим, как выглядит эта конструкция:


ВЫБОР 
    КОГДА ПродажиОстаткиИОбороты.Регистратор = НЕОПРЕДЕЛЕНО ТОГДА NULL
    ИНАЧЕ ПродажиОстаткиИОбороты.Регистратор 
КОНЕЦ КАК Регистратор

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

Пошаговый алгоритм настройки схемы компоновки данных

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

Шаг 1. Модификация текста запроса в СКД

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

Пример правильного запроса для набора данных:


ВЫБРАТЬ
    ПродажиОстаткиИОбороты.Номенклатура КАК Номенклатура,
    ВЫБОР 
        КОГДА ПродажиОстаткиИОбороты.Регистратор = НЕОПРЕДЕЛЕНО ТОГДА NULL
        ИНАЧЕ ПродажиОстаткиИОбороты.Регистратор 
    КОНЕЦ КАК Регистратор,
    ПродажиОстаткиИОбороты.ПериодСекунда КАК ПериодСекунда,
    ПродажиОстаткиИОбороты.КоличествоКонечныйОстаток КАК Остаток,
    ПродажиОстаткиИОбороты.КоличествоОборот КАК Количество
ИЗ
    РегистрНакопления.Продажи.ОстаткиИОбороты(, , Авто, , ) КАК ПродажиОстаткиИОбороты

Обратите внимание: В параметрах виртуальной таблицы мы указываем периодичность Авто. Это заставляет СКД динамически подстраивать выборку под те периоды, которые пользователь выберет в настройках отчета.

Шаг 2. Настройка ролей полей (Вкладка "Наборы данных")

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

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

Шаг 3. Использование флага «Обязательное»

В целях оптимизации СКД анализирует структуру отчета, настроенную пользователем. Если поле ПериодСекунда добавлено в запрос, но не выведено на экран в выбранных полях или группировках, платформа может полностью исключить его из итогового SQL-запроса к СУБД. Это сломает механизм расчета остатков.

Чтобы принудительно заставить систему всегда выбирать это поле из базы данных, найдите в строке поля ПериодСекунда колонку Обязательное и установите там флаг (истина).

Шаг 4. Настройка структуры отчета (Вкладка "Настройки")

Чтобы отчет выглядел презентабельно, мы не должны принудительно группировать данные по регистратору в основной структуре. Настроим структуру следующим образом:

  1. Создаем группировку по полю Номенклатура.
  2. В Выбранные поля отчета добавляем наши ресурсы (например, Количество, Сумма, Остаток).
  3. Поле Регистратор мы добавляем в список доступных полей, но убираем его из выбранных полей группировки Номенклатура. Это позволит пользователю при необходимости самостоятельно сделать расшифровку.

Альтернативный вариант: Интерактивная расшифровка

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

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

Оптимизация производительности: «Авто» против «Регистратор»

Рассмотрим ситуацию с производительностью на больших базах данных. Использование периодичности виртуальной таблицы Авто заставляет СКД выполнять сложные SQL-запросы с множественными соединениями, чтобы динамически определять временные интервалы.

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

Программная обработка расшифровки в управляемой форме

Иногда стандартное поведение расшифровки (когда при двойном клике открывается меню с выбором полей) не устраивает заказчика. Требуется, чтобы при двойном клике на ячейку с документом или даже на строку номенклатуры сразу открывалась форма соответствующего документа-регистратора.

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


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

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

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

← На главную