Как вывести сводную информацию из табличной части документов на новую закладку управляемой формы 1С?

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

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

Давайте рассмотрим различные подходы к решению этой задачи на управляемых формах 1С и проанализируем их преимущества и недостатки.

Основные подходы к выводу сводной информации

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

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

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

Использование Таблицы значений для вывода сводных данных

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

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

Рассмотрим пример заполнения таблицы значений:


&НаКлиенте
Процедура ЗаполнитьСводнуюИнформациюПоТаблицеЗначений()

    // Создаем таблицу значений, если она еще не создана
    Если ТипЗнч(РеквизитФормыТаблицаЗначений) = Неопределено Тогда
        РеквизитФормыТаблицаЗначений = Новый ТаблицаЗначений;
        РеквизитФормыТаблицаЗначений.Колонки.Добавить("Клиент");
        РеквизитФормыТаблицаЗначений.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
        РеквизитФормыТаблицаЗначений.Колонки.Добавить("Часы", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 2)));
    КонецЕсли;

    РеквизитФормыТаблицаЗначений.Очистить(); // Очищаем перед заполнением

    // Пример запроса (выполняется на сервере)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    Документ.Клиент КАК Клиент,
        |    СУММА(Документ.Сумма) КАК Сумма,
        |    СУММА(Документ.Часы) КАК Часы
        |ИЗ
        |    Документ.ТабличнаяЧасть КАК Документ
        |
        |СГРУППИРОВАТЬ ПО
        |    Документ.Клиент
        |
        |ИТОГИ ПО
        |    ОБЩИЕ";

    РезультатЗапроса = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);

    Для Каждого Строка ИЗ РезультатЗапроса Цикл
        НоваяСтрока = РеквизитФормыТаблицаЗначений.Добавить();
        НоваяСтрока.Клиент = Строка.Клиент;
        НоваяСтрока.Сумма = Строка.Сумма;
        НоваяСтрока.Часы = Строка.Часы;
    КонецЦикла;

    // Добавляем общий итог
    Если РезультатЗапроса.Итоги() <> Неопределено Тогда
        НоваяСтрока = РеквизитФормыТаблицаЗначений.Добавить();
        НоваяСтрока.Клиент = "ИТОГО";
        НоваяСтрока.Сумма = РезультатЗапроса.Итоги().Сумма;
        НоваяСтрока.Часы = РезультатЗапроса.Итоги().Часы;
    КонецЕсли;

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

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

Использование Поля табличного документа на форме

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

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

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

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

Программное заполнение табличного документа без макета

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

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

На стороне сервера должен быть выполнен запрос, результатом которого будут наши агрегированные данные. Предположим, что функция на сервере возвращает объект РезультатЗапроса.


&НаСервере
Функция ПолучитьСводныеДанныеСервер()

    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    Документ.Клиент КАК Клиент,
        |    СУММА(Документ.Сумма) КАК Сумма,
        |    СУММА(Документ.Часы) КАК Часы
        |ИЗ
        |    Документ.ТабличнаяЧасть КАК Документ
        |
        |СГРУППИРОВАТЬ ПО
        |    Документ.Клиент
        |
        |ИТОГИ ПО
        |    ОБЩИЕ"; // Для получения общего итога

    Возврат Запрос.Выполнить();

КонецФункции

&НаКлиенте
Процедура ЗаполнитьСводныйТабличныйДокументБезМакета()

    Результат = ПолучитьСводныеДанныеСервер(); // Получаем результат запроса с сервера

    // Инициализируем реквизит формы типа ТабличныйДокумент
    Если ТипЗнч(СводныйТабличныйДокумент) = Неопределено Тогда
        СводныйТабличныйДокумент = Новый ТабличныйДокумент;
    КонецЕсли;

    СводныйТабличныйДокумент.Очистить(); // Очищаем перед новым заполнением

    // Определяем параметры форматирования, если нужно
    ШрифтЗаголовка = Новый Шрифт(,,Истина);
    ШрифтИтогов = Новый Шрифт(,,Истина,Истина);
    ЦветФонаИтогов = Новый Цвет(240, 240, 240); // Светло-серый фон

    // Вывод заголовков колонок
    КоличествоКолонок = Результат.Колонки.Количество();
    НомерТекущейСтроки = 1;

    Для ИндексКолонки = 0 По КоличествоКолонок - 1 Цикл
        КолонкаЗапроса = Результат.Колонки[ИндексКолонки];
        ОбластьЗаголовка = СводныйТабличныйДокумент.Область(НомерТекущейСтроки, ИндексКолонки + 1);
        ОбластьЗаголовка.Текст = КолонкаЗапроса.Имя;
        ОбластьЗаголовка.Шрифт = ШрифтЗаголовка;
        ОбластьЗаголовка.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
        ОбластьЗаголовка.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
        ОбластьЗаголовка.ЦветФона = Новый Цвет(200, 220, 255); // Пример цвета фона
        ОбластьЗаголовка.ГраницаСлева = Новый Линия(ТипЛинииТабличногоДокумента.Тонкая);
        ОбластьЗаголовка.ГраницаСверху = Новый Линия(ТипЛинииТабличногоДокумента.Тонкая);
        ОбластьЗаголовка.ГраницаСправа = Новый Линия(ТипЛинииТабличногоДокумента.Тонкая);
        ОбластьЗаголовка.ГраницаСнизу = Новый Линия(ТипЛинииТабличногоДокумента.Тонкая);
    КонецЦикла;
    СводныйТабличныйДокумент.Вывести(СводныйТабличныйДокумент.ПолучитьОбласть(НомерТекущейСтроки, 1, НомерТекущейСтроки, КоличествоКолонок));
    НомерТекущейСтроки = НомерТекущейСтроки + 1;

    // Вывод детальных записей
    Выборка = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); // Используем ПоГруппировкам для получения группировок и общих итогов
    Пока Выборка.Следующий() Цикл
        Если Выборка.Уровень() = 0 Тогда // Это детальная запись или группировка первого уровня
            Для ИндексКолонки = 0 По КоличествоКолонок - 1 Цикл
                КолонкаЗапроса = Результат.Колонки[ИндексКолонки];
                ОбластьДанных = СводныйТабличныйДокумент.Область(НомерТекущейСтроки, ИндексКолонки + 1);
                ОбластьДанных.Текст = Выборка[КолонкаЗапроса.Имя];
                ОбластьДанных.ГраницаСлева = Новый Линия(ТипЛинииТабличногоДокумента.Тонкая);
                ОбластьДанных.ГраницаСверху = Новый Линия(ТипЛинииТабличногоДокумента.Тонкая);
                ОбластьДанных.ГраницаСправа = Новый Линия(ТипЛинииТабличногоДокумента.Тонкая);
                ОбластьДанных.ГраницаСнизу = Новый Линия(ТипЛинииТабличногоДокумента.Тонкая);
            КонецЦикла;
            СводныйТабличныйДокумент.Вывести(СводныйТабличныйДокумент.ПолучитьОбласть(НомерТекущейСтроки, 1, НомерТекущейСтроки, КоличествоКолонок));
            НомерТекущейСтроки = НомерТекущейСтроки + 1;
        КонецЕсли;
    КонецЦикла;

    // Вывод общего итога, если он есть
    Если Результат.Итоги() <> Неопределено Тогда
        ОбластьИтогов = СводныйТабличныйДокумент.Область(НомерТекущейСтроки, 1, НомерТекущейСтроки, КоличествоКолонок);
        
        // Для первой колонки (Клиент)
        СводныйТабличныйДокумент.Область(НомерТекущейСтроки, 1).Текст = "ИТОГО";
        СводныйТабличныйДокумент.Область(НомерТекущейСтроки, 1).Шрифт = ШрифтИтогов;
        СводныйТабличныйДокумент.Область(НомерТекущейСтроки, 1).ЦветФона = ЦветФонаИтогов;
        СводныйТабличныйДокумент.Область(НомерТекущейСтроки, 1).ГраницаСлева = Новый Линия(ТипЛинииТабличногоДокумента.Тонкая);
        СводныйТабличныйДокумент.Область(НомерТекущейСтроки, 1).ГраницаСверху = Новый Линия(ТипЛинииТабличногоДокумента.Тонкая);
        SvodnyyTablichnyyDokument.ObRast(NomerTekushcheyStroki, 1).GranitsaSprava = Novaya Liniya(TipLiniiTablichnogoDokumenta.Tonkaya);
        SvodnyyTablichnyyDokument.ObRast(NomerTekushcheyStroki, 1).GranitsaSnizu = Novaya Liniya(TipLiniiTablichnogoDokumenta.Tonkaya);

        // Для колонки Сумма
        Для ИндексКолонки = 1 По КоличествоКолонок - 1 Цикл // Начинаем со второй колонки (индекс 1)
            КолонкаЗапроса = Результат.Колонки[ИндексКолонки];
            СводныйТабличныйДокумент.Область(НомерТекущейСтроки, ИндексКолонки + 1).Текст = Результат.Итоги()[КолонкаЗапроса.Имя];
            СводныйТабличныйДокумент.Область(НомерТекущейСтроки, ИндексКолонки + 1).Шрифт = ШрифтИтогов;
            СводныйТабличныйДокумент.Область(НомерТекущейСтроки, ИндексКолонки + 1).ЦветФона = ЦветФонаИтогов;
            SvodnyyTablichnyyDokument.ObRast(NomerTekushcheyStroki, IndeksKolonki + 1).GranitsaSleva = Novaya Liniya(TipLiniiTablichnogoDokumenta.Tonkaya);
            SvodnyyTablichnyyDokument.ObRast(NomerTekushcheyStroki, IndeksKolonki + 1).GranitsaSverhu = Novaya Liniya(TipLiniiTablichnogoDokumenta.Tonkaya);
            SvodnyyTablichnyyDokument.ObRast(NomerTekushcheyStroki, IndeksKolonki + 1).GranitsaSprava = Novaya Liniya(TipLiniiTablichnogoDokumenta.Tonkaya);
            SvodnyyTablichnyyDokument.ObRast(NomerTekushcheyStroki, IndeksKolonki + 1).GranitsaSnizu = Novaya Liniya(TipLiniiTablichnogoDokumenta.Tonkaya);
        КонецЦикла;
        
        СводныйТабличныйДокумент.Вывести(ОбластьИтогов);
    КонецЕсли;

    // Автоматическая ширина колонок
    Для ИндексКолонки = 1 По КоличествоКолонок Цикл
        СводныйТабличныйДокумент.УстановитьШиринуКолонки(ИндексКолонки, СводныйТабличныйДокумент.ПолучитьШиринуКолонки(ИндексКолонки) + 1);
    КонецЦикла;

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

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

Это подробное решение отвечает на вопрос из сообщения 8 о том, откуда брать ОбластьВывода – она формируется динамически методом ТабличныйДокумент.Область() или ТабличныйДокумент.ПолучитьОбласть().

Заполнение табличного документа с использованием макета

Более структурированным и часто предпочтительным способом является использование макетов табличного документа. Этот подход, упомянутый в сообщении 11, позволяет отделить логику формирования данных от их оформления. В этом случае мы:

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

Давайте посмотрим на пример кода с использованием макета. Предположим, у нас есть макет с именем "МакетСводнойИнформации", в котором определены области:


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

    Возврат Запрос.Выполнить();
КонецФункции

&НаКлиенте
Процедура ЗаполнитьСводныйТабличныйДокументСМакетом()

    Результат = ПолучитьСводныеДанныеСервер();

    // Инициализируем реквизит формы типа ТабличныйДокумент
    Если ТипЗнч(СводныйТабличныйДокумент) = Неопределено Тогда
        СводныйТабличныйДокумент = Новый ТабличныйДокумент;
    КонецЕсли;

    СводныйТабличныйДокумент.Очистить();

    // Загружаем макет
    Макет = ПолучитьМакет("МакетСводнойИнформации"); // Если макет в документе, то Объект.ПолучитьМакет()

    // Получаем области макета
    ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
    ОбластьДетальныеЗаписи = Макет.ПолучитьОбласть("ДетальныеЗаписи");
    ОбластьИтоги = Макет.ПолучитьОбласть("Итоги");

    // Выводим заголовок
    СводныйТабличныйДокумент.Вывести(ОбластьЗаголовок);

    // Выводим детальные записи
    Выборка = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    Пока Выборка.Следующий() Цикл
        Если Выборка.Уровень() = 0 Тогда // Детальные записи
            ОбластьДетальныеЗаписи.Параметры.Заполнить(Выборка); // Заполняем параметры из выборки
            СводныйТабличныйДокумент.Вывести(ОбластьДетальныеЗаписи);
        КонецЕсли;
    КонецЦикла;

    // Выводим итоги
    Если Результат.Итоги() <> Неопределено Тогда
        ОбластьИтоги.Параметры.ОбщаяСумма = Результат.Итоги().Сумма;
        ОбластьИтоги.Параметры.ОбщиеЧасы = Результат.Итоги().Часы;
        СводныйТабличныйДокумент.Вывести(ОбластьИтоги);
    КонецЕсли;

    // Опционально: устанавливаем режим просмотра
    СводныйТабличныйДокумент.Показать(); // В случае реквизита формы, это не всегда нужно. Элемент формы сам отобразит.

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

Использование макетов делает код более читаемым и упрощает изменение внешнего вида без правки программного кода. Область.Параметры.Заполнить(Выборка) автоматически сопоставляет имена параметров в макете с именами полей в выборке запроса.

Использование Отчета на Системе Компоновки Данных (СКД)

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

Упоминание в сообщении 2 "использование отчета. Без макетов и прочего" и последующее удивление в сообщении 13 ("Отчет без макета? Это что-то новенькое...") указывает на непонимание того, как работает СКД. СКД может формировать отчет без явно созданного разработчиком макета. В этом случае она использует свой "стандартный макет", формируемый автоматически на основе настроек компоновки данных (группировки, поля, ресурсы).

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

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

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

    Для этого мы:

    1. Программно формируем СхемуКомпоновкиДанных.
    2. Создаем КомпоновщикМакетаКомпоновкиДанных для получения МакетаКомпоновкиДанных.
    3. Создаем ПроцессорКомпоновкиДанных для выполнения компоновки и получения ПроцессорВыводаКомпоновкиДанных, который выведет результат в ТабличныйДокумент.

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

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

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

Использование Динамического списка

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

Для использования динамического списка:

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

// Пример произвольного запроса для динамического списка (указывается в свойстве "ПроизвольныйЗапрос")
// ВЫБРАТЬ
//     ДокументСсылка.Клиент КАК Клиент,
//     СУММА(ДокументСсылка.Сумма) КАК СуммаПоКлиенту,
//     СУММА(ДокументСсылка.Часы) КАК ЧасыПоКлиенту
// ИЗ
//     Документ.ИмяВашегоДокумента.ТабличнаяЧасть КАК ДокументСсылка
//
// СГРУППИРОВАТЬ ПО
//     ДокументСсылка.Клиент

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

Выбор оптимального варианта

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

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

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

← На главную