サーチ…


備考

私たちは皆それを知っていますが、これらの慣行はVBAでプログラムを始める人にとってははるかに明らかではありません。


常に "Option Explicit"を使用してください。

VBAエディタウィンドウで、[ツール]メニューから[オプション]を選択します。

ここに画像の説明を入力

次に、[エディタ]タブで、[変数宣言が必要]チェックボックスがオンになっていることを確認します。

ここに画像の説明を入力

このオプションを選択すると、 Option ExplicitがすべてのVBAモジュールの先頭に自動的に配置されます。

小さなメモ:これはこれまでに開かれていないモジュール、クラスモジュールなどに当てはまります。たとえば、オプション "Require Variable Declaration"を有効にする前に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のエラーを正確に示すエラーメッセージが表示されmyvariable

ここに画像の説明を入力


Option Explicit and Arrays動的配列の宣言に関する注意

ReDimステートメントを使用して、プロシージャー内で暗黙的に配列を宣言することができます。

  • ReDimステートメントを使用するとき、配列の名前のスペルを間違えないように注意してください

  • Option Explicitステートメントがモジュールに含まれていても、新しい配列が作成されます

    Dim arr() as Long

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

範囲ではなく配列で作業する

Officeブログ - Excel VBAパフォーマンスコーディングのベストプラクティス

可能な限りRangeの使用を避けることによって、最高のパフォーマンスが得られることがよくあります。この例では、 Rangeオブジェクト全体を配列に読み込み、配列内の各番号を四角にしてから、配列をRange戻します。 Rangeは、 Range 2回しかアクセスしませんが、ループは、読み取り/書き込みのために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

読みやすさを向上させるためです。


オブジェクトブラウザを使用して、利用可能なVB定数を検索します。 ビュー→オブジェクトブラウザまたはVBエディタからのF2

ここに画像の説明を入力

検索するクラスを入力

ここに画像の説明を入力

利用可能なメンバーを表示

ここに画像の説明を入力

記述的な変数命名を使用する

コード内の記述的な名前と構造は、コメントを不要にするのに役立ちます

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

1つの行に複数の変数を宣言する場合は、以下のように変数の型を指定してください。

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

以下は最後の変数のみを宣言し、最初の変数はVariantままです。

Dim ductWidth, ductHeight, ductArea As Double

エラー処理

良好なエラー処理により、エンドユーザーはVBAランタイムエラーを見ることができなくなり、開発者はエラーを簡単に診断して修正することができます。

VBAでは3つの主なエラー処理方法がありますが、コードで特に必要とされている場合を除き、2つは分散プログラムでは避けるべきです。

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

On Error Resume Next呼び出しを使用せず、Powerpointアプリケーションがまだ開いていない場合、 GetObjectメソッドはエラーをスローします。したがって、 On Error Resume Nextは、アプリケーションの2つのインスタンスを作成しないようにするために必要でした。

注:また、エラーハンドラをすぐにリセットするには、 On Error Resume Nextコールが不要になったらすぐにリセットすることをお勧めします


エラー時にGoTo <line>

このエラー処理方法は、他のユーザーに配布されているすべてのコードに対してお勧めします。これにより、プログラマは、指定された行にコードを送信することにより、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ブログの詳細- Excel VBAパフォーマンスコーディングのベストプラクティス

そして、それをマクロの始めと終わりに呼び出します:

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プロシージャの「拡張」と見なすことができますが、 Application.EnableEvents = Falseイベント処理を無効にすることは、 Worksheet_Change値を変更する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までSpeedUp True呼び出しをコメントアウトしてください。

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

ExcelでActiveCellまたはActiveSheetを使用しないようにする

何らかの理由でコードが間違った場所で実行された場合、 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使用している場合、問題が発生する可能性がありますSheets("MyOtherSheet").Select 、読み書きを開始する前にどのシートにいるかを忘れてしまいました。

ワークシートを決して使わない

すべての作業が単一のワークシートに指示されている場合でも、コード内にワークシートを明示的に指定することは、非常に良い方法です。この習慣により、後でコードを拡張したり、 SubFunction一部(またはすべて)を他の場所で再利用するほうがずっと簡単になります。多くの開発者は、コード内のワークシートに同じローカル変数名を使用するという習慣を確立し、そのコードの再利用をさらに簡単にします。

例として、次のコードはあいまいですが、動作します! - 開発者が別のワークシートをアクティブ化または変更しない限り、

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がアクティブな場合は、 Sheet1 A1セルに現在の日付と時刻が入力されます。しかし、ユーザーが何らかの理由でワークシートを変更した場合、コードはワークシートが現在アクティブであるものを更新します。宛先ワークシートはあいまいです。

ベストプラクティスは、コードが参照するワークシートを常に識別することです。

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の習得を始めたばかりの方は、マクロレコーダーを使ってアクションを記録し、コードを見てみることをおすすめします。たとえば、Sheet2のセルD3に値を入力するために実行されたアクションを記録し、マクロコードは次のようになります。

Option Explicit
Sub Macro1()
'
' Macro1 Macro
'

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

しかし、マクロレコーダーはあなたの(ユーザー)アクションごとに1行のコードを作成することを覚えておいてください。これは、ワークシート・タブをクリックしてシート2( Sheets("Sheet2").Select )をSheets("Sheet2").Select 、値D3を入力する前にセルD3をクリックしてRange("D3").Selectし、現在選択されているセルの下のセルを選択する: Range("D4").Select )。

.Select使用には複数の問題があります:

  • ワークシートは常に指定されているわけではありません。これは、記録中にワークシートを切り替える必要がない場合に発生し、さまざまなアクティブなワークシートに対して異なる結果をもたらすことを意味します。
  • .Select()は遅いです。 Application.ScreenUpdatingFalseに設定されていても、これは処理される不必要な操作です。
  • .Select().Select()です。 Application.ScreenUpdatingTrueままになっていると、Excelは実際にはセル、ワークシート、フォームなどを選択します。これは目にストレスがあり、見るのが本当に不愉快です。
  • .Select()はリスナーをトリガーします。これはもう少し進んでいますが、回避しなければ、 Worksheet_SelectionChange()ような関数がトリガされます。

VBAでコーディングしているときは、「タイプする」アクション(つまりSelectステートメント)はすべて必要なくなりました。コードを1つのステートメントに減らして、値をセルに入れることができます。

'--- 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

(上のより良い例では中間変数を使ってセル参照の異なる部分を区切っていますが、GOODの例は常にうまく動作しますが、ずっと長いコードモジュールでは扱いにくく、参照の1つが誤っているとデバッグが難しくなります。 )

**注:マクロレコーダーは、入力するデータの種類について多くの仮定を行います。この場合、値を作成する式として文字列値を入力します。あなたのコードはこれを行う必要はなく、上記のように単にセルに直接数値を割り当てることができます。

** NOTE2:推奨される方法は、 ActiveWorkbook代わりにローカルワークブック変数をThisWorkbookに設定することです(明示的に必要な場合を除きます)。なぜなら、マクロは、VBAコードがどのようなワークブックであっても、そのワークブックの外側には見えないようなリソースを必要とします。 Excelで複数のワークブックを開いている場合、 ActiveWorkbookは、 VBAエディタで表示されているワークブックとは異なるフォーカス持つワークブックです。つまり、実際に別のワークブックを参照しているときに1つのワークブックで実行していると思います。 ThisWorkbookは、実行されているコードを含むブックを参照します。

すべてのワークブックとシートへの参照を常に定義および設定する

複数の開いているワークブックで作業する場合は、それぞれに複数のシートがある場合は、すべてのワークブックとシートを参照して定義するのが最も安全です。

ActiveWorkbookまたはActiveSheetは、ユーザーによって変更される可能性があるため依存しないでください

次のコード例は、「Data.xlsx」ワークブックの「RAW_DATA」シートから「Results.xlsx」ワークブックの「Refined_Data」シートの範囲をコピーする方法を示します。

また、 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で解決できるものなら、ifを使うことができます。

それらの最初の試みは、範囲をループし、セルごとにセルを処理することです(範囲を使用して)。

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

1つの改善点は、範囲値を配列に格納し、次のように処理することです。

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使用することもでき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

そして、最終的に、各25,000回のSubsを超えて走っているここでは、平均(5回のテスト)時間がミリ秒単位で表示されます(もちろん、各PCで異なるでしょうが、お互いに比べて同様に動作します)。

  1. UseWorksheetFunction:2156ミリ秒
  2. UseArray:2219 ms(+ 3%)
  3. UseEvaluate:4693 ms(+ 118%)
  4. UseRange:6530 ms(+ 203%)

プロパティまたはメソッドの名前を変数として再定義しないでください

プロパティまたはメソッドの予約された名前を、独自のプロシージャおよび変数の名前として再利用することは、一般に「ベストプラクティス」とはみなされません。

悪いフォーム - 以下は(厳密に言えば)合法的なコードですが、 FindメソッドとRowColumnAddressプロパティの再利用は名前のあいまいさに問題を引き起こす可能性があり、一般的に混乱します。

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