gifts2017

Оптимизированный подсчет суммы выделенных ячеек табличного документа (как в 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
270
.epf 9,34Kb 270 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

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

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

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

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

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

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

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

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