Фильтруем и выводим "ТаблицуЗначений"

27.06.06

Разработка - Универсальные функции

Демонстрация возможностей фильтрации "ТаблицЗначений" без ВК (альтернатива - 1с++ )
Фильтруем и выводим "ТаблицуЗначений"

Эта статья предназначена для демонстрации возможностей фильтрации "ТаблицЗначений" с помощью процедуры "ФильтрТабы" и для облегчения формирования кода при выводе таблиц со сложными группировками, при необходимости получить итоги до перебора строк запроса 1С или просто при фильтрации "ТаблицЗначений" по одной или нескольким колонкам.
Сам код процедуры "ФильтрТабы" (приведен в конце статьи) сложился на основе конкурса по быстрейшему удалению строк ТЗ, и в принципе может быть оптимизирован, хотя и так работает отлично.

Сразу перейду к примеру.
Допустим имеется таблица "тзнДанные" с колонками "Контрагент", "Товар" и "Сумма".
Нам необходимо вывести общую сумму по контрагенту до перебора товаров, а также все товары по контрагенту с суммами.
И так по каждому контрагенту.
 
 
1. Для начала отсортируем нашу таблицу чтобы потом уже не сортировать её, а только фильтровать. Сортировать обязательно надо в той последовательности, которой будем потом фильтровать её, т.е. сначала по "Контрагент", а потом уже как угодно. Если заранее не сортировать, то надо будет раскомментировать строчку в процедуре "ФильтрТабы".
тзнДанные.Сортировать("Контрагент, Товар");
2. Чтобы получить список контрагентов без повторений, мы выгрузим их в отдельный список (таблицу значений) и свернём (сортировать не надо, если вы это сделали в п.1) :

тзнКонтрагенты = СоздатьОбъект("ТаблицаЗначений");
тзнДанные.Выгрузить(тзнКонтрагенты, ,, "Контрагент");
тзнКонтрагенты.Свернуть( "Контрагент",);

3. Теперь пробежимся по всем контрагентам и выведем информацию:
 
тзнКонтрагенты.выбратьСтроки();
Пока тзнКонтрагенты.ПолучитьСтроку()=1 Цикл
  текКонтрагент = тзнКонтрагенты.Контрагент;
  тзнДанныеПоКонтрагенту = ФильтрТабы( тзнДанные, "Контрагент", текКонтрагент);

 4. Здесь мы получили таблицу "тзнДанныеПоКонтрагенту" с суммами и товарами по одному контрагенту (из нашего списка). Можно брать из неё итоговые суммы или перебирать товары, всё в наших руках.

 
всегоПоКонтрагенту = тзнДанныеПоКонтрагенту.Итог("Сумма");
  Сообщить( "Всего по Контрагенту """+текКонтрагент+""" = "+всегоПоКонтрагенту );

  тзнДанныеПоКонтрагенту.выбратьСтроки();
  Пока тзнДанныеПоКонтрагенту.ПолучитьСтроку()=1 Цикл
    текТовар = тзнДанныеПоКонтрагенту.Товар;
    текСуммаТовар = тзнДанныеПоКонтрагенту.Сумма;
    Сообщить( "Сумма по товару """+текТовар+""" = "+текСуммаТовар );
  КонецЦикла; //по товарам

КонецЦикла; //по контрагентам

Собственно вот и всё! Можно выводить таблицы, или просто обрабатывать данные, доработав этот шаблон до необходимого вам функционала.
С вертикальными группировками будет немного по другому, но не намного сложнее. Надо будет заранее сформировать список "столбцов" и выводить всегда все(!) столбцы, даже если они не попались в этой горизонтальной группировке.


Ниже приведёны код примера (без комментариев) и код процедуры "ФильтрТабы".
--------------------------------------------------------------------------------
тзнДанные.Сортировать("Контрагент, Товар");

тзнКонтрагенты = СоздатьОбъект("ТаблицаЗначений");
тзнДанные.Выгрузить(тзнКонтрагенты, ,, "Контрагент");
тзнКонтрагенты.Свернуть( "Контрагент",);

тзнКонтрагенты.выбратьСтроки();
Пока тзнКонтрагенты.ПолучитьСтроку()=1 Цикл
  текКонтрагент = тзнКонтрагенты.Контрагент;
  тзнДанныеПоКонтрагенту = ФильтрТабы( тзнДанные, "Контрагент", текКонтрагент);

  всегоПоКонтрагенту = тзнДанныеПоКонтрагенту.Итог("Сумма");
  Сообщить( "Всего по Контрагенту """+текКонтрагент+""" = "+всегоПоКонтрагенту );

  тзнДанныеПоКонтрагенту.выбратьСтроки();
  Пока тзнДанныеПоКонтрагенту.ПолучитьСтроку()=1 Цикл
    текТовар = тзнДанныеПоКонтрагенту.Товар;
    текСуммаТовар = тзнДанныеПоКонтрагенту.Сумма;
    Сообщить( "Сумма по товару """+текТовар+""" = "+текСуммаТовар );
  КонецЦикла; //по товарам

КонецЦикла; //по контрагентам


См. также

Библиотека процедур и функций для технологической платформы "1С: Предприятие 7.7"

Универсальные функции Платформа 1С v7.7 Россия Абонемент ($m)

В библиотеку собраны различные функции по работе с документами, журналами, типами данных, строками, датой и временем, таблицами значений, Excel, файлами, XML, JSON, Http-сервисами, SMTP серверами и т.п.

1 стартмани

22.12.2023    657    9    user706545_kseg1971    0    

4

1С 7.7 и новый 1С:Контрагент

Универсальные функции Платформа 1С v7.7 Конфигурации 1cv7 Россия Бесплатно (free)

Получение реквизитов контрагентов из 1С:Контрагент для старых конфигураций под 1с 7.7.

25.04.2022    1820    zhenyat    7    

6

Печать таблицы значений в 1С 7.7 при отладке

Универсальные функции Платформа 1С v7.7 Россия Бесплатно (free)

Функция выводит таблицу значений в табличный документ. (v7.7) Особенно полезно при отладке. Не нужно вносить изменения в код, вызываем функцию как вычисляемое выражение при останове. Если таблица обрабатывается в несколько этапов, можно вывести её после каждого и визуально проследить эволюцию.

30.06.2021    4401    Zoltan_Black    11    

2

Установка принтера по умолчанию для 1С 7.7

Универсальные функции Платформа 1С v7.7 Конфигурации 1cv7 Абонемент ($m)

Установка принтера по умолчанию в 1С 7.7. Обработка может быть полезна в том случае, когда нужно установить принтер по умолчанию, а доступа к рабочему столу нет (например, терминальный режим без рабочего стола или remoteApp)

1 стартмани

13.02.2019    13286    4    alsen    3    

4

Формирование строки json в 1С: 7.7

Универсальные функции Платформа 1С v7.7 Конфигурации 1cv7 1С:Комплексная 7.7 Абонемент ($m)

Предлагается набор функций 1с 7.7 для формирования строки json стандартными средствами.

1 стартмани

10.12.2018    10100    malovandrey    3    

18

Как создать индикатор в 1С:Предприятии 7.7

Универсальные функции Работа с интерфейсом Платформа 1С v7.7 Конфигурации 1cv7 Россия Абонемент ($m)

В статье дано описание создания индикатора на форме в среде разработки 1С:Предприятие 7.7 исключительно типовыми средствами.

1 стартмани

27.09.2016    18674    2    HAMMER_59    6    

2
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Чум 16.06.06 06:38 Сейчас в теме
Тупой перебор строк таблицы значений с проверкой услвия?
А "метод рупора" уже отменили?
2. 26.06.06 22:52 Сейчас в теме
Тупой не тупой, но всегда удивляли авторы из нашей страны. На пальцах можно перебрать, кто писать умеет, а не пропускает через переводчик хелп программы, а после необработанный текст дает в тираж. Иностранцы пишут проще, въезжаешь сразу. Такие статьи необходимы, своего пользователя найдут. Поддержим автора.
3. support 4484 28.06.06 16:21 Сейчас в теме
Подсветка кода с помощью новых тэгов [ code ] [ /code ]
4. alexqc 150 29.08.06 10:44 Сейчас в теме
Что есть "метод рупора"?
5. lov-kot 21.09.06 02:18 Сейчас в теме
Если ТЗ получили из Запрос.Выгрузить - то зачем все это?
Если иначе - все правильно, так и надо. +1
6. karat60 07.09.06 20:58 Сейчас в теме
7. WWWolfy 132 21.09.06 10:56 Сейчас в теме
2(lov-kot) Конечно же это предназначено для сложных случаев, например когда данные надо группировать в разных последовательностях и когда сами данные сливаются из нескольких (иногда разных) источников.
8. JohnyDeath 301 21.09.06 11:08 Сейчас в теме
Я примерно такими же способами у себя страдал. Представляете, если кол-во строк около 10000? И ещё один столбец или даже два... ;)
Потом я увидел в 1с++ ИндексированнуюТаблицу и сразу же влюбился... Посмотрите только на это: http://www.1cpp.ru/docum/IndexedTable.html
9. WWWolfy 132 21.09.06 13:42 Сейчас в теме
2(JohnyDeath) Представляю. Только читаться отчёт в 10000 строк будет очень плохо как с экрана так и на бумаге, да и сформировать таблицу (теми же БухИтогами) на 10000 строк выйдет в разы дольше чем выводить их вышеописанным способом. Так что проблемы не вижу.
Про "1с++ ИндексированнуюТаблицу" знаю давно, но не каждый клиент будет ставить себе 1с++, а тут всё стандартными средствами.
10. WWWolfy 132 21.09.06 14:17 Сейчас в теме
Кстати попробовал 10000 строк разнородной инфы на примере выше. Получилось примерно 3 сек.
11. JohnyDeath 301 22.09.06 10:56 Сейчас в теме
2(WWWolfy) Я нисколько не хотел оскорбить тебя или твой метод. Просто предложил альтернативу причём не дурную альтернативу.
А насчет чтения отчета в 10000 строк: дык не факт, что выводиться будут все 10000!
12. WWWolfy 132 22.09.06 14:45 Сейчас в теме
2(JohnyDeath) А я нисколько и не оскорбился. 1С++ сам применял ни раз (в основном прямые запросы) и высказывал респект его авторам. Но ТЗ предпочитаю фильтровать именно своим способом, потому он подходит везде.
13. 25.09.06 12:09 Сейчас в теме
Можно избавиться от цикла поиска конечной строки, если передавать в функцию ФильтрТабы не только ТЕКУЩЕЕ значФильтра, но и СЛЕДУЮЩЕЕ из тзнКонтрагенты..
тогда:

если тзнДанные.НайтиЗначение(значФильтраNEXT,КонСтрока,имяФильтра) = 1 Тогда
КонСтрока = КонСтрока - 1;
конецесли;

надо только предусмотреть ветвление для последней строки тзнКонтрагенты, когда КонСтрока = тзнДанные.КоличествоСтрок();

Думаю, будет работать еще быстрее..
14. WWWolfy 132 25.09.06 15:14 Сейчас в теме
Можно, но думаю не сильно повлияет на скорость. Мерять надо..
И универсальность функции потеряется.
15. tarasenkov 340 23.01.08 21:40 Сейчас в теме
Можно значительно ускорить работу при многократном вызове фильтра,
заменив создание таблицы на "ЗначениеИзСтрокиВнутр".

[code]Перем ШаблонТз; // Объявим в начале модуля

// Немного изменим код
Функция ФильтрТабы( тзнДанные, имяФильтра, значФильтра)
//тзнДанные.Сортировать(имяФильтра);//не нужно если уже отсортировано
//тзнРезульт =СоздатьОбъект("ТаблицаЗначений");
тзнРезульт = ЗначениеИзСтрокиВнутр(ШаблонТз);
...
// В теле модуля, в самом конце добавим
ШаблонТз = ЗначениеВСтрокуВнутр(СоздатьОбъект("ТаблицаЗначений"));[code/]

Тест на 38000 вызовов - различие в 15 раз.
СоздатьОбъект("ТаблицаЗначений") - 8.5 секунды
ЗначениеИзСтрокиВнутр(ШаблонТз) - 0.5 секунды

За счет такой оптимизации в реальной задаче удалось сократить время в два раза.
16. tarasenkov 340 23.01.08 21:41 Сейчас в теме
*Фикс
Можно значительно ускорить работу при многократном вызове фильтра,
заменив создание таблицы на "ЗначениеИзСтрокиВнутр".

Код
Перем ШаблонТз; // Объявим в начале модуля

// Немного изменим код 
Функция ФильтрТабы( тзнДанные, имяФильтра, значФильтра)
//тзнДанные.Сортировать(имяФильтра);//не нужно если уже отсортировано
//тзнРезульт =СоздатьОбъект("ТаблицаЗначений");
тзнРезульт = ЗначениеИзСтрокиВнутр(ШаблонТз);
...
// В теле модуля, в самом конце добавим
ШаблонТз = ЗначениеВСтрокуВнутр(СоздатьОбъект("ТаблицаЗначений"));
Показать полностью


Тест на 38000 вызовов - различие в 15 раз.
СоздатьОбъект("ТаблицаЗначений") - 8.5 секунды
ЗначениеИзСтрокиВнутр(ШаблонТз) - 0.5 секунды

За счет такой оптимизации в реальной задаче удалось сократить время в два раза.
17. JohnyDeath 301 24.01.08 09:57 Сейчас в теме
+(16) у замечательного человека Кости aka 33lab в его конфе "СКАТ-профессионал" подсмотрел такую вот маленькую глобальную процедуру:
Код
Функция _Новый(стрОбъект) Экспорт
   Если стрОбъект="СписокЗначений" Тогда Возврат ЗначениеИзСтрокиВнутр("{""VL"",{}}"); КонецЕсли;
   Если стрОбъект="ТаблицаЗначений" Тогда
      Возврат ЗначениеИзСтрокиВнутр("{""VT"",""1"",{""0"",{{"""",""0"",""0"",""0"","""",""2""}}}}");
   КонецЕсли;
КонецФункции
Показать полностью
tarasenkov; +1 Ответить
18. NoMax 232 19.09.08 11:12 Сейчас в теме
Огромное спасибо.
Сэкономило время и позволило выкинуть, лишний мусор
при группировке из тз.
И самое замечательное что все реализуется штатными 1С средствами
Оставьте свое сообщение