Contents
開発環境
準備
標準のマクロエディタはエディタに文を書くと自動で構文チェックする。具体的にはカーソルが現在の行から離れたタイミングである。この際に、コンパイルエラーがあるとダイアログが表示される。
例えばある行の一部を切り取ってほかの行に張り付ける際は切り取った際にエラーが出てしまう。開発中はこのようなことがよくあり、毎回ダイアログを消すのは面倒である。そのため、ダイアログは非表示にする。
なお、構文エラーがあると赤字で表示されるが、ダイアログを非表示にしても赤字表示はされるのでエラーがあるとすぐに気づける。
- マクロエディタ
- ツール > オプション
- 編集タブ
- 自動構文チェックをオフにする
強制終了
無限ループに陥ってしまった場合などに強制終了させることができる
Escキーを押しながら、タスクバーでエクセル、マクロエディタから別のウインドウに何度か切り替える。
文法
Hello World
MsgBox ("Hello World")
- 改行する場合
MsgBox ("Hello" & vbCrLf & "World")
プロンプト
inputResult = InputBox(Prompt:="Input This Form", Default:="default value")
コメント
' コメント
複数行のコメントはできない
型と値
- Boolean
- Byte ※0~255の値をとる
- Integer
- Long
- Single ※float相当
- Double
- Date
- String
- Object
- Variant ※何でも代入可能な型
NullはVariant 型にのみ代入可能
変数宣言
変数は宣言しなくても使用可能である。
宣言することも可能。その際型は省略可能であるが、型を指定することも可能。
- 宣言せずに使用
i = 100
- 型を指定せずに宣言して使用
Dim i i = 100
次は同じ
Dim i As Variant i = 100
- 型を指定して宣言して使用
Dim i As Integer i = 100
行分割
行末尾を「空白+_」にすることで、次の行につなげることができる。
a = _ b + c
演算
除算
ans = 5 / 2 ' ans = 2.5
整数除算
ans = 5 \ 2 ' ans = 2
整数剰余
ans = 5 mod 2 ' ans = 1
累乗
ans = 5 ^ 2 ' ans = 25
インクリメント
a = a + 1
比較演算
文字列
- 一致
If Str1 = Str2 Then
' same
Else
' different
End If - 不一致
If Str1 <> Str2 Then
' different
Else
' same
End If - パターン
任意の複数文字 * 任意の単一文字 ? 任意の単一数字 # 任意の文字セット一文字 [A-Z] or [A,C,E] 任意の文字セット以外一文字 [!A-Z] or [!A,C,E]
If "abcde" Like "abc*" Then
' same
Else
' different
End If
論理演算
- and
If Num1 > 1 And Num1 < 10 Then
' match
Else
' no match
End If - or
If Num1 > 1 or Num1 < 10 Then
' match
Else
' no match
End If - not
If Not Num1 > 1 Then
' match
Else
' no match
End If
条件
andやorはこちら
if
If i = 10 Then ... End If
if not
If Not i = 10 Then ... End If
or
If i <> 10 Then ... End If
if else
If i <= 10 Then ... ElseIf i >= 20 Then ... Else ... End If
ループ
for
For i = 1 To 10 ... Next i
ループ脱出
whileループでは脱出できない(do-whileなら可能)
For i = 1 To 10 If i = 3 Then Exit For End If Next i
continue
For i = 1 To 10 If i = 3 Then GoTo Continue End If Continue: Next i
for each
For Each nextCell In Range("A1", "A3") Debug.Print (cell.Value) Next
while
Do While i < 10 ... Loop
文字列
エスケープ
ダブルクォーテーションはエスケープが必要
ダブルクォーテーション2つでダブルクォーテーションとして扱われる。
次はダブルクォーテーション1つの文字列定数である。
""""
改行
改行コードは次のシステム定数で表される。
vbCrLf
タブ
タブコードは次のシステム定数で表される。
vbTab
連結
文字列、”&”の間には必ず空白が必要。
"ABC" & "DEF"
文字列長
Len(str)
部分文字列
Left(str, Len(str) - N)
エスケープ
ダブルクォーテーションのみエスケープが必要。
以下のように書くことで、ダブルクォーテーションと認識される。
""
例
"I say ""Hello"""
配列
宣言
Dim list(10)
代入
配列インデックスは0から
list(0) = 1
まとめて代入
list = Array(1, 2, 3)
配列長
UBound(list)
可変長配列
可変長配列ではあるものの、要素格納前には配列長を決定しなければならない。
配列長を与える際、ReDimでは既存の要素はデフォルトで破棄されるので、残す場合は別途Preserveオプションが必要。
Dim list() As Integer ReDim list(10) For i = 1 To 10 list(i) = i Next i For i = 11 To 20
ReDim Preserve list(UBound(list) + 1) list(UBound(list)) = i
Next i
サブルーチン(プロシージャ)
Excel VBAにはSubプロシージャとFunctionプロシージャと2種類の関数相当の機能がある。それぞれ下記の違いがある。
- SubプロシージャはExcelから単独で呼び出せるのに対し、Functionプロシージャでは他のプロシージャからしか呼び出せない
- Subプロシージャは戻り値を返せないのに対し、Functionプロシージャでは戻り値を返せる
値渡しと参照渡し
プロシージャの引数はデフォルトでは参照渡しである。
ByValをつけることで値渡しにできる
Sub Proc(Str As String) Str = "XXX" ' Strは上書きされない End Sub
ByRefをつけることで、明示的に参照渡しにできるので、混在する場合は宣言するとわかりやすい
Subプロシージャ
定義
Sub <プロシージャ名>(<変数名> As <型>)
' 処理の内容
End Sub
Functionプロシージャ
定義
- 標準系
Function <プロシージャ名>()
' 処理の内容
End Function
- 戻り値あり
戻り値にObject型を返す場合はSetをプロシージャ名の前につける
Function <プロシージャ名>() As <戻り値の型名>
' 処理の内容
<プロシージャ名> = <戻り値>
End Function
- 引数あり
Function プロシージャ名(ByVal <引数1> As <引数1型>, ByVal <引数2> As <引数2型>, ...) As 戻り値のデータ型
プロシージャ名 = 戻り値
End Function
呼び出し
()で引数を囲ってはいけない
subA str1, num1
ただし、先頭にCallをつける場合は囲ってもよい。
Call subA(str1, num1)
返り値を受け取る場合
val = funcA()
返り値無
Sub subA(arg1 As String, arg2 As Long) MsgBox ( arg1 & "+" & arg2 ) End Sub
途中終了
Exit Sub
返り値有
関数名に戻り値を代入する
Function funcA(arg1 As String, arg2 As Long) funcA = ( arg1 & "+" & arg2 ) End Function
その他
マクロ終了
Exit Sub
関数
文字列
substring
Mid( str, start, [length] )
開始位置は1から始まる。
文字列長を省略した場合は、開始位置から末尾までを切り出す。
Split
Split("a,b,c", ",")
配列を返す
日付
この関数はWindowsの設定により返すフォーマットが異なる。
その為、この関数で取得した値を元に処理を行う場合、下記の別の関数をし
Date()
年
YYYYの形式で返る
Year (Date)
月
Mの形式で返る
Month (Date)
MMで取得する場合
mm = "0" & Month(Date) mm = Mid(mm, Len(mm) - 1)
日付検査
targetDate = InputBox(Prompt:="年月", Default:=targetDate) If Not IsDate(targetDate) Then MsgBox "日付形式が不正です(2001/8)" End If
現在時刻
Now関数を用いる
nowStr = Format(Now, “yyyy年mm月dd日 hh時mm分ss秒”)
セル
Cells
単一のセルを指定する場合に使用する。
列番号をアルファベットではなく、数値で指定しなければならない。
' B1のセルの値を取得 Cells(1, 2).Value
- 代入
Cells(1, 2).Value = newVal
- 結合判定
If Cells(i, 1).MergeCells Then
' 処理
End If
Range
主に複数のセルを指定する場合に使用する。
' A1:B2のセルの値を取得 array = Range("A1:B2").Value ' B1のセルの値を取得 val = array(1,2)
以下は同じ
val = Range("B1").Value
- 代入
Range("B1").Value = newVal
選択セル
※変数宣言は不要
row = Selection.Row
column = Selection.Column
範囲選択している場合は、左上のセルのアドレスが格納される
シート
コピー
末尾に追加
Sheets("copied").Copy After:=Sheets(Worksheets.Count)
クリップボード
ライブラリの参照
クリップボードを扱う”DataObject”型は標準では使用できないので、参照設定が必要である。
- マクロのエディタを開く
- ツール > 参照設定
※参照設定がグレーアウトしている場合、おそらくマクロが実行中なので、停止すること - 参照
- C:\Windows\System32\FM20.DLL を開く
- Microsoft Forms 2.0 Object Libraryが選択されるのでOK
クリップボードへコピー
Dim ClipBoard As New DataObject
Dim str As String
str = "clip board test"
With ClipBoard
.SetText str
.PutInClipboard
End With
Tips
数値から列名取得
colName = Cells(1, <列番号>).Address(True, False) colName = Mid(colName, 1, Len(colName) - 2)
長い行の途中で改行する
途中で改行するには半角スペースとアンダースコアを行末に書く
list = Array( _
"A", _
"B", _
"C" _
)