Повторение 100 ячеек занимает слишком много времени - PullRequest
3 голосов
/ 18 февраля 2011

В моем коде Excel VBA мне нужно переместить некоторые данные из диапазона на другой лист.

На данный момент я перебираю диапазон и копирую значения следующим образом:

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

Однако итерация и копирование значений для 100 ячеек занимает почти минуту.

Будет ли лучше использовать функцию копирования-вставки программно или есть способ скопировать сразу весь диапазон? Что-то вроде:

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

Ответы [ 6 ]

2 голосов
/ 18 февраля 2011

Вы можете прочитать весь диапазон сразу в массив 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, поскольку они медленные. Наличие таких взаимодействий в цикле очень медленно.

2 голосов
/ 18 февраля 2011

Вы можете ускорить код и остановить мерцание с помощью:

Application.ScreenUpdating = False

'YOUR CODE

Application.ScreenUpdating = True

Подробнее: http://www.ozgrid.com/VBA/excel-macro-screen-flicker.htm

2 голосов
/ 18 февраля 2011

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

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

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

1 голос
/ 03 мая 2012

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

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

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

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

Если вы используете «Правка» - «Перейти к ...» - нажмите «Специальные» - затем выберите «Объекты» - и вы не видите ничего хорошего - если вы видите на своей странице группу объектов, о которых вы не знали, не хорошо.

1 голос
/ 19 февраля 2011

Копирование и вставка имеют приличную нагрузку в 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 и заканчивая количеством ячеек в массиве. Немного сложнее, но если вы идете на скорости, я не думаю, что я когда-либо придумал что-нибудь быстрее. Кроме того, я сделал это на макушке головы, поэтому, пожалуйста, проверьте и убедитесь, что вы не отрежете клетку здесь и там.

1 голос
/ 18 февраля 2011
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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...