|
|
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
Есть циклический алгоритм формирования (большого) отчета. Трассировка показывает, что более половины времени работы занимает строка Код: plaintext далее destrange заполняется полями данных. Отказаться от строки templateRange.Copy destRange не просто, т.к. В этой одной команде происходит копирование фиксированного содержимого образца раздела отчета – labels, внедренные рисунки, форматирование клеток, комментарии к клеткам и т.п. – все за раз. Можно ли написать на VBA пользовательскую процедуру (произвольной сложности и размера), которая сумела бы обогнать метод Range.Copy Excel? Задача: Требуется на VBA написать пользовательскую процедуру (произвольной сложности и размера), которая скопирует полностью содержимое диапазона-образца в диапазон-назначение (другой книги): значения и формулы в клетках, комментарии, внедренные в область диапазона объекты, форматы, цвета и размеры клеток, (объединения клеток). То есть повторить функционал templateRange.Copy destRange полностью, но так, чтобы результат был быстрее. Может ли такая задача иметь решение? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 16:56:21 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
бабайЕсть циклический алгоритм формирования (большого) отчета. Трассировка показывает, что более половины времени работы занимает строка Код: plaintext далее destrange заполняется полями данных. Отказаться от строки templateRange.Copy destRange не просто, т.к. В этой одной команде происходит копирование фиксированного содержимого образца раздела отчета – labels, внедренные рисунки, форматирование клеток, комментарии к клеткам и т.п. – все за раз.дадада. умея заполнять большие рэнджи заливкой массива тем не менее - много удобнее построчно раскопировать темплейт. (я так по ленности до сих пор и делаю) думаю, что быстро - это посчитать все количество строк, вкуда надо влить один и тот же шаблон ренча, а в посчитанное - вливать (из массивов) отдельные детали шаблона - те же Formula, Formula2, форматирование и т.п. Кстати, слиятель ренчей (clsFormater) тут не понадобицца ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 17:10:50 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
авторКстати, слиятель ренчей (clsFormater) тут не понадобицца вроде не должен. я его все равно потерял. если будет нужен - придется искать огрызки по форуму. много какого кода потерял за лето, как неожиданно выяснилось при востановлении рухнувшей машинки. что до задачки - пока даже страшно браться, не имея представления о перспективе. мне легче всего самому себе сказать, что этого сделать нельзя. Но... - может быть найдутся основания для опровержения такого мнения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 17:24:51 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
кстати, проблема реально напрягает только на больших отчетах. Вот ее то можно порешать - там, как правило, пролеты рядов, в коих один и тот же формат - весьма велики. правильно ли я понял, что вставляете вы совсем в другой лист (или даже книгу) чем сам шаблон? (я обычно прямо в шаблон луплю, при этом автоматом сдвигаются именованные области из подвала отчета). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 17:33:08 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
авторправильно ли я понял, что вставляете вы совсем в другой лист (или даже книгу) чем сам шаблон? (я обычно прямо в шаблон луплю, при этом автоматом сдвигаются именованные области из подвала отчета). правильно поняли. речь идет об очете с вложенными уровнями группировки. копировать раздел-образец в точку вставки - самая простая логика, сохраняющая внешний вид отчета. образец где-то жить должен. либо на другом листе, либо в отдельной книге. у меня - в отдельной книге-образце отчета. иначе всякий раз придется собирать из подвалов раздела разъехавшееся фиксированное форматирование блока (лабелс, картинкос, цветуечки и прпр) при наличии в нем вложенных групповых разделов. т.е. как раз решать эту самую задачу, которую я частично не знаю, как хорошо решить ( например, в части форматов, цветов и границ клеток), а частично пока думаю, что альтернативы будут еще медленнее. я не хочу услышать "нет". т.к. сам с этим нет сейчас сижу. хотелось бы услышать обоснованное "попробуй так - тут что-то проглядывается". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 17:42:16 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
бабайпока думаю, что альтернативы будут еще медленнее.Правильно думаешь. Ну почти правильно :) бабайя не хочу услышать "нет". т.к. сам с этим нет сейчас сижу. хотелось бы услышать обоснованное "попробуй так - тут что-то проглядывается". Есть несколько способов наполнить лист на основе шаблона: 1) Скопировать файл книги-шаблона в новый файл 2) Скопировать лист-шаблон целиком в новую или существующую книгу 3) Скопировать область через sourcerange.Copy destRange 4) Заполнить целевой лист форматами через макрос. Первый способ самый быстрый, четвертый самый медленный. Минусы сам найдешь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 18:01:34 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
авторЕсть несколько способов наполнить лист на основе шаблона: 1) Скопировать файл книги-шаблона в новый файл 2) Скопировать лист-шаблон целиком в новую или существующую книгу 3) Скопировать область через sourcerange.Copy destRange 4) Заполнить целевой лист форматами через макрос. Первый способ самый быстрый, четвертый самый медленный. Минусы сам найдешь. из перечисленных шагов у меня используется вариация на тему 1) (при старте дважды add шаблоннной книге) и 3) в цикле заполнения (смотри пост с вопросом) 3) и занимает >50% времени выполнения отчета. Ближайший конкурент по медленности где-то в районе 10% времени выполнения находится. Предположим, что я написал самый плохой в мире алгоритм заполнения отчета. И в нем много медленно работающего кода. и другая логика заполнения работала в каких-то конкретных фрагментах быстрее и даже в разы быстрее в каком-нибудь особо поддающемся к оптимизации фрагменте. Однако, в силу автор3) и занимает >50% времени выполнения отчета. менять логику заполнения бесмысленно, пока не будет решена проблема 3). Если решения нет, то и существенного выигрша от потраченных усилий не будет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 18:17:44 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
бабайОднако, в силу автор3) и занимает >50% времени выполнения отчета. менять логику заполнения бесмысленно, пока не будет решена проблема 3). Если решения нет, то и существенного выигрша от потраченных усилий не будет.Невнимательно читаешь. Смотри пункт 2 :) Копировать лист целиком намного быстрее чем копировать область. А если область содержит встроенные объекты (картинки, кнопки, рисунки) то ее копирование будет идти еще дольше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 18:25:21 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
авторНевнимательно читаешь смотри вопрос в первом посте и разъяснения к нему в последующих. Range описывает область циклического заполнения - одиночный раздел отчета, который сам по себе может включать в себя вложенные дочерние разделы, и каждый такой раздел подлежит многократному заполнению из повторно получаемых для данного раздела наборов данных. Не изволите ли уточнить - в какое именно место вы предлагаете засунуть копирование листа? (Проблема старта и первичного форматирования книи-результата отчета меня в данный момент не интересует и не является существом заданного вопроса) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 18:33:10 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
бабайсмотри вопрос в первом посте и разъяснения к нему в последующих. Range описывает область циклического заполнения - одиночный раздел отчета, который сам по себе может включать в себя вложенные дочерние разделы, и каждый такой раздел подлежит многократному заполнению из повторно получаемых для данного раздела наборов данных. гм. я вот тут подумал: ЭтаКнига.Sheets("лист1").Range("A6","H6").Copy Union(ЭтаКнига.Sheets("лист2").Range("A6","H12"),ЭтаКнига.Sheets("лист2").Range("A14","H24")) - работает, т.е. вопрос: - вы льете .Copy построчно в цикле, или сразу в большие просчитанные заранее однородные "пролеты"? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 18:45:53 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
бабай авторНевнимательно читаешь смотри вопрос в первом посте и разъяснения к нему в последующих.Убедил, это я невнимательно читаю, прошу прощения. Тогда вынужден огорчить, копирование областей целиком это самый-самый быстрый способ. Быстрее не выходя из Экселя не получится в принципе. Но можно временно выйти за пределы Экселя... Формируешь на диске html со всеми шаблонами, картинками, и заполненый данными а потом загружаешь его в книгу на новый лист. Сохраняешь книгу и убиваешь html. Этот путь будет несколько посложнее чем простая работа с листом, но чуть-чуть побыстрее потому что Экселю не прийдется заниматся перераспределением памяти. Он ее потратит только в конце (при загрузке html'я), и разом на весь документ. Еще можно упрощать шаблон. В первую очередь убрать из него все картинки и метки. Оставить только тексты и форматы в ячейках. Все наклейки на лист ОЧЕНЬ утяжеляют работу с областью. Но это мне кажется не совсем то решение что ты ищешь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 18:46:24 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
White OwlФормируешь на диске html со всеми шаблонами, картинками, и заполненый данными а потом загружаешь его в книгу на новый лист.с html я как то нарвался на какие-то ограничения. а именно - то ли по числу столбцов, то ли по сложности таблицы. К тому же требовалось ваять с группировками. А влудить в html работающую формулу (Сумма(диапазон)) и втянуть в xl будет не так легко. Нет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 18:54:47 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
assa с html я как то нарвался на какие-то ограничения.имеетс в виду - при втаскивании его в XL ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 18:55:48 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
html - возможно это кардинальный вариант. но, видимо, на потом. сейчас затребует непозволительного времени для разборок - надо сыскать описание, желательно совместимое аж с 97й версией, разобраться, ну и "погонять" на предмет разъезжаемости картинков, примечаний и прпр. за ссылки на описание и примеры скажу спасибо. Про хатеэмэль пока не думалось... но... вдруг и без хатеэмэля какой-нибудь ExecuteExcel4Macro чудес наделает? нет ли на этих путях каких просветов и/или примеров? пока писал этот пост - про клипборд только на чтение еще подумал. но как-то не очень верится. усложнение заметное, а результат непонятен. хотя бы "в принципе" - ну там как-то через xll, допустим, - что-то можно сделать без полного ухода на промежуточную отрисовку на стороннее полотно (т.е. типа html) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 18:59:08 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
assaгм. я вот тут подумал: ЭтаКнига.Sheets("лист1").Range("A6","H6").Copy Union(ЭтаКнига.Sheets("лист2").Range("A6","H12"),ЭтаКнига.Sheets("лист2").Range("A14","H24")) - работает, т.е. вопрос: - вы льете .Copy построчно в цикле, или сразу в большие просчитанные заранее однородные "пролеты"? а что на этом можно сэкономить в смысле времени работы Copy? Могу я понимать это как заявление о том, что в рамках одного экземпляра Excel Copy диапазона c листа на лист одной и той же книги работает быстрее, чем Copy с листа одной книги на лист в другой книге, открытой в том же экземпляре Excel? --------------------------------------------------------- лью поблочно. в размер текущего блока-образца. простого и очевидного каунта на входном потоке нет. поэтому нет предварительного расчета итоговой высоты группы. Есть "метка блока", к которому относится текущая часть входного потока. полным проходом по всему потоку можно было бы получить и каунт. Тогда отчет должен будет строиться в два прохода по потоку. в большинстве наличных случаев наборы пригодны к переходу вверх/вниз. Код усложнится и распухнет. Пока на такую возможность не думал закладываться. Copy само по себе при этом не исчезнет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 19:33:21 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
бабайМогу я понимать это как заявление о том, что в рамках одного экземпляра Excel Copy диапазона c листа на лист одной и той же книги работает быстрее, чем Copy с листа одной книги на лист в другой книге, открытой в том же экземпляре Excel?Да. Выигрыш будет, но очень мизерный. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2007, 20:06:41 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
Я тут попробовал у себя на компе (Win Vista Business, MSO 2007 Ultimate, Intel Core 2 Duo 2,16 MHz, RAM 3.325 MB) запустить такую несколько экстремальную фиговину: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. В результате Test() выдал 36.7 сек. Отсюда вопрос: Ты отключил перерисовку экрана, события и пересчет формул? Application.ScreenUpdating = False Application.EnableEvents = False Application.Calculation = xlCalculationManual KL [MVP - Microsoft Excel] ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2007, 06:20:47 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
2 KL (XL) да. отключил. в абсолютных величинах сейчас скорость работы построителя отчетов - 200 строк в секунду (P4 2.8 512 мб ram) маловато малек. глядя на твой "экстремальный" пример пока подумал вот что - сейчас блоки копирования представляют собой цельнострочные диапазоны. попробую ограничить размер области копирования прямоугольными диапазонами. возможно это даст некоторый эффект. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2007, 17:17:38 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
бабайв абсолютных величинах сейчас скорость работы построителя отчетов - 200 строк в секунду (P4 2.8 512 мб ram) маловато малек. Да уж не ахти даже для такой "относительно слабой" машины :D Может покажешь код? Вот это на Win Vista Business, MSO 2007 Ultimate (Compatibility Mode), Intel Core 2 Duo 2,16 MHz, RAM 3.325 MB дает 10.000 строк - 14 сек : Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2007, 17:50:19 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
извиняюсь за задержку - переключал компьютеры для доступа к коду и прочие отвлекающие обстоятельства проявились... код такой копируется ранее уже заполненный блок для повторного заполнения Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. в pTemplateRange содержится фиксированный текст (labels) а также комментарии к клеткам. могут быть внедренные объекты вроде рисунков тормоз в строке pTemplateRange.Copy pCurrentRange пока попробую поискать крайнюю правую занятую хоть чем-нибудь клетку диапазона и копировать прямоугольными областями. Можно ли найти такую клетку без цикла по строкам с End на каждом шаге цикла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2007, 19:05:15 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
точка в предпоследней строке не откусилась при копировании из предыдущий - это дефект офоормления поста. в коде ее нет, конечно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2007, 19:06:58 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
оценки такие: твой тестовый код на моем домашнем компе (атлон5000 гиг памяти, ексель2002) дает время исполнения 12.3 - 13.6 сек на разных запусках. мой собственный код в тесовом прогоне на 4400 строк работает на "рабочей" машине 23 сек, на домашней - 10.3 - 9.7 сек. т.е. отношение скорости работа/дом около 2.3 значит на рабочей машине твой тест будет идти ? 13.6*2.3= 31 сек а мой отчет, увеличенный до 10000 строк - ? 23& * 10000/4412= 52 сек из которых 31 (59%) будет занято временем работы единственной строки кода. В этом и есть существо вопроса - можно что-то другое умное поделать, но ниже 31 сек опуситься будет "совсем нельзя". т.е. улучшить скорость наличного кода нельзя более чем на 40% прнинципиально. А реальное улучшение окажется гарантированно серьезно меньше при любой умности в условиях сохранения строки templateRange.Copy destRange Если что-то придумается с копированием - может быть существенный выигрыш в общей производительности. Отсюда был вопрос. Не знаю готов ли к реализации чего-то сильно альтернативного, но если будут идеи - пусть самые неожиданные - с удовольствием попробую понять возможность их применимости. Пока такая была одна с предупреждением - рисуй типа хатемеэль. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2007, 19:54:36 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
попробовал усечь диапазоны копирования. Вроде бы эффект есть. но не превышает 10% и в текущем тестовом окружении, к сожалению, трудно отличим от ошибки измерения. т.к. против вероятно ускорившегося копирования замедлилась вставка, которая теперь требует явного обращения к EntireRow Т.е. - может быть и помогло, но не кардинально. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2007, 21:29:36 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
бабай Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. Чё то как то не очень понятно. До меня струдом доходит зачем так делать, либо ты ошибся и не то написал. В предпоследней строке точно ошибка, там наверное диапазон переопределяться должен должен. и из текущей логики lNewHeight и pStartHeight не одно и то же разве ? Может лучше примерчик сварганишь в файле и выложишь файл. Если хочешь конечно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2007, 23:10:29 |
|
||
|
Тормозит Range.Copy. можно ли его обогнать, обмануть или победить?
|
|||
|---|---|---|---|
|
#18+
pStartHeight это templateRange.Rows.Count pCurrentRange.Rows.Count может от него произвольно отличаться к моменту копирования из-за наличия вложенных блоков. Извини, полного примера выложить не могу. Целью моего вопроса не являлось обсуждение конкретных деталей конкретной реализации элемента построителя отчетов в сторонней системе. А только попытка понимания, может ли существовать custom реализация метода Copy, работающая быстрее стандартной. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2007, 23:28:34 |
|
||
|
|

start [/forum/topic.php?fid=61&msg=34770409&tid=2182351]: |
0ms |
get settings: |
10ms |
get forum list: |
17ms |
check forum access: |
5ms |
check topic access: |
5ms |
track hit: |
51ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
58ms |
get tp. blocked users: |
1ms |
| others: | 243ms |
| total: | 401ms |

| 0 / 0 |
