ワクワクV057回目配列完全解説3回目(2021-09-18)

配列,VBA,エクセル,
1
ほえほえ@スプシマン @hoehoe1234

②1)ーb)具象配列ーByRefバリアント 推奨する形式です。仮引数のバリアントは実引数配列へのポインタとして機能します。配列のコピーも発生しませんし、実引数を書き換えられます。バリアントは型を動的に割り当てられますのでどのような具象配列も受け入れることができます。

2021-10-06 02:50:15
ほえほえ@スプシマン @hoehoe1234

③1)ーC)具象配列ーByValバリアント 配列のコピーが発生します。元の配列を書き換えることはできません。仮引数がバリアントなのでどのような具象配列も受け入れることができます。配列のコピーは代入で作成できますのでわざわざこの形式を選択する理由はないかなと思います。

2021-10-06 02:52:36
ほえほえ@スプシマン @hoehoe1234

④2)ーa)バリアントバインド配列ーByRef具象型 仮引数は同じ変数を求めますので厳密な一致が必要でありエラーとなります。

2021-10-06 02:57:05
ほえほえ@スプシマン @hoehoe1234

⑤2)-b)バリアントバインド配列ーByRefバリアント 推奨形式です。実引数と仮引数は同じバリアントですので同じ変数となります。実引数の配列を別名でアクセスできるイメージです。同じ変数とは変数名は違っても同じ領域が割り当てられた変数のことです。ポインタではないので注意してください。

2021-10-06 03:00:04
ほえほえ@スプシマン @hoehoe1234

⑥2)-C)バリアントバインド配列ーByValバリアント 実引数、仮引数ともにバリアントですがByValのために実引数と仮引数は別の変数となり配列のコピーが発生します。

2021-10-06 03:01:47
ほえほえ@スプシマン @hoehoe1234

①~⑥のパターンごとの挙動をみてきたとおり、配列を受け入れる関数の仮引数は「ByRef バリアント変数」一択となります。その他の指定は実質、制限のみ厳しくなり意味がありません。実態を正しく知ることにより、シンプルで適切な関数インタフェースを選択できるよい事例だと思います。

2021-10-06 03:03:51
ほえほえ@スプシマン @hoehoe1234

演習13です。Jag配列の作成となります。 pic.twitter.com/1hKvucN0du

2021-10-06 03:06:03
拡大
ほえほえ@スプシマン @hoehoe1234

Jag配列の説明です。配列の要素が配列である配列をJag配列といいます。2次元配列に似ていますね。相互変換も容易ですので目的に合わせて2次元配列とJag配列を使い分けていくとよいと思います。 pic.twitter.com/3DUx4a6Kqi

2021-10-06 03:07:59
拡大
ほえほえ@スプシマン @hoehoe1234

図中にあるように、内側の配列を「レコード型」として使う使い方もあります。本来はここに構造体が来るべきなのですが残念ながらエラーとなります。クラスのインスタンスもよい代替候補ですが1クラスモジュール、1クラスというかなり厳しい制限があります。

2021-10-06 03:09:27
ほえほえ@スプシマン @hoehoe1234

演習14です。extend関数を実装します。append関数は「配列の最後に要素を追加」、extend関数は「配列に他の配列の要素すべてを追加」という機能(抽象化)になります。たったこれだけの共通関数を作成することにより配列が劇的に使いやすくなります。 pic.twitter.com/2XZL4QRa1S

2021-10-06 03:11:32
拡大
ほえほえ@スプシマン @hoehoe1234

配列の論理的な位置とメモリ上での配置は行列が逆になっています。図のような2次元配列、arr(i, j)を考えてみます。iは行、jは列を表す変数です。青色の数字が配列の要素です。これを1~12の順で出力することを考えます。第一候補は①の二重forループになるでしょう。 pic.twitter.com/D67Y4nQv3U

2021-10-06 03:14:43
拡大
ほえほえ@スプシマン @hoehoe1234

様々な配列を受け入れる関数では、全要素をイテレートするには、配列の次元数を考慮するか、もしくはfor each文を使う必要があります。周知のようにfor each文を使うと縦方向にイテレートされます(1,5,9...4,8,12の順でイテレートされます)。

2021-10-06 03:16:35
ほえほえ@スプシマン @hoehoe1234

メモリ上の値を調べてみると、図右のようになっています。メモリ上では1,5,9...4,8,12の順番で値が格納されています。配列の値の横にi,jの値を追記すると低い次元数のiから先に変わっていっていることがわかります。 pic.twitter.com/6OPzDf5sEW

2021-10-06 03:18:28
拡大
ほえほえ@スプシマン @hoehoe1234

上位の変数(この場合j)の変わる単位をブロックとすると、メモリ上には列をブロックとして並んでいることになります。(不確かですが)VBAの仕様でも配列に対するfor eachはこのように動作すると書かれています。配列のfor eachは要素をメモリ順に出力しているだけなんですね。

2021-10-06 03:20:33
ほえほえ@スプシマン @hoehoe1234

for eachで出力される順番は、イテレータ(他の呼び方もあります)と呼ばれるものが規定しています。なのでオブジェクトの種類ごとにイテレート順は決まります。配列では低次元が先に変わる、すなわちメモリ順に出力されているんですね。

2021-10-06 03:22:24
ほえほえ@スプシマン @hoehoe1234

これは以前にも講義しましたが、配列の種別による初期値とredimによる挙動の説明です。コード番号(①~⑤)と左の赤い番号を対応しています。静的配列では①の宣言で赤枠で示した配列の実態まで確保されます。 pic.twitter.com/c7jxogy1Lr

2021-10-06 03:26:07
拡大
ほえほえ@スプシマン @hoehoe1234

動的配列では②の宣言で配列変数だけ確保されます。32ビットエクセルの場合は4バイト長の変数となります。この変数には配列構造体のアドレスが格納されます。参照型変数と同じしくみですね。そして、④のRedimで配列の実態が確保されます。 pic.twitter.com/mJQB76nSB7

2021-10-06 03:28:45
拡大
ほえほえ@スプシマン @hoehoe1234

バリアントバインド配列では③の宣言でバリアントを宣言し、⑤のRedimで配列の実態を割り当てます。動的配列と同じ仕組みですね。Dim宣言をせずいきなりRedim vari_arr(1 to 3)のようにすると動的配列になってしまうので注意してください。 pic.twitter.com/2xOX9npdnc

2021-10-06 03:33:45
拡大
ほえほえ@スプシマン @hoehoe1234

バリアント変数は「型」を含めて値をバインドできますので、Redimを行った時点で初めて配列型として認識されます。動的配列はRedimを行う前から(宣言時から)配列の実態はありませんが「配列型」という認識はされています。バリアントに空の配列をバインドすることによりこの問題は解決できます。

2021-10-06 03:35:39
ほえほえ@スプシマン @hoehoe1234

以上、今回は配列と仮引数、配列の実態というちょっとわかりにくい、調べにくいことを解説してみました。まだ3回目です。配列は本当に多彩な機能と要素がありますね。エクセルVBA全体に関わる重要な機能ですのでしっかりと理解しましょう。 おしまい。

2021-10-06 03:37:27