一件だけで止まるマクロ

LWP | 一件だけで止まるマクロ

一件だけで止まるマクロ

減らしたのに止まる。受け取った「形」に隠れた落とし穴

Copyright © 2026 LWP 山中 一弘

本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。

ストーリー

今日は一件だけ。コイ丸先輩の軽いひと言で始まった確認作業が、なぜか終わりません。昨日は動いたマクロが、対象を減らすと止まってしまうのです。ココさんが試してみると、ますます不思議な結果が見えてきました。

舞台は、セルから受け取った値を、行と列のある配列として読むExcel VBAの動作確認。架空の職場の一幕です。対象は一続きのセル範囲とし、Range.Value2で値を読み取ります。

1 一件だけなのに

少ない仕事なら、確認も簡単。その見通しが、実行ボタンを押したところで外れます。

一件に減らしたマクロが止まり、昨日の二件では動いたと説明するココさんと、驚くコイ丸先輩

図1|件数を減らすと止まる、配列を前提にした処理。

2 増やせば動く?

ココさんは、縦にも横にも範囲を変えて比較します。動く条件が分かっても、そのまま対処にしてよいとは限りません。

A1の一セルでは止まり、A1:A2とA1:B1では動く比較。空セルまで読もうとするココさんに、コイ丸先輩が対象範囲の確認を促す

図2|読む範囲を広げれば動いても、必要な対象まで変えてしまう。

3 一件だけ、箱の外

呼ばれたシャケもんが確かめたのは、セルの中身に加えて、マクロが受け取る値の形でした。

シャケもんが一セルのValue2は単独の値、複数セルは二次元配列と説明する。裸の値10を、値を変えず一行一列の配列へ包む図

図3|単独の値10を、1行1列の配列に包む。中身は10のまま。

4 一件でも、箱入り

入口で形をそろえて、もう一度確認します。ようやく、件数の少なさが素直にありがたくなったと思ったら……。

一セルでも縦二セルでも同じ処理が通ったと報告するココさん。コイ丸先輩が午後の追加依頼を渡し、ココさんが件数は増えるのですねと笑う

図4|処理対象は増やさず、受け渡す形をそろえる。

まとめ

対象が少ないからといって、プログラムへの渡され方まで同じとは限りません。1セルと複数セルの違いを入口で吸収すると、後の処理は同じ行・列の扱いにそろえられます。

今回の仕掛け

一続きの範囲をRange.Value2で読むと、1セルでは単独の値が返り、複数セルでは二次元配列が返ります。1行だけ、あるいは1列だけでも、複数セルなら二次元です。配列だと思って単独の値をdata(1,1)のように読むと、エラーになります。

TakiLibのrngEnsureDim2Arrayは、Range.Value2から受け取った単独の値を1行1列の配列に包み、配列はそのまま返します。シートにセルや架空のデータを足す操作ではありません。なお、任意の一次元配列を二次元に変換する関数ではありません。今回の使い方は「一続きの範囲のValue2を渡す」ことが前提です。

今回のソースコードのサンプル

サンプルコード 受け取った値を包み、行数と列数を確かめる

01

Option Explicit

02

03

Public Function SampleRangeShape() As String

04

    Dim data As Variant

05

    data = rngEnsureDim2Array( _

06

        ThisWorkbook.Worksheets(1).Range("A1").Value2)

07

    SampleRangeShape = UBound(data, 1) & "行 " & _

08

                       UBound(data, 2) & "列"

09

End Function

コードの説明

05~06行目で、マクロを置いたブックの先頭シートからA1の値を読み、rngEnsureDim2Arrayへ渡します。A1が10なら、data(1,1)が10の配列になります。Rangeオブジェクトそのものではなく、Value2を渡すところがポイントです。

07~08行目のUBoundは、配列の指定した次元の上限を返します。第1次元が行、第2次元が列です。この例で受け取る配列は、どちらの下限も1なので、上限を行数・列数として表示できます。

入力・概要

TakiLibを導入済みのExcelマクロ有効ブックで使う、関数全体の例です。標準モジュールへコードを置き、先頭シートのA1に10を用意します。VBEのイミディエイトウィンドウで「? SampleRangeShape()」を実行すると、戻り値を確認できます。コード自体はセルを書き換えません。

結果

このまま実行すると「1行 1列」を返します。06行目の範囲をA1:A2にすると「2行 1列」、A1:B1にすると「1行 2列」です。いずれも専用の新規Excelブックで、掲載コードと範囲変更例を実行して確認しました。

読むポイント

形をそろえる処理は、値を受け取る入口の05~06行目にまとめています。後の処理では、1セルだけの分岐を繰り返さずに済みます。ただし、空セルやセルエラーも値として残ります。配列になったことと、数値計算に使えることは別に確認します。

サンプルコード TakiLibのソースコード:rngEnsureDim2Array

01

Public Function rngEnsureDim2Array(a_data)

02

    If typeIsPureArray(a_data) Then

03

        rngEnsureDim2Array = a_data

04

    Else

05

        ReDim xrbuff(1 To 1, 1 To 1)

06

        xrbuff(1, 1) = a_data

07

        rngEnsureDim2Array = xrbuff

08

    End If

09

End Function

出典メモ

  • Microsoft Learn:Range.Value — 複数セルから返る二次元配列と、複数領域の注意。

  • Microsoft Learn:Range.Value2 — Valueとの違いはCurrency・Date型を使わない点。

  • Microsoft Learn:UBound関数 — 指定した次元の配列上限。

  • TakiLib Ver3.5.4:rngEnsureDim2Arrayと配列判定の実装を確認。SampleRangeShapeは、TakiLibを呼び出すこの記事用の例です。rngEnsureDim2Arrayは、原典の解説コメントを省略して掲載しています。

  • 動作確認:2026年9月9日、Windows版Excel 16.0 Build 20326。1セル・縦列・横行・長方形、空セル・数式・セルエラー、一次元配列の反例、掲載コードを含む14項目を確認しました。結合セル、複数領域、可視セルだけの範囲は扱っていません。

人物と出来事はフィクションです。図版はLWPのキャラクター参照を用いてCodexの画像生成機能で作成し、掲載文字・人物・技術内容を確認しています。