Давно заметил, что ничего так не радует глаз пользователя и не заставляет его ценить твою профпригодность как наличие множества "галочек", "штучек", "пимпочек" и кнопочек на экранной форме. Ну, конечно, при условии, что все они работают и работают правильно. У меня обычно выходило так, что большинство написанных отчетов обрастали по меньшей мере еще третью от первоначального количества опций, а код угрожающе кренился в полную сумятицу от перегрузки условными операторами и дополнительными переменными.
Примечательно, что в основном приходится по разному группировать либо фильтровать одни и те же данные. Традиционно это делается безжалостным вторжением через оператор Если в тело запроса и процедуру печати. Конечно сам код от этого не становился ни понятнее ни проще, а где-то, где получение данных запросом было невозможно все превращалось в дикие танцы вокруг таблицы значений.
У каждого программиста есть свой способ выводить ТЗ на печать по нужным группировкам - кто то использует класс индексированных таблиц, а кто-то сам вводит в ТЗ индексы, а может есть и еще более или менее эффективные способы. Речь сейчас не о них.
Столкнувшись недавно с проблемой наличия просто сумасшедшего количества необходимых пользователю вариантов группировки данных для вывода на печать да еще и слитых из двух разных конфигураций твердо решил засунуть построение итоговой таблицы значений в одну процедуру. Независимо от количества групп и нужного пользователю порядка их следования.
Когда эту проблему удалось решить вслед за ней решилась и вторая проблема - создание печатных форм. Формат печаной формы также может быть универсальным - достаточно разработать макет вывода для каждого из уровней группировки, а в таблицу значений, получаемую для вывода на печать просто добавляем колонку с уровнем группировки и в зависимости от значения этого уровня применяем нужную секцию печатной таблицы. Весьма типичный пример того как правильное решение одной проблемы приводит к упрощению решения другой.
В чистом остатке мы получили 1(одну) функцию получения предназначенной для печати таблицы значений для любых возможных вариантов группировки и очень простую печатную форму для опять же любого варианта отчета.
Макет печаной формы приведен на картинке, а сама функция звучит так:
Функция ИтоговаяПоГруппировкамТЗ(исхТЗ,СтрГруппировок,СтрИтогов,ДобУровень = 0)
Если (ПустоеЗначение(СтрГруппировок) = 1) Или (ПустоеЗначение(СтрИтогов) = 1) Тогда
Предупреждение("Не отмечены поля группировок или поля итогов!!!");
Возврат "";
КонецЕсли;
ТЗ = СоздатьОбъект("ТаблицаЗначений");
исхТЗ.Выгрузить(ТЗ,,,СтрГруппировок+","+СтрИтогов);
ТЗ.Свернуть(СтрГруппировок,стрИтогов);
ТЗИтогов = СоздатьОбъект("ТаблицаЗначений");
ТЗ.Выгрузить(ТЗИтогов);
спТаблиц = СоздатьОбъект("СписокЗначений");
спСвертки = СоздатьОбъект("СписокЗначений");
свернутьПо = "";
сДляСписка = СтрЗаменить(стрГруппировок,",",РазделительСтрок);
СчетчикЦикла = 0;
Для ф = 1 По СтрКоличествоСтрок(сДляСписка) Цикл
спСвертки.ДобавитьЗначение(СтрПолучитьСтроку(сДляСписка,ф));
КонецЦикла;
Для ф=1 По спСвертки.РазмерСписка()-1 Цикл
времТ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.Выгрузить(времТ);
свернутьПо = свернутьПо + ?(ф=1,"",",") + спСвертки.ПолучитьЗначение(ф);
времТ.Свернуть(свернутьПо,СтрИтогов);
спТаблиц.ДобавитьЗначение(времТ,свернутьПо);
КонецЦикла;
Если ДобУровень = 1 Тогда
ТЗ.НоваяКолонка("Уровень_Группировки","Число");
КонецЕсли;
Для ф=1 По спТаблиц.РазмерСписка() Цикл
времТ = СпТаблиц.ПолучитьЗначение(ф);
ВремТ.ВыбратьСтроки();
Пока ВремТ.ПолучитьСтроку() = 1 Цикл
ТЗ.НоваяСтрока();
Для ы = 1 По ВремТ.КоличествоКолонок() Цикл
идКолонки = времТ.ПолучитьПараметрыКолонки(ы);
текЗнач = ВремТ.ПолучитьЗначение(времТ.НомерСтроки,идКолонки);
ТЗ.УстановитьЗначение(ТЗ.НомерСтроки,идКолонки,текЗнач);
Если ДобУровень = 1 Тогда
ТЗ.УстановитьЗначение(ТЗ.НомерСтроки,"Уровень_Группировки",ф);
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЦикла;
ТЗ.Сортировать(стрГруппировок);
Возврат ТЗ;
КонецФункции
ИсхТЗ - это обычная таблица значений, как на первом рисунке, а возвращаемая таблица значений показана на втором рисунке.
СтрГруппировок - это обычная строка с разделенными запятыми идентификаторами полей группировки.
А СтрИтогов - строковое выражение из идентификаторов суммируемых при группировке колонок.
Когда родилась универсальная функция возникла идея сделать ее логичное продолжение - универсальную обработку. Универсальная группировка и универсальная печать любой переданной параметром таблицы значений должна, имхо, сильно пригодиться в том случае когда удается получить таблицу значений, а вот с группировками и печатью заморачиваться некогда или не хочется, да и заказчик сам толком не понимает в каком виде ему будет удобнее анализировать данные (а скорее всего в каких видах). Обработка имеет и демо режим запуска без переданной таблицы значений - в этом случае ТЗ будет сгенерирована автоматически и весь функционал обработки можно будет оценить без построения ненужной ТЗ передачи ее с вызовом из ненужной обработки.
Еще как опцию ввел в обработку фильтр значений ТЗ. Сначала думал, отбор можно сделать предварительно, до передачи таблицы в обработку, но раз уж делать универсальную фабрику изготовления отчетов, то нужно развязать руки разработчику и в этом вопросе.
Если обработку немного допилить, то можно кроме ТЗ передавать параметром опции группировки и подведения итогов и сразу группировать и вызывать печать, не показывая формы. Тоже удобно, но интерфейсы отбора и настройки вывода данных нужно каждый раз писать в вызывающем отчете. Если хочется, то почему бы и нет:)
Последний из передаваемых аргументов функции сортировки - это флаг добавления в таблицу результата колонки с уровнем группировки. При ДобУровень установленном на 1 таблица значений на выходе получает еще одну колонку Уровень_Группировки, которая заполняется числами от 1 (самый главный уровень) по возрастающей. В соответствии с признаком группировки и используется секция печатной формы для вывода соответствующей строки сгруппированной таким образом таблицы значений. Так как количество секций для уровней в печатной форме в принципе не может быть бесконечным (в отличие от потенциального количества группируемых колонок), то в печатную форму введена секция для уровня 0, который используется для вывода всех уровней группировки корорых нет в подготовленной нами печатной форме. Я лично разместил пять секций для возможных уровней (дальше фантазия иссякла), а это значит что все уровне начиная с шестого буду выводиться на печать в дизайне секции "Уровень_0"
Вот собственно и все. Быстрых и качественных всем разработок!:)