
基本的なことなのでしょうがまだよくわかっていません。
ワークシートにたとえると、1次元は縦方向(行番号方向)、二次元は横方向(列番号方向)ですよね?
列数、行数にあたるのが1次元、二次元それぞれの添字ですよね?
そしてセルに当たるのが「要素」ですよね?
以上の解釈があっていたら、
1.A列やB列にあたるものはなんと呼ぶのでしょうか?
2.1行目や2行目にあたるのはなんと呼びますか?
3.ワークシートで行や列を削除するような感じで2次元配列の行や列にあたるものを削除することはできますか?
4.UBound関数は、配列の大きさを調べられますが、この大きさは添字です。ワークシートのCells(65536,1).End(xlUp)Rowのように実際にデータがどこまで入っているか調べられますか?
教えてください。
前提とした解釈自体が違っていたらそれもご指摘ください。
No.9ベストアンサー
- 回答日時:
#8の回答者です。
コードは基本的な間違いがありましたので、修正しました。
もう一度、見ていただけますか?MaikingMatrix等で、少なくとも10行×8列以上の行列を出しておいてから、試してみてください。
'//
Sub Test1R()
'配列を抜き出す修正版
Dim ar, x, y, i, j
Dim ar1
Dim ary
ar = Range("A1").CurrentRegion
ReDim arx(1 To UBound(ar, 1))
'行
j = 1
For i = 1 To UBound(ar, 1)
If i <> 5 Then '5行目を省く
arx(j) = i
j = j + 1
End If
Next
ReDim ary(2, 0)
'列抜き出し
ary(0, 0) = 1
ary(1, 0) = 3
ary(2, 0) = 5
ar1 = Application.Index(ar, arx, ary)
ar1 = Application.Transpose(ar1)
x = UBound(ar1, 1)
y = UBound(ar1, 2)
Range("A15").CurrentRegion.ClearContents
Range("A15").Resize(x - 1, y).Value = ar1
End Sub
>なぜar1に配列arのデータがループしてないのに入るのかも理解できませんでした。
なぜかというのはブラックボックス化して分かりませんが、これは、古いExcelのVer.4 のマクロの名残りのテクニックです。マクロ関数が配列を排出しますので、それと同時に使われた関数を、利用出来るのではないかと、私が考えました。今では、TRANSPOSEなどの新しい関数が頻繁に用いられますが、古くからあるINDEX関数の他にも、COLUMNS、ROWS関数というものが、使われることがあります。
他には、VBA関数のFilter 関数、Join関数、Split関数などが扱われます。これらは、2次元配列は用いられません、1次元配列のみです。上手に、ワークシート関数を用いれば、便利なツールになるものだと思います。
ところで、話は戻りますが、VBAの配列を再確認するために、ここにご質問になったのですよね。こうした些末な情報は、返って混乱にはなるかとは思いましたが、配列は、私にとって研究課題です。
実際に、仕事の時のプログラミングでコードを書くときは、こういうテクニックを頻繁に使うことはハバカられますが、試しで使うには良いことだと思います。実務上では、意外に正攻法なコードしか書かないものです。二次元の動的配列まで使えれば、配列は卒業です。その後を研究している人はあまりいませんが、仮に、ワークシート関数が使えるとか、使えないかとかいう話は、裏技にしか過ぎません。しかし、今後将来、再び、このテクニックは出会うことになります。
4は、Small関数を使って、並べ替えしていますが、5は、.Net を使った並べ替えの技術です。
'//
Sub Test4()
'並べ替え
Dim ar, arx(1 To 10)
ar = Range("A1:A10").Value
ar = Application.Transpose(ar)
For i = 1 To 10: arx(i) = i: Next i
ar = Application.Small(ar, arx)
Range("A15").Resize(10, 1) = Application.Transpose(ar)
End Sub
Sub Test5()
'並べ替え
Dim AL As Object
Dim i As Long
Set AL = CreateObject("System.Collections.ArrayList")
For i = 1 To 10
AL.Add Cells(i, 1).Value
Next i
AL.Sort
Range("A15").Resize(10, 1) = Application.Transpose(AL.ToArray)
End Sub
> VBAの配列を再確認するために、ここにご質問になったのですよね。
そうです。
なんどもありがとうございました。
ちょっと私にはまだ高度すぎたようです。
No.8
- 回答日時:
私も、少し、書かせていただきます。
前回の話の続きというか、私の前回のコードの説明になりますが、一部の方と回答とは違います。
1,2
>ワークシートにたとえると、1次元は縦方向(行番号方向)……
行列(Matrix)というのは、言葉どおり「行」と「列」ですが、概念として逆だったと思います。
配列を、[For Each in 配列]で、ループすると、縦に進んでいきます。行は、縦(Vertical)、列は、横(Horizontal)です。数学の概念を持ち込むとややこしいので、VBAでは、一般的には、1次側、2次側と読んでいることが多いです。
ただ、Excelの場合は、ワークシートから取ると、ジャグ配列という、特殊な配列構造になってしまいます。あまり、気にする必要はありません。
>3.ワークシートで行や列を削除するような感じで2次元配列の行や列に……
ExcelとVBAでは厳密には違ってきますが、ふつうは、ループして、もうひとつ別の配列に入れて上げます。下を切るのは、Redim Preserve で可能です。Index 関数を使って切り出すことも可能です。
Sub MakingMatrix()
'行列を作る
Dim r
Set r = Range("A1").Resize(10, 8)
With r
r.Formula = "=RANDBETWEEN(1,99)"
r.Value = r.Value
End With
End Sub
'---------
Sub Test1()
Dim ar, x, y
Dim ar1
Dim ary
ar = Range("A1").CurrentRegion
ReDim arx(1 To UBound(ar, 1))
'行
For i = 1 To UBound(ar, 1)
If i <> 5 Then '5行目を省く
arx(i) = i
End If
Next
ReDim ary(2, 0)
'列抜き出し
ary(0, 0) = 1
ary(1, 0) = 3
ary(2, 0) = 5
ar1 = Application.Index(ar, arx, ary)
ar1 = Application.Transpose(ar1)
x = UBound(ar1, 1)
y = UBound(ar1, 2)
Range("A15").CurrentRegion.ClearContents
Range("A15").Resize(x, y).Value = ar1
End Sub
行を、ひとつ(5行目)を抜き、列(1,3,5)を抜き出す
>4.UBound関数は、配列の大きさを調べられますが、……実際にデータがどこまで入っているか調べられますか?
Sub Test3()
Dim ar As Variant, x, y
ar = Range("A1").CurrentRegion
x = UBound(ar, 1)
y = UBound(ar, 2)
End Sub
2次元配列では、空のデータとの区別は付きません。
>COUNTA関数のようなものでデータ数をひろうなんてことも不可。
そういうことではなくて、2次元配列だから、ダメのなのです。
一旦、1次元配列に変換しないと分かりません
Transpose 関数や、Index 関数で、1次元配列を抜き取ります。
配列を扱えるワークシート関数なら、扱うことは出来ます。例えばMatcht関数などは良く用いられます。
Dim ar, ret
ar = Range("A1:A100").Value
ar = Application.Index(ar, 0, 1)
ar = Application.Transpose(ar)
ret = Application.Match(10 ^ 10, ar, 1) '最終行を探す
Test1 の場合、
ar2 = Application.Index(ar1, 0, 1)
ar2 = Application.Transpose(ar2)
j = Application.CountA(ar2)
最後の行を切りだして、そして、その列を調べるということをしますが、通常、ループしながら調べる方法を取ります。
ご丁寧にありがとうございます。
> 配列を、[For Each in 配列]で、ループすると、縦に進んでいきます。
知りませんでした。
Sub 進行方向確認()
Dim V, a
V = Range("A1:C3").Value
For Each a In V
MsgBox a
Next
End Sub
としたらそのとおりでした。
> 行を、ひとつ(5行目)を抜き、列(1,3,5)を抜き出す
Sub Test1()をそのまま実行したところ、列(1,3,5)は抜き出されましたが、5行目は1行目のデータに入れ替わったみたいで行数には変更がありませんでした。
ar1 = Application.Index(ar, arx, ary) でなぜar1に配列arのデータがループしてないのに入るのかも理解できませんでした。
ありがとうございます。
No.7
- 回答日時:
すみません、間違えました。
あれでは、横配列になります。コードの6行目を訂正しました。
Sub 一次元配列TEST()
Dim tmp As Variant
tmp = Split("A,B,C,D", ",")
i = 0
Do While i < 4
Cells(i + 1, 1) = tmp(i)
i = i + 1
Loop
'Range("A1:D1").Value = tmp '正しく転記
'Range("A1:A4").Value = tmp 'Aのみ4つ転記
End Sub
No.6
- 回答日時:
4個の要素で構成されるデータがあるとしまして、エクセルシート上に、A1,B1,C1,D1に配置してもA1,A2,A3,A4,に配置しても一次元です。
4個の要素を、
A1,B1
A2,B2
に配置するなら二次元配列です。
VBA上で、区切りのある文字列をSplit関数で処理すると、複数の要素を持つ一次元配列になります。このとき、VBA上では数学的仮想空間なので、縦(行)方向とか、横(列)方向とかの性質はありません。
貴殿は、シート上で縦方向に配列するのが一次元、横方向に配列するのが二次元と理解されていますので、Splitの戻り値が一次元配列になるのだから、ワークシート上で縦に配列すると、正しく分離された要素が表示されると考えていらっしゃることが分かりました。(質問の意味が分かりました。)
しかし、先にも述べたとおり、VBA上では縦横の性質を持ちませんので、配列をシート上に投影したとき縦にするか横にするかはVBAのコードで決めるしかありません。
貴ご呈示のサンプルを次のようにしてみました。
Sub 一次元配列TEST()
Dim tmp As Variant
tmp = Split("A,B,C,D", ",")
i = 0
Do While i < 4
Cells(1, i + 1) = tmp(i)
i = i + 1
Loop
'Range("A1:D1").Value = tmp '正しく転記
'Range("A1:A4").Value = tmp 'Aのみ4つ転記
End Sub
No.5
- 回答日時:
> 1.2は配列でもやはり行や列でOkなんですね。
まぁ、そう認識しても問題ない。と言ったところかと。
人によってはX,Yとか言う人もいますし。
認識上、2次元配列は行列としてみても構わないという感じかな。
原則は質問4以降に書いたものなので。厳密には、行とか列とかいう固定的な呼び方は無いです。
おおよそ適正ではないかと思う呼び方であれば、「第○次元目の配列」という感じになるかと。
> 3.はその行を削除するのではなく中の要素を消去するだけで、下の行を繰り上げることはできないということでしょうか?
その認識で良いです。
配列で、消した部分を詰めるなら、その処理を記述する必要があります。
> 4は不可ということですね?
そうです。
UBound関数で要素数を取って、その跡にループ処理で、中身をチェックするという方法を取る必要があります。
丁寧に説明していただきよくわかりました。
2次元配列はワークシートに似てるけど、あくまで別物。
COUNTA関数のようなものでデータ数をひろうなんてことも不可。
やるなら全部の要素をループしてカウントする必要があるってことですね。
ありがとうございます。
No.4
- 回答日時:
一次元は「線」、二次元は「面」、三次元は、「立体」と考えたらいいと思います。
三次元はエクセルシート上では展開しにくいので、二次元までとし、二次元はセルを横(列)方向にいくつか、縦(行)方向にいくつかとった、領域になります。
一次元は横または縦方向にいくつかとった領域になります。
VBAの場合は、シート上ではなく、数学的な仮想空間なので自由に三次元でも四次元でも考えることができます。
一つの要素からなる変数の例: hennsuu
一次元の変数の例: hennsuu(i)
二次元の変数の例: hennsuu(i,j)
VBAではシートという制限がないので三次元も: hennsuu(i,j,k)
一次元の変数の要素は i 個あります。hennsuu(1), hennsuu(2), hennsuu(3) .....
二次元の変数の要素は i x j 個あります。
わかりやすい説明をありがとうございます。
それで二次元配列の場合、1次元は縦方向、二次元は横方向ですよね?
ところが
Sub 一次元配列TEST()
Dim tmp
tmp = Split("A,B,C,D", ",")
Range("A1:D1").Value = tmp '正しく転記
Range("A1:A4").Value = tmp 'Aのみ4つ転記
End Sub
のように一次元配列をワークシートにそのまま転記すると2次元方向にしないといけないのが不思議です。
1次元方向にうるにはTranspose関数が必要になってしまいます。
No.3
- 回答日時:
エクセルで?、数学的?、プログラミング定義で?、
それぞれ調べると良いのでは?。
列、行、セル、X軸、Y軸、ベクトル、添え字、インデックス、・・・・等。
列=カラム(column)、綴りは間違えやすいです。
縦方向=row
横方向=column
プログラムなどで、
xxケタ目を「xxカラム目」と言うことあります。
3の意味がわかりませんが、
どの言語だったか、
配列(3,4)をいったん配列(1,1)にして
配列(3,4)にし初期化を試みるようなことはありました。
No.2
- 回答日時:
1
列(Row)です。
2
行(Calumn)です。
3
消すというよりはNULLにするという感じになるかと。
原則として、VBAでの変数は一度宣言すると、データの有無に関係なく、その領域を固定で確保します。
Redimによって配列数等の宣言しなおし等かのですが、これにも制約があり、シートのようには扱えない場合があります。
4
UBound関数は対象次元の配列の大きさを取得するだけなので、
中のデータがどこまで入っているかというのは、それだけでは調べられないでしょう。
基本的にシートと2次元配列は別個のものです。
ただ、考え方として、行列にすると判りやすいので、
参考書等では2次元配列は、行列の形で説明されている場合が多いというだけです。
配列変数はあくまで「配列」であって「行列」ではないので。
そのため、シート関連の命令と同じようなことをするには、ループや判定等でプログラムを組んでやる必要があります。
また、変数は構造体という概念もあるのでそういったものを活用します。
シート関連ははあくまでブック、シート、セルでしか扱うことは出来ません。
ありがとうございました。
1.2は配列でもやはり行や列でOkなんですね。
3.はその行を削除するのではなく中の要素を消去するだけで、下の行を繰り上げることはできないということでしょうか?
4は不可ということですね?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 複数csvを横に追加していくマクロについて 2 2023/04/25 09:19
- Visual Basic(VBA) VBA 検索と入力 Excel ブック ぶぶぶ シート ししし 列V 検索対象の列です 最終行は、お 6 2023/05/17 01:40
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- Visual Basic(VBA) 列と行の名前(重複あり)が交差するセルに、データを入力したい 2 2022/06/25 22:42
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Excel(エクセル) エクセルの条件付き書式 個人シートを参照して集計シートに色付けしたい 1 2023/06/22 00:39
- Visual Basic(VBA) VBAで最新のデータを別シートに転記する方法をお教えください。 3 2022/04/07 19:20
- Visual Basic(VBA) フォルダの場所を可変にしたいです(マクロ) 4 2023/05/11 10:00
- Perl perlで2次元配列をサブルーチンに値渡しで渡す 5 2022/12/17 18:49
- Visual Basic(VBA) 数字が「0」の列を削除するため、下記のコードを実行しましたが、コンパイルエラーSubまたはFunct 3 2022/12/04 00:00
関連するカテゴリから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列の商...
-
配列内の内容を全て表示する方法
-
配列に同じ値を入れる方法
おすすめ情報