При разработке отчетов в системе 1С:Предприятие 8.3 часто возникает задача, когда необходимо представить данные в иерархическом виде: основной документ, а под ним – все документы, которые являются его регистраторами, то есть создали движения по регистрам, связанные с этим основным документом. Типичным примером является отчет по больничным листам, где для каждого больничного листа нужно увидеть, какие документы (например, начисления, отсутствие на работе) были связаны с ним. В этом руководстве мы подробно разберем, как реализовать такую структуру отчета с помощью Системы Компоновки Данных (СКД), используя несколько наборов данных и параметры связи. Отметим, что мы рассматриваем визуальную настройку.
Задача кажется нетривиальной, поскольку СКД по умолчанию не предлагает прямой механизм для автоматического получения всех регистраторов для произвольного документа. Однако, используя возможности виртуальных таблиц регистров и гибкую настройку связей наборов данных, мы можем добиться желаемого результата.
Давайте рассмотрим ситуацию: у нас есть документ "Больничный лист", и мы хотим видеть, какие записи в регистрах сведений или накопления были сделаны по этому больничному листу, а также какие документы эти записи породили. Например, документ "Начисление зарплаты" может быть регистратором по отношению к больничному листу, если он рассчитывал какие-либо суммы по этому больничному. Наша цель – собрать эти данные в единый, структурированный отчет.
СКД по своей природе ориентирована на работу с одним или несколькими связанными источниками данных (таблицами, регистрами, документами). Чтобы объединить информацию об основном документе и его движениях через регистраторы, нам потребуется использовать два независимых набора данных и затем установить между ними логическую связь.
Прежде всего, нам нужен набор данных, который будет извлекать информацию об основных документах. В нашем примере это будут документы "Больничный лист".
ВЫБРАТЬ
БольничныйЛист.Ссылка КАК БольничныйЛист,
БольничныйЛист.Дата КАК ДатаБольничногоЛиста,
БольничныйЛист.Сотрудник КАК Сотрудник
ИЗ
Документ.БольничныйЛист КАК БольничныйЛист
Здесь БольничныйЛист.Ссылка – это уникальный идентификатор каждого документа "Больничный лист". Это поле будет ключевым для связи с вторым набором данных.
Теперь нам нужен второй набор данных, который будет получать информацию о движениях регистров, а главное – о документах, которые эти движения породили (регистраторах). Мы будем использовать виртуальную таблицу "Движения" соответствующего регистра.
Движения нужного регистра. В нашем примере, предположим, что больничные листы могут создавать движения в регистре сведений НачисленияБольничныхЛистов или в регистре накопления ВзаиморасчетыПоЗарплате. Мы возьмем НачисленияБольничныхЛистов для примера.
ВЫБРАТЬ
ДвиженияРегистра.Регистратор КАК ДокументРегистратор,
ДвиженияРегистра.Период КАК ДатаДвижения,
ДвиженияРегистра.ВидДвижения КАК ВидДвижения,
ДвиженияРегистра.Сотрудник КАК СотрудникДвижения,
ДвиженияРегистра.БольничныйЛист КАК БольничныйЛистИзДвижения
ИЗ
РегистрСведений.НачисленияБольничныхЛистов.Движения КАК ДвиженияРегистра
ГДЕ
ДвиженияРегистра.БольничныйЛист = &БольничныйЛистПараметр
Обратите внимание на строку ГДЕ ДвиженияРегистра.БольничныйЛист = &БольничныйЛистПараметр. Здесь &БольничныйЛистПараметр – это параметр запроса. Мы будем передавать в него значение ссылки на БольничныйЛист из первого набора данных.
Если вам нужно получить регистраторы из нескольких регистров, вы можете либо сделать "Объединение" в рамках этого запроса, либо создать отдельные наборы данных для каждого регистра и затем объединить их через механизм СКД. Для простоты сейчас рассматриваем один регистр.
Это самый важный шаг. Нам нужно "сказать" СКД, что для каждого элемента из первого набора данных (ОсновныеДокументы) нужно выполнить запрос второго набора данных (ДвиженияРегистраторов), передав в него ссылку на текущий основной документ.
БольничныйЛист из набора данных "ОсновныеДокументы". Это ссылка на документ "Больничный лист".БольничныйЛистПараметр, который мы определили в запросе второго набора данных "ДвиженияРегистраторов".Таким образом, мы настроили передачу ссылки на каждый основной документ в запрос, который извлекает движения регистров, фильтруя их по этой ссылке.
Теперь, когда данные связаны, нам нужно правильно настроить структуру отчета, чтобы получить желаемую иерархию.
Сотрудник из набора данных "ОсновныеДокументы" (если это актуально для вашего отчета).Сотрудник добавьте следующую группировку – по полю БольничныйЛист из набора данных "ОсновныеДокументы". Это будет наш основной документ.БольничныйЛист добавьте "Детальные записи". Убедитесь, что для этих детальных записей в поле "Используемые поля" (или в соответствующем списке) выбраны поля из набора данных "ДвиженияРегистраторов" (например, ДокументРегистратор, ДатаДвижения, ВидДвижения).Пример желаемой структуры в макете СКД будет выглядеть примерно так:
- Сотрудник (Группировка из "ОсновныеДокументы")
- БольничныйЛист (Группировка из "ОсновныеДокументы")
- Детальные записи (из "ДвиженияРегистраторов")
- Поле: ДокументРегистратор
- Поле: ДатаДвижения
- Поле: ВидДвижения
Что делать, если нужные регистраторы находятся в нескольких регистрах? Есть несколько подходов:
ОБЪЕДИНИТЬ ВСЕ в запросе второго набора данных для сбора данных из разных виртуальных таблиц Движения разных регистров. Главное, чтобы структуры выбираемых полей были совместимы.
ВЫБРАТЬ
ДвиженияРС.Регистратор КАК ДокументРегистратор,
ДвиженияРС.Период КАК ДатаДвижения,
"РегистрСведений" КАК ТипРегистра,
ДвиженияРС.БольничныйЛист КАК БольничныйЛистИзДвижения
ИЗ
РегистрСведений.НачисленияБольничныхЛистов.Движения КАК ДвиженияРС
ГДЕ
ДвиженияРС.БольничныйЛист = &БольничныйЛистПараметр
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ДвиженияРН.Регистратор КАК ДокументРегистратор,
ДвиженияРН.Период КАК ДатаДвижения,
"РегистрНакопления" КАК ТипРегистра,
ДвиженияРН.ИзмерениеБольничныйЛист КАК БольничныйЛистИзДвижения
ИЗ
РегистрНакопления.ВзаиморасчетыПоЗарплате.Движения КАК ДвиженияРН
ГДЕ
ДвиженияРН.ИзмерениеБольничныйЛист = &БольничныйЛистПараметр
Обратите внимание на добавление поля ТипРегистра для лучшего понимания источника данных в отчете и на возможное различие в именах полей (например, БольничныйЛист и ИзмерениеБольничныйЛист).
Движения могут быть ресурсоемкими. Если вы используете не прямые запросы, а внешние источники, обратите внимание на статью про оптимизацию отчетов с набором данных - объект. Старайтесь максимально точно указывать условия в секции ГДЕ для минимизации выборки данных.Ссылка или уникальные идентификаторы для связи наборов данных, чтобы избежать неоднозначностей.&БольничныйЛистПараметр) автоматически появился на вкладке "Параметры" для этого набора данных.Таким образом, используя механизм нескольких наборов данных и параметров связи в СКД, мы получаем мощный инструмент для построения сложных иерархических отчетов, объединяющих данные об основном объекте и его движениях, что значительно расширяет аналитические возможности системы 1С:Предприятие. А если вы хотите предоставить продвинутым пользователям возможность самим настраивать подобные связи без Конфигуратора, вам может быть интересна Пользовательская СКД в виде внешнего отчета.