ワクワクV056回目配列完全解説2回目(2021-09-11)

1
ほえほえ@スプシマン @hoehoe1234

ワクワクV056回目 2021-09-11 配列完全解説2回目 配列の情報を表示する演習です。さまざまな配列を受け入れるために仮引数は参照型バリアント変数としています。どうしてバリアントでなければいけないのか?はいづれ解説します。 pic.twitter.com/k2yxg4kGzT

2021-10-04 19:53:46
拡大
ほえほえ@スプシマン @hoehoe1234

配列の次元数を取得後、ループで各次元の下限、上限を取得します。全要素の表示はfor each構文を使用しています。これにより配列の次元数を気にすることなく簡易的に全要素を出力できます。次元数の低い(1次元側)から先にインデックスが変わることに注意してください。

2021-10-04 19:56:53
ほえほえ@スプシマン @hoehoe1234

1,2,3 4,5,6 とあれば1,4,2,5,3,6の順番で出力されます。これは配列をarr(i,j)とした場合、メモリ上にはiが先に変わるように並んでいるからです。(出どころは不明ですが、教えていただいた)仕様にもそのようなことが記載されています。

2021-10-04 19:58:16
ほえほえ@スプシマン @hoehoe1234

VBAの配列は要素にアクセスするために arr(i) arr(i,j) arr(i,j,k) のように次元数によりアクセスするための構文が固定されますので、とりあえず値を表示するだけならfor each構文を使うことで不要の複雑さを回避できます。

2021-10-04 19:59:32
ほえほえ@スプシマン @hoehoe1234

VBAでは変数が配列かどうかの判断にisArray関数が使えます。ただし、覚えておくことがあります。isArrayy関数中ではデフォルトプロパティを呼び出しているような挙動を示すことです。 pic.twitter.com/8zOxPYCVpn

2021-10-04 20:01:27
拡大
ほえほえ@スプシマン @hoehoe1234

具体的には、図にあるようにisArray関数の引数をレンジオブジェクトにするとレンジが配列として評価可能であればisArray関数はTrueを返します。isObject関数に同一のレンジを渡してもTrueになることからisArray関数内でデフォルトプロパティの起動がされている(だろう)ことがわかります。

2021-10-04 20:03:08
ほえほえ@スプシマン @hoehoe1234

多くの場合はこれで問題ありませんが、配列とオブジェクトを明確に区別する必要がある場合は   isArray(a_var) and not isObjct(a_var) とする必要があります。類似事例に  ?isMissing(array()) がTrueを返すという現象もあります。これについては別の機会に説明したいと思います。

2021-10-04 20:07:34
ほえほえ@スプシマン @hoehoe1234

ですからisArray関数では、実引数がオブジェクトの場合はデフォルトプロパティ(以下DP)があればDPが起動され、そのDPが配列を返せばisArray関数の戻り値はTrueになると覚えれば良いでしょう。このDPの起動についてもまた別の機会に説明したいと思います。

2021-10-04 20:09:35
ほえほえ@スプシマン @hoehoe1234

演習9は配列の種類と調査方法です。配列には3つの種類があります。 ①静的配列 図中fix_arr ②動的配列 図中dyn_arr ③バリアントにバインドした動的配列 図中var_arr となります。 ②と③はどちらも動的配列ですが挙動が違いますので当塾では③別立てし「バリアントバインド配列」呼んでいます。

2021-10-04 20:15:06
ほえほえ@スプシマン @hoehoe1234

配列を調査する関数は ①isArray関数 配列かどうか ②Join関数 配列の要素を結合 ③L/Ubound関数 配列の次元ごとの上限下限を取得 ④TypeName 変数の型を調査 となります。これらの関数を組み合わせることで配列の種類(型)、下限/上限、要素を表示することができます。

2021-10-04 20:18:44
ほえほえ@スプシマン @hoehoe1234

1次元配列の特殊の形としてジャグ配列があります。「配列の要素が配列という」配列です。2次元配列と似ていますね。ジャグ配列の要素を参照するにはarr(i)(j)と書きます。2次元arr(i,j)に似ていますね。 pic.twitter.com/BO8V0JyATs

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

ジャグ配列はコレクションの要素に配列を使った場合などと異なり、jag(i)(j)で要素の参照と書換ができます。jag(i)で配列のコピーが生成されず、jag(i)(j)で要素が書き換えられるのはとても便利です。2次元配列とは用途により使い分けられるようになりましょう。

2021-10-04 20:29:32
ほえほえ@スプシマン @hoehoe1234

空の配列が作れます。空の配列は要素のない配列です。からの配列を使うことにより、特殊な状態がなくなりますので配列を返す関数をうまく設計できます。 空の配列は下限0、上限1となり、要素数は上限ー下限+1ですので、要素数ゼロとなります。 pic.twitter.com/wk8BFwRLta

2021-10-04 20:35:25
拡大
ほえほえ@スプシマン @hoehoe1234

通常空の配列はarray関数に引数を指定しないことで作ります。Split関数に空文字列を指定することでも作れますが、戻ってくる配列がString()型になっています。多くのケースではarray関数の返すVariant()型のほうが使いやすいでしょう。

2021-10-04 20:37:00
ほえほえ@スプシマン @hoehoe1234

空の配列はredimで下限を修正できません。array関数の返す配列は下限がゼロなので下限1の空の配列を作ることはできません。ただし、Option base 1を指定すればそのモジュールではArray関数で下限1の配列を作成できますが、依然VBA.Array関数は下限ゼロのままです。どうしても下限1の空配列が

2021-10-04 20:39:11
ほえほえ@スプシマン @hoehoe1234

必要な場合はoption base 1、「VABと修飾のないarray関数」で作れますが空の配列は「要素がない」、すなわちfor eachで空振りループするところが重要ですのでoption base 1を使ってまで下限1の空配列をつくる場面は少ないのではないかと思います。

2021-10-04 21:53:48
ほえほえ@スプシマン @hoehoe1234

プログラミングでは「特殊な状態をなくす」ことは制御構造、データ構造の基本であり、習得すべき技法です。一般的には番兵とかダミーノードとか言われます。これがあることにより特殊な状態がなくなり、制御構造をシンプルかつエレガントに記述することができます。

2021-10-04 21:55:22
ほえほえ@スプシマン @hoehoe1234

関数が配列を帰す場合、返すべき要素がなければ空の配列を返すのがよい設計でしょう。なぜなら「要素がないが配列だから」です。ここで初期化されていない動的配列を返すと、(後日記事しますが)配列の実態がないために配列として機能しないことになってしまいます。

2021-10-04 22:30:49
ほえほえ@スプシマン @hoehoe1234

VBAでワークシート関数を値として設定し、かつ、スピルさせるにはFormula2プロパティを使用します。レンジの.Valueに配列を設定する場合はレンジを拡張しなければいけないので不便ですが、数式の場合はFormula2が使えるので便利ですね。最近まで知りませんでした。 pic.twitter.com/OOHhqXY655

2021-10-04 22:36:49
拡大
ほえほえ@スプシマン @hoehoe1234

evaluate/[{...}]を使って配列を生成できます。evaluate関数は[]と同じと言われていますが本当なのでしょうか?前者は文字列を処理し、後者は識別子を処理しているように見えます。それはさておき、[]記法(以下括弧記法といいます。)は「まるでセルに入力しているように入力」するとよいでしょう。 pic.twitter.com/HXwHsXOgOj

2021-10-04 22:41:37
拡大
ほえほえ@スプシマン @hoehoe1234

括弧の中は本当にセルに入力するようなイメージですので、先頭に「=」をつけても動くようです。 ①VBAで値をすべて記入 ②ワークシート関数をセルに代入 ③ワークシート上で新関数等により転記 様々なパターンがありますね。いずれ整理したいと思います。すべて配列とスピルが深く関わっています。

2021-10-04 22:46:55
ほえほえ@スプシマン @hoehoe1234

配列情報表示関数です。次元数、各次元数ごとの上限/下限、全要素の表示をしています。 pic.twitter.com/mPMoxJpOyl

2021-10-05 00:34:24
拡大
ほえほえ@スプシマン @hoehoe1234

配列リテラルはテスト用関数で特に便利ですね。一次元配列、N行1列、N行M列の配列を簡単につくれます。ただし、1行M列の配列はredim等で作成する必要があります。 pic.twitter.com/PkRgsOw6KI

2021-10-05 00:37:35
拡大
ほえほえ@スプシマン @hoehoe1234

繰り返しのことをイテレーションと言います。範囲(レンジ)と二次元配列は似ています。新関数によりシート上では範囲と配列をほぼ同一視することができます。しかし、for eachで使うとレンジは横に配列は縦に取得することになります。bbbbとbbbb2の違いに注目してください。

2021-10-05 00:45:48
ほえほえ@スプシマン @hoehoe1234

添付を忘れていました。範囲を配列に変換すると依然、同じイメージであり、 for i = for j = debug.print arr(i,j) であればレンジと同じ出力順となります。ですので配列のfor eachは「縦方向にイテレートする」と覚えると良いと思います。 pic.twitter.com/P6qFUquw7W

2021-10-05 00:48:22
拡大