電子書籍の厳選無料作品が豊富!

VBAの宣言の中にOption Base というのがあります。
Option Base 1で配列の添字を1から始まるように出来るというやつです。
ところが、
例えば、「Option Baseの指定も、ReDimも無しで」
セルA1~A10を対象に

Dim A as Vriant
A=ThisWorkBook.Sheets("sheet1").Range(Cells(1, 1), Cells(10, 1)).Value

とやると何故か
A(1,1)~A(10,1)にA1~A10の値が入るようです。
この方が、配列の添字とセルの添字が一致するので良いには良いのですが、なぜ、A(0,0)~A(9,0)ではないのでしょうか?
また、
セルA2~A11を対象に

A=ThisWorkBook.Sheets("sheet1").Range(Cells(2, 1), Cells(11, 1)).Value

とやるとA(1,1)~A(10,1)にA2~A11の値が入るようです。
この場合は、配列の添字とセルの添字は当たりまえですが一致しません。
なんとなく、暗黙の設定で添字が1から始まるような気がしますが・・・

有名な下記サイトでもそういうコードの書き方をしています。
http://officetanaka.net/excel/vba/speed/s11.htm

しかし、Option Base 1や、ReDimの宣言をしているなら分かるんですが、こういう場合、暗黙に添字が1から始まるっぽい?のは信用していいのでしょうか?
試しに同じコードで頭にOption Base 1 の設定をしても動作は変わらないようです。

何故こんな事が気になるかというとVBの方ではOption Baseが廃止になったようで、VBAでもバージョン変わったら動作がおかしくなるのではないか?と思うからです。

この辺り、どういう事になっているのか、ご存知の方いらっしゃいますでしょうか?

A 回答 (2件)

こんばんは。



私は、基本的には、Option Base 1は使わないようにしています。それは、旧VBの仕様だからです。人には使うなとはいいませんが、配列の初期値を1で使うと、最初のうちは、便利に感じますが、そのうち混乱してきます。

>VBの方ではOption Baseが廃止になったようで、VBAでもバージョンが違ったら動作がおかしくなるのではないか?

VB.Net やC#とは、互換性はありません。VBAは、あくまでもVBAで、基本的には変わることはありません。一時期、VBAの廃止の噂も出ましたが、当分の間、続くことを、Microsoft Office チームのリーダからの発表がありました。しかし、実際に、VSTA(Visutal Studio Tools for Application)が加わると、Ver.4マクロと同じような扱いになると思います。ただ、VB.Net などへのコンバータは付けられるはずです。

-------------------------------------------
Option Base を言う前に、きちんとした書き方をしてください。

Dim A As Variant
A=ThisWorkBook.Sheets("sheet1").Range(Cells(1, 1), Cells(10, 1)).Value

Sheets("sheet1").Range まではつながっていますが、引数のCellsプロバティは、浮いてしまっていますから、きちんと、Sheet 側とつなげてください。(閉じ括弧は直したようですが。)

-------------------------------------------
'例えば
Dim A As Variant

With ThisWorkBook.Worksheets("Sheet1")
   A = .Range(.Cells(1, 1), .Cells(10, 1)).Value
End With

としてください。

問題の配列ですが、これは、ジャグ配列(または他段階配列)という種類のものですが、Range をヘルプで調べると、Range コレクションとなっています。この初期値には、「0」はありません。「1」からです。コレクションは、すべて、「1」から始まっていると考えたほうがよいです。Sheets コレクションも、「1」からですし、Workbooks コレクションも、「1」からです。

>この場合は、配列の添字とセルの添字は当たりまえですが一致しません。

セルは配列ではありません。似てはいてもオブジェクトの集合体(コレクション)です。だから、添え字ではありません。

ただ、VBAなどでは、Option Base 1 を使われる可能性も考えて、LBound と Ubound を使って、このように書きます。私は、以下のサイトは、あまりお勧めしません。さしずめ、田中亨氏の実験場のようなものだと思います。
'-------------------------------------------
'http://officetanaka.net/excel/vba/speed/s11.htm

Sub Test2()
  Dim i As Long, j As Long, buf As Long, C As Variant
  C = Range("A1:C10")
  For i = LBound(C, 1) To UBound(C, 1)
    For j = LBound(C, 2) To UBound(C, 2)
      buf = C(i, j)
    Next j
  Next i
End Sub
'-------------------------------------------
なお、今、前の質問も読ませていただきました。
    • good
    • 0
この回答へのお礼

非常に丁寧な解説ありがとうございました。
セルの一部の範囲を切って入れてもコレクションだから、1から必ず始まると考えれば良いのでしょうか。
コレクションは使ってみると便利なのですが、このやり方を目にするまで、入っている順番を考えて使用するものでは無いと思っていました。
予め配列の大きさを宣言しておいて、一セルづつ場所を指定してセル内容を代入する作業と比較すれば、いきなり全部代入出来るこの方法は非常に魅力的です。
コレクションの順番の規則性を理解すればそれも可能という事でしょうか。
それとも、私が無知なだけでこういう使い方は当たり前なんでしょうか。

そもそもセル範囲の内容を代入して使う場合は、各セル内容が入ってる場所がはっきりしないと使い物になりませんよね。

お礼日時:2009/10/05 09:58

こんにちは。



>セルの一部の範囲を切って入れてもコレクションだから、1から必ず始まると考えれば良いのでしょうか。

逆に、コレクションで、0から始まるものが何かあるのかなって思うのです。これは、経験値ですから、はっきりと言えません。

コレクションと配列は良く似ていますし、コレクションから配列には、そのまま移行できますが、逆はできないはずです。ただ、コレクションというものは、同種のオブジェクトをまとめたものを言いますから、戻しても、その一部だけになってしまいます。

ところで、お話には、少し食い違いがあるようです。結果的には、確かに、Range はコレクションなのでが、現在の方法で、特にコレクションとして使っているわけではありません。最後に、サンプルコードを示します。

>一セルづつ場所を指定してセル内容を代入する作業と比較すれば、いきなり全部代入出来るこの方法は非常に魅力的です。

>コレクションの順番の規則性を理解すればそれも可能という事でしょうか。

こうしたものは、あまり決まったものではありませんが、Rangeを、配列に入れる目的は、第一には、処理スピードを速くするためだと思うのです。ワークシートでいうと、「形式を選択して貼り付け--->値」という方法です。どちらかというと、Excel VBAでは、裏技に近いものだと思います。

それ以外では、指定範囲の値を確保して、その部分を加工するためです。他には、このような配列は、ワークシート関数は使えませんし、使いようかありません。

結果的に、コレクションとなっていますが、あまりコレクションとしては、役には立っていないように思います。コレクションとして使うというのは、本来は、以下のような使い方が、コレクション・オブジェクトの使い方です。

実務では出会わないコードですが、以下のような方法がコレクションの使い方です。

'-------------------------------------------

Sub Test1()
Dim myRng As Range
Dim myColl As Collection
Dim i As Long
Dim c As Variant
Set myRng = Range("A1:C10")
Set myColl = New Collection
For Each c In myRng
 myColl.Add c
Next c
Set myRng = Nothing
End Sub

'-------------------------------------------
    • good
    • 0
この回答へのお礼

親切にお答え頂きありがとうございました。
最初の質問以上の事まで教えて頂けたと思います。

質問を締め切らせて頂きます。

お礼日時:2009/10/05 17:02

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!