ExcelVBAの基礎知識

イミディエイトウィンドウの使い方

イミディエイトウィンドウは、変数やプロパティの値や式の結果を出力することができます。

変数などの値の確認に使われることが多いです。
イミディエイトウィンドウに出力するには、Debug.Printメソッドを使います。
Debug.Print 出力したい内容


たとえば、変数でセルを指定している時、自分が取得したいと思っているセルと実際に取得しているセルが違ってマクロがうまく動かない……といったことがあります。
そんな時はセルのアドレスをイミディエイトウィンドウに出力して、ちゃんとセルが取得できているかを調べることができます。

サンプルコード



Public Sub ImmediateWindowsTest1()
  Dim LastRow As Long
  
  With ThisWorkbook.Worksheets(1)
    LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
    Debug.Print .Cells(LastRow, "A").Address
  End With
End Sub


また、コードを書かずにイミディエイトウィンドウに直接出力もできます。
イミディエイトウィンドウにカーソルを合わせ、「?出力したい内容」を書いて、Enterキーを押すと、次の行に結果が表示されます。

VBAでは文字列はダブルクォーテーション(")で囲むのですが、ダブルクォーテーション自体を出力したいときはダブルクォーテーションをダブルクォーテーションで囲む必要があります。
慣れないとダブルクォーテーションが足りずにダブルクォーテーションが出力できていなかったり、逆に多すぎて2個出力されていたりと、これが結構難しい。

そんな時も、イミディエイトウィンドウで出力できたのを確認してから、実際のコードペインにコピー&ペーストすると、うまくいきます。
ImmediateWindow01.jpg

出力したい内容には変数だけではなく、式も入れることができます。
変数のデータ型でエラーが出たときにTypeName関数で変数のデータ型を調べたり、2つのオブジェクト変数が等しいか確認するなんて事もできます。

マクロがうまく動かないときは、ステップインで1行ずつ実行しながらイミディエイトウィンドウで変数の値を確認して、OKだったらまた次の行を実行して……という風に繰り返していくことで、エラーが見つけやすくなります。

ExcelVBAの基礎知識

マクロの確認をする

コンパイルでVBAコードをチェックする


最初のうちは入門書やネットのコードを見よう見真似で書いても、細かいところが間違っていて「マクロが動かない!」ということがよくあります。

VBEのメニューから[デバッグ(D)]→[VBAProjectのコンパイル(L)]を実行すると、
書いたコードがVBAの文法に合っているかをチェックできます。

compile01.jpg

間違っている箇所が反転し、エラー内容がメッセージボックスに表示されます。
compile02.jpg


コンパイルエラーになる例


コンパイルエラーになる例はいろいろありますが、頻度が高いものをあげてみます。

  1. 存在しないメソッド・プロパティを指定する

  2. Public Sub CompileTest1()
      ThisWorkbook.Test
    End Sub


  3. 読み取り専用のプロパティに値を入れる

  4. Public Sub CompileTest2()
      ThisWorkbook.Path = "C:¥Test"
    End Sub


  5. 終了ステートメントがない

  6. ステートメントの中には、「IfステートメントならEnd Ifステートメント」、「WithステートメントならEnd Withステートメント」といったように、開始と終了のステートメントをセットで使うものがあります。

    終了ステートメントが抜けていたり、ステートメントを入れ子にしていて、終了ステートメントの順番が開始ステートメントの順番と違っていると、コンパイルエラーになります。

    下のサンプルでは、End WithとForステートメントのNextの位置が逆になっているので、コンパイルエラーになります。
    Public Sub CompileTest()
      Dim i As Long
      For i = 1 To 5
        With ThisWorkbook.Worksheets(1)
          If i = 1 Then
            '処理
          End If
        Next i
      End With
    End Sub



ExcelVBAの基礎知識

VBA用語集

プログラム全般に関する用語


コード
プログラム言語で書いた命令文のこと。
ソースともいう。

コーディング
プログラムのコードを書くこと。

バグ
プログラムの中にある不具合のこと。

デバッグ
プログラムがきちんと動くか、動作確認すること。
また、バグが発生した場合にコードを修正すること。

デバッガー
デバッグをする人。

VBAの命令に関わる用語


メソッド
VBAの命令のうち、オブジェクトやコレクションに対して特定の操作を行う命令。
操作のオプションとして、引数(ひきすう)を指定することもある。
Openメソッド、Copyメソッド、Closeメソッドなどなど。
マクロ記録でコードを記録できる。

プロパティ
セルの色、シートの名前、ブックのパスなどのオブジェクトの設定値。
プロパティには、値を取得するだけのプロパティと、
値を入れることのできるプロパティがある。

ステートメント
VBAの命令のうち、オブジェクトには関係しない命令。
条件分岐をするIfステートメント、Select...Caseステートメント、
繰り返し処理をするDo...Loopステートメントなど。
ステートメントは「ステートメント名」で始まって、「End ステートメント名」で終了することが多い。
(例)
If 条件式 Then
 '処理
End If


関数
引数をもとに、計算を行い結果を返すプログラム。
Date関数など、引数を指定しない関数もある。
Functionステートメントでオリジナルの関数を作ることもできる(ユーザー定義関数)

引数
メソッドや関数を実行する時に、指定する値。
メソッドでは、処理のオプションを引数で指定することが多い。
(Findメソッドなら検索オプションなど)

戻り値
関数を実行したあとに、返ってくる結果。
VBAでは、関数の戻り値を取得する場合は引数を()で囲む。
Msgbox "Test"・・・・・・メッセージを表示するだけで、戻り値は取得しない。
result = Msgbox("Test")・・・・・・戻り値を取得する。


ExcelVBAの基礎知識

実際にマクロを作りはじめる前に

マクロの対象ブックとマクロ本体はわける



たとえば、ブックからデータを集計するマクロだったら、
集計対象のブックとマクロを書くブックはわけた方が無難です。

データが入力されているブックというのは、間違えてデータいじってしまっても
復元できるように、バックアップを取ることがあります。

マクロをデータのあるブックに直接書いてしまうと、
データのバックアップをとったとき、当然マクロも一緒にバックアップされます。

マクロを修正して問題がないことを確認したあと、
手動操作でミスをしてファイルをバックアップから復元した場合、
マクロが意図せず修正前に戻ってしまいます。

特に、会社で複数人数で使っているファイルだと、いつ誰が復元するか予測がつきません。

いつのまにか修正したところが元に戻っている、というのは
様々なエラーの原因になります。

ですので、データのあるブックとマクロ本体はわけた方がいいのです。

そこで重要になるのが、ブックやシートの指定の仕方です。
他のブックやシートを指定する方法はマクロ記録では得られないうえに
使用頻度が高いので、しっかりと覚える必要があります。

また、ブックやシートをマクロで指定すればアクティブではないブックも操作できます。
いちいちSelectメソッドでアクティブにする必要がなくなるので、
マクロの大幅な高速化にも役にたちます。


マクロはなるべく標準モジュールに書く


マクロは、標準モジュールのほかにもWorkbookオブジェクトやWorksheetオブジェクト内にも書くことができます。
ただし、特別なことがない限り、標準モジュールに書くのがおすすめです。

標準モジュールは、当たり前ですがマクロがないブックには存在しません。
標準モジュールに書けば、プロジェクトエクスプローラでモジュールが何個あるかすぐわかります。
WorkbookオブジェクトやWorksheetオブジェクトはマクロがあろうがなかろうが存在するオブジェクトのため、これらに書いてしまうとマクロが見つけにくくなります。

また、Worksheetオブジェクトに書いてしまうと、シートをコピーしたときにマクロも一緒にコピーされます。
前述の「マクロの対象ブックとマクロ本体はわける」とも共通しますが、
意図せずにマクロのコピーが量産されると、どれが正しい最新版かがわからなくなり、
エラーの原因になります。

ExcelVBAの基礎知識

配列とは

変数には様々な値が格納できますが、1つの変数には1つの値しか入れる事ができません。
沢山の値を入れたい場合、1つ1つ変数を宣言していったら大変ですね。

そこで配列というものを使います。
配列は変数が集まったものです。
配列は変数と同じく、Dimステートメントで宣言します。

◆Dimステートメント
Dim 配列名(要素数) As データ型

要素数は値を入れる場所の番号(インデックス)です。
何も指定しなければ0から始まります。
要素数の指定方法は複数あります。

◆方法1:最大要素数を指定する場合
Dim Ary(1) As Long

配列Aryを最大要素数を1にして作成します。
最大要素数が1なので、Ary(0)とAry(1)の2つの場所が作成されます。

◆方法2:要素数の最小と最大を指定する場合
Dim Ary(1 To 5) As Long

配列Aryの要素数を1〜5で作成します。
Ary(1)〜Ary(5)までの5か所に値を入れる事ができます。
最小値と最大値は、正の数ならば自由に設定できます。
0や1以外からも始める事ができます。
Dim Ary (3 To 5) As Long

この場合、Ary(3)、Ary(4)、Ary(5)の3つの場所が作成されます。

◆方法3:要素数を指定しない場合
Dim Ary() As Long

この場合、要素数0の配列を作成します。

もちろん、このままでは使えないので使うにはマクロの中で
ReDimステートメントで配列の要素数を再定義する必要があります。

このような要素数0の配列は、マクロを実行してから要素数を決めたい場合に使用します。
(シート内のデータ件数をカウントして、データ件数分の要素数をもつ配列を定義したい場合など)

こうした配列のことを動的配列といいます。

配列に値を格納する、配列から値を取り出す



配列名(インデックス)で配列のデータを指定する事ができます。
上の例で言えば、
Ary(1) = 1


とすれば配列Aryのインデックス番号1番に1を格納します。

サンプルコード


A列に日付、B列に値が入ったリストから今月分の値を、
日付ごとに値を配列aryDateに集計します。

A列   B列
2010/3/1 5
2010/3/2 2
2010/3/3 6


配列aryDateの要素数は1〜最終日の日付です。
最終日の日付は「翌月1日のシリアル番号-1」になります。

コードを書く段階では要素数が確定していません。
(要素数が実行日の最終日の日付になるため)

ですので、一度空の配列を作成し、コード内でReDimステートメントで再定義しています。


Sub 日付ごとに集計()

Dim aryDate() As Long
Dim DayCount As Long
Dim lngRow As Long
Dim i As Long

DayCount = Day(DateSerial(Year(Date), Month(Date) + 1, 1) - 1)
ReDim aryDate(1 To DayCount)

lngRow = 1
With ThisWorkbook.Worksheets(1)
  Do Until .Cells(lngRow, "A").Value = ""
    If DateSerial(Year(Date), Month(Date), Day(.Cells(lngRow, "A").Value)) = .Cells(lngRow, "A").Value Then
      i = Day(.Cells(lngRow, "A").Value)
      aryDate(i) = aryDate(i) + .Cells(lngRow, "B").Value
    End If
    lngRow = lngRow + 1
  Loop
End With

End Sub

ExcelVBAの基礎知識

マクロ記録で記録できない命令

何かと便利なマクロ記録ですが、記録できないものもあります。
ステートメント(オブジェクトに影響しない命令)は記録できません。

また、一般機能同様、VBAでも関数が使用できます。
一般機能でセルに関数を書いた場合は記録できますが、
VBAにしかない関数は記録できません。

ExcelVBAの基礎知識

メソッド・プロパティの調べ方

最初のうちは「こういう動作をさせたいけど、どんなメソッド・プロパティを使ったらいいかわからない」という事が多々あると思います。

その時は、まずマクロ記録で動作を記録してみましょう。

Excelのメソッドやプロパティ名は英語なので、マクロ記録をすればたいてい、どのメソッドがどんな動作をするのかが見当つくと思います。

そうしたら、次はヘルプでそのメソッドを引数がどんなものがあるか、詳しく調べます。

はじめは面倒かもしれませんが、慣れるうちにだんだん覚えていき、
調べる量も減っていきますよ。

ExcelVBAの基礎知識

ブックやシートを指定しなかった時の動作

ブックやシートを指定しないでセルなどのオブジェクトを捜査しようとした場合、動作はそのマクロが書かれている場所によって異なります。

マクロが標準モジュールに書かれていた場合は、
アクティブのブック・シートのオブジェクトに対して実行されます。

下記のコードは、A1セルに「TEST」と入力するマクロです。

サンプルコード



Sub ブックやシートを指定しないときのテスト()

Cells(1, 1) = "TEST"

End Sub

このマクロが標準モジュールに書かれている場合、

Book1のSheet1がアクティブならSheet1のA1セル、
Sheet2がアクティブならSheet2のA1セルに記入されます。

Boo2がアクティブだったらBook2のアクティブシートの
A1セルに記入されます。


マクロは標準モジュール以外にも書くことができます。
それは、WorksheetやWorkbookオブジェクト内です。

上記サンプルがWorksheetオブジェクト内に書かれていた場合、
マクロが書かれたシートのA1セルに記入されます。

Workbookオブジェクト内に書かれていた場合、
そのブックのアクティブシートのA1セルに記入されます。


アクティブセルというのは、実行する人によって変わるものです。

意図しない処理の原因になりますので、ブックやシートは省略せず
記述することを強くおすすめします。

ExcelVBAの基礎知識

変数を使ってセルを操作する

変数を使ってセルを操作する場合は以下のようになります。

サンプルコード1



Sub 変数を使ってセル指定1()

Dim lngRow As Long

lngRow = 1
ThisWorkbook.Worksheets(1).Cells(lngRow, 1).Value = "test1" 'A1セルに記入

End Sub


行数や列数は数字で指定する必要があるので、変数をLong型で宣言しています。

Cellsプロパティを使う場合は、行番号・列番号のところに変数を指定します。

一方、Rangeオブジェクトを使う場合は列名を文字列として指定した後、
列名や「:」は文字列として書き、
そこに行番号を格納した変数を「&」でつなげます。


サンプルコード2



Sub 変数を使ってセル指定2()

Dim lngRow As Long

lngRow = 1

With ThisWorkbook.Worksheets(1)
.Range("B" & lngRow & ":B" & lngRow + 1).Value = "test3" 'B1〜B2セルに記入
.Range(.Cells(lngRow, "C"), .Cells(lngRow + 2, "C")).Value = "test4" 'C1〜C3セルに記入
End With

End Sub


慣れるまでは間違えて変数まで""で囲んでしまう場合が多いので、注意が必要です。


◆間違いやすい例(変数も""で囲んでしまっている)
.Range("A1:B & lngRow").Value = "Test"

変数を使いこなせるようになると、マクロ記録で記録したマクロよりも
柔軟性のあるマクロが作れるようになりますが、
その分自分でコードを書く場面も増えます。


初心者が作ったマクロはまず、正常に動きません。
そこで、ちゃんと実行できるか動作確認する必要があります。

この動作確認の事をデバッグといいます。


ExcelVBAの基礎知識

別のモジュールにあるプロシージャから同じ変数を使う

別のモジュールのプロシージャから変数を呼び出すには、
宣言セクションにてPublicステートメントで宣言します。

◆Publicステートメント
Public 変数名 As データ型

Publicステートメントで変数を宣言する時は、
宣言セクションでなければいけません。

マクロの中でPublicステートメント
変数を宣言しようとした場合、コンパイルエラーが発生します。

サンプルコード


※エラーが発生します。

Sub Publicステートメントで変数を宣言する()

Public test As String

End Sub


変数10


1 2 3 4 >>


Powered by Seesaa
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。