Групмейкер для таблицы значений.





Универсальная функция и обработка для свертки и группировки таблицы значений. Очень простой способ подвести итоги по призвольным группам в произвольном порядке любой таблицы значений для быстрого вывода на печать нужной пользователю последовательности и детализации группировок.

 

 

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

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

 У каждого программиста есть свой способ выводить ТЗ на печать по нужным группировкам — кто то использует класс индексированных таблиц, а кто-то сам вводит в ТЗ индексы, а может есть и еще более или менее эффективные способы. Речь сейчас не о них.

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

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

 В чистом остатке мы получили 1(одну) функцию получения предназначенной для печати таблицы значений для любых возможных вариантов  группировки  и очень простую печатную форму для опять же любого варианта отчета.

 Макет печаной формы приведен на картинке, а сама функция звучит так:

Функция ИтоговаяПоГруппировкамТЗ(исхТЗ,СтрГруппировок,СтрИтогов,ДобУровень = 0)

       Если (ПустоеЗначение(СтрГруппировок) = 1) Или (ПустоеЗначение(СтрИтогов) = 1) Тогда

             Предупреждение(«Не отмечены поля группировок или поля итогов!!!»);

             Возврат «»;

       КонецЕсли;

       ТЗ = СоздатьОбъект(«ТаблицаЗначений»);

       исхТЗ.Выгрузить(ТЗ,,,СтрГруппировок+«,»+СтрИтогов);

       ТЗ.Свернуть(СтрГруппировок,стрИтогов);

      

       ТЗИтогов = СоздатьОбъект(«ТаблицаЗначений»);

       ТЗ.Выгрузить(ТЗИтогов);

      

       спТаблиц = СоздатьОбъект(«СписокЗначений»);

       спСвертки = СоздатьОбъект(«СписокЗначений»);

       свернутьПо = «»;

      

       сДляСписка = СтрЗаменить(стрГруппировок,«,»,РазделительСтрок);

       СчетчикЦикла = 0;

       Для ф = 1 По СтрКоличествоСтрок(сДляСписка) Цикл

             спСвертки.ДобавитьЗначение(СтрПолучитьСтроку(сДляСписка,ф));

       КонецЦикла;

      

       Для ф=1 По спСвертки.РазмерСписка()-1 Цикл

             времТ = СоздатьОбъект(«ТаблицаЗначений»);

             ТЗ.Выгрузить(времТ);

             свернутьПо = свернутьПо + ?(ф=1,«»,«,») + спСвертки.ПолучитьЗначение(ф);

             времТ.Свернуть(свернутьПо,СтрИтогов);

             спТаблиц.ДобавитьЗначение(времТ,свернутьПо);

       КонецЦикла;

      

       Если ДобУровень = 1 Тогда

             ТЗ.НоваяКолонка(«Уровень_Группировки»,«Число»);

       КонецЕсли;

      

       Для ф=1 По спТаблиц.РазмерСписка() Цикл

             времТ = СпТаблиц.ПолучитьЗначение(ф);

             ВремТ.ВыбратьСтроки();

             Пока ВремТ.ПолучитьСтроку() = 1 Цикл

                    ТЗ.НоваяСтрока();

                    Для ы = 1 По ВремТ.КоличествоКолонок() Цикл

                           идКолонки = времТ.ПолучитьПараметрыКолонки(ы);

                           текЗнач = ВремТ.ПолучитьЗначение(времТ.НомерСтроки,идКолонки);

                           ТЗ.УстановитьЗначение(ТЗ.НомерСтроки,идКолонки,текЗнач);

                           Если ДобУровень = 1 Тогда

                                  ТЗ.УстановитьЗначение(ТЗ.НомерСтроки,«Уровень_Группировки»,ф);

                           КонецЕсли;

                    КонецЦикла;

             КонецЦикла;

       КонецЦикла;

       ТЗ.Сортировать(стрГруппировок);

       Возврат ТЗ;

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

ИсхТЗ — это обычная таблица значений, как на первом рисунке, а возвращаемая таблица значений показана на втором рисунке.

СтрГруппировок — это обычная строка с разделенными запятыми идентификаторами полей группировки.

А СтрИтогов — строковое выражение из идентификаторов суммируемых при группировке колонок.

 Когда родилась универсальная функция возникла идея сделать ее логичное продолжение — универсальную обработку. Универсальная группировка и универсальная печать любой переданной параметром таблицы значений должна, имхо, сильно пригодиться в том случае когда удается получить таблицу значений, а вот с группировками и печатью заморачиваться некогда или не хочется, да и заказчик сам толком не понимает в каком виде ему будет удобнее анализировать данные (а скорее всего в каких видах). Обработка имеет и демо режим запуска без переданной таблицы значений — в этом случае ТЗ будет сгенерирована автоматически и весь функционал обработки можно будет оценить без построения ненужной ТЗ передачи ее с вызовом из ненужной обработки.

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

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

 Последний из передаваемых аргументов функции сортировки — это флаг добавления в таблицу результата колонки с уровнем группировки. При ДобУровень  установленном на 1 таблица значений на выходе получает еще одну колонку  Уровень_Группировки, которая заполняется числами от 1 (самый главный уровень) по возрастающей. В соответствии с признаком группировки и используется секция печатной формы для вывода соответствующей строки сгруппированной таким образом таблицы значений. Так как количество секций для уровней в печатной форме в принципе не может быть бесконечным (в отличие от потенциального количества группируемых колонок), то в печатную форму введена секция для уровня 0, который используется для вывода всех уровней группировки корорых нет в подготовленной нами печатной форме. Я лично разместил пять секций для возможных уровней (дальше фантазия иссякла), а это значит что все уровне начиная с шестого буду выводиться на печать в дизайне секции «Уровень_0»

 Вот собственно и все. Быстрых и качественных всем разработок!:)

14 Comments

  1. brr

    группировки в одной колонке, не?

    Reply
  2. dusha0020

    Группировки во всех нужных колонках. Хоть в одной хоть в 101:)

    Reply
  3. kompas-dm

    (0) Это и многое другое — «ИндексированнаяТаблица» , 1CPP.

    Reply
  4. dusha0020

    (3) kompas-dm, Согласен на 100%. Однако, это работает везде где просто установлена клюшка. Я очень люблю писать штуки, которые работают всегда и везде. А еще это просто выпендреж и дань тщеславию

    Reply
  5. TrinitronOTV

    очень здорово это выглядит, спасибо

    Reply
  6. rimma_n

    (4) Полностью согласна. обработки должны работать всегда и везде, где есть только 1С. Ну и конечно, выпендриться тож приятно!

    Reply
  7. chemezov

    интересно, спасибо 🙂

    Reply
  8. Yurus

    Очень полезная обработка. Спасибо.

    Reply
  9. berezdetsky

    Похоже, оно навернётся на сворачивании элементов с одинаковым представлением. 🙂

    Reply
  10. dusha0020

    (9) berezdetsky, Метод Свернуть() ни разу не наворачивался при свертке элементов с одинаковым представлением пока я работаю в 1С. Ну а ТЗ с совпадающими идентификаторами колонок попробуйте создать:)

    Reply
  11. berezdetsky

    (10) 1. Берём двухуровневый справочник и такой код:

    тз = СоздатьОбъект(«ТаблицаЗначений»);
    тз.НоваяКолонка(«Колонка1»);
    тз.НоваяКолонка(«Колонка2»);
    тз.НоваяКолонка(«Счетчик»);
    спр = СоздатьОбъект(«Справочник.Номенклатура»);
    спр.ВыбратьЭлементы();
    Пока спр.ПолучитьЭлемент() = 1 Цикл
    Если спр.Уровень() = 2 Тогда
    тз.НоваяСтрока();
    тз.Колонка1 = спр.Родитель;
    тз.Колонка2 = спр.ТекущийЭлемент();
    тз.Счетчик  = 1;
    КонецЕсли;
    КонецЦикла;
    тз = ИтоговаяПоГруппировкамТЗ(тз, «Колонка1,Колонка2», «Счетчик»);
    тз.ВыбратьСтроку();
    

    Показать

    Видим красивую картинку: (см. Снимок1).

    2. Теперь делаем представление группы 2 таким же, как у группы 1 и видим: (см. Снимок2).

    3. Добавляем сортировку по внутреннему значению. 😉

    Reply
  12. dusha0020

    (11) berezdetsky, Любопытно у Вас получилось. Но все еще не понятно.

    Теперь делаем представление группы 2 таким же, как у группы 1

    Это как делалось? Или код приведите, пожалуйста, а то если и дописывать, то нужно понимать почему такое происходит.

    Reply
  13. berezdetsky

    (12) Нет никакого кода. 🙂 Просто скопировал наименование в форме справочника. Получилось две группы с одинаковым наименованием.

    Reply
  14. dusha0020

    (13) berezdetsky, Жестокий эксперимент:) Не буду ничего переписывать — занят новыми проблемами.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *