Страницы: 1
RSS
Медленная работа штатного цикла Do WHILE при копировании строк
 
Добрый день!

Лист1 содержит 50 столбцов, 60 строк - данным кодом копируется построчно на Лист2 18 секунд.
Хотя по идее должны копироваться за 0.5 сек
Код
n = 1
Do While Worksheets("Лист1").Cells(n, 1) <> ""
   Worksheets("Лист1").Rows(n).Copy Worksheets("Лист2").Range("A" & n)
   'MsgBox Sheets("Лист1").Cells(n, 1).Value & " = " & Sheets("Лист2").Cells(n, 1).Value
n = n + 1
Loop

Укажите, пжлст, где собака порылась...
Кто виноват и что делать?...)))

Традиционное спасибо всем откликнувшимся!
Великий и могучий утес, сверкающий бой, с ногой на небе, живущий, пока не исчезнут машины.
 
Do While  оправдан и не виновен. и не сильно нужен
Код
Worksheets("Лист1").Range("A1").CurrentRegion.Copy Worksheets("Лист2").Range("A1")
По вопросам из тем форума, личку не читаю.
 
Цитата
Джек Восмеркин написал: Кто виноват
Тот, кто макрос писал.

Цитата
Джек Восмеркин написал: что делать?
Написать так
Код
Sub Собака_Порылась()
    Worksheets("Лист1").Range(Worksheets("Лист1").Cells(1, 1), Worksheets("Лист1").Cells(Rows.Count, 1).End(xlUp)).EntireRow.Copy Worksheets("Лист2").Range("A1")
End Sub
 
Джек Восмеркин,
Код
Option Explicit

Sub Copy()

Dim sh As Worksheet
Dim shDest As Worksheet

Set sh = ActiveSheet
Set shDest = ThisWorkbook.Sheets(2)
sh.UsedRange.Copy
shDest.Paste (shDest.Cells(1, 1))

End Sub
 
Цитата
копируется построчно на Лист2
Великий и могучий утес, сверкающий бой, с ногой на небе, живущий, пока не исчезнут машины.
 
При работе с листом нужно отключать обновление экрана и пересчет.
И что-то странно - на Вашем файле Ваш цикл отрабатывает за 0,35 сек, никак не  18 сек. А с отключениями - 0,38 сек

Вот такой код у меня отрабатывает примерно за 0,009 сек
Код
Sub tthh()
    t_ = Timer
    Sheets("Лист1").UsedRange.Copy Sheets("Лист2").Cells(1)
    MsgBox Timer - t_
End Sub
Скажи мне, кудесник, любимец ба’гов...
 
Цитата
Джек Восмеркин написал:
копируется построчно на Лист2
зачем? Почему именно построчно? Почему не все сразу?
Скажи мне, кудесник, любимец ба’гов...
 
UsedRange - в зависимости от условий может и не корректным быть. Вдруг там две таблицы и между ними пустая строка, но это скорее редкость, а вот с CurrentRegion скорость у меня выше 0,031 к  0,054
По вопросам из тем форума, личку не читаю.
 
Листами копировать - в конкретно моем случае будет неверно.
Поскольку надо именно строки - потому что в Лист1 идет сравнение по ключу, который находится в другом листе, и в зависимости от условия - копировать строку столько раз, сколько раз встретится ключ.Каждой строке соответствует свой ключ.
Меня интересует именно скорость перебора строк - желательно что бы пользователь ни о чем не успел догадаться...)))
Изменено: Джек Восмеркин - 11.04.2019 13:40:30
Великий и могучий утес, сверкающий бой, с ногой на небе, живущий, пока не исчезнут машины.
 
Цитата
Джек Восмеркин написал:
потому что в Лист1 идет сравнение по ключу, который находится в другом листе
И где это в примере? А если и так, то лучше копировать тогда отфильтрованный диапазон или сперва собрать диапазон через UNION.
По вопросам из тем форума, личку не читаю.
 
Джек Восмеркин, я бы порекомендовал воспользоваться SQL, альтернативно, можно сначала скопировать все необходимые для работы данные в массивы и работать с ними, а потом вставить готовый результат. Чтобы ускорить исполненние в текущем виде, то отключите обновление книги и пересчет формул.
 
В данном случае, при такой скорости, до сравнения ключей  далековато будет...)))

Я даже не знаю насколько затратны по времени операции перебора или копирования.
Если операция перебора очень затратна по времени  - наверно, стоит перебор организовать как то по другому.
Или копирование строк с листа на лист затрантан - может это как то в памяти отработать, и потом целиком на лист.
Или вообще уйти от использования  DO WHILE...

Честно говоря, алгоритмы  с использованием "отфильтрованный диапазон " или UNION еще не попадались на глаза...
Великий и могучий утес, сверкающий бой, с ногой на небе, живущий, пока не исчезнут машины.
 
Я бы с радостью воспользовался SQL и реализовал все на нем - поскольку в VBA пришел из TSQL.
Но насколько я помню, надо создавать строку подключения и там указывается путь к файлу.(((
Для пользователей  - это гарантированный ступор ...)))
Великий и могучий утес, сверкающий бой, с ногой на небе, живущий, пока не исчезнут машины.
 
Джек Восмеркин, если обращаться к листу при каждом сравнении, то это это трудозатратно. Куда быстрее пробегаться по массиву.
Строка подключения может формироваться автоматически в VBA вместе с путем к файлу, как и сам запрос SQL пишется в VBA. Будет работать даже быстрее, чем через массивы.
 
Цитата
iMrTidy написал:
Чтобы ускорить исполненние в текущем виде, то отключите обновление книги и пересчет формул.
А поможет? :-) В данном случае скорее нет.

Джек Восмеркин, без примера токо что вы там хотите фильтровать , трудно сделать хоть что-то рабочее и показательное. при этом SQL VBA, SQL MS Query? PowerQuery и просто правильные  VBA варианты дадут нормальный по скорости результат.
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал: А поможет?
Если на зависимых листах присутствуют "тяжелые" вычисления, то поможет, если листы это только данные, то разница будет не заметна.
 
Вот дополненный пример.
Вкратце так:
Код
Копируем строки из Лист1 в Лист2. По условию:
   If Лист1.id= Лист3.id То копируем строку в Лист2
          до тех пор пока  Лист1.id= Лист3.id ' То есть строк и 1  и 2 может быть
  If Лист1.id= Лист4.id То копируем в Лист1.Cell(id,n) <-- Лист4.Cell(id,m)

Тапками не кидаться - как смог...
Изменено: Джек Восмеркин - 11.04.2019 15:10:15
Великий и могучий утес, сверкающий бой, с ногой на небе, живущий, пока не исчезнут машины.
 
Гляжу в сторону - загнать каждый лист в массив, цикл по всем массивам по id, перебрать и обработать массивы, результат arr2(Лист2,2) скинуть на Лист2.
Более скоростных вариантов пока не вижу...
Великий и могучий утес, сверкающий бой, с ногой на небе, живущий, пока не исчезнут машины.
 
Джек Восмеркин, SQL будет куда проще. На всякий случай, в массив диапазон загоняется одним коротким действием. Pearson в помощь.
 
Ссылочка - как бальзам на душу.
Там все понятно рассказано.
Спасибо.

В SQL тоже тоже тонкости есть - я не смогу сделать типа
Код
SELECT * 
INTO Лист2
FROM ( SELECT * FROM Лист1 a
       Left Join (SELECT * FROM Лист3) b ON b.id=a.id
       Left Join (SELECT * FROM Лист4) c ON c.id=b.id ) z
WHERE id IS NOT NULL
так как надо явно перечислять все поля, для обработки.
И есть ограничение на размер запроса - 25 строк и 1024 байта в строке.
Так что с SQL тоже не все так
Изменено: Джек Восмеркин - 11.04.2019 16:11:48
Великий и могучий утес, сверкающий бой, с ногой на небе, живущий, пока не исчезнут машины.
 
Джек Восмеркин, а как же Вы собираетесь без знания полей работать с массивом? Откуда такие ограничения? Поделитесь ссылкой.

Дополнение: полгаю, что ACE.OleDb 12.0 имеет такие ограничения.
Дополнение2: SQL VBA в запросе позволяет ссылаться на поля под их номерами, а не только именами, например, F1, F2...
Изменено: iMrTidy - 11.04.2019 16:30:49
 
Это библиотека sqloledb - столкнулся с ограничениями, когда писал запросы в VBA  к SQL-серверу.
Это ограничение библиотеки или самого VBA - уже не помню.
Долго искал причины ошибок, когда писал большие портянки - уперлось именно в эти ограничения.
Ссылку уже наверно и не найду.
Наверно да, библиотека ACE.OleDb 12.0 таких ограничений не имеет, лишь бы VBA позволил - перечислять более 50 столбцов.
Сейчас попробуем
Великий и могучий утес, сверкающий бой, с ногой на небе, живущий, пока не исчезнут машины.
Страницы: 1
Наверх