サーチ…


適格参照

worksheetrangeまたは個々の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

ActiveWorkbookThisWorkbook 、各オブジェクトが関連するものを完全に理解することなく、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コントロールを更新する手順を作成する必要があります。

ご了承ください :

  1. すべてのExcelアプリケーションレベルのウィンドウメソッド、イベント、およびプロパティは影響を受けません。 ( Application.ActiveWindowApplication.Windows ...)
  2. Excel 2013以降(SDI)では、すべてのブックレベルのウィンドウメソッド、イベント、およびプロパティがトップレベルウィンドウで操作されるようになりました。 Application.HwndApplication.Hwndこの最上位ウィンドウのハンドルを取得することは可能です

詳細については、この例のソースMSDNを参照してください。

これは、モードレスユーザーフォームにもいくつかの問題を引き起こします。解決方法はこちらをご覧ください。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow