2022/07/24

配列の行列入れ替え(Transposeメソッド)

二次元配列の行と列を入れ替える作業は意外と多くあります。例えば何行あるか分からないデータを配列に収めていく際には、ReDimで配列を拡大しながら値を代入していくことになりますが、拡大していく方向が「最後の次元のみ」であるため通常は「列方向を拡大」することになります。そうなると「行列の反転した配列に値を代入した後、配列を正常な行列の状態に戻す」作業が必要となり、それにTransposeを使うことになります。

但しTransposeを使う上では、以下の点に注意する必要があります。
 1.入れ替えた配列のインデックスは1から始まる。
 2.二次元配列を入れ替えると、一次元配列になる場合がある。
 3.入替え後に、データ型が変わってしまう型がある。またエラーが出るデータ型もある。
 4.要素内にNullやObject型がある場合は、Transpose実行時にエラーが出る。


1.インデックスは1から始まる

元の配列のインデックスとは無関係に、行列入れ替え後の配列は図1の右のように「インデックスは1始まり」となります。
行列入れ替え後はインデックスは1始まり
図1


2.単一列の二次元配列の入れ替え

元の配列が複数行×複数列の場合、行列入れ替え後の配列は図1のように「二次元配列」となります。また、単一行×複数列の二次元配列の場合も、入替え後は図2のように「二次元配列」となります。
単一行の二次元配列の入替え
図2


一方、単一列の二次元配列の場合、行列入れ替え後の配列は図3のように「一次元配列」になります。
単一列の二次元配列の入替え
図3


また、一次元配列に対してTransposeを実行すると、図4のように「二次元配列」となります。
一次元配列の入替え
図4


データベースなどからレコードを取得し「ReDimで配列を拡大しながら代入」していく方式で配列化する場合、取得するのが「複数レコード」の場合は図1のようになりますし、「単一レコード」だった場合は図3のようになります。
つまり「取得するレコード数によって、Transpose後の姿が二次元になったり一次元になったり」します。対応策としては、完成した配列の行数を確認して処理を分岐する方法が考えられます。またTransposeを使用せず、行と列が逆転した二次元配列のままで処理を流したり、またはタイトル行(空行でもOK)を必ず入れることで「単一レコードでも、配列は2行を確保」するような工夫も考えられます。

3.データ型の変化

「元の配列要素のデータ型」と「Transposeを使って行列入れ替えをした後の配列要素のデータ型」を並べたのが図5です。 縦軸が「元」、横軸が「変換後」になっています。
最も良いのが「変換前後でデータ型が変わらない」事だと思いますので、そのエリアを薄緑色にしています。
なお「Null」はデータ型ではありませんが、どの型にも当てはまらずに、しかもエラーを発生させるため載せています。
データ型の変化の対照表
図5


図5を見て「データ型が不変」なのは、「Boolean型」「String型」「Double型」のみです。
数値型である「Byte型」「Integer型」「Long型」「Single型」は、より精度の高い「Double型」になるので良しとしても、14バイトの「Decimal型」が8バイトの「Double型」になってしまうのは少し違う気がします。

また「Date型」は「String型」に変わってしまいます。例えば「2022/1/1」と日付型で入っていたものが「"2022/1/1"」と文字列型になってしまいます。このままでは日付の計算が出来ませんので、CDate関数などで日付型に戻してから処理するような事が必要です。
「Currency型(通貨型)」の場合も同じくString型ですが、「数値の前に『¥印』が付いた文字列」になってしまいます。後処理がより面倒そうです。

4.NullやObjectがあるとエラー発生

図5の、元の配列要素内に「Object」や「Null」が入っていると、Transpose実行時にエラーが発生します。Nullについては「Nullと分かっていて配列に入れる」という人は少ないと思います。しかし、例えばデータベースから抽出した値を配列に入れる場合、値が無い部分はNull値となっている場合があるため、気が付かないうちにNullが入る可能性があります。
ExcelにとってはNullは異質な部類に入るようで、ListBoxなどへ値をセットする場合もNull値があるとエラーが出てしまいますので、例えば「""(長さゼロの文字列)」に変換してから配列に入れるなどの工夫が必要です。

一方Objectについては、「別な配列に仮代入」しておきTranspose実行後に「正式代入」するくらいの手しか思い浮かびません。

アプリ実例

テキストデータのスケジュール帳
CSVファイルの読み込み
共有資料の登録と閲覧ができるサーバーシステム
先入先出の入出庫管理システム
先行予約可能な備品予約・貸出システム