Управляемые формы. Итоги в динамических списках

15.12.16

Разработка - Работа с интерфейсом

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

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Обработка для 1С:Бугалтерия 3.0. Остатки номенклатуры. Иерархический список и итогом.
.epf 8,99Kb
7
7 Скачать (1 SM) Купить за 1 850 руб.
Расширение для 1С:Бугалтерия 3.0. Итоги в журнале банковских выписок
.cfe 41,26Kb
10
10 Скачать (2 SM) Купить за 2 150 руб.

Рассмотрим на примере неких колонок Поступило и Списано в динамическом списке

1. Размещаем реквизиты итогов

На форму добавляем числовые реквизиты ИтогиПоступилоПодвал и ИтогиСписноПодвал и назначаем их в подвал таблицы к полям Поступило и Списано в качестве ПутьКДаннымПодвала

2. Отлавливаем изменения на клиенте

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

Пока нерешенной проблемой остается изменение поиска. Стоит заметить, что если поиск выполняется средствами СУБД (не через индекс полнотекстового поиска), то настройки компоновки содержат отбор, соответствующий поиску. Поэтому, если использоватья явный вызов расчета на сервере, то итоги будут рассчитаны с учетом поиска. Но вот отследить на клиенте когда нужно вызвать сервер при поиске пока у меня не получилось.

Добавляем на форме строковый реквизит НастройкаСписка, который и будет нашим флагом. Запускаем обработчик ожидания и следим за изменениями. Если что-то поменялось - обращаемся на сервер за расчетом итогов

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	НастройкиСписка = "...";//при первом вызове посчитаем
	ПодключитьОбработчикОжидания("ПроверкаИзменения",1);
КонецПроцедуры

&НаКлиенте
Процедура ПроверкаИзменения()
	
	НастройкиСпискаТек = "";
	Для Каждого ЭлементПользНастроек Из	Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
		//тут отборы и сортировка - отловим их
		НастройкиСпискаТек = НастройкиСпискаТек + СокрЛП(ЭлементПользНастроек) + СокрЛП(Элементы.Список.Период.ДатаНачала) + СокрЛП(Элементы.Список.Период.ДатаОкончания);
	КонецЦикла;
	//тут добавим в ловушку период списка (если это список документов)
	НастройкиСпискаТек = НастройкиСпискаТек + СокрЛП(Элементы.Список.Период.ДатаНачала) + СокрЛП(Элементы.Список.Период.ДатаОкончания);
	
	Если не НастройкиСписка = НастройкиСпискаТек Тогда	
	 
	 	//чей-то поменялось
		НастройкиСписка = НастройкиСпискаТек;
		
		СчитаемИтогиНаСервере();	
		
	КонецЕсли;
	
КонецПроцедуры

3. Расчитываем реквизиты итогов на сервере

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

Вот пример для журнала банковских выписок:

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

зы:

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

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

ну и для справочника можно добавить вот это:

&НаКлиенте
Процедура ДинамическийСписокПриСменеТекущегоРодителя(Элемент)
	НастройкиСписка = "..."; //сбросили - расчитаем на сервере на след шаге обработчика ожидания
КонецПроцедуры

К статье приложил пару файлов.

управляемая форма динамический список итоги

См. также

Работа с интерфейсом Рабочее место Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Платные (руб)

Богатый редактор картинок 1С предназначен для обработки изображений в режиме «Предприятие», с возможностью РИСОВАТЬ на них. Поддерживается работа как в обычных формах (толстый клиент) так и на управляемых формах (тонкий клиент). Обработка позволяет редактировать как картинки, хранимые в базе, так и графические файлы с диска на файловой системе. Помимо базовых функций (изменение размеров, преобразование формата, обрезание картинки, повороты и т.п.) – редактор имеет богатый набор инструментов для рисования. Доступна функция вставки изображения из буфера обмена. Объект может быть использован: на стороне клиента, на стороне сервера, из внешнего соединения. Обработка будет особенно полезна тем, кто вносит картинки в базу (изображения номенклатуры, фотографии физических лиц и т.п.). Функционал реализуется с использованием JavaScript и бесплатного ПО ImageMagick (без использования внешних компонент).

6000 руб.

16.01.2015    63172    44    59    

82

Работа с интерфейсом Программист Платформа 1С v8.3 Конфигурации 1cv8 1С:ERP Управление предприятием 2 Платные (руб)

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

2400 руб.

29.06.2020    19052    26    6    

41

Работа с интерфейсом Программист Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Россия Платные (руб)

Редактор графов в 1С - внешний отчет, который формирует графы на основе таблицы значений, используя рисунки табличного документа. Есть возможность добавления, редактирования объектов графа и выгрузки результата в таблицу значений.

1500 руб.

06.10.2020    10391    7    7    

10

Работа с интерфейсом Программист Стажер Платформа 1С v8.3 Бесплатно (free)

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

20.08.2024    18093    mrXoxot    43    

122

Работа с интерфейсом Программист Платформа 1С v8.3 Бесплатно (free)

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

27.05.2024    8268    smielka    37    

101

Работа с интерфейсом Платформа 1С v8.3 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Зарплата и Управление Персоналом 3.x 1С:Управление нашей фирмой 3.0 Бесплатно (free)

Добавьте новогоднего настроения! Расширение создает декорацию в виде гирлянды на некоторых формах объектов.

27.12.2023    15525    1011    elcoan    49    

117

Инструментарий разработчика Работа с интерфейсом Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

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

2 стартмани

10.04.2023    12088    165    acces969    31    

124
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Lukich66 83 21.12.16 08:37 Сейчас в теме
из текста "Тут нужно сказать спасибо разработчикам ..."- года 2 назад в длинные новогоднии каникулы
"развлекся" нечто подобным (итогами в журнале документов учета путевых листов- бац оперативно посмотреть в отборе циферки гсм,РВ и т.п.), когда столкнулся с непреодолимыми на моем уровне проблемами- то б/удовольствия стал смотреть на УФ и ДС. Вот почему некоторый создатель не желает совершенствовать свой -же продукт?
2. argut 117 21.12.16 13:25 Сейчас в теме
Совершенствуют потихоньку :) Поиск более менее нормальный вот не так давно запилили и экспериментируют с ним. Может и события появятся.
3. Dementor 1037 21.12.16 16:56 Сейчас в теме
оставим споры, что мол это не нужно


Управляемые формы - это просто песня и легкость разработки. Вот у меня клиент пару месяцев назад в УТ10 в журнале заказов заказал нумерацию списка - что бы сбоку были порядковые номера. При этом при смене периода журнала, при наложении фильтров, при смене сортировок, что бы эта нумерация пересчитывалась и была актуальной: нашел по поиску нужный документ и видишь, что он 15345, а вверх и вниз идет уменьшение и увеличение счетчика. Для УФ это было бы легко, но тут обычная форма. Пытался я его отговорить, но ему нужно, а иначе он работать не может.... Пришлось сделать, даже не тормозило при прокрутке :)

Кстати, использование данных для вывода значения в подвале - правильное решение. Если пробовать менять текст в свойстве ТекстПодвала, то это будет приводить к пересозданию формы и лишнему серверному вызову.
4. EvgeniuXP 21.12.16 23:57 Сейчас в теме
(3) дополнение к последнему абзацу: а если на форме еще есть горизонтальные и вертикальные сплитеры - то они будут сбрасываться на первоначальное положение в форме - что опять же будет не удобно пользователю.
6. Yashazz 4796 06.02.17 18:54 Сейчас в теме
(3) "Управляемые формы - это просто песня и легкость разработки"? Это вы или иронизируете, или грустно шутите, наверное. Всерьёз такое сказануть вряд ли можно.
7. Dementor 1037 06.02.17 22:48 Сейчас в теме
(6) Вы совершенно верно все подметили - это была грустная шутка для тех, кто в теме.
С одной стороны некоторые вещи стали проще чем были в обычных формах (те же гибкие ДинамическиеСписки вместо дубовых объектов СправочникСписок и ДокументСписок), но с другой - многое бесит. Невозможность управлять самопоявляющимися отступами на форме, недоступность изменения свойств заголовков элементов, слетающие условные оформления на сложных списках и так далее...
5. Yashazz 4796 06.02.17 18:49 Сейчас в теме
Мдя. Не понял причин ажиотажа. Задача тривиальная, решение так себе, ресурсоёмкое и не очень-то универсальное.

За пассажи вроде получения результата в таблицу значений и потом итог по колонке вообще сразу минусовать хочется. Автор, видимо, не в курсе, что умеет СКД в части агрегирования данных и вообще итогов. И уж точно автор не представляет, что будет с сеансовыми данными при солидной выборке. Так что - учить матчасть.

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

Впрочем, это хорошая публикация. Чем больше их будет, тем больше нам потом заработка на оптимизации отчаянно тормозящей системы)))
DmitrySinichnikov; +1 Ответить
8. argut 117 07.02.17 07:01 Сейчас в теме
(5)
Автор, видимо, не в курсе, что умеет СКД в части агрегирования данных и вообще итогов.

Ну так тут СКД и формирует таблицу из одной строки уже сагрегированную.

(5)
И уж точно автор не представляет, что будет с сеансовыми данными при солидной выборке.

Для этого и обсуждаем чтобы люди, которые опытнее могли помочь менее опытным.
9. Yashazz 4796 07.02.17 10:35 Сейчас в теме
(8) Одну сагрегированную? Ну это наивные надежды, что, грохнув группировки, мы добьёмся от СКД нужного результата. Это ж надо нормальную пустую группировку создать, авто-поле, все дела. СКД понимает, только когда ей всё жёстко "в лоб" указано.
10. Leits 2 20.09.18 09:51 Сейчас в теме
Спасибо, пригодилось! Интересно, на данный момент более простого способа разработчики не изобрели?
11. bob_ 95 07.11.18 11:18 Сейчас в теме
Спасибо, но заработало только после следующих изменений:

// этот кусок
        Результат = ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
	
	//заполняем реквизиты итогов подвала
	ИтогиПоступилоПодвал 	= Результат.Итог("Поступление");
	ИтогиСписаноПодвал 		= Результат.Итог("Списание");
// --------------------

// заменил этим:
        ДанныеТЗ = Новый ТаблицаЗначений;
	ПроцессорВывода.УстановитьОбъект(ДанныеТЗ);
	
	Результат = ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
	
	Для каждого СтрокаТЗ Из ДанныеТЗ Цикл
		ИтогиПоступилоПодвал =  СтрокаТЗ.Поступление;
		ИтогиСписаноПодвал = СтрокаТЗ.Списание;
	КонецЦикла;	
// --------------
Показать

до изменений Результат это табличныйдокумент, для него итог не работает.
12. Andruykha 179 18.09.19 05:29 Сейчас в теме
13. OksDallas 22 04.12.19 06:48 Сейчас в теме
Для ФормыСписка справочника заменила вот этот эпизод
Для Каждого ЭлементПользНастроек Из	Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
		//тут отборы и сортировка - отловим их
		НастройкиСпискаТек = НастройкиСпискаТек + СокрЛП(ЭлементПользНастроек) + СокрЛП(Элементы.Список.Период.ДатаНачала) + СокрЛП(Элементы.Список.Период.ДатаОкончания);
	КонецЦикла;


на вот такой:
     Для Каждого Эл Из Список.Отбор.Элементы Цикл
	     НастройкиСпискаТек = НастройкиСпискаТек + СокрЛП(Эл.ЛевоеЗначение) + СокрЛп(Эл.ВидСравнения) +   СокрЛП(Эл.ПравоеЗначение) + СокрЛП(Эл.Использование);
	КонецЦикла;


Почему-то в Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы было пусто после настройки списка - установки отбора. Может потому-что не запоминала настройки? (надо проверить)

А теперь вот какой вопрос: Если не выполнять отбор в настройке списка, а использовать "Поиск" то в отборах ничего не меняется, и где можно увидеть, что менялось значение для поиска?
14. Dzenn 894 12.01.21 11:19 Сейчас в теме
статья в стиле "а давайте отпилим троллейбусу рога и сделаем из него прекрасный автобус"
15. user1162192 24.03.21 16:37 Сейчас в теме
&НаСервере
Процедура Получить_ТЗ_Из_ДинамическогоСписка()
 
	Схема = Элементы.ЧекиККМ.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
	Настройки = Элементы.ЧекиККМ.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
	
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных();
	МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
	
	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
 
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
	
	ТЗ = Новый ТаблицаЗначений;
	ПроцессорВывода.УстановитьОбъект(ТЗ); 
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);
	//Возврат ТЗ;
	
	нал1 = 0;
	карта1 = 0;
	общ1 = 0;
	сдач1 = 0;
	
	Для Каждого Строка Из ТЗ Цикл
       нал1 = нал1+?(Строка.ПолученоНаличными = null,0,Строка.ПолученоНаличными);
	   карта1 = карта1+?(Строка.ПолученоКарта = null,0,Строка.ПолученоКарта);
	   общ1 = общ1+?(Строка.СуммаДокумента = null,0,Строка.СуммаДокумента);
		//общ1 = общ1+?(Строка.СуммаДокумента = null,0,Строка.СуммаДокумента);
		сдач1 = сдач1+?(Строка.Сдача = null,0,Строка.сдача);

      
    КонецЦикла;
нал = Строка(нал1);
карт = Строка(карта1);
общ = Строка(общ1);
сдач = Строка(сдач1);

 
КонецПроцедуры
Показать


я так сделал. И повесил события на отборы.
16. user1475334 04.04.21 18:43 Сейчас в теме
Спасибо большое автор и все кто написал.
задача решена
17. frkbvfnjh 805 26.08.21 08:38 Сейчас в теме
Единственное нормальное решение
Оставьте свое сообщение