gifts2017

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

Опубликовал Andrey Smirnov (dusha0020) в раздел Программирование - Инструментарий

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

 

 

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

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

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

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

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

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

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

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

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

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

             Возврат "";

       КонецЕсли;

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

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

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

      

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

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

      

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

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

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

      

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

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

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

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

       КонецЦикла;

      

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

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

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

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

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

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

       КонецЦикла;

      

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

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

       КонецЕсли;

      

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

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

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

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

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

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

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

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

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

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

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

                           КонецЕсли;

                    КонецЦикла;

             КонецЦикла;

       КонецЦикла;

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

       Возврат ТЗ;

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

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

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

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

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

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

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

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

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

Скачать файлы

Наименование Файл Версия Размер
GroupmakerV1.ert 56
.ert 192,50Kb
19.11.12
56
.ert 192,50Kb Скачать

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Brr (brr) 20.11.12 12:28
группировки в одной колонке, не?
2. Andrey Smirnov (dusha0020) 20.11.12 12:31
Группировки во всех нужных колонках. Хоть в одной хоть в 101:)
3. Дмитрий Литовченко (kompas-dm) 20.11.12 18:20
(0) Это и многое другое - "ИндексированнаяТаблица" , 1CPP.
Прикрепленные файлы:
IndexedTable.html
4. Andrey Smirnov (dusha0020) 20.11.12 18:32
(3) kompas-dm, Согласен на 100%. Однако, это работает везде где просто установлена клюшка. Я очень люблю писать штуки, которые работают всегда и везде. А еще это просто выпендреж и дань тщеславию
5. Александр Лыткин (TrinitronOTV) 20.11.12 18:47
очень здорово это выглядит, спасибо
6. rimma_n (rimma_n) 21.11.12 09:38
(4) dusha0020, Полностью согласна. обработки должны работать всегда и везде, где есть только 1С. Ну и конечно, выпендриться тож приятно!
7. Александр Чемезов (chemezov) 22.11.12 09:41
8. Юрий Усков (Yurus) 26.11.12 10:42
Очень полезная обработка. Спасибо.
9. Иван Берездецкий (berezdetsky) 27.11.12 14:25
Похоже, оно навернётся на сворачивании элементов с одинаковым представлением. :)
10. Andrey Smirnov (dusha0020) 27.11.12 14:54
(9) berezdetsky, Метод Свернуть() ни разу не наворачивался при свертке элементов с одинаковым представлением пока я работаю в 1С. Ну а ТЗ с совпадающими идентификаторами колонок попробуйте создать:)
11. Иван Берездецкий (berezdetsky) 29.11.12 10:25
(10) 1. Берём двухуровневый справочник и такой код:
тз = СоздатьОбъект("ТаблицаЗначений");
тз.НоваяКолонка("Колонка1");
тз.НоваяКолонка("Колонка2");
тз.НоваяКолонка("Счетчик");
спр = СоздатьОбъект("Справочник.Номенклатура");
спр.ВыбратьЭлементы();
Пока спр.ПолучитьЭлемент() = 1 Цикл
	Если спр.Уровень() = 2 Тогда
		тз.НоваяСтрока();
		тз.Колонка1 = спр.Родитель;
		тз.Колонка2 = спр.ТекущийЭлемент();
		тз.Счетчик  = 1;
	КонецЕсли;
КонецЦикла;
тз = ИтоговаяПоГруппировкамТЗ(тз, "Колонка1,Колонка2", "Счетчик");
тз.ВыбратьСтроку();
...Показать Скрыть

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

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

3. Добавляем сортировку по внутреннему значению. ;-)
Прикрепленные файлы:
12. Andrey Smirnov (dusha0020) 29.11.12 11:24
(11) berezdetsky, Любопытно у Вас получилось. Но все еще не понятно.
Теперь делаем представление группы 2 таким же, как у группы 1
Это как делалось? Или код приведите, пожалуйста, а то если и дописывать, то нужно понимать почему такое происходит.
13. Иван Берездецкий (berezdetsky) 29.11.12 13:43
(12) Нет никакого кода. :-) Просто скопировал наименование в форме справочника. Получилось две группы с одинаковым наименованием.
14. Andrey Smirnov (dusha0020) 29.11.12 14:06
(13) berezdetsky, Жестокий эксперимент:) Не буду ничего переписывать - занят новыми проблемами.