目次
はじめに
Excel VBAでセルを操作する際、CellsとRangeのどちらを使うべきか迷ったことはありませんか? どちらも同じセルを指定できますが、実は得意な場面が異なります。この使い分けを理解すると、コードがぐっと書きやすくなり、他の人が読んでも分かりやすいコードが書けるようになります。
基本的な使い方
Rangeの特徴
Rangeは、Excel上で見たままのセル番地を使ってセルを指定します。これは私たちが普段Excelを使うときと同じ感覚で書けるため、とても直感的です。
Range("A1").Value = "こんにちは"
Range("B2:D4").Interior.Color = RGB(255, 200, 200)
Range("A1:B10").Font.Bold = True
Range("A1")のように、普段Excelで使っている「A1」という表記がそのまま使えます。また、複数セルの範囲指定も"B2:D4"のように書けるのが特徴です。
Rangeは文字列で指定するため、セル番地が固定されている場合に特に読みやすくなります。たとえば、請求書のテンプレートで「必ずB5セルに日付を入れる」といった処理を書くとき、コードを見ただけで何をしているか一目瞭然です。
Cellsの特徴
一方、Cellsは行番号と列番号の数字でセルを指定します。プログラミング的な発想に近い書き方です。
Cells(1, 1).Value = "こんにちは"
Cells(2, 2).Interior.Color = RGB(255, 200, 200)
Cells(5, 3).Font.Bold = True
Cells(1, 1)は「1行目の1列目」という意味で、これがA1セルに相当します。最初の数字が行、次の数字が列です。Cells(5, 3)なら「5行目の3列目」でC5セルになります。
数字で指定することの最大のメリットは、変数が使いやすいことです。プログラムで計算した結果の行番号や列番号を、そのまま使えます。
使い分けのポイント
固定されたセルにはRange
特定のセル(例えば必ずA1セルやD5セル)を操作するなら、Rangeが読みやすくておすすめです。
Range("A1").Value = "売上集計表"
Range("A2").Value = "2024年度"
Range("B5").Value = "合計金額"
このコードを見れば、A1セルにタイトル、A2セルに年度、B5セルに項目名を入力していることがすぐ分かります。コードの可読性(読みやすさ)が高いため、後から見直したり、他の人に引き継いだりする際にも理解しやすいです。
帳票(レポートや伝票など決まった形式の書類)のように、セルの位置が固定されているものを作成する場合は、Rangeを積極的に使うことをおすすめします。
ループ処理にはCells
変数を使って繰り返し処理をする場合は、Cellsの出番です。
Dim i As Long
For i = 1 To 10
Cells(i, 1).Value = i * 10
Next i
このコードは、A1からA10まで順番に「10、20、30...100」と書き込みます。変数iがそのまま行番号として使えるため、コードがシンプルになります。
もし同じことをRangeでやろうとすると、文字列結合(文字と文字をつなげる処理)が必要になり、少し複雑になります。
' Rangeで同じことをする場合
For i = 1 To 10
Range("A" & i).Value = i * 10
Next i
動作は同じですが、"A" & iという書き方に慣れていないと、少し読みにくく感じるかもしれません。
行と列の両方を変数にすることもできます。
Dim i As Long
Dim j As Long
For i = 1 To 5
For j = 1 To 5
Cells(i, j).Value = i * j
Next j
Next i
これは九九の表のように、行と列の組み合わせで値を計算して入れる場合に便利です。5×5のマス目に、各マスの行番号×列番号を入力しています。
【実践例:データ入力の自動化】
実際の業務でよくある「最終行を探して、その次の行にデータを追加する」という処理を見てみましょう。
Sub AddDataExample()
Dim lastRow As Long
Dim newRow As Long
' A列の最終行を取得
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
' 次の行番号を計算
newRow = lastRow + 1
' 新しいデータを追加
Cells(newRow, 1).Value = "2025/12/03"
Cells(newRow, 2).Value = "商品A"
Cells(newRow, 3).Value = 1500
End Sub
lastRowという変数に最終行の番号を取得し、その次の行に日付、商品名、金額を入力しています。行番号が変数で管理されているため、データがどれだけ増えても自動的に正しい位置に追加できます。
このような「データの行数が変わる」処理では、Cellsを使うことで柔軟に対応できます。
注意点
【Cellsの列番号は数字で指定】
Cellsを使うとき、列は数字で指定するのが基本ですが、実は文字列(アルファベット)でも指定できます。
Cells(1, 1).Value = "数字で指定" ' A1セル
Cells(1, "A").Value = "文字列で指定" ' A1セル(どちらも可能)
A列は1、B列は2、C列は3...という対応になります。Z列は26、AA列は27です。
ただし、変数を使ったループ処理では数字の方が扱いやすいため、実務では数字で指定することが多いです。
' ループでは数字指定が便利
For i = 1 To 10
Cells(i, 1).Value = i * 10 ' 変数iをそのまま使える
Next i
列をアルファベットで指定したい場合や、固定された列名を使いたい場合は、素直にRangeを使う方がコードの意図が分かりやすくなります。
【Rangeで変数を使う場合の書き方】
Rangeでも変数を使えますが、&演算子(文字列結合用の記号)で文字列をつなぐ必要があります。
Dim rowNum As Long
Dim colLetter As String
rowNum = 5
colLetter = "B"
Range(colLetter & rowNum).Value = "5行目のB列"
&で文字列をつなげて"B5"という形にしています。変数が1つだけなら、この書き方でも問題ありません。
ただし、列も変数にしたい場合は少し厄介です。列番号を一度アルファベットに変換する必要があるため、素直にCellsを使った方が楽です。
【RangeとCellsの組み合わせ】
実は、Rangeの中でCellsを使うこともできます。これは変数を使って範囲を動的に(その場で計算して)指定したい場合に便利です。
Dim startRow As Long
Dim endRow As Long
Dim startCol As Long
Dim endCol As Long
startRow = 2
endRow = 5
startCol = 1
endCol = 3
Range(Cells(startRow, startCol), Cells(endRow, endCol)).Select
これは「A2からC5までの範囲」を選択します。開始位置と終了位置の両方を変数で指定できるため、データの量に応じて範囲を変える処理に使えます。
たとえば、「データがある範囲全体に罫線を引く」といった処理を書くときに、この方法が活躍します。
Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
Range(Cells(1, 1), Cells(lastRow, 5)).Borders.LineStyle = xlContinuous
A1セルから、最終行の5列目(E列)までの範囲に罫線を引いています。データが10行でも100行でも、自動的に範囲を調整してくれます。
パフォーマンスについて
RangeとCellsの実行速度はほぼ同じです。どちらを使っても、処理速度に大きな違いはありません。
ただし、大量のセルを操作する場合は、セルに1つずつアクセスするよりも、配列(データをまとめて扱うための入れ物)を使った方が高速です。これはRangeでもCellsでも同じです。
' 遅い書き方
For i = 1 To 1000
Cells(i, 1).Value = i
Next i
' 速い書き方
Dim dataArray() As Variant
ReDim dataArray(1 To 1000, 1 To 1)
For i = 1 To 1000
dataArray(i, 1) = i
Next i
Range("A1:A1000").Value = dataArray
1000回セルにアクセスするのではなく、配列にデータをためてから一度にセルに書き込む方が、圧倒的に速くなります。
配列の次元と出力方向の関係
一次元配列は横方向(1行n列)の形式としてセル範囲に出力されます。そのため、A1からA1000という縦方向(複数行×1列)に出力したい場合は、2次元配列として(行数, 1)の形式で定義する必要があります。
もし横方向(1行×複数列)に出力するなら、一次元配列でも問題ありません。
' 横方向なら一次元配列でOK
Dim dataArray() As Variant
ReDim dataArray(1 To 1000)
For i = 1 To 1000
dataArray(i) = i
Next i
Range("A1:AML1").Value = dataArray ' 横方向に出力
よくある間違い
【行と列を逆にしてしまう】
Cellsは「Cells(行, 列)」の順番です。これを逆にしてしまうミスがよくあります。
' 間違い: 列が1、行が5になってしまう
Cells(1, 5).Value = "A5セルに入れたつもり"
' 正しい: 行が5、列が1でA5セル
Cells(5, 1).Value = "A5セルに入れる"
「行が先、列が後」と覚えておきましょう。英語では「Row, Column」なので、その頭文字をとって「RC」と覚える方法もあります。
【Rangeで変数を使うときの引用符】
変数を使うときは、引用符(ダブルクォーテーション)の位置に注意が必要です。
' 間違い: 全体が文字列になってしまう
Range("A" & i).Value = "データ"
' 正しい: Aだけが文字列で、iは変数
Range("A" & i).Value = "データ"
"A" & iのように、文字列部分だけを引用符で囲みます。
まとめ
固定されたセルを操作するならRange、ループや変数を使った動的な処理ならCellsが便利です。それぞれの得意分野を理解して、場面に応じて使い分けましょう。
Rangeは直感的で分かりやすく、Cellsは柔軟で計算しやすいという特徴があります。最初は迷うかもしれませんが、何度か書いているうちに自然と手が動くようになりますよ。どちらか一方だけを使うのではなく、両方の良いところを活かしてコードを書いていきましょう!