2011-02-17 3 views
3

В моем коде Excel VBA мне нужно переместить некоторые данные из диапазона на другой лист.Итерация 100 ячеек занимает слишком много времени

В настоящее время, я перебор диапазона и копирование значения, как это:

For offset = 0 To 101 
     ActiveWorkbook.Sheets(Sheet).Range("C3").offset(offset, 0).Value = ActiveSheet.Range("D4").offset(offset, 0).Value 
    Next offset 

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

Могу ли я использовать программную копию Copy-Paste, или есть способ скопировать весь диапазон сразу? Что-то вроде:

ActiveWorkbook.Sheets(Sheet).Range("C3:C102").Value = ActiveSheet.Range("D4:D104").Value 

ответ

2

Вы можете прочитать весь диапазон сразу в массив Variant, а затем записать его обратно в другой диапазон. Это также быстро, без мерцания и имеет дополнительный бонус, который вы можете скопировать некоторые операции над данными, если вы так склонны.

Dim varDummy As Variant 
varDummy = ActiveSheet.Range("D4:D104") 
' Can insert code to do stuff with varDummy here 
Workbook.Sheets(Sheet).Range("C3:C103") = varDummy 

Это я узнал трудный путь: Избегайте Копировать/Вставить, если это вообще возможно! Копировать и вставить используйте буфер обмена. Другие программы могут считывать/записывать в буфер обмена во время работы вашего кода, что приведет к непредсказуемым результатам.

Также, как правило, рекомендуется минимизировать количество взаимодействий между VBA и Excel, потому что они медленны. Наличие таких взаимодействий в цикле многократно медленное.

+0

".... Другие программы могут читать/записывать в буфер обмена во время работы вашего кода, что вызовет дикие, непредсказуемые результаты ....« Это отличный совет – CaBieberach

1
Columns("A:Z").Select 
Selection.Copy 
Sheets("Sheet2").Select 
Range("A1").Select 
ActiveSheet.Paste 

Это будет копировать столбцы А до Я от листа 1 к Листу 2. Это был порожден записью макроса. Вы также можете применить его к диапазонам примерно с таким:

Range("D4:G14").Select 
Selection.Copy 
Sheets("Sheet2").Select 
Range("D4").Select 
ActiveSheet.Paste 

Это что-то вроде того, что вы после?

Если вам что-то нужно, и вы можете сделать это вручную (например, скопировать и вставить), запишите макрос, чтобы получить код VBA для него.

+0

Я надеялся не копировать-вставить, потому что, когда вы это делаете, ваш вид листа перескакивает с исходного листа на лист адресата. Мне нужно повторить это примерно в 20 раз, и я в конечном итоге смотрю на превосходные мигающие листы. Но я попробую, и если производительность будет значительно быстрее, мне придется пойти на это. – xbonez

+0

Интересно, что это занимает до 45 секунд всего за 100 строк. У меня есть макрос, который повторяется через 1000 строк за раз, и он обновил примерно 50 или около того из другой таблицы, и все это работает через несколько секунд. – joshhendo

+1

Важно принять участие в Application.Calculation. Если вы включили вычисление, каждое значение, введенное в ячейку, вызовет перерасчет (каждой открытой книги). – CaBieberach

2

Итак, глупый я не пробовал, прежде чем отправлять здесь. По-видимому, я могу перемещать данные для всего диапазона таким образом:

Workbook.Sheets(Sheet).Range("C3:C102").Value = ActiveSheet.Range("D4:D104").Value 

Сво так же быстро, как копирование пасты без переключения листов. Итерация по диапазону с использованием цикла for занимает около 45 секунд для 100 ячеек, в то время как эти два варианта являются мгновенными.

+2

Эти диапазоны не кажутся одинакового размера, поэтому следите за неожиданными результатами. –

+0

Вы правы. Регулировка размера заставила его работать довольно snappily, хотя. – xbonez

1

Копирование и вставка имеет приличное количество накладных расходов в VBA, а также имеет дело с такими диапазонами. Это было время, так как я сделал VBA, но если я правильно помню, самый быстрый способ сделать что-то вроде этого - записать нужные значения в массив, а затем использовать функцию Resize. Так что-то вроде этого:

Option Base 0 
Dim firstrow as integer 
Dim lastrow as integer 
Dim valuesArray() as Long 
Dim i as integer 

//Set firstrow and lastrow however you deem appropriate 
... 

//Subtracing first row from last row gets you the needed size of the 0 based array 
ReDim valuesArray(lastrow-firstrow) 

for int i = 0 to (lastrow-firstrow) 
    valuesArray(i)=Cells(i+firstrow, COLUMNNUMBER).value 
next i 

Конечно заменить ColumnNumber с любой столбец это вы итерация. Это должно заполнить ваш массив желаемыми значениями. Затем выберите ячейку назначения и используйте Resize для ввода значений.Так что, если ваш мобильный назначения D4:

Range("D4").Resize(UBound(valuesArray)+1, 0).value = valuesArray 

Это написать все значения в массиве, начиная с D4 и спускаясь, как много клеток в массиве. Чуть сложнее, но если вы собираетесь на скорость, я не думаю, что когда-либо придумывал что-нибудь быстрее. Также я сделал это с верхней части головы, поэтому, пожалуйста, проверьте и убедитесь, что вы не отрезаете камеру здесь и там.

+0

просто хотел добавить, что в этом сценарии я определил массив принимает длинные типы данных, поэтому это не удастся, если вы пытаетесь скопировать строки или что-то еще. в любом случае, если вы пытаетесь переместить строки, измените объявление массива как строку. если вы не знаете, что будет в массиве, вы можете объявить его как вариант, но, конечно, это будет не так быстро, как явное объявление типа данных –

1

Это OzGrid страница имеет очень полезную информацию - http://www.ozgrid.com/VBA/SpeedingUpVBACode.htm

В моем случае, мне нужно форматирование, чтобы быть скопированы, а поэтому я использую это:

Sheet1.Range("A1:A200").Copy Destination:=Sheet2.Range("B1") 

, но по-прежнему с очень медленным исполнение - до момента блокировки приложения - я, наконец, нашел проблему - в какой-то момент в прошлом на мою страницу попало несколько пустых текстовых полей - и когда они были скопированы каждый раз, когда мой код запускался, они не были стерты моей код для очистки рабочей зоны. Результатом было что-то вроде 4500 пустых текстовых полей - каждый из которых был скопирован и вставлен даже кодом выше.

Если вы используете Edit - Go To ... - Нажмите Special - затем выберите Objects - и вы не увидите ничего хорошего - если вы видите кучу объектов, о которых вы не знали на своей странице это не хорошо.

Смежные вопросы