top of page

​タグ一覧

配列処理(73)

階層化フォーム(33)

ファイル操作(28)

開発事例(22)

シート・セル操作(19)

図形操作(15)

コード自動生成(10)

ユーザーフォーム(9)

設計思想(9)

文字列操作(8)

講座実施報告(7)

開発効率化(6)

数学(6)

GAS(5)

アニメーション(5)

技術解説(4)

イミディエイトウィンドウ(4)

Googleスプレッドシート(4)

副業(4)

クリップボード(4)

条件付き書式(4)

その他(4)

ココナラ(3)

小説(3)

HTML(3)

JavaScript(3)

OneDrive(2)

イベントプロシージャ(2)

Enum(2)

PDF(2)

フリーランス(2)

リスキリング(2)

Outlook(2)

介護(2)

Discord(2)

シフト表(2)

LookerStudio(2)

日報(2)

カレンダー(2)

罫線(2)

パズル(2)

小ネタ(2)

コード解説(2)

クラスモジュール(2)

ステータスバー(1)

コード解析(1)

バックアップ(1)

可変長引数配列(1)

ブック処理(1)

スクレイピング(1)

スプレッドシート(1)

coconala(1)

リボン登録マクロ(1)

QRコード(1)

実行予約(1)

給与計算(1)

VBA不使用(1)

リボン(1)

超勉強会(1)

スピログラフ(1)

図名描写(1)

連想配列(1)

溶接ロボット(1)

保育士(1)

楽天市場(1)

経理(1)

医療(1)

文書作成(1)

発注書(1)

ショートカット(1)

WebAPI(1)

色操作(1)

スーパー開発ショートカット(1)

ライブラリ処理(1)

放課後等デイサービス(1)

児童福祉支援(1)

学校(1)

UI(1)

CAD(1)

カーソル操作(1)

チェックボックス(1)

VBAのセル参照は「名前定義」で書くべき理由 ~A1直書き・Cells(1,1)が保守で壊れる“本当の原因”~

はじめに:VBAは「動く」より「運用で壊れない」が価値になる


Excel VBAの解説でよく出てくるセル参照は、だいたいこの2つです。

  • Range("A1")

  • Cells(1,1)

どちらも分かりやすいし、学習段階では便利です。でも、実務でツールとして納品し、運用が始まると、ここが“保守の爆弾”になります。


なぜなら、Excelは運用中に 行・列の挿入/削除や、セルの移動でレイアウトが変わる からです。そしてレイアウトが変わると、参照先がズレて、コードの書き換えが発生する(もしくは、気づかない誤動作が起きる)からです。


この記事では、セル参照を「位置」ではなく「意味」で扱える 名前定義(Named Range) を使うべき理由と、弱点のカバー方法までまとめます。


VBAのセル参照は「名前定義」で書くべき理由 ~A1直書き・Cells(1,1)が保守で壊れる“本当の原因”~

よくあるセル参照:アドレス直指定のメリットと致命点


Excel VBAでは、セルの値を取り出して変数に入れるとき、まず教科書的に紹介されるのが セル番地を直接指定して読む方法です。

たとえば、下図のように「従業員名」が C2セル に入力されているとします。この値(例:今治 太郎)をVBAで取り出して、変数に格納する最もシンプルな書き方は次のとおりです。

シート上に従業員名を入力
シート上に従業員名を入力

また、セル番地ではなく「行番号・列番号」で指定する方法(Cells)もよく使われます。

C列の2行目は「列=3、行=2」なので、次のようにも書けます。


この2つ(Range("C2") / Cells(2, 3))は、VBA学習で最初に習うセル参照として非常に分かりやすく、 「どのセルを読んでいるか」がコード上ですぐ見えるのがメリットです。


しかし、ここに大きな落とし穴があります。

たとえば下図のように、2行目に1行挿入したとします。すると、もともと C2 に入っていた「従業員名」 は C3 に移動します。


2行目が挿入されて従業員名のセルが移動

ところがコード側が

  • Range("C2")

  • Cells(2, 3)

のように 番地(行・列)を固定して参照していると、挿入後も変わらず「C2」を参照してしまいます。つまり、参照先がズレてしまい、意図しないセルの値を読んだり、書き込んだりする状態になります。


このような「ズレ」は、行の挿入だけでなく、

  • 行・列の削除

  • 別の場所への挿入

  • セルの切り取り/コピー → 貼り付けによる移動

  • 表のレイアウト調整(ドラッグ移動など)


といった、いわゆる ワークシートのレイアウト変更 でも簡単に発生します。


そして問題は、こうした変更が起きるたびに、アドレス直指定のコードは動かなくなったり、コードの書き換えが必要になったりすることです。(しかも怖いのは、エラーで止まらず “それっぽく動いてしまう” ケースもある点です)


「シートのレイアウトが変わったら、その都度コードを書き換えるしかない」――教科書どおりに学ぶと、そう思ってしまう方も多いかもしれません。


しかし、この問題を解決する方法があります。それが、セルに名前を付け、その名前で参照する「名前定義」 という方法です。

名前定義の設定方法

 

名前定義の設定方法は基本操作なので、ここでは手順だけ軽く押さえます。流れは下図のとおりです。

  1. 名前を付けたいセル(または範囲)を選択する

  2. リボンの [数式]タブ →[名前の定義] をクリック

  3. 「名前」「参照範囲(スコープ)」「参照範囲」を設定してOK


名前は、あとから見たときに意味が分かるように、例えば 「従業員名」 のような分かりやすい名称にしておくのがおすすめです。


セルの名前定義の設定手順
セルの名前定義の設定手順

また「参照範囲(スコープ)」には、ブック全体で有効にするか、特定のワークシート内だけで有効にするかの選択があります。もし「そのワークシート内だけで使う」前提なら、参照範囲は ブックではなく、対象のワークシート名(例:Sheet1) を選ぶ方が管理しやすくなります。


実務では、名前定義を設定したワークシートを 複製して使い回す ケースがよくあります。このとき、もし名前定義の参照範囲(スコープ)を 「ブック全体」 にしていると、複製したシートの分だけ 同名の名前定義がブック内に大量に増える 状況になりがちです。


そうなると、どの名前定義がどのシートを指しているのかが分かりづらくなり、VBA側でも参照先の特定が面倒になります。結果として、コードの可読性や保守性が下がり、扱いづらい設計になってしまいます。


そのため、同じ構成のシートを複製して運用する可能性があるなら、名前定義は基本的に「ワークシート範囲(シート内のみ有効)」で設定しておく方が、VBAをコーディングする上でもメリットが大きいです。

名前定義を利用したセルの参照コード

  上のように名前定義を設定しておけば、VBA側は「元のセル番地(C2など)」を直接書かずに、名前でセルを参照できるようになります。具体的には、Range オブジェクトの引数に 名前定義の名前(例:従業員名) を指定するだけです。


たとえば従業員名を取得する場合は、次のように書けます。

 この方法のメリットは、レイアウト変更に強いことです。仮に行の挿入などで「従業員名」のセルが C2 から別の位置へ移動しても、名前定義が参照先に追従していれば、コードを書き換えなくても正しい値を取得できます。


一方でデメリットとして、コードを見ただけでは「その名前が具体的にどのセルを指しているか」が分かりづらくなります。その対策として、上の例のように コメントで元の番地(例:' C2)を書いておくと、後から見返すときの手がかりになり、保守が楽になります。


では、実際にこのコードを実行して結果を確認してみます。

下図のとおり、途中で 2行目を挿入したことで、「従業員名」の入力セルは C2 → C3 に移動しています。


2行目が挿入されてセルが移動した
2行目が挿入されてセルが移動した

それでも、VBA側は Sheet1.Range("従業員名").Value と 名前で参照しているため、セルの位置が変わっても参照先が追従し、正しい値(今治 太郎)を取得できます。


確認のため、取得した値を Debug.Print でイミディエイトウィンドウに出力すると、下図のように 「従業員名:今治 太郎」 と表示されます。これにより、セルが移動した後でも名前定義が正しく機能し、コードを書き換えずに値を参照できていることが分かります。


名前定義のコードのセル移動後の実行例
名前定義のコードのセル移動後の実行例

ヘッダーのセルを基準とする場合


ここまでは「単一セル」を名前定義で参照する例でしたが、もう少し実務寄りの応用として、ヘッダー行(見出しセル)を基準にして一覧を参照するケースを紹介します。


たとえば下図のように、B2セルに「従業員名一覧」という見出しがあり、その下(B3以降)に従業員名が縦に並んで入力されているとします。


従業員名一覧が入力されてある
従業員名一覧が入力されてある

この一覧をVBAで順番に取得して表示したい場合、教科書的には Cells(行, 列) を使って次のように書くことが多いです。

  • Cells(i + 2, 2) のように、行番号・列番号を増やしながら参照する方法

ただしこの書き方は、行の挿入・削除や列の追加などでレイアウトが変わると、参照位置がズレて コードの書き換えが必要になりやすいのが弱点です。一覧のように「繰り返し参照する範囲」ほど、このズレの影響を受けやすく、保守面で扱いづらくなります。


そこで有効なのが、ヘッダーセルに名前定義を設定し、そのセルを基準(起点)としてOffsetで参照する方法です。


たとえば、見出しセルのB2に対して「従業員名一覧」という名前定義を設定しておきます。

ヘッダーセルに名前定義設定
ヘッダーセルに名前定義設定

すると、VBA側ではまずその名前定義セルを取得し、そこから

  • 1行下(B3)

  • 2行下(B4)

  • 3行下(B5)


というように、Offset(行, 列) を使って値を順番に参照できます。


この書き方のメリットは、レイアウト変更に強いことです。

仮に行の挿入などで一覧の開始位置が下にずれても、「従業員名一覧」という基準セルに名前定義が追従していれば、参照も一緒に追従するため、コードの修正を最小限に抑えられます。


最後に、実行してイミディエイトウィンドウに出力すると、下図のように「従業員名1〜3」が正しく取得できていることが確認できます。


一覧データを扱う場面では、**「基準セルを名前定義」+「Offsetで展開」**の組み合わせが、保守性の高い書き方として特におすすめです。


ヘッダーセルの名前定義を利用した場合の実行例
ヘッダーセルの名前定義を利用した場合の実行例

まとめ

今回紹介したとおり、Range("A1") や Cells(行,列) のような番地ベースの参照は、学習段階では分かりやすい反面、行・列の挿入/削除やセル移動で簡単に参照ズレが起きます。その結果、コードの書き換えが発生したり、最悪の場合は“気づきにくい誤動作”につながります。


一方、名前定義で「意味」を基準に参照しておけば、レイアウト変更が入っても追従しやすく、保守性と信頼性が大きく上がります。一覧のような繰り返し処理も、基準セルを名前定義→Offsetで展開するだけで、壊れにくい構造にできます。「場所」ではなく「意味」で参照する――これが、運用前提のVBAでは重要です。


私が開発するマクロツールも、基本方針として名前定義を前提に設計し、レイアウト変更に強い作りにしています。保守や改修のコストを減らし、長く安心して使えるVBAにしたいなら、名前定義の活用は“ほぼ必須”だと考えてください。

Excel VBAによる業務自動化・ツール開発をご検討の方へ

​"脱Excel"の前に、現状のExcelの潜在能力を120%発揮してみませんか?

Softex-Celware

​インボイス登録番号:T5810983887134

  • Facebook
  • Twitter
  • YouTube

©2023 softex-celware。Wix.com で作成されました。

bottom of page