Как вывести данные из регистра накопления в колонки по месяцам?

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

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

Способ 1. Использование Системы компоновки данных (СКД)

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

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

Способ 2. Программный обход выборки с условиями

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

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Обороты.Подразделение КАК Подразделение,
    |   Обороты.Проект КАК Проект,
    |   Обороты.СтатьяДвиженияДенежныхСредств КАК СтатьяДДС,
    |   Обороты.СуммаПриход КАК Сумма,
    |   Обороты.Период КАК Период
    |ИЗ
    |   РегистрНакопления.ht_ПланированиеДенежныхСредств.Обороты(&Начало, &Конец, Месяц, ) КАК Обороты";

Запрос.УстановитьПараметр("Начало", НачалоГода);
Запрос.УстановитьПараметр("Конец", КонецГода);
РезультатЗапроса = Запрос.Выполнить();

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


Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
    НомерМесяца = Месяц(Выборка.Период);
    
    // В зависимости от номера месяца, записываем данные в нужную колонку
    Если НомерМесяца = 1 Тогда
        СуммаЯнварь = Выборка.Сумма;
    ИначеЕсли НомерМесяца = 2 Тогда
        СуммаФевраль = Выборка.Сумма;
    // ... и так далее для всех 12 месяцев
    КонецЕсли;
КонецЦикла;

Важный нюанс: Чтобы данные по разным месяцам одной и той же статьи "склеились" в одну строку, необходимо использовать итоги в запросе или предварительно выгрузить результат в ТаблицаЗначений и сгруппировать её.

Способ 3. Формирование колонок прямо в теле запроса (Pivot)

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

Рассмотрим пример такого запроса:


Запрос.Текст = 
    "ВЫБРАТЬ
    |   Подразделение,
    |   Проект,
    |   СтатьяДвиженияДенежныхСредств КАК СтатьяДДС,
    |   СУММА(ВЫБОР КОГДА МЕСЯЦ(Период) = 1 ТОГДА СуммаПриход ИНАЧЕ 0 КОНЕЦ) КАК Январь,
    |   СУММА(ВЫБОР КОГДА МЕСЯЦ(Период) = 2 ТОГДА СуммаПриход ИНАЧЕ 0 КОНЕЦ) КАК Февраль,
    |   СУММА(ВЫБОР КОГДА МЕСЯЦ(Период) = 3 ТОГДА СуммаПриход ИНАЧЕ 0 КОНЕЦ) КАК Март,
    |   СУММА(ВЫБОР КОГДА МЕСЯЦ(Период) = 4 ТОГДА СуммаПриход ИНАЧЕ 0 КОНЕЦ) КАК Апрель
    |ИЗ
    |   РегистрНакопления.ht_ПланированиеДенежныхСредств.Обороты(&Начало, &Конец, День, ) КАК Обороты
    |СГРУППИРОВАТЬ ПО
    |   Подразделение, Проект, СтатьяДвиженияДенежныхСредств";

В этом случае мы сразу получаем результат, где каждая строка уникальна по набору аналитик, а суммы распределены по полям Январь, Февраль и т.д. Это наиболее производительный метод для работы с большими объемами данных.

Способ 4. Метод левых соединений (по сообщению №11)

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

  1. Создаем временную таблицу ТКлючи, в которой выбираем все уникальные комбинации Подразделение + Проект + Статья.
  2. Для каждого месяца создаем отдельную временную таблицу (например, ТЗаписиЯнваря), куда фильтруем данные только за этот период.
  3. В финальном запросе соединяем ТКлючи левым соединением со всеми двенадцатью таблицами месяцев.

Пример финального объединения:


ВЫБРАТЬ
    ТКлючи.Подразделение,
    ТКлючи.Проект,
    ТЗаписиЯнваря.Сумма КАК СуммаЯнварь,
    ТЗаписиФевраля.Сумма КАК СуммаФевраль
ИЗ
    ТКлючи КАК ТКлючи
    ЛЕВОЕ СОЕДИНЕНИЕ ТЗаписиЯнваря КАК ТЗаписиЯнваря 
        ПО ТКлючи.Подразделение = ТЗаписиЯнваря.Подразделение 
        И ТКлючи.СтатьяДДС = ТЗаписиЯнваря.СтатьяДДС
    ЛЕВОЕ СОЕДИНЕНИЕ ТЗаписиФевраля КАК ТЗаписиФевраля 
        ПО ТКлючи.Подразделение = ТЗаписиФевраля.Подразделение 
        И ТКлючи.СтатьяДДС = ТЗаписиФевраля.СтатьяДДС

Резюме: Если вы делаете отчет — выбирайте СКД. Если вам нужны данные в коде для дальнейших расчетов — используйте запрос с конструкцией ВЫБОР КОГДА. Метод с ручным перебором выборки в цикле (через Если Месяц = ...) лучше оставить для самых простых задач, где не требуется высокая производительность.

← На главную