Оптимизация цикла для vba macro excel 2007

У меня есть этот код, который работает. он сбрасывает диапазон и удаляет пустые строки, разделяет первый символ на другой столбец, если это не число или отрицательный знак.
Этот код РАБОТАЕТ. но он слишком МЕДЛЕННЫЙ для объема данных, которые мне нужны для этого. Спасибо вам за ваше предложение о том, как оптимизировать этот код и сделать его быстрее.

Я уже отключил автоматические вычисления. обновление экрана. и видимость применения.

Dim rng As Range Dim i As Long Dim Tracking As Long Dim textval As String Dim limitz As String Dim remaining As String Range("B1").End(xlDown).Offset(0, 5).Select Set rng = Range("G2", ActiveCell).Select i = 1 Range("G2").Select For Tracking = 1 To rng.Rows.Count textval = rng.Cells(i).Value limitz = Left(textval, 1) If limitz = "" Then rng.Cells(i).EntireRow.Delete ElseIf limitz <> "0" And limitz <> "1" And limitz <> "2" And limitz <> "3" And limitz <> "4" And limitz <> "5" And limitz <> "6" And limitz <> "7" And limitz <> "8" And limitz <> "9" And limitz <> "-" Then remaining = Right(textval, Len(textval) - 1) rng.Cells(i) = remaining rng.Cells(i).Offset(0, 1).Value = limitz i = i + 1 Else i = i + 1 End If Next 

Существует не так много кода, который кажется явно неэффективным .

Вот несколько советов о том, что я могу сказать:

  • Не выбирайте ячейки, если вы тоже не навязаны (так как это не входит в ваш цикл, это не самое худшее)
  • Попробуйте использовать синтаксический анализ вместо использования Long
  • Измените свой тест с помощью инструкции vba, такой как IsNumeric
  • Использовать With чтобы избежать вызова объекта несколько раз

Вот попытка (возможно, я изменил какое-то поведение, потому что я не мог понять, хотите ли вы разбирать ячейки или строки):

 Sub test() Dim rng As Range, row As Range Dim i As Long Dim textval As String Dim limitz As String Dim remaining As String Set rng = Range("G2", Range("B1").End(xlDown).Offset(0, 5)) i = 1 For Each row In rng.Rows With row textval = .Cells(i).Value limitz = Left(textval, 1) If limitz = "" Then .Cells(i).EntireRow.Delete ElseIf limitz <> "-" And Not IsNumeric(limitz) Then remaining = Right(textval, Len(textval) - 1) With .Cells(i) .Value = remaining .Offset(0, 1).Value = limitz End With i = i + 1 Else i = i + 1 End If End With Next End Sub 

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

Непроверенные:

 Sub test() Dim rng As Range, c As Range Dim numRows As Long Dim Tracking As Long Dim textval As String Dim limitz As String Set rng = Range("G2", Range("B1").End(xlDown).Offset(0, 5)) numRows = rng.Rows.Count For Tracking = numRows To 1 Step -1 Set c = rng.Cells(Tracking) textval = c.Value limitz = Left(textval, 1) If limitz = "" Then c.EntireRow.Delete ElseIf Not limitz Like "[0-9-]" Then c.Value = Right(textval, Len(textval) - 1) c.Offset(0, 1).Value = limitz End If Next End Sub 

Это должно быть довольно быстро. Надеюсь, я не слишком сильно изменил ваш код, чтобы что-то изменить, чего я не должен был.

Схват всех данных в варианте делает его намного быстрее, поскольку VBA не слишком много взаимодействует с Excel. Использование специальных ячеек также делает это. Использование «like» очищает код вверх, не знаю, лучше ли для него производительность.

 Dim rng As Range Dim vData As Variant Dim i As Long Dim limitz As String Set rng = Range("G2", Range("B1").End(xlDown).Offset(0, 5).Address) 'Delete empty cells On Error Resume Next rng.SpecialCells(xlCellTypeBlanks).EntireRow.Delete On Error GoTo 0 'Get all data in range vData = rng.Resize(, 2) For i = 1 To UBound(vData) limitz = Left$(CStr(vData(i, 1)), 1) If limitz Like "[!0-9,!-]" Then vData(i, 1) = Right$(CStr(vData(i, 1)), Len(vData(i, 1)) - 1) vData(i, 2) = limitz End If Next rng.Resize(, 2) = vData 

Следующий код не проверен, но должен работать и идти довольно быстро. Следует отметить, что удаленные целые строки достаточно дорогостоящие (временные), чтобы сделать, хотя вы можете свести к минимуму время с помощью метода, приведенного ниже, это все равно займет некоторое время, и вы не можете с ним справиться:

 dim bUnion as boolean Dim rng As Range, rUnion as range Dim vData As Variant Dim i As Long Dim limitz As String Set rng = Range("G2", Range("B1").End(xlDown).Offset(0, 5).Address) 'Get all data in range vData = rng.Resize(, 2) bunion=false For i = 1 To UBound(vData) if len(vdata(i,1))>0 THEN limitz = Left$(CStr(vData(i, 1)), 1) If limitz Like "[!0-9,!-]" Then vData(i, 1) = Right$(CStr(vData(i, 1)), Len(vData(i, 1)) - 1) vData(i, 2) = limitz End If else if bunion then set runion=union(runion,range("A" & i+1)) else set runion=range("A" & i+1) bunion=true end if end if Next rng.Resize(, 2) = vData runion.entirerow.delete 
  • Как динамически переименовать имя листа Excel в C #
  • Открыть объект ExcelPackage с помощью приложения Excel без сохранения его на пути к локальному файлу
  • Установка значения ячейки Excel в десятичное число на C #. Различия между .NET 2 и .NET 4
  • Строка агностической версии Excel
  • Редактирование файла excel при экспорте данных из MS-доступа в другой файл excel с использованием c # без ошибок
  • Worksheet.SaveAs ("file.csv") работает по-разному в .NET 3.5 и .NET 4.0
  • C # конвертировать csv в xls (используя существующий файл csv)
  • Способ автоматизации сбора данных из Excel?
  • Open XML SDK пишите Double Value в ячейку Excel
  • Копирование гиперссылок из ячейки в другую с помощью NPOI
  • oledb vs excel interop vs open xml vs управления доступом к данным для чтения больших данных Excel в .net
  • Давайте будем гением компьютера.