
前任者から引き継いだマクロファイルがあり、VBA初心者ながらコードを理解しようとしています。
質問は下記2行の記述についてです。(vはバリアント型変数です)
v=array(WorksheetFunction.Transpose(range("a1:a1000")), WorksheetFunction.Transpose(range("c1:c1000")))
v=WorksheetFunction.Transpose(v)
worksheets(2).cells(1,1).resize(1000,2)=v
1~2行目で、A1:A3とC1:C3を二次元配列として変数vに格納して、3行目で隣のシートに配列の中身をコピーしています。
なぜこういう形でTransposeを2回(1行目と2行目)かけると二次元配列になるのでしょうか?
いきなりv=array(range("a1:a1000"), range("c1:c1000"))じゃダメなんでしょうか。
Transposeは配列の行列を逆にする関数なんですよね。
2行目実行時点では変数vの中身は二次元配列が入っているので、
1行目実行時点では、それと行列が逆の二次元配列が入っているのかと思ったのですが、違いました。
1行目を実行しただけだと、変数vには要素数2個の一次元配列が格納されているようです。
それにTransposeをかけたら、2行×1列の二次元配列になりそうな気がするのですが、どうしてそうならないのでしょうか。
分かりにくい説明で申し訳ありません。
どなたかご教授いただけると幸いです。
No.4ベストアンサー
- 回答日時:
こんにちは。
私の解答は視点が違いますが、Transpose を多用するというのは、実際は、パターン化できれば良いかもしれませんが、思い出しながら、書くというのは、ちょっと面倒な気がします。
Transpose 関数というのは、縦のものを横にすると、2次元から1次元に落とす働きを持つ関数です。横のものを縦にすると1次元に変わるのが、Index関数です。このようなテクニックは、Ver.4時代に培われたもののようです。
<サンプルは、全て規模を縮小します。>
With Application
a = .Transpose(Range("A1:A10").Value) '縦を横にして1次元
b = .Index(Range("A1:J1").Value, 1, 0) '横を縦にして1次元
End With
これは、両方共1次元に変わります。
これについては、Ubound を使わなくても、一目瞭然だと思いますが……。
だから、一旦縦横を替えたものを、もう一度使えば、元の縦横に戻りながら、1次元のデータが得られるわけです。
以下は、配列ではありません。PCの性能にも依存してきますから、必ずしも、ベストではありませんが、ずっと変わらないまま残る関数テクニックと、時代とともに廃れてしまう書き方もあるような気がします。スピードを速めるために使ったテクニックもPCの性能が上がれば、不要なものもあります。
>v=array(range("a1:a1000"), range("c1:c1000"))
この場合は、このようにすればよいはずです。
Sub Test2()
v = Array(Range("A1:A10"), Range("C1:C10"))
v(0).Copy Range("A11")
v(1).Copy Range("B11")
End Sub
Sub Test3()
Set Rng = Union(Range("A1:A10"), Range("C1:C10"))
Rng.Copy Range("A11")
End Sub
なお、Transpose 等の関数の配列の限界数は、以前、書いたことがありますが、Ver. 2007にはなくなったように、Microsoft サポートでは読めますが、Transpose関数の限界数は、Ver.2007で、65,536(=2^16) まででした。現在、手元のExcel 2013で見る限りは、Transpose には、フルレインジ[Range("A1",Cells(Rows.Count,1)).Value ]まで扱っても問題は発生しません。
https://support.microsoft.com/ja-jp/help/166342/ …
> Transpose 関数というのは、縦のものを横にすると、2次元から1次元に落とす働きを持つ関数
やはり、そういうことなのですね!スッキリしました。
また、書いていただいたUNIONを使ったコードでちゃんと動くことも確認しました。シート上の行列をいったん配列へ格納するやり方は高速化テクニックとしてよく紹介されていますが、実際に動きが重くて困っているわけでもないのにわざわざ複雑なコードを採用する必要はないということですね。
すごく勉強になりました。ありがとうございます。ベストアンサーに選ばせて頂きます。
また何かありましたらよろしくお願いいたします。
No.3
- 回答日時:
No.1の補足に対して。
>なぜtransposeによって二次元に変わるのか?
私個人は変わったのはあくまで行・列であって、一次元が二次元に変わったとは思ってません。
1行目について言えばですけど。
配列の配列も結局は行・列が存在するものであって、それを一次元と言えるのでしょうか?
ちょっと疑問に感じました。
No.2
- 回答日時:
Transpose は、そういう動きをするもの・・・・と思うしかないかも
以下で、ステップ実行しながら、各変数がどのような配列になるか・・・
確認してみるしか・・・・
ちなみに、v2 と vC は同じになります
Sub t()
Dim vA As Variant, vB As Variant, vC As Variant
Dim v1 As Variant, v2 As Variant, v3 As Variant
v1 = Range("A1:A5").Value
v2 = Range("A1:B5").Value
vA = WorksheetFunction.Transpose(v2)
v3 = Range("B1:B5").Value
With WorksheetFunction
vB = Array(.Transpose(v1), .Transpose(v3))
vC = .Transpose(vB)
End With
End Sub
なお、Transpose には動作上限がある?みたいで、
以下での返信 2017/12/18 09:12:53 も併せて確認してみるとか
VBA で検索速度を早くする方法はありませんか?
https://detail.chiebukuro.yahoo.co.jp/qa/questio …
ありがとうございます。
そのままステップ実行したり、少しずつコードを変えて試したりしているので、変数の中身がどう動いていくかについては判明している状態です。
なぜそうなるのか?をきちんと理解したいなって思いました。
ただTransposeに上限があることは知りませんでした。今後このマクロを流用したりするかもしれないので、気を付けたいと思います。
ご回答ありがとうございました。
No.1
- 回答日時:
詳しい訳ではないですが。
>1行目を実行しただけだと、変数vには要素数2個の一次元配列が格納されているようです。
Excelのセルは行列が存在するので、1次元配列になる事はありません。
それは
Dim v As Variant
v = Range("A1:A5")
Debug.Print UBound(v, 1), UBound(v, 2)
結果: 5 1
行数が5、列数が1である事で検証出来ると思います。
UBound(v,2)を無視してUBound(v)としてしまえば1次元のように思うでしょう。
けど、
Debug.Print v(3)
ではエラーになり、
Debug.Print v(3, 1)
ではきちんと値を表示してくれます。
1行目でやっているのは、離れた列の値をそれぞれ行列入れ替えて結合しているのでは?
⇒範囲外のB列の値を省きたいが為に
Dim v As Variant
v = Array(WorksheetFunction.Transpose(Range("A1:A5")), WorksheetFunction.Transpose(Range("C1:C5")))
v = WorksheetFunction.Transpose(v)
Debug.Print UBound(v, 1), UBound(v, 2)
結果: 5 2
行数5、列数2になります。
なぜこうなるのか?
自分も疑問はありますが、Arrayによって仮想シートが作られている・・・みたいな?
仮にArrayでTransposeしなければ、値の取得には
Debug.Print v(0)(3), v(1)(3)
のようなジャグ配列(配列の配列)となり結果的にセルへの一括書き出しは難しくなりそう。
と、素人的にはみています。
正確な理由は経験豊富な方にお任せですかね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) エクセルのマクロでコピー後の貼り付け先を毎回指定したところにしたい 5 2022/08/12 10:47
- Visual Basic(VBA) ExcelVBAで質問です。離れた二次元配列を一つにしたい 4 2022/07/26 19:06
- Visual Basic(VBA) 複数csvを横に追加していくマクロについて 2 2023/04/25 09:19
- Visual Basic(VBA) Sheet1のA列にコードB列にメアド、Sheet2のB列にコード一覧とD列にメアド一覧があり、Sh 3 2022/10/19 11:57
- Excel(エクセル) 【困っています】VBA 追加処理の記述を教えてください。 1 2022/08/25 22:54
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- Visual Basic(VBA) 【ご教示ください】VBAの記述方法がわかりません。 2 2022/08/12 21:28
- Visual Basic(VBA) 【困っています2】VBA 追加処理の記述を教えてください。 2 2022/08/26 11:42
- Visual Basic(VBA) まとめシートから集計シートへA列のコードが一致したら1行コピーするマクロをネット上で見つけました。こ 1 2022/08/30 14:11
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列数式の解除
-
配列変数の添字が範囲外ですと...
-
2つ以上の変数を比較して最大数...
-
OutlookVBAでサブフォルダ一括作成
-
Excel-VBAで内臓のMINVERSE,MM...
-
配列数式って何ですか??
-
AES暗号にて、AES_set_encrypt_...
-
エクセルVBAの配列二重ループ処...
-
FORTRANのCOMMON文
-
VBA:配列の中で文字列が何番目...
-
友愛数を探すプログラム
-
VBA 1次元配列を2次元に追加する
-
subの配列引数をoptionalで使う...
-
C#イベントで作る変数の受け渡し
-
配列を任意の数値で埋める方法
-
重複するパターンの算出について。
-
VB6 配列を初期化したい
-
ビンゴ
-
Array配列の末尾に追加したい。
-
ListViewで、非表示列って作れ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
配列数式の解除
-
2つ以上の変数を比較して最大数...
-
VBA 1次元配列を2次元に追加する
-
特定のセル範囲で4文字以上入力...
-
subの配列引数をoptionalで使う...
-
VB6 配列を初期化したい
-
配列変数の添字が範囲外ですと...
-
2次元動的配列の第一引数のみを...
-
ListViewで、非表示列って作れ...
-
Excel-VBAの配列「Public Const...
-
for each の現在の配列ポインタ...
-
AES暗号にて、AES_set_encrypt_...
-
Dim は何の略ですか?
-
VBのFunctionで、配列を引数...
-
配列を任意の数値で埋める方法
-
verilogで配列の任意の8bitを取...
-
エクセルで最小値から0を除く方法
-
《エクセル2000》A列・B列の商...
-
配列内の内容を全て表示する方法
-
配列に同じ値を入れる方法
おすすめ情報
> Excelのセルは行列が存在するので、1次元配列になる事はありません。
「v = Range("A1:A5")」のように一続きのセル範囲をそのまま配列へ格納したら、たとえ一行であっても二次元配列になる、ということは一応理解しています。
私の載せたコードを試して頂くと分かるのですが、今回のように二つの範囲をArray()で配列へ入れると、V(1)(1)で値をとれるような配列の配列(一次元)になるのです。
そのこと自体は、Array()の動き方として不思議はないのですが、なぜtransposeによって二次元に変わるのか?というところを理解したいなと思いました。
ご回答ありがとうございました。
返信ありがとうございます。
vは行だけの配列でも、もしvの中の一要素が列をもっていたら、v自体を「二次元配列」と呼ぶべきということでしょうか・・?
「行列」で表現すると、シート上のデータは確かに行列だと思います。
が、1列ずつtranspose()をかけながらarray()でvに格納すると、各要素が「行」をもつ「一行の」配列になってます。
(ubound()は指定した次元が存在しないとエラーが返りますが、1行目ではubound(v,2)もubound(v(0), 2)も両方エラーになります。これが2行目ではubound(v, 2)は値が返るようになります。)
つまり「各要素が行をもつ行の配列」→「行列の配列」に変化した感じです。
なぜそうなるのか?と思い質問させていただきました。