ExcelマクロVBA技術解説
VBAにおける配列やコレクションの起点について

ExcelマクロVBAの問題点と解決策、エクセルVBAの技術的解説
最終更新日:2019-10-07

VBAにおける配列やコレクションの起点について


VBAの配列を扱っていると、0から開始されていたり1から開始されていたりします。
さすがに、混乱したり、間違ってしまう事もあると思います。


0から開始される場合を、「0オリジン」英語では「zero-based」
1から開始される場合を、「1オリジン」英語では「one-based」
このような呼び方をします。
VBAでの、これらの違いについてお話したいと思います。

配列の起点について

VBAの配列の起点はOption Baseで指定できます。

Option Base
Dim ary(3)
特に指定が無ければ、これは0オリジンで、0~3の配列になります。
特に指定が無ければと書きましたが、
Option Base 1
これを指定すると、1オリジンとなり、1~3の配列になります。

Option Baseでは、0or1が指定できます。
マイナスや2以上は指定できません。
既定は、Option Base 0です。

つまりVBAではOption Baseで、「0オリジン」と「1オリジン」を選択できるという事です。
もちろん、
Dim ary(1 To 3)
このようにすれば、Option Baseに関係なく1オリジンの配列になります。

セル範囲から作成される配列
Variant変数 = Range(・・・).Value
これで作成される配列は、

Option Baseの影響を受けることなく常に1オリジンの2次元配列になります。

逆に、配列をセル範囲に入れるときの、
Range(・・・).Value = 配列
この配列は0オリジンでも1オリジンでも、2次元配列でさえあればどっちでも構いません。
どちらでも、動作結果は同じになります。

Split関数で作成される配列
変数 = Split(・・・)
Split関数で作成される配列は、Option Baseの影響を受けることなく常に0オリジンになります。
Split関数の結果を1オリジンにする書き方は、私の知る限りでは存在しません。

Array関数で作成される配列
変数 = Split(・・・)
これで作成される配列は、Option Baseにより決定されます。
Base 0なら、0オリジンになります。
Base 1なら、1オリジンになります。
Base 0が既定ですので、通常は0オリジンという事です。

ですが、Base 1の時も0オリジンになる書き方があります。
変数 = VBA.Split(・・・)
変数 = VBA.[_HiddenModule].Array(・・・)
このようにタイプ ライブラリの名前で修飾した書き方をすると、
Option Baseの影響を受けずに常に0オリジンになります。


ParamArray指定の引数
プロシージャー名(ParamArray 引数名())
ParamArrayキーワードを指定した引数の配列は、Option Baseの影響を受けることなく常に0オリジンになります。
呼び出し側でこの引数を省略した場合は、LBoundは0、UBoundは-1となります。

コレクション

WorksheetsやWorkbooks等、Excelのコレクションは常に1オリジンです。
Worksheets(0)やWorkbooks(0)はエラーとなります。

コレクションと配列は全く別物です。
コレクションと配列の記述が同じになっているので混同されがちですが、
コレクションにおける、コレクション(インデックス)
これは、
コレクション.Item(インデックス)
この記述の省略形になります。

Itemがこれらコレクションの既定のメンバーとなっているため、

メンバーを省略した場合はItemを指定したことと同じになります。
Itemはプロパティですので、プロパティが引数を受け取って値を返しているので、
0オリジンか1オリジンかは、プロパティ次第という事です。
ただし、Excelに用意されているコレクションは全て0オリジンで統一されています。

クラスを自作して、0オリジンのItemプロパティを作ることは出来ますので、
あくまで、Excel作成したときの都合で1オリジンにしたというだけの事になります。

Collectionオブジェクト

VBAには、独自のコレクションを作成するためのオブジェクトとしてCollectionオブジェクトが用意されています。
このCollectionオブジェクトも常に1オリジンです。

Dim c As New Collection
c.Add "A"
Debug.Print c(1)

c(0)は、エラーとなります。
c(1)は、c.Item(1)の省略形です。

少し話が脱線しますが
CollectionのItemはプロパティではなくメソッドになっています。
なぜメソッドにしたのかは分かりませんが、
少なくともメソッドであるがゆえに、以下の記述はできなくなっています。
c(1) = "B"
メソッドですから、値を受け取ることはできても値を入れることはできません。
ただし、プロパティでも読み取り専用にすればよいので、これはメソッドにしている理由ではないでしょう。

その他:文字列関数

配列とは話が大分変ってしまいますが、文字列系の関数の文字位置は1オリジンになっています。
Right、Mid、Left、InStr等々
先頭から1文字目が1、これだけを見たらわかりやすいとは思います。
ですが、配列と合わせて使う場合には注意が必要になってきます。

配列の起点の原則

・既定は0オリジン
・Rangeから作成は1オリジン
・Splitは常に0オリジン
・ParamArrayは常に0オリジン
・Option Baseで変更できるのはDimおよびRedimの配列
・コレクションは1オリジン
・文字列関数は1オリジン

うーん、結局7つも原則があったら、混乱しますね。
原則として、Option Baseは使わないことにすれば、
・Rangeから作成は1オリジン
・コレクションは1オリジン
・文字列関数は1オリジン
・以外は0オリジン

これくらいなら覚えやすいのではないでしょうか。



同じテーマ「マクロVBA技術解説」の記事

Excelアドインの作成と登録について
VBAでのタイマー処理(SetTimer,OnTime)
マクロでShift_JIS文字コードか判定する
Byte配列と文字コード関数について
VBA+SeleniumBasicで検索順位チェッカー(改)
Applicationを省略できるApplicationのメソッド・プロパティ一覧
PowerQueryの強力な機能をVBAから利用する方法
ShapesとDrawingObjectsの相違点と使い方
新規挿入可能なシート名の判定
VBAにおける配列やコレクションの起点について
VBAのマルチステートメント(複数のステートメントを同じ行に)


新着記事NEW ・・・新着記事一覧を見る

VBAクラスのAttributeについて(既定メンバーとFor…Each)|VBA技術解説(10月19日)
VBAの用語について:ステートメントとは|VBA技術解説(10月16日)
VBAのマルチステートメント(複数のステートメントを同じ行に)|VBA技術解説(10月14日)
VBAコードの全プロシージャー・プロパィ一覧を取得|VBAサンプル集(10月12日)
VBAでエラー行位置(行番号)を取得できるErl関数|VBA技術解説(10月11日)
手動計算時の注意点と再計算方法|ExcelマクロVBA技術解説(10月9日)
引数の数を可変にできるパラメーター配列(ParamArray)|VBA入門(10月7日)
VBEの使い方:デバッグ|ExcelマクロVBA入門(10月6日)
VBAにおける配列やコレクションの起点について|VBA技術解説(10月5日)
VBEの使い方:オブジェクト ブラウザー|VBA入門(10月5日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.RangeとCellsの使い方|ExcelマクロVBA入門
4.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
5.変数とデータ型(Dim)|ExcelマクロVBA入門
6.繰り返し処理(For Next)|ExcelマクロVBA入門
7.マクロって何?VBAって何?|ExcelマクロVBA入門
8.ひらがな⇔カタカナの変換|エクセル基本操作
9.空白セルを正しく判定する方法(IsEmpty,IsError,HasFormula)|VBA技術解説
10.セルに文字を入れるとは(Range,Value)|VBA入門



  • >
  • >
  • >
  • VBAにおける配列やコレクションの起点について

  • このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


    記述には細心の注意をしたつもりですが、
    間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
    なお、掲載のVBAコードは自己責任で使ってください。万一データ破損等の損害が発生しても責任は負いません。




    このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
    本文下部へ