Поиск…


замечания

Мы все знаем их, но эти практики гораздо менее очевидны для тех, кто начинает программировать в VBA.


ВСЕГДА Используйте «Option Explicit»

В окне редактора VBA в меню «Сервис» выберите «Параметры»:

введите описание изображения здесь

Затем на вкладке «Редактор» убедитесь, что «Требовать переменную декларацию» отмечен:

введите описание изображения здесь

При выборе этой опции автоматически добавляется Option Explicit в верхней части каждого модуля VBA.

Небольшое примечание: это верно для модулей, модулей классов и т. Д., Которые пока не были открыты. Поэтому, если вы уже рассмотрели, например, код Sheet1 перед тем как активировать опцию «Требовать объявление переменной», Option Explicit не будет добавлен!

Option Explicit требует, чтобы каждая переменная была определена перед использованием, например, с помощью оператора Dim . Без Option Explicit , любое непризнанное слово будет приниматься компилятором VBA как новая переменная типа Variant , вызывая чрезвычайно сложные ошибки, связанные с типографскими ошибками. Если Option Explicit включена, любые непризнанные слова вызовут ошибку компиляции, указывая на строку нарушения.

Пример :

Если вы запустите следующий код:

Sub Test()
  my_variable = 12
  MsgBox "My Variable is : " & myvariable
End Sub

Появится следующее сообщение:

введите описание изображения здесь

Вы сделали ошибку, написав myvariable вместо my_variable , затем в поле сообщения отображается пустая переменная. Если вы используете Option Explicit , эта ошибка невозможна, потому что вы получите сообщение об ошибке компиляции, указывающее на проблему.

введите описание изображения здесь

Теперь, если вы добавите правильное объявление:

Sub Test()
  Dim my_variable As Integer
  my_variable = 12
  MsgBox "My Variable is : " & myvariable
End Sub

Вы получите сообщение об ошибке с указанием ошибки с myvariable :

введите описание изображения здесь


Примечание по Option Explicit и Array ( объявление динамического массива ):

Вы можете использовать оператор ReDim, чтобы объявить массив неявно в рамках процедуры.

  • Будьте осторожны, чтобы не пропустить имя массива при использовании оператора ReDim

  • Даже если оператор Option Explicit включен в модуль, будет создан новый массив

    Dim arr() as Long

    ReDim ar() 'creates new array "ar" - "ReDim ar()" acts like "Dim ar()"

Работа с массивами, а не с диапазонами

Офисный блог - лучшие методы кодирования производительности Excel VBA

Часто достигается наилучшая производительность, позволяя максимально избегать использования Range . В этом примере мы читаем весь объект Range в массив, каждый квадрат в массиве, а затем возвращаем массив обратно в Range . Это позволяет получить доступ к Range только дважды, тогда как цикл будет обращаться к нему 20 раз для чтения / записи.

Option Explicit
Sub WorkWithArrayExample()
    
Dim DataRange As Variant
Dim Irow As Long
Dim Icol As Integer
DataRange = ActiveSheet.Range("A1:A10").Value ' read all the values at once from the Excel grid, put into an array

For Irow = LBound(DataRange,1) To UBound(DataRange, 1) ' Get the number of rows.
  For Icol = LBound(DataRange,2) To UBound(DataRange, 2) ' Get the number of columns.
    DataRange(Irow, Icol) = DataRange(Irow, Icol) * DataRange(Irow, Icol) ' cell.value^2
  Next Icol
Next Irow
ActiveSheet.Range("A1:A10").Value = DataRange ' writes all the results back to the range at once
    
End Sub

Дополнительные советы и информация с приуроченными примерами можно найти в статье Чарльза Уильямса «Эффективные VBA UDF» (часть 1) и других статьях в этой серии .

Используйте константы VB, если они доступны

If MsgBox("Click OK") = vbOK Then

могут быть использованы вместо

If MsgBox("Click OK") = 1 Then

чтобы улучшить удобочитаемость.


Используйте Object Browser, чтобы найти доступные константы VB. Просмотр → Обозреватель объектов или F2 из редактора VB.

введите описание изображения здесь

Введите класс для поиска

введите описание изображения здесь

Просмотреть участников

введите описание изображения здесь

Использовать описательные имена переменных

Описательные имена и структура в коде помогут сделать комментарии ненужными

Dim ductWidth  As Double
Dim ductHeight As Double
Dim ductArea   As Double

ductArea = ductWidth * ductHeight

лучше, чем

Dim a, w, h

a = w * h

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

Dim myWB As Workbook
Dim srcWS As Worksheet
Dim destWS As Worksheet
Dim srcData As Range
Dim destData As Range

Set myWB = ActiveWorkbook
Set srcWS = myWB.Sheets("Sheet1")
Set destWS = myWB.Sheets("Sheet2")
Set srcData = srcWS.Range("A1:A10")
Set destData = destWS.Range("B11:B20")
destData = srcData

Если вы объявляете несколько переменных в одной строке, обязательно указывайте тип для каждой переменной:

Dim ductWidth As Double, ductHeight As Double, ductArea As Double

Следующие будут объявлять только последнюю переменную, а первая останется Variant :

Dim ductWidth, ductHeight, ductArea As Double

Обработка ошибок

Хорошая обработка ошибок не позволяет конечным пользователям видеть ошибки времени выполнения VBA и помогает разработчику легко диагностировать и исправлять ошибки.

Существует три основных метода обработки ошибок в VBA, два из которых следует избегать для распределенных программ, если это специально не требуется в коде.

On Error GoTo 0 'Avoid using

или же

On Error Resume Next 'Avoid using

Предпочитают использовать:

On Error GoTo <line> 'Prefer using

По ошибке GoTo 0

Если в вашем коде не установлена ​​ошибка, On Error GoTo 0 является обработчиком ошибок по умолчанию. В этом режиме любые ошибки времени выполнения запускают типичное сообщение об ошибке VBA, позволяющее либо закончить код, либо ввести режим debug , идентифицируя источник. При написании кода этот метод является самым простым и полезным, но его всегда следует избегать для кода, который распространяется среди конечных пользователей, поскольку этот метод очень непригляден и затруднен для понимания конечными пользователями.


Вкл.

On Error Resume Next VBA будет игнорировать любые ошибки, возникающие во время выполнения для всех строк, следующих за вызовом ошибки, до тех пор, пока обработчик ошибок не будет изменен. В очень конкретных случаях эта строка может быть полезна, но ее следует избегать за пределами этих случаев. Например, при запуске отдельной программы из макроса Excel вызов On Error Resume Next может быть полезен, если вы не уверены, открыта ли программа или нет:

'In this example, we open an instance of Powerpoint using the On Error Resume Next call
Dim PPApp As PowerPoint.Application
Dim PPPres As PowerPoint.Presentation
Dim PPSlide As PowerPoint.Slide

'Open PPT if not running, otherwise select active instance
On Error Resume Next
Set PPApp = GetObject(, "PowerPoint.Application")
On Error GoTo ErrHandler
If PPApp Is Nothing Then
    'Open PowerPoint
    Set PPApp = CreateObject("PowerPoint.Application")
    PPApp.Visible = True
End If

Если бы мы не использовали GetObject вызов On Error Resume Next и приложение Powerpoint еще не было открыто, метод GetObject бы ошибку. Таким образом, для устранения двух экземпляров приложения необходимо было On Error Resume Next .

Примечание. Также рекомендуется сразу же сбросить обработчик ошибок, как только вам больше не понадобится On Error Resume Next вызова»


Вкл. Ошибка GoTo <строка>

Этот метод обработки ошибок рекомендуется для всего кода, который распространяется среди других пользователей. Это позволяет программисту точно контролировать, как VBA обрабатывает ошибку, отправив код в указанную строку. Тег можно заполнить любой строкой (включая числовые строки) и отправить код в соответствующую строку, за которой следует двоеточие. Несколько блоков обработки ошибок можно использовать, выполняя различные вызовы On Error GoTo <line> . Нижеприведенная подпрограмма демонстрирует синтаксис вызова On Error GoTo <line> .

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

Sub YourMethodName()
    On Error GoTo errorHandler
    ' Insert code here
    On Error GoTo secondErrorHandler

    Exit Sub 'The exit sub line is essential, as the code will otherwise
             'continue running into the error handling block, likely causing an error

errorHandler:
    MsgBox "Error " & Err.Number & ": " & Err.Description & " in " & _
        VBE.ActiveCodePane.CodeModule, vbOKOnly, "Error"
    Exit Sub

secondErrorHandler:
    If Err.Number = 424 Then 'Object not found error (purely for illustration)
        Application.ScreenUpdating = True
        Application.EnableEvents = True
        Exit Sub
    Else
        MsgBox "Error " & Err.Number & ": " & Err.Desctription
        Application.ScreenUpdating = True
        Application.EnableEvents = True   
        Exit Sub
    End If      
    Exit Sub

End Sub

Если вы выйдете из своего метода с кодом обработки ошибок, убедитесь, что вы очистили:

  • Отменить все, что частично завершено
  • Закрыть файлы
  • Сбросить обновление экрана
  • Сбросить режим расчета
  • Сбросить события
  • Сбросить указатель мыши
  • Вызов метода выгрузки для экземпляров объектов, которые сохраняются после End Sub
  • Сброс строки состояния

Документируйте свою работу

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

Function Bonus(EmployeeTitle as String) as Double
    If EmployeeTitle = "Sales" Then
        Bonus = 0    'Sales representatives receive commission instead of a bonus
    Else
        Bonus = .10
    End If
End Function

Если ваш код настолько неясен, что он требует комментариев, чтобы объяснить, что он делает, подумайте о том, чтобы переписать его, чтобы быть более понятным, а не объяснять его с помощью комментариев. Например, вместо:

Sub CopySalesNumbers
    Dim IncludeWeekends as Boolean
    
    'Boolean values can be evaluated as an integer, -1 for True, 0 for False.
    'This is used here to adjust the range from 5 to 7 rows if including weekends.
    Range("A1:A" & 5 - (IncludeWeekends * 2)).Copy
    Range("B1").PasteSpecial
End Sub

Уточнить код, который будет проще следовать, например:

Sub CopySalesNumbers
    Dim IncludeWeekends as Boolean
    Dim DaysinWeek as Integer
    
    If IncludeWeekends Then
        DaysinWeek = 7
    Else
        DaysinWeek = 5
    End If
    Range("A1:A" & DaysinWeek).Copy
    Range("B1").PasteSpecial
End Sub 

Отключение свойств во время выполнения макроса

Лучше всего на любом языке программирования избегать преждевременной оптимизации. Однако, если тестирование показывает, что ваш код работает слишком медленно, вы можете получить некоторую скорость, отключив некоторые свойства приложения во время его запуска. Добавьте этот код в стандартный модуль:

Public Sub SpeedUp( _
    SpeedUpOn As Boolean, _
    Optional xlCalc as XlCalculation = xlCalculationAutomatic _
)
    With Application
        If SpeedUpOn Then
            .ScreenUpdating = False
            .Calculation = xlCalculationManual
            .EnableEvents = False
            .DisplayStatusBar = False 'in case you are not showing any messages
            ActiveSheet.DisplayPageBreaks = False 'note this is a sheet-level setting
        Else
            .ScreenUpdating = True
            .Calculation = xlCalc
            .EnableEvents = True
            .DisplayStatusBar = True
            ActiveSheet.DisplayPageBreaks = True
        End If
    End With
End Sub

Дополнительная информация о Office Blog - Excel VBA Performance Code Best Practices

И просто назовите его в начале и в конце макросов:

Public Sub SomeMacro
    'store the initial "calculation" state
    Dim xlCalc As XlCalculation
    xlCalc = Application.Calculation

    SpeedUp True

    'code here ...

    'by giving the second argument the initial "calculation" state is restored
    'otherwise it is set to 'xlCalculationAutomatic'
    SpeedUp False, xlCalc
End Sub

Хотя они могут в значительной степени рассматриваться как «усовершенствования» для обычных Public Sub процедур Public Sub , отключение обработки событий с помощью Application.EnableEvents = False должно считаться обязательным для макросов частного события Worksheet_Change и Workbook_SheetChange которые изменяют значения на одном или нескольких листах. Невозможность отключить триггеры событий заставит макрос события рекурсивно запускаться поверх себя, когда значение изменится и может привести к «замороженной» книге. Не забудьте снова включить события, прежде чем покинуть макрос события, возможно, с помощью обработчика ошибок «безопасного выхода».

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("A:A")) Is Nothing Then
        On Error GoTo bm_Safe_Exit
        Application.EnableEvents = False
        
        'code that may change a value on the worksheet goes here
        
    End If
bm_Safe_Exit:
    Application.EnableEvents = True
End Sub

Одно предостережение. Хотя отключение этих настроек улучшит время выполнения, они могут затруднить отладку приложения. Если код не работает надлежащим образом , закомментируйте SpeedUp True вызов , пока вы не выяснить проблему.

Это особенно важно, если вы пишете ячейки на листе, а затем читаете в вычисленных результатах из функций листа, поскольку xlCalculationManual позволяет xlCalculationManual книгу. Чтобы обойти это без отключения SpeedUp , вы можете включить Application.Calculate для выполнения расчета в определенных точках.

ПРИМЕЧАНИЕ. Поскольку это свойства самого Application , вам нужно убедиться, что они снова включены до того, как вы закончите макрос. Это делает особенно важным использование обработчиков ошибок и избежание множественных точек выхода (например, End или Unload Me ).

С обработкой ошибок:

Public Sub SomeMacro()
    'store the initial "calculation" state
    Dim xlCalc As XlCalculation
    xlCalc = Application.Calculation

    On Error GoTo Handler
    SpeedUp True
    
    'code here ...
    i = 1 / 0
CleanExit:
    SpeedUp False, xlCalc
    Exit Sub
Handler:
    'handle error
    Resume CleanExit
End Sub

Избегайте использования ActiveCell или ActiveSheet в Excel

Использование ActiveCell или ActiveSheet может быть источником ошибок , если (по любой причине) код выполняется в неправильном месте.

ActiveCell.Value = "Hello" 
'will place "Hello" in the cell that is currently selected
Cells(1, 1).Value = "Hello" 
'will always place "Hello" in A1 of the currently selected sheet

ActiveSheet.Cells(1, 1).Value = "Hello" 
'will place "Hello" in A1 of the currently selected sheet
Sheets("MySheetName").Cells(1, 1).Value = "Hello" 
'will always place "Hello" in A1 of the sheet named "MySheetName"
  • Использование Active* может создавать проблемы в длинных макросах, если ваш пользователь скучает и нажимает на другой рабочий лист или открывает другую книгу.
  • Это может создать проблемы, если ваш код открывается или создает другую книгу.
  • Это может создать проблемы, если ваш код использует Sheets("MyOtherSheet").Select и вы забыли, какой лист вы были, прежде чем начинать читать или писать на него.

Никогда не допускайте рабочий лист

Даже когда вся ваша работа направлена ​​на один рабочий лист, все же очень хорошая практика явно указывать рабочий лист в вашем коде. Эта привычка значительно облегчает расширение вашего кода позже или поднять части (или все) Sub или Function которые будут повторно использоваться где-то еще. Многие разработчики устанавливают привычку (re) использовать одно и то же имя локальной переменной для рабочего листа в своем коде, что делает повторное использование этого кода еще более простым.

Например, следующий код неоднозначен, но работает! - пока разработчик не активирует или не переключается на другой рабочий лист:

Option Explicit
Sub ShowTheTime()
    '--- displays the current time and date in cell A1 on the worksheet
    Cells(1, 1).Value = Now()  ' don't refer to Cells without a sheet reference!
End Sub

Если Sheet1 активен, ячейка A1 на Листе 1 будет заполнена текущей датой и временем. Но если пользователь по какой-либо причине меняет листы, тогда код обновит все текущие рабочие листы. Рабочий лист адресата неоднозначен.

Лучшая практика - всегда определять, какой лист, на который ссылается ваш код:

Option Explicit
Sub ShowTheTime()
    '--- displays the current time and date in cell A1 on the worksheet
    Dim myWB As Workbook
    Set myWB = ThisWorkbook
    Dim timestampSH As Worksheet
    Set timestampSH = myWB.Sheets("Sheet1")
    timestampSH.Cells(1, 1).Value = Now()
End Sub

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

Избегайте использования SELECT или ACTIVATE

Очень редко вы когда-либо захотите использовать Select или Activate в своем коде, но некоторые методы Excel требуют, чтобы рабочий лист или рабочая книга были активированы до того, как они будут работать должным образом.

Если вы только начинаете изучать VBA, вам часто предлагается записать ваши действия с помощью макросъемщика, а затем взглянуть на код. Например, я записал действия, предпринятые для ввода значения в ячейке D3 на Sheet2, и макрокоманда выглядит следующим образом:

Option Explicit
Sub Macro1()
'
' Macro1 Macro
'

'
    Sheets("Sheet2").Select
    Range("D3").Select
    ActiveCell.FormulaR1C1 = "3.1415"   '(see **note below)
    Range("D4").Select
End Sub

Помните, однако, макрорекордер создает строку кода для КАЖДОГО из ваших (пользовательских) действий. Это включает в себя щелчок на вкладке рабочего листа, чтобы выбрать Sheet2 ( Sheets("Sheet2").Select ), щелкнув по ячейке D3 перед вводом значения ( Range("D3").Select ) и с помощью клавиши Enter (которая эффективно « выбрав «ячейку ниже текущей выбранной ячейки: Range("D4").Select ).

Существует несколько проблем с использованием. .Select здесь:

  • Рабочий лист не всегда указывается. Это происходит, если вы не меняете рабочие листы во время записи и означает, что код даст разные результаты для разных активных рабочих листов.
  • .Select() работает медленно. Даже если для параметра Application.ScreenUpdating установлено значение False , это необработанная операция, которая должна быть обработана.
  • .Select() неуправляем. Если Application.ScreenUpdating остается равным True , Excel будет фактически выбирать ячейки, рабочий лист, форму ... независимо от того, с чем вы работаете. Это стрессово для глаз и действительно неприятно смотреть.
  • .Select() вызовет прослушиватели. Это уже немного продвинуто, но если не работать, будут запускаться такие функции, как Worksheet_SelectionChange() .

Когда вы кодируете в VBA, все действия «набрав» (т. Select Команды Select ) больше не нужны. Ваш код может быть сведен к одному оператору, чтобы поместить значение в ячейку:

'--- GOOD
ActiveWorkbook.Sheets("Sheet2").Range("D3").Value = 3.1415

'--- BETTER
Dim myWB      As Workbook
Dim myWS      As Worksheet
Dim myCell    As Range

Set myWB = ThisWorkbook             '*** see NOTE2
Set myWS = myWB.Sheets("Sheet2")
Set myCell = myWS.Range("D3")

myCell.Value = 3.1415

(Пример BETTER выше показывает использование промежуточных переменных для разделения разных частей ссылки на ячейку. Пример GOOD всегда будет работать очень хорошо, но может быть очень громоздким в гораздо более длинных модулях кода и более сложным для отладки, если одна из ссылок неверна. )

** ПРИМЕЧАНИЕ. Макросъемщик делает много предположений о типе данных, которые вы вводите, в этом случае вводите строковое значение в качестве формулы для создания значения. Ваш код не должен делать этого и может просто назначить числовое значение непосредственно ячейке, как показано выше.

** Примечание 2: рекомендуемая практика , чтобы установить локальную переменную рабочую книгу ThisWorkbook вместо ActiveWorkbook (если явно не нужно). Причина заключается в том, что ваш макрос обычно должен / использовать ресурсы в любой книге, из которой возникает код VBA, и НЕ будет выглядеть за пределами этой книги - опять же, если вы явно не назовете свой код работать с другой книгой. Когда вы открываете несколько книг в Excel, ActiveWorkbook - это та, которая может отличаться от рабочей книги, просматриваемой в редакторе VBA . Итак, вы думаете, что работаете в одной книге, когда вы действительно ссылаетесь на другую. ThisWorkbook относится к книге, содержащей исполняемый код.

Всегда определяйте и устанавливайте ссылки на все книги и таблицы

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

Не полагайтесь на ActiveWorkbook или ActiveSheet поскольку они могут быть изменены пользователем.

В следующем примере кода показано , как скопировать диапазон от листа «Raw_Data» в книге «Data.xlsx» на листе «Refined_Data» в книге «Results.xlsx».

Эта процедура также демонстрирует, как копировать и вставлять, не используя метод Select .

Option Explicit

Sub CopyRanges_BetweenShts()

    
    Dim wbSrc                           As Workbook
    Dim wbDest                          As Workbook
    Dim shtCopy                         As Worksheet
    Dim shtPaste                        As Worksheet
    
    ' set reference to all workbooks by name, don't rely on ActiveWorkbook
    Set wbSrc = Workbooks("Data.xlsx")
    Set wbDest = Workbooks("Results.xlsx")
    
    ' set reference to all sheets by name, don't rely on ActiveSheet
    Set shtCopy = wbSrc.Sheet1 '// "Raw_Data" sheet
    Set shtPaste = wbDest.Sheet2 '// "Refined_Data") sheet
    
    ' copy range from "Data" workbook to "Results" workbook without using Select
    shtCopy.Range("A1:C10").Copy _
    Destination:=shtPaste.Range("A1")

End Sub

Объект WorksheetFunction выполняется быстрее, чем эквивалент UDF

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

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

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

Sub UseRange()
    Dim rng as Range
    Dim Total As Double
    Dim CountLessThan01 As Long
    
    Total = 0
    CountLessThan01 = 0
    For Each rng in Sheets(1).Range("A1:A100")
        Total = Total + rng.Value2
        If rng.Value < 0.1 Then
            CountLessThan01 = CountLessThan01 + 1
        End If
    Next rng
    Debug.Print Total & ", " & CountLessThan01
End Sub

Одним из улучшений может быть сохранение значений диапазона в массиве и процесс, который:

Sub UseArray()
    Dim DataToSummarize As Variant
    Dim i As Long
    Dim Total As Double
    Dim CountLessThan01 As Long
    
    DataToSummarize = Sheets(1).Range("A1:A100").Value2 'faster than .Value
    Total = 0
    CountLessThan01 = 0
    For i = 1 To 100
        Total = Total + DataToSummarize(i, 1)
        If DataToSummarize(i, 1) < 0.1 Then
            CountLessThan01 = CountLessThan01 + 1
        End If
    Next i
    Debug.Print Total & ", " & CountLessThan01
End Sub

Но вместо написания любого цикла вы можете использовать Application.Worksheetfunction что очень удобно для выполнения простых формул:

Sub UseWorksheetFunction()
    Dim Total As Double
    Dim CountLessThan01 As Long
    
    With Application.WorksheetFunction
        Total = .Sum(Sheets(1).Range("A1:A100"))
        CountLessThan01 = .CountIf(Sheets(1).Range("A1:A100"), "<0.1")
    End With
    
    Debug.Print Total & ", " & CountLessThan01
End Sub

Или, для более сложных вычислений вы можете даже использовать Application.Evaluate :

Sub UseEvaluate()
    Dim Total As Double
    Dim CountLessThan01 As Long
    
    With Application
        Total = .Evaluate("SUM(" & Sheet1.Range("A1:A100").Address( _
            external:=True) & ")")
        CountLessThan01 = .Evaluate("COUNTIF('Sheet1'!A1:A100,""<0.1"")")
    End With
    
    Debug.Print Total & ", " & CountLessThan01
End Sub

И, наконец, работая над Subs 25 000 раз каждый, вот среднее (5 тестов) время в миллисекундах (конечно, это будет отличаться на каждом ПК, но по сравнению друг с другом они будут вести себя аналогичным образом):

  1. UseWorksheetFunction: 2156 мс
  2. UseArray: 2219 мс (+ 3%)
  3. UseEvaluate: 4693 мс (+ 118%)
  4. UseRange: 6530 мс (+ 203%)

Избегайте повторного назначения имен свойств или методов в качестве переменных

Обычно не считается «лучшей практикой» повторно назначать зарезервированные имена свойств или методов как имя (имена) ваших собственных процедур и переменных.

Плохая форма. В то время как следующий (строго говоря) законный, рабочий код повторное назначение метода Find, а также свойства Row , Column и Address могут вызвать проблемы / конфликты с неоднозначностью имени и просто путают в целом.

Option Explicit

Sub find()
    Dim row As Long, column As Long
    Dim find As String, address As Range
    
    find = "something"
    
    With ThisWorkbook.Worksheets("Sheet1").Cells
        Set address = .SpecialCells(xlCellTypeLastCell)
        row = .find(what:=find, after:=address).row        '< note .row not capitalized
        column = .find(what:=find, after:=address).column  '< note .column not capitalized
        
        Debug.Print "The first 'something' is in " & .Cells(row, column).address(0, 0)
    End With
End Sub

Хорошая форма. Все зарезервированные слова, переименованные в близкие, но уникальные аппроксимации оригиналов, избегали любых возможных конфликтов имен.

Option Explicit

Sub myFind()
    Dim rw As Long, col As Long
    Dim wht As String, lastCell As Range
    
    wht = "something"
    
    With ThisWorkbook.Worksheets("Sheet1").Cells
        Set lastCell = .SpecialCells(xlCellTypeLastCell)
        rw = .Find(What:=wht, After:=lastCell).Row         '◄ note .Find and .Row
        col = .Find(What:=wht, After:=lastCell).Column     '◄ .Find and .Column
        
        Debug.Print "The first 'something' is in " & .Cells(rw, col).Address(0, 0)
    End With
End Sub

Хотя может наступить время, когда вы хотите намеренно переписать стандартный метод или свойство в соответствии со своими собственными спецификациями, эти ситуации немногочисленны и далеки друг от друга. По большей части избегайте повторного использования зарезервированных имен для ваших собственных конструкций.




Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow