IE 2016

Оптимизированный подсчет суммы выделенных ячеек табличного документа (как в Excel)

Опубликовал Evg-Lylyk в раздел Программирование - Практика программирования

Оптимизированный расчет данных выделенных ячеек

В Excel есть удобный механизм подсчет суммы выделенных ячеек в 1С к сожалению такого нет. 1С предлагает нам пользоваться кнопками калькулятора "М" что не так удобно как вариант предлагаемый ниже.

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

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

Оптимизированный вариант расчета

Производится обработка только тех ячеек которые добавлены к выделению (при выделении разом большого количества ячеек медленно как и для простого варианта, но в случае постепенного выделение замедления нет)

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

Оптимизированный вариант более сложный, но более эффективный в плане скорости.
Особый случай с выделением через Crtl + A т.к. в этом случае в процедуру передается Область (0,0,0,0) подсчет не производится и это разумно в этом случае пользователь выделяет не для подсчета суммы.

p.s.
За любые идеи по улучшению производительности буду очень признателен
Если функции ВычислитьСуммуОбласти, ПолучитьЧислоИзСтроки  реализовать через ВК думаю производительность возрастет. Может кто поможет ;)

Функция ВычислитьСуммуОбласти (ТабличныйДокумент, Верх, Лево, Низ, Право)

   
Сумма = 0;

    Для
ЯчВерт = Верх По Низ Цикл
        Для
ЯчГориз = Лево По Право Цикл
           
ОдиночнаяОбласть = ТабличныйДокумент.Область(ЯчВерт,ЯчГориз);

            Сумма = Сумма + ПолучитьЧислоИзСтроки(ОдиночнаяОбласть.Текст);
        КонецЦикла;
    КонецЦикла;

    Возврат
Сумма;

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

Функция
ПолучитьЧислоИзСтроки(Текст)

    Попытка
       
Результат = Число(Текст);
    Исключение
       
Результат = 0;
    КонецПопытки;

    Возврат
Результат;

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

 Внимание!!! Код выше не является основой обработки. Вынесены процедуры которые желательно реализовать через ВК для повышения скорости

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

Наименование Файл Версия Размер Кол. Скачив.
Пример 8.1
.epf 9,34Kb
01.10.09
269
.epf 9,34Kb 269 Скачать

См. также

Лучшие комментарии

8. bashta.aleksey (файл скачал) 28.09.2009 17:46
Извините.
Функция ВычислитьСуммуВыделенныхЯчеекТабличногоДокумента(ПолеТабличногоДокумента) Экспорт
Сумма = 0;
Для Каждого Область Из ПолеТабличногоДокумента.ВыделенныеОбласти Цикл
Если ТипЗнч(Область) = Тип("ОбластьЯчеекТабличногоДокумента") Тогда
Для ИндексСтрока = Область.Верх По Область.Низ Цикл
Для ИндексКолонка = Область.Лево По Область.Право Цикл
Попытка
Сумма = Сумма + Число(СтрЗаменить(ПолеТабличногоДокумента.Область("R" + Формат(ИндексСтрока, "ЧГ=0") + "C" + Формат(ИндексКолонка, "ЧГ=0")) .Текст, " ", ""));
Исключение
КонецПопытки;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат Сумма;
КонецФункции
Ответили: (9)
+ 1 [ director04; ]
# Ответить
25. Ish_2 (файл скачал) 01.10.2009 21:22
В строке функции :
ОдиночнаяОбласть = ТабличныйДокумент.Область(ЯчВерт,ЯчГориз)
приведено неверное обращение к ячейке.
Правильным обращением при суммировании ячеек будет
ОдиночнаяОбласть = 
ТабличныйДокумент.Область(ЯчВерт,ЯчГориз,ЯчВерт,ЯчГориз)

При обращении к области по двум координатам можно получить не одинарную , а ячейку , которая объединяет несколько ячеек (объединенная ячейка). Подсчет сумм в этом случае будет неверным.
+ 1 [ Evg-Lylyk; ]
# Ответить
17. Gleb K. 30.09.2009 14:06
Всем привет. А я себе сделал вот так.
У меня учитывается мультивыделение, наличие скрытых строк и/или столбцов, плюс парочка проверок "на дурака".

[1C-CODE]Процедура ТДПриАктивизацииОбласти(Элемент)
	Сумма = 0;
	Для Каждого Область из ЭлементыФормы.ТД.ВыделенныеОбласти Цикл
		Если Не Область = Неопределено И НЕ (Область.Верх = 0 И Область.Низ = 0) И НЕ (Область.Лево = 0 И Область.Право = 0) Тогда
		Для i = Область.Верх по Область.Низ Цикл
			Для j = Область.Лево по Область.Право Цикл
				Ячейка = ЭлементыФормы.ТД.Область(i,j);
				Если Ячейка.СодержитЗначение
					И Ячейка.Видимость
					И Ячейка.ТипЗначения = Новый ОписаниеТипов("Число")
					И Не Ячейка.Значение = Неопределено Тогда
					Сумма = Сумма + Ячейка.Значение;
				КонецЕсли;
			КонецЦикла;
		КонецЦикла;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры
...Показать Скрыть
[/1C-CODE]
Ответили: (19) (18)
+ 1 [ director04; ]
# Ответить

Комментарии

1. highlander 28.09.2009 15:51
А я вот интересуюсь... а возможно такое на 7-ке?
Ответили: (13) (3)
# Ответить
2. Evg-Lylyk (файл скачал) 28.09.2009 15:59
(2) посмотрел вроде нет предопределенной процедуры аналогичной 8.1 аналогично наверно не сделать

Надеюсь ветка не превратится в ветку, а как сделать тоже самое на 7.7 :)
Ответили: (2)
# Ответить
3. Арчибальд 28.09.2009 16:03
4. highlander 28.09.2009 16:12
Нет не превратиться... не волнуйтесь :D Но за идею плюс однозначно
Ответили: (5)
# Ответить
5. Evg-Lylyk (файл скачал) 28.09.2009 16:31
(4) самая идея подсчета суммы работает через 5 минут, а вот над оптимизацией пришлось поломать голову
Ответили: (6)
# Ответить
6. Stepa86 (файл скачал) 28.09.2009 17:13
(5) какое самое узкое место? наверно получение одиночной области и вынимание из нее текста...
# Ответить
7. bashta.aleksey (файл скачал) 28.09.2009 17:45
Evg-Lylyk в конфе "Бухгалтерия предприятия КОРП" рел 2.0.6.3 этот механизм уже есть в стандартных отчетах.
Думаю это тебе поможет:
Функция ВычислитьСуммуВыделенныхЯчеекТабличногоДокумента(ПолеТабличногоДокумента) Экспорт
Сумма = 0;
Для Каждого Область Из ПолеТабличногоДокумента.ВыделенныеОбласти Цикл
Если ТипЗнч(Область) = Тип("ОбластьЯчеекТабличногоДокумента") Тогда
Для ИндексСтрока = Область.Верх По Область.Низ Цикл
Для ИндексКолонка = Область.Лево По Область.Право Цикл
Попытка
Сумма = Сумма + Число(СтрЗаменить(ПолеТабличногоДокумента.Область("R" + Формат(ИндексСтрока, "ЧГ=0") + "C" + Формат(ИндексКолонка, "ЧГ=0")) .Текст, " ", ""));
Исключение
КонецПопытки;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат Сумма;
КонецФункции
...Показать Скрыть
Ответили: (10)
# Ответить
8. bashta.aleksey (файл скачал) 28.09.2009 17:46
Извините.
Функция ВычислитьСуммуВыделенныхЯчеекТабличногоДокумента(ПолеТабличногоДокумента) Экспорт
Сумма = 0;
Для Каждого Область Из ПолеТабличногоДокумента.ВыделенныеОбласти Цикл
Если ТипЗнч(Область) = Тип("ОбластьЯчеекТабличногоДокумента") Тогда
Для ИндексСтрока = Область.Верх По Область.Низ Цикл
Для ИндексКолонка = Область.Лево По Область.Право Цикл
Попытка
Сумма = Сумма + Число(СтрЗаменить(ПолеТабличногоДокумента.Область("R" + Формат(ИндексСтрока, "ЧГ=0") + "C" + Формат(ИндексКолонка, "ЧГ=0")) .Текст, " ", ""));
Исключение
КонецПопытки;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат Сумма;
КонецФункции
Ответили: (9)
+ 1 [ director04; ]
# Ответить
9. Evg-Lylyk (файл скачал) 28.09.2009 19:04
(8) и это в типовой? ))))))))))
# Ответить
10. Evg-Lylyk (файл скачал) 28.09.2009 19:05
(7) мой метод "нормальный" 8)
# Ответить
11. bashta.aleksey (файл скачал) 28.09.2009 21:22
12. 4ish (файл скачал) 29.09.2009 10:57
Не сочтите за каприз, но попробовал выделять отдельные ячейки через Ctrl - не работает. :(
Ответили: (14)
# Ответить
13. venger 29.09.2009 12:07
(1) > А я вот интересуюсь... а возможно такое на 7-ке?

Вот, например: http://infostart.ru/public/16000/
Ответили: (53)
# Ответить
14. Evg-Lylyk (файл скачал) 29.09.2009 12:27
(12) Мультивыделение работает и система оптимизации для мультивыделений тоже. Просто это пример... функция "ПолучитьИнформациюПоВыделеннымОбластям" возвращает информацию по каждой области в структуре дальше используете как хотите я просто не стал делать сумму выделенных областей т.к. просто пример. Сейчас поправлю.
# Ответить
15. Yashazz 29.09.2009 16:32
О! Всё ждал, пока кто-нибудь сделает...
Спасибо!
Ответили: (16)
# Ответить
16. 4ish (файл скачал) 29.09.2009 20:40
(15) Благодарю. :)
# Ответить
17. Gleb K. 30.09.2009 14:06
Всем привет. А я себе сделал вот так.
У меня учитывается мультивыделение, наличие скрытых строк и/или столбцов, плюс парочка проверок "на дурака".

[1C-CODE]Процедура ТДПриАктивизацииОбласти(Элемент)
	Сумма = 0;
	Для Каждого Область из ЭлементыФормы.ТД.ВыделенныеОбласти Цикл
		Если Не Область = Неопределено И НЕ (Область.Верх = 0 И Область.Низ = 0) И НЕ (Область.Лево = 0 И Область.Право = 0) Тогда
		Для i = Область.Верх по Область.Низ Цикл
			Для j = Область.Лево по Область.Право Цикл
				Ячейка = ЭлементыФормы.ТД.Область(i,j);
				Если Ячейка.СодержитЗначение
					И Ячейка.Видимость
					И Ячейка.ТипЗначения = Новый ОписаниеТипов("Число")
					И Не Ячейка.Значение = Неопределено Тогда
					Сумма = Сумма + Ячейка.Значение;
				КонецЕсли;
			КонецЦикла;
		КонецЦикла;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры
...Показать Скрыть
[/1C-CODE]
Ответили: (19) (18)
+ 1 [ director04; ]
# Ответить
18. Evg-Lylyk (файл скачал) 30.09.2009 15:46
(17) метод сабжа более оптимален почитайте внимательно и посмотрите код
# Ответить
19. Evg-Lylyk (файл скачал) 30.09.2009 16:09
(17)
"Если Не Область = Неопределено И НЕ (Область.Верх = 0 И Область.Низ = 0) И НЕ (Область.Лево = 0 И Область.Право = 0) Тогда"
Нужно только "Если Не Область = Неопределено" и то не знаю пример когда
Во внутреннем условии тоже не все условия нужны
Строка 100 не будет суммироваться, что как мне кажется, неправильно.

Видимо волна материалов захлестнула инфостарт и все ждут примитивизма, а вот фиг :) это не ко мне
# Ответить
20. Gleb K. 01.10.2009 13:06
(18, 19) Если Не Область = Неопределено возникает когда щелкаешь мышью между заголовков колонок или строк.
С внутренними условиями я перемудрил, у вас лучше.
На счет 100 строки не понял.
А вот скрытые ячейки у вас будут суммироваться, что правильно, но не логично :) Хотя это зависит от процедуры вызывающей функцию ВычислитьСуммуОбласти.
Ответили: (21)
# Ответить
21. Evg-Lylyk (файл скачал) 01.10.2009 15:45
(20) Я имел ввиду что строка "100" не будет суммироваться т.к. имеет Тип("Строка")
На счет скрытых ячеек поправил так логичные (не подумал)
Ответили: (22)
# Ответить
22. artbear 01.10.2009 17:26
(21) Пробовал писать ПолучитьЧислоИзСтроки(Текст) без блока Попытка-Исключение ?
ИМХО должно быть быстрее.
Ответили: (23)
# Ответить
23. Evg-Lylyk (файл скачал) 01.10.2009 18:58
(22) Рад тебя слышать. Конечно быстрее, а что с ошибками делать
Ответили: (34)
# Ответить
24. Ish_2 (файл скачал) 01.10.2009 19:45
Несколько выделенных областей могут имет непустое пересечение .
В этом случае подсчет сумм будет неверным.
Я правильно понял ?
Ответили: (28)
# Ответить
25. Ish_2 (файл скачал) 01.10.2009 21:22
В строке функции :
ОдиночнаяОбласть = ТабличныйДокумент.Область(ЯчВерт,ЯчГориз)
приведено неверное обращение к ячейке.
Правильным обращением при суммировании ячеек будет
ОдиночнаяОбласть = 
ТабличныйДокумент.Область(ЯчВерт,ЯчГориз,ЯчВерт,ЯчГориз)

При обращении к области по двум координатам можно получить не одинарную , а ячейку , которая объединяет несколько ячеек (объединенная ячейка). Подсчет сумм в этом случае будет неверным.
+ 1 [ Evg-Lylyk; ]
# Ответить
26. Ish_2 (файл скачал) 01.10.2009 22:46
Не приводит к неправильно вычисленной сумме и обращение к ячейке , используемое в Бухгалтерии КОРП ("R..C..").
Ответили: (27)
# Ответить
27. Evg-Lylyk (файл скачал) 01.10.2009 22:57
(26) Спасибо понял поправлю ... по мне лучше ТабличныйДокумент.Область(ЯчВерт,ЯчГориз,ЯчВерт,ЯчГориз)
# Ответить
28. Evg-Lylyk (файл скачал) 01.10.2009 22:58
(24) должно нормально отрабатывать кэш для каждой отдельно
Ответили: (29)
# Ответить
29. Ish_2 (файл скачал) 01.10.2009 23:03
(28) Не понял.
Если две выделенные области имеют пересечение (т.е. общие ячейки) , то эти ячейки будут просуммированы дважды :
сначала в одной выделенной области , потом в другой.
# Ответить
30. Ish_2 (файл скачал) 01.10.2009 23:07
+28 Я налетел на этот эффект у себя в теме , где используется не одиночное выделение ячейки в табличном документе , а множественное выделение : "строка" или "крест".
Ответили: (31)
# Ответить
31. Evg-Lylyk (файл скачал) 01.10.2009 23:11
(30) да т.к. это две разные выделенные области.
# Ответить
32. Evg-Lylyk (файл скачал) 01.10.2009 23:13
31+ будут показываться сумма каждой выделенной области + сумма
# Ответить
33. elizarovs (файл скачал) 02.10.2009 09:22
(+) Классно! Еще бы в форме документа такое сделать...
Ответили: (35)
# Ответить
34. artbear 02.10.2009 09:38
(23) Я к тому, что может быть быстрее вместо Попытки анализировать первый символ - если это цифра, то суммировать.
Также сначала можно использовать СокрЛ (не СокрЛП)
или вообще регулярным выражением проверить :)
Ответили: (36) (35)
# Ответить
35. Evg-Lylyk (файл скачал) 02.10.2009 12:23
(33) добавить можно в любую форму с ТабДок это пример
(34) Это проверено еще на консоли медленнее, регуляры так вообще. Вариан описан в p.s. нужно функции ВычислитьСуммуОбласти, ПолучитьЧислоИзСтроки реализовать через ВК должно быть быстрее
Ответили: (40)
# Ответить
36. Ish_2 (файл скачал) 04.10.2009 20:41
(34) Странно.
Пусть текст ячейки начинается с цифры и мы начинаем его суммировать без попытки. В этом случае пользователь получит сообщение об ошибке, если в тексте ячейки - " 1 показатель".
Хрен редьки не слаще.
Применение ВК для подсчета сумм тоже смотрится , на мой взгляд, диковато.
Думаю ,при практическом применении ,например ,в бухгалтерских отчетах скорость подсчета мало существенна. Неоходим лишь быстро вычисляемоый грубый подсчет количества ячеек в выделенных ячейках. И ограничение на их количество.
# Ответить
37. zag2art 12.10.2009 19:31
А чем это лучше чем выделить группу ячее и нажать M+ в калькуляторе 8.1?
Ответили: (38)
# Ответить
38. Evg-Lylyk (файл скачал) 13.10.2009 17:43
(37) тем что не надо ничего нажимать плюс можно среднее посчитать или еще чтото
про М+ мало кто знает
# Ответить
39. banne (файл скачал) 03.11.2009 05:01
Обработка СУПЕР!!! :D
# Ответить
40. elizarovs (файл скачал) 24.11.2009 11:39
(35) Вот именно, с ТабДок, а там везде ТЗ. А у ТЗ нет события ПриАктивизацииОбласти, как и объекта ВыделенныеОбласти.
Ответили: (41)
# Ответить
41. Evg-Lylyk (файл скачал) 25.11.2009 00:59
(40) В ТЗ нельзя выделить одну ячейку в Колонке1 Строке1 и одну ячейку в Колонке2 Строке2 только построчно.
Ответили: (42)
# Ответить
42. elizarovs (файл скачал) 25.11.2009 06:55
(41) Похоже, что так, во всяком случае я не нашёл описания такой возможности или примера. Хотя, если поставить в свойствах выделения строки - Ячейка, а в режиме выделения - множественное, то в форме прекрасно выделяются ячейки в любой комбинации. Выцепить же список выделенных ячеек из кода я не смог. Може кто поможет? Ну очень нужного свойства в 1С не хватает (сумма группы выделенных ячеек)...
Ответили: (43)
# Ответить
43. Evg-Lylyk (файл скачал) 25.11.2009 12:41
(42) опиши когда это нужно (я даже не представляю примера)
Ответили: (44)
# Ответить
44. elizarovs (файл скачал) 26.11.2009 09:21
(43) Большая организация, несколько подразделений и даже несколько баз данных оперативного учета. В базу бухгалтерии сливаются все документы из первичных баз. Любимое занятие бухов - сравнивать документы по наличию и по суммам. Открывают журнал, берут калькулятор и строчат, как из пулемёта. А так бы просто мышкой потыкали. Думаю, можно много ситуаций похожих найти.
Другой пример (реальный). На фирме, на базе 1С, стоит система, в которой итого по документу не сходится с итого по таблице. Не говорю, что это правильно, но так получилось. А я пытаюсь разгрести... Приходится вываливать каждый раз в список, чтобы сложить
Ответили: (45)
# Ответить
45. Evg-Lylyk (файл скачал) 26.11.2009 15:51
(44) как сделать подобное в ТЗ, ТЧ не представляю. Может поможет: для сравнения данных есть СравнениеФайлов очень полезная вещь
# Ответить
46. Kate123 (файл скачал) 28.01.2010 13:18
Спасибо за обработку, очень полезная функция. Подскажите, пожалуйста, как сделать подсчет для табличного поля документа. Для ТЧ документа нет "ПриАктивизацииОбласти",также нет свойства ВыделеннаяОбласть. Куда и как правильно прописать?
Ответили: (47)
# Ответить
47. Evg-Lylyk (файл скачал) 28.01.2010 13:46
(46) Для ТЧ не получится. Почитайте внимательно комментарии этот вопрос поднимали.
# Ответить
48. tango 28.01.2010 13:47
ну, не знаю.
открыли калькулятор.
выделили область.
нажали кнопку.
чем встроеная фича хуже всей этой возни?
Ответили: (49) (50)

Прикрепленные файлы:

123.JPG
# Ответить
49. Evg-Lylyk (файл скачал) 28.01.2010 14:02
(48) Потому что автоматически и не надо ничего нажимать
Вы не первый почитайте комментарии
Даже 1С решили что это нужно и в Бух. КОРП сделали в шаблонах отчетов эту функцию
Ответили: (50)
# Ответить
50. Ish_2 (файл скачал) 28.01.2010 14:08
(48),(49) И в скоро выходящей на замену 1.6 новой версии БП 2.0 предусмотрен этот функционал.

И получается , Миша, что автор предвосхитил появление такого функционала в типовых конфигурациях.
# Ответить
51. tango 28.01.2010 14:18
или содрал в КОРПе :). Гоша.
Ответили: (52)
# Ответить
52. Evg-Lylyk (файл скачал) 28.01.2010 17:30
53. Fisherru 16.02.2010 09:59
(13)
Ваша ссылочка хороша, плюсик поставил, но это не совсем тоже самое...
У вас там идет работа с печатными формами, а хочется с табличными частями документа и со справочниками в форме списка...
Вот что очень хочется http://infostart.ru/forum/forum19/topic31264/
Ответили: (54)
# Ответить
54. Evg-Lylyk (файл скачал) 16.02.2010 10:08
(53) на семерке не подскажу
А в 8.х вроде как нельзя так как в Таблицах, деревьях нельзя получить диапазон выделенных ячеек только выделенные строки
# Ответить
55. zba 28.12.2012 09:19
В управляемой форме не побывал сделать, а то чета там данная функция не работает
# Ответить
56. tamaks 10.12.2013 18:00
Использовал представленые в публикации процедуры для выгрузки привязаных фото для выделеной пользователем в отчете номенклатуры. Сформировал отчет - выделил строки с наименованием номенклатуры - нажал выгрузить фото.
# Ответить
57. le0nard 25.12.2015 23:37
вот чуть измененная из типовой, скрытые не учитывает.

Функция ВычислитьСуммуВыделенныхЯчеекТабличногоДокумента(ПолеТабличногоДокумента) Экспорт
	Сумма = 0;
	Для Каждого Область Из ПолеТабличногоДокумента.ВыделенныеОбласти Цикл
		Если ТипЗнч(Область) = Тип("ОбластьЯчеекТабличногоДокумента") Тогда
			Для ИндексСтрока = Область.Верх По Область.Низ Цикл
				Для ИндексКолонка = Область.Лево По Область.Право Цикл
					Попытка
						адресЯчейки="R" + Формат(ИндексСтрока, "ЧГ=0") + "C" + Формат(ИндексКолонка, "ЧГ=0");
						ячейка=ПолеТабличногоДокумента.Область(адресЯчейки);
						если ячейка.Видимость тогда
							ЧислоЯчейки=Число(СтрЗаменить(ячейка.Текст, " ", ""));
							Сумма = Сумма +ЧислоЯчейки;
						конецесли;
					Исключение
					КонецПопытки;
				КонецЦикла;
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	Возврат Сумма;
КонецФункции
...Показать Скрыть
# Ответить
Внимание! За постинг в данном форуме $m не начисляются.
Внимание! Для написания сообщения необходимо авторизоваться
Текст сообщения*
Прикрепить файл