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

15.12.16

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

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

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

Наименование Файл Версия Размер
Обработка для 1С:Бугалтерия 3.0. Остатки номенклатуры. Иерархический список и итогом.
.epf 8,99Kb
7
.epf 8,99Kb 7 Скачать
Расширение для 1С:Бугалтерия 3.0. Итоги в журнале банковских выписок
.cfe 41,26Kb
10
.cfe 41,26Kb 10 Скачать

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

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

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

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

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

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

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

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

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

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

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

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

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

зы:

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

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

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

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

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

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

См. также

Богатый редактор картинок, хранимых в базе, с возможностью РИСОВАНИЯ. Редактор внешних файлов картинок. Объект, расширяющий возможности работы с картинками из встроенного языка (Три в одном) + Обработка «Стандартизация картинок»

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

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

6000 руб.

16.01.2015    61793    43    59    

80

[Расширения] Динамическое управление видимостью и доступностью элементов форм (УФ) (8.3.6+)

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

Механизм «Динамическое управление доступом к элементам форм объектов 1С8» предназначен для обеспечения возможности оперативного управления видимостью и доступностью элементов форм документов и справочников продуктов фирмы «1С» «1С:Предприятие 8». Решение универсальное, встраивается в любую конфигурацию с минимальными доработками, что позволяет без проблем обновлять типовые решения.

5000 руб.

14.01.2016    54399    16    21    

42

Управление дашбордами

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

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

2400 руб.

29.06.2020    16695    21    4    

35

Новогоднее оформление для 1С

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

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

27.12.2023    10735    750    elcoan    45    

106

Конструктор HTML, CSS и javascript

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

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

2 стартмани

10.04.2023    9609    151    acces969    31    

118

Модель состояния для MVC

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

"MVC плохо применима в 1С" - познакомьтесь с моделью состояния и, возможно, ваше мнение поменяется! Представленное решение является эволюционным развитием идеи реализации MVC для 1С. В новой версии добавлены DSL для описания модели состояния, а также параметризация свойств параметров и элементов формы.

1 стартмани

05.07.2022    3665    kalyaka    2    

27

Табло очереди заказов на экран телевизора

WEB-интеграция Работа с интерфейсом Платформа 1С v8.3 1С:Розница 2 Платные (руб)

Связка из веб-приложения и расширения для 1С: Розница 2.3.

3600 руб.

29.04.2022    12078    1    5    

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


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

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

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

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

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

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

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

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

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

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

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


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


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

А теперь вот какой вопрос: Если не выполнять отбор в настройке списка, а использовать "Поиск" то в отборах ничего не меняется, и где можно увидеть, что менялось значение для поиска?
14. Dzenn 870 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 785 26.08.21 08:38 Сейчас в теме
Единственное нормальное решение
Оставьте свое сообщение