サーチ…
適格参照
worksheet
、 range
または個々のcells
を参照する場合、参照を完全に修飾することが重要です。
例えば:
ThisWorkbook.Worksheets("Sheet1").Range(Cells(1, 2), Cells(2, 3)).Copy
完全ではありません: Cells
参照には、ワークブックとワークシートが関連付けられていません。明示的な参照がない場合、CellsはデフォルトでActiveSheet
を参照します。 Sheet1
以外のワークシートが現在のActiveSheet
場合、このコードは失敗します(間違った結果を生成します)。
これを修正する最も簡単な方法は、 With
ステートメントを次のように使用するWith
です。
With ThisWorkbook.Worksheets("Sheet1")
.Range(.Cells(1, 2), .Cells(2, 3)).Copy
End With
あるいは、ワークシート変数を使用することもできます。 (これは、あるシートから別のシートにデータをコピーする場合など、コードが複数のワークシートを参照する必要がある場合には、最も好ましい方法です)。
Dim ws1 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
ws1.Range(ws1.Cells(1, 2), ws1.Cells(2, 3)).Copy
別の頻繁な問題は、ワークブックを限定することなくワークシートコレクションを参照することです。例えば:
Worksheets("Sheet1").Copy
ワークシートSheet1
は完全修飾されていないし、ブックがありません。コード内で複数のワークブックが参照されている場合、これは失敗する可能性があります。代わりに、次のいずれかを使用します。
ThisWorkbook.Worksheets("Sheet1") '<--ThisWorkbook refers to the workbook containing
'the running VBA code
Workbooks("Book1").Worksheets("Sheet1") '<--Where Book1 is the workbook containing Sheet1
ただし、次の使用は避けてください。
ActiveWorkbook.Worksheets("Sheet1") '<--Valid, but if another workbook is activated
'the reference will be changed
同様にrange
オブジェクトの場合、明示的に修飾されていない場合、 range
は現在アクティブなシートを参照します:
Range("a1")
同じです:
ActiveSheet.Range("a1")
ループ内の行または列の削除
ループ内の行(または列)を削除する場合は、常に範囲の終わりからループし、すべてのステップに戻る必要があります。コードを使用する場合:
Dim i As Long
With Workbooks("Book1").Worksheets("Sheet1")
For i = 1 To 4
If IsEmpty(.Cells(i, 1)) Then .Rows(i).Delete
Next i
End With
あなたはいくつかの行を欠場するでしょう。たとえば、コードが行3を削除すると、行4は行3になります。ただし、変数i
は4に変更されます。この場合、コードは1行を欠き、以前に範囲外だった別の行をチェックします。
正しいコードは
Dim i As Long
With Workbooks("Book1").Worksheets("Sheet1")
For i = 4 To 1 Step -1
If IsEmpty(.Cells(i, 1)) Then .Rows(i).Delete
Next i
End With
ActiveWorkbook対ThisWorkbook
ActiveWorkbook
とThisWorkbook
、各オブジェクトが関連するものを完全に理解することなく、VBAの新しいユーザーによって交換可能に使用されることがあります。これは、実行時に望ましくない動作を引き起こす可能性があります。これらのオブジェクトはどちらもApplicationオブジェクトに属します
ActiveWorkbook
オブジェクトは、実行時に現在Excelアプリケーションオブジェクトの一番上のビューにあるブックを参照します。 (たとえば、このオブジェクトが参照された時点で表示され、対話できるブック)
Sub ActiveWorkbookExample()
'// Let's assume that 'Other Workbook.xlsx' has "Bar" written in A1.
ActiveWorkbook.ActiveSheet.Range("A1").Value = "Foo"
Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints "Foo"
Workbooks.Open("C:\Users\BloggsJ\Other Workbook.xlsx")
Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints "Bar"
Workbooks.Add 1
Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints nothing
End Sub
ThisWorkbook
オブジェクトは、コードが実行されているときにコードが属するワークブックを参照します。
Sub ThisWorkbookExample()
'// Let's assume to begin that this code is in the same workbook that is currently active
ActiveWorkbook.Sheet1.Range("A1").Value = "Foo"
Workbooks.Add 1
ActiveWorkbook.ActiveSheet.Range("A1").Value = "Bar"
Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints "Bar"
Debug.Print ThisWorkbook.Sheet1.Range("A1").Value '// Prints "Foo"
End Sub
単一ドキュメントインタフェース対複数ドキュメントインタフェース
Microsoft Excel 2013(以上)はシングルドキュメントインターフェイス(SDI)を使用し、Excel 2010(以下)は複数ドキュメントインターフェイス(MDI)を使用することに注意してください。
これは、Excel 2013(SDI)では、1つのExcelインスタンス内の各ブックに独自のリボンUIが含まれていることを示しています。
逆に、Excel 2010の場合、Excelの単一インスタンス内の各ワークブックは共通のリボンUI(MDI)を使用していました。
リボンとやり取りするVBAコード(2010 < - > 2013)を移行する場合は、いくつかの重要な問題が発生します。
Excel 2013以降のすべてのブックで、同じ状態のリボンUIコントロールを更新する手順を作成する必要があります。
ご了承ください :
- すべてのExcelアプリケーションレベルのウィンドウメソッド、イベント、およびプロパティは影響を受けません。 (
Application.ActiveWindow
、Application.Windows
...) - Excel 2013以降(SDI)では、すべてのブックレベルのウィンドウメソッド、イベント、およびプロパティがトップレベルウィンドウで操作されるようになりました。
Application.Hwnd
をApplication.Hwnd
この最上位ウィンドウのハンドルを取得することは可能です
詳細については、この例のソースMSDNを参照してください。
これは、モードレスユーザーフォームにもいくつかの問題を引き起こします。解決方法はこちらをご覧ください。