セルの操作
セルの入力
Sub celltest()
'文字の代入
Range("A1").Value = "let's test"
'数式の代入
Range("A2").Value = "=1+1"
End Sub
セルのコピー
Sub copytest()
'[コピー元セル].copy [貼り付け先セル]
Range("A1").Copy Sheet2.Range("A1")
'注意点:書式などもコピーされる
'値だけをコピーしたいなら代入する
'変数の代入と同じ形になる(.copyとは左右が逆転する)点に注意
Sheet2.Range("A2").Value = Range("A1").Value
'表示形式だけコピー(実際やることは代入)
Range("C4").NumberFormatLocal = Range("A4").NumberFormatLocal
End Sub
セルの値を取得
Sub celltest2()
'セルに「=1+1」という数式が入ってる場合
Debug.Print Range("A2").Value '結果:2
Debug.Print Range("A2").Value2 '結果:2
Debug.Print Range("A2").Formula '結果:=1+1
'セルに日付「2022/3/24」が入ってる場合
Debug.Print Range("A3").Value '結果:2022/3/24
Debug.Print Range("A3").Value2 '結果: 44644 ※シリアル値(先頭に半角スペース有)
Debug.Print Range("A3").Formula '結果:44644 ※シリアル値
'セルに参照「=A1」が入ってる場合
Debug.Print Range("C3").Value '結果:let's test
Debug.Print Range("C3").Value2 '結果:let's test
Debug.Print Range("C3").Formula '結果:=A1
End Sub
セルの表示形式
Sub celltest3()
'セルの値「10000」→「\10,000」という表示にする
Range("A4").NumberFormatLocal = "\#,###"
End Sub
セルのクリア
Sub cellclear()
'書式はそのままで、値だけ消す
Range("A1").ClearContents
'この""の代入でも同じ結果になる
Range("A1").Value = ""
'範囲指定
Range("A1:C3") = ""
'書式ごと全消去する
Range("A1").Clear
'書式だけ消去する
Range("A1").ClearFormats
End Sub
セルに枠線を引く
Sub celltest4()
'すべての縦、横に細い線
Range("A1:C4").Borders.LineStyle = xlContinuous
'太い外枠
Range("A1:C4").BorderAround Weight:=xlMedium
End Sub
列の横幅を調整する
Sub columnwidth()
'自動調整
Columns("A:C").AutoFit
'1文字分スペースを追加
Columns("A:A").columnwidth = Columns("A:A").columnwidth + 1
'5文字分という指定(pxではない)
Columns(3).columnwidth = 5
End Sub
変数のデータ型
データ型の名前を調べる:TypeName()
Dim strA As String: strA = "hello"
Debug.Print TypeName(strA) 'String
Debug.Print TypeName(1234) 'Integer
データ型の変換
公式:データ型変換関数
Dim strB As String: strB = "01223"
Debug.Print TypeName(strB) 'String
Debug.Print TypeName(CLng(strB)) 'Long
数値:Long型
大体-2G~2Gの間 数字はとりあえずLong型にしとけばOK
Integer型は-32k~32kの間しかなく、オーバーフローエラーになりやすい
Byte型は0~255まで
数値型かどうかチェックする:IsNumeric()
Debug.Print IsNumeric("hello") 'False
Debug.Print IsNumeric(1234) 'True
小数点がある場合Currency型が安全
Double型だと小数点の計算時に予期せぬ結果になる可能性あり
Dim numA As Currency: numA = 0.1 + 0.2
Dim numB As Double: numB = 0.1 + 0.2
Debug.Print 0.3 = numA 'True
Debug.Print 0.3 = numB 'False
文字:String型
数字をString型にする:Str()
Debug.Print TypeName(123) ' Integer
Debug.Print TypeName(Str(123)) 'String
文字数のカウント:Len()
Dim strA As String
Dim strB As String
strA = "hello"
Debug.Print Len(strA) '5
Debug.Print Len(strB) '0
文字列に変数を埋め込む方法
Pythonならf"hello, {name}"
みたいに書けるが、VBAではreplace関数を使うか、文字と変数を&
でつなげるしかない
Debug.Print "こんにちは。現在" & Now() & "です"
'こんにちは。現在2024/12/15 14:55:59です
Debug.Print Replace("こんにちは。現在now_です", "now_", Now())
'こんにちは。現在2024/12/15 14:55:59です
長文を書く方法:改行コード「vbCrLf」で行をつなげる
コード自体の改行は「_
」で可能
' 各行を配列として用意
Dim arr: arr = Array( _
"VBAを学習するメリット", _
"1)業務の効率化・自動化:繰り返し作業や定型処理を自動化することで、手作業の時間を大幅に削減できる", _
"2)生産性向上:大量データの処理スピードが劇的に向上する", _
"3)柔軟なツール開発:自分やチームの要望に合わせて独自の機能やツールを構築できる", _
"4)メンテナンス性向上:システム開発に頼らず自力で改修・メンテナンスが可能となる", _
"5)キャリアアップへの貢献:業務改善提案やITリテラシー向上により、職場での評価にプラスとなる" _
)
' Join関数で配列の要素をvbCrLfで連結
MsgBox Join(arr, vbCrLf)
日付:Date型
#YYYY/MM/DD#と書くと自動的に日付型となる
Debug.Print #12/14/2024# '2024/12/14
Debug.Print TypeName(#12/15/2024#) 'Date
※年を末尾にする必要はない。「#2024/12/15#」と書くとエディタが勝手に「#12/15/2024#」に置き換えてしまうだけ
日付の表示形式を指定する:Format() ※String型になる
Debug.Print Format(Now(), "YY/MM/DD") '24/12/15
Debug.Print TypeName(Format(Now(), "YY/MM/DD")) 'String
日数の計算:DateDiff()
第1引数に単位、第2引数と第3引数に日付を渡す
単位は日ならd、月ならm、年ならyyyyなど決まっている(公式ドキュメント参照)
Dim diff As Long: diff = DateDiff("d", Now(), #1/1/2025#)
Debug.Print Replace("お正月まであとdiff日", "diff", diff)
'お正月まであと17日
曜日の判定:Weekday(), WeekdayName()
Weekday()に日付を渡すと曜日番号を返し、
WeekdayName()に番号を渡すと曜日名を返す
Debug.Print Weekday(Now()) '1
Debug.Print WeekdayName(1) '日曜日
Debug.Print WeekdayName(2) '月曜日
条件分岐
If 文
ある条件の時はこうする、という感じで処理を分岐する超重要構文
ElseIf で2つ目以降も条件を追加できる
Elseでどの条件にも当てはまらなった場合の処理を書く(省略可)
Dim level As Long: level = 50
If level < 10 Then
Debug.Print "Lv10になるまでスライムを倒そう"
ElseIf level < 50 Then
Debug.Print "Lv50になるまで洞窟で修行しよう"
Else
Debug.Print "そろそろ魔王をぶっ倒しに行こう!"
End If
Select Case 文
与えられた変数に対して、いろいろなパターン分けができる構文。ElseIfを大量に書くのが面倒な場合に使える
Dim Number: Number = 8
Select Case Number
Case 1 To 5
Debug.Print "Between 1 and 5"
Case 6, 7, 8
Debug.Print "Between 6 and 8"
Case 9 To 10
Debug.Print "Greater than 8"
Case Else
Debug.Print "Not between 1 and 10"
End Select
実行しますか?はい/いいえの確認ダイアログ
Dim res As Long
res = MsgBox("本当に実行しますか?", vbYesNo, "確認")
If res = vbYes Then
Debug.Print "実行しました"
Else
Debug.Print "キャンセルしました"
End If
ループ処理
For Next
自分で回数を指定して処理を繰り返す方法。1から順番に処理したい場合はこれを使う
Dim i As Long
For i = 1 To 10
Cells(1, i).Value = "hello " & i
Next i
For Each
回数を指定せずにすべての要素を巡回する方法
全部の要素を調べるけど順番は重要じゃない、という場合によく使われる
例えばワークシートを1個ずつ調べて、ある条件に一致したら名前を変更したり削除したりする、といった処理
Dim ws As Worksheet
' 現在のブックに含まれる各ワークシートを巡回
For Each ws In ThisWorkbook.Worksheets
Debug.Print ws.Name
Next ws
Do Loop
終了条件を満たすまで無限にループするタイプ。ゲームプログラミングでよく使われる
Dim userValue As Variant
Do
' ユーザーに数値の入力を求める
userValue = InputBox("1~20の間で好きな数字を入力してください。(正解は10です)")
' キャンセルが押された場合はループを終了
If userValue = False Then
Exit Do
End If
' 入力が正解かどうか判定
If IsNumeric(userValue) Then
If CInt(userValue) = 10 Then
MsgBox "正解です!"
Exit Do ' 条件が満たされたのでループを抜ける
Else
MsgBox "不正解。もう一度入力してください。"
End If
Else
MsgBox "数値を入力してください。"
End If
Loop
処理の中断やスキップの方法
途中で処理を終了
- For NextとFor Eachは「Exit For」でループを終了できる
- Do Loopは「Exit Do」でループを終了できる
特定の場合に処理をスキップ
Pythonならcontinueという構文で処理をスキップできるが、VBAはcontinueに相当するものが無いので、if文で何もしない分岐を作るか、GoToで次のループに移行する方法がある。どちらを選ぶかは好みの問題
何もしないif文を作る例
Dim i As Long
For i = 1 To 10
' 特定条件を満たす場合は後続処理を飛ばしたい
If i = 5 Then
' continue相当:何も実行せずにNext iへ
Else
' 条件を満たさない場合は通常処理
Cells(1, i).Value = "hello " & i
End If
Next i
GoToでスキップする例 ※長い・複雑なコードでGoToを使うと、どこに飛ぶかわからなくて嫌われるので注意
Sub test()
Dim i As Long
For i = 1 To 10
' 特定条件を満たす場合は後続処理を飛ばしたい
If i = 5 Then GoTo nextLoop
Cells(1, i).Value = "hello " & i
nextLoop:
Next i
End Sub
結果はどちらも同じ
エラーが発生した場合の処理
エラーを無視して次の処理に進む:Resume Next
Dim x As Long, y As Long
x = 1
On Error Resume Next
Debug.Print x / y
Debug.Print x, y ' 1 0
特定のラベルに飛ばす:GoTo ラベル名
エラー処理のラベルを書くときは必ず「Exit Sub」を書くようにする
エラーが起きなかったらExit Subで処理終了、
エラーが起きたらラベルに飛ぶ、という意味になる
「Exit Sub」を書き忘れると、エラーが起きなかった場合もエラーラベルの内容を実行してしまう
Sub test()
Dim x As Long, y As Long
x = 1
On Error GoTo ErrHandler
Debug.Print x / y
Exit Sub
ErrHandler:
Debug.Print "エラー:" & Err.Description
'エラー:0 で除算しました。
End Sub
ラベルから元の行に戻る:Resume
下記のコードではyが0なので8行目でエラーが発生し12行目に飛ぶ→13行目でyに5を代入する→14行目で8行目に戻る→今度は8行目でエラーが発生しないので、10行目に到達して処理が終了する
この場合で「Exit Sub」を書き忘れると永遠に14行目から1行前に戻り続ける無限ループになるので注意
Sub test()
Dim x As Long, y As Long
x = 1
On Error GoTo errHandler
Debug.Print x / y '0.2
Exit Sub
errHandler:
y = 5
Resume
End Sub