• ベストアンサー

2次元配列について、教えてください。

基本的なことなのでしょうがまだよくわかっていません。 ワークシートにたとえると、1次元は縦方向(行番号方向)、二次元は横方向(列番号方向)ですよね? 列数、行数にあたるのが1次元、二次元それぞれの添字ですよね? そしてセルに当たるのが「要素」ですよね? 以上の解釈があっていたら、 1.A列やB列にあたるものはなんと呼ぶのでしょうか? 2.1行目や2行目にあたるのはなんと呼びますか? 3.ワークシートで行や列を削除するような感じで2次元配列の行や列にあたるものを削除することはできますか? 4.UBound関数は、配列の大きさを調べられますが、この大きさは添字です。ワークシートのCells(65536,1).End(xlUp)Rowのように実際にデータがどこまで入っているか調べられますか? 教えてください。 前提とした解釈自体が違っていたらそれもご指摘ください。

質問者が選んだベストアンサー

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答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

emaxemax
質問者

お礼

> VBAの配列を再確認するために、ここにご質問になったのですよね。 そうです。 なんどもありがとうございました。 ちょっと私にはまだ高度すぎたようです。

その他の回答 (8)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答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) 最後の行を切りだして、そして、その列を調べるということをしますが、通常、ループしながら調べる方法を取ります。

emaxemax
質問者

お礼

ご丁寧にありがとうございます。 > 配列を、[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のデータがループしてないのに入るのかも理解できませんでした。 ありがとうございます。

  • m_and_dmp
  • ベストアンサー率54% (974/1797)
回答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

emaxemax
質問者

お礼

ありがとうございました。

  • m_and_dmp
  • ベストアンサー率54% (974/1797)
回答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

emaxemax
質問者

お礼

そうでしたか。 一次元はあくまで長さという概念だから縦横は存在しないってことですね。 ありがとうございます。

  • MRT1452
  • ベストアンサー率42% (1392/3296)
回答No.5

> 1.2は配列でもやはり行や列でOkなんですね。 まぁ、そう認識しても問題ない。と言ったところかと。 人によってはX,Yとか言う人もいますし。 認識上、2次元配列は行列としてみても構わないという感じかな。 原則は質問4以降に書いたものなので。厳密には、行とか列とかいう固定的な呼び方は無いです。 おおよそ適正ではないかと思う呼び方であれば、「第○次元目の配列」という感じになるかと。 > 3.はその行を削除するのではなく中の要素を消去するだけで、下の行を繰り上げることはできないということでしょうか? その認識で良いです。 配列で、消した部分を詰めるなら、その処理を記述する必要があります。 > 4は不可ということですね? そうです。 UBound関数で要素数を取って、その跡にループ処理で、中身をチェックするという方法を取る必要があります。

emaxemax
質問者

お礼

丁寧に説明していただきよくわかりました。 2次元配列はワークシートに似てるけど、あくまで別物。 COUNTA関数のようなものでデータ数をひろうなんてことも不可。 やるなら全部の要素をループしてカウントする必要があるってことですね。 ありがとうございます。

  • m_and_dmp
  • ベストアンサー率54% (974/1797)
回答No.4

一次元は「線」、二次元は「面」、三次元は、「立体」と考えたらいいと思います。 三次元はエクセルシート上では展開しにくいので、二次元までとし、二次元はセルを横(列)方向にいくつか、縦(行)方向にいくつかとった、領域になります。 一次元は横または縦方向にいくつかとった領域になります。 VBAの場合は、シート上ではなく、数学的な仮想空間なので自由に三次元でも四次元でも考えることができます。 一つの要素からなる変数の例: hennsuu 一次元の変数の例: hennsuu(i) 二次元の変数の例: hennsuu(i,j) VBAではシートという制限がないので三次元も: hennsuu(i,j,k) 一次元の変数の要素は i 個あります。hennsuu(1), hennsuu(2), hennsuu(3) ..... 二次元の変数の要素は i x j 個あります。

emaxemax
質問者

お礼

わかりやすい説明をありがとうございます。 それで二次元配列の場合、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関数が必要になってしまいます。

  • layy
  • ベストアンサー率23% (292/1222)
回答No.3

エクセルで?、数学的?、プログラミング定義で?、 それぞれ調べると良いのでは?。 列、行、セル、X軸、Y軸、ベクトル、添え字、インデックス、・・・・等。 列=カラム(column)、綴りは間違えやすいです。 縦方向=row 横方向=column プログラムなどで、 xxケタ目を「xxカラム目」と言うことあります。 3の意味がわかりませんが、 どの言語だったか、 配列(3,4)をいったん配列(1,1)にして 配列(3,4)にし初期化を試みるようなことはありました。

emaxemax
質問者

お礼

ありがとうございます。 3の意味は、二次元配列でそのrowを削除して、下のrowを繰り上げることはできないかということです。

emaxemax
質問者

補足

> エクセルで?、数学的?、プログラミング定義で?、 ワークシートと書いたのですからエクセルのことです。

  • MRT1452
  • ベストアンサー率42% (1392/3296)
回答No.2

1 列(Row)です。 2 行(Calumn)です。 3 消すというよりはNULLにするという感じになるかと。 原則として、VBAでの変数は一度宣言すると、データの有無に関係なく、その領域を固定で確保します。 Redimによって配列数等の宣言しなおし等かのですが、これにも制約があり、シートのようには扱えない場合があります。 4 UBound関数は対象次元の配列の大きさを取得するだけなので、 中のデータがどこまで入っているかというのは、それだけでは調べられないでしょう。 基本的にシートと2次元配列は別個のものです。 ただ、考え方として、行列にすると判りやすいので、 参考書等では2次元配列は、行列の形で説明されている場合が多いというだけです。 配列変数はあくまで「配列」であって「行列」ではないので。 そのため、シート関連の命令と同じようなことをするには、ループや判定等でプログラムを組んでやる必要があります。 また、変数は構造体という概念もあるのでそういったものを活用します。 シート関連ははあくまでブック、シート、セルでしか扱うことは出来ません。

emaxemax
質問者

お礼

ありがとうございました。 1.2は配列でもやはり行や列でOkなんですね。 3.はその行を削除するのではなく中の要素を消去するだけで、下の行を繰り上げることはできないということでしょうか? 4は不可ということですね?

  • layy
  • ベストアンサー率23% (292/1222)
回答No.1

A1やA2やA3の1や2や3が添え字です。 配列とは? 何かをネットや用語辞書で探して見ましょう。

emaxemax
質問者

お礼

ありがとうございます。 でもそんなこと聞いてません。

関連するQ&A

  • 多次元配列はなぜ必要???

    なぜ多次元配列というものが必要なのでしょうか? 長さ10の1次元配列と、2行5列の2次元配列だと、記憶できる量は同じではないですか? よく2次元配列を表に例えて「表のように使います」と説明しているサイト等がありますが、 DBと違って配列は添え字でしか管理できないんだか、表のように考えるメリットもよくわかりません。 更にもっと謎なのが3次元以上の配列の存在です。 これは実際に使っている人はいるのでしょうか・・・?

  • 二次元配列が、勝手に一次元配列になってしまう

    Excelのマクロで、二次元配列を格納したバリアント型を戻り値とする関数を作ったのですが、… 二次元型配列のひとつの要素数が1の時、受け取ったバリアント型変数は、一次元配列になっています。 列ベクトルなら、それもありかな~と思うのですが、なんで、行ベクトルまで、一次元配列にするんだよ~って、困っています。 シートから関数を呼んだ場合は、列ベクトルは列ベクトル、行ベクトルは行ベクトルとして、表示されるので、マクロの中で関数を呼び出した場合も、行列の情報を保持できる方法があるんじゃないかと思ったのですが。 どなたか、ご教示頂けるとありがたいです。 よろしくお願いします。

  • textboxの二次元配列で質問

    textboxの二次元配列で質問 Visual Web Developer 2008を使いWebアプリケーションの入力フォームを開発中です。言語はVBです。  複数行のtextboxに入力された文字を連結する方法が分かりません。ネットでいろいろ検索して二次元配列をすれば可能なようですが、分かりやすく書いてあるサイトが見つからず、苦戦しています。列数は10列。行数は50行ぐらいあります。 ↓(サンプル)  例えば、下のような入力フォームのtextboxにあ・い・う・え・お・か・き……と入力された文字列で、buttonをクリックしたら「あいうえおかきくけこ…」と文字列の連結した実行結果を出したい場合です。       列   あ|い|う|え|お| | |   か|き|く|け|こ| | | 行 さ|し|す|せ|そ| | |   た|ち|つ|て|と| | |   な|に|ぬ|ね|の| | |    | | | | | | |    | | | | | | |    textboxが多いので、二次元配列と繰り返し処理(文字がなくなるまで繰り返す)を使って、簡単にできないでしょうか? 初心者なので分かりづらい質問で申し訳ありません。 参考になるページやコードがあったら教えて下さい。 よろしくお願いします。

  • 多次元配列(リファレンス)

    @dat=( [1,2,3], [4,5,6], [7,8,9]) という多次元の配列を作ったときに,$size=@datとすれば行列の行数が得られますが,列数を取得するためにはどうすればよいのでしょうか。 つまりこの場合$dat[0][0]に1が, $dat[0][1]に2が, そして$dat[0][2]には3が入っていますから,3という(列数の)値を取得したいのです。

    • ベストアンサー
    • Perl
  • 配列の列数を取得するには?

     いつもお世話になっております。  配列の行数を取得するには、ubound関数を使えば取得できますが、列数を取得するにはどうしたらよいのでしょうか。  よろしくお願いします。

  • 二次元配列のインデックスについて

    基礎的な質問かもしれませんが、ネットで調べたのですが、うまく回答が見つからなかったので、教えて下さい。 VB.netで二次元配列を扱っているのですが、この要素はどこにあるのかを知りたいのです。 一次元配列でしたら、Indexof を使えば、どこのインデックスに配置されているかが分かると思うのですが、 二次元配列の場合は、どうすればインデックス数が分かるのでしょうか。 例えば、列は0で固定だけど、どこの行にこの要素が格納されているか分からないから、行番号を知りたいと言うときです。 よろしくお願いいたします。

  • 動的に多次元配列を使用したい

    動的に多次元配列を使用したい お世話になります。 adobe flash professional :ActionScript 3.0 を使用しています。 例えば、 [ア][あ] [イ][い] [ウ][う] ・ ・ ・ の、x行・2列の動的な多次元配列を使用したいのですが、 動的な多次元配列の作成の仕方を教えて頂けないでしょうか? お手数ですがよろしくお願いします。

    • ベストアンサー
    • Flash
  • 1次元配列をワークシートに高速で転記する方法について質問します。

    1次元配列をワークシートに高速で転記する方法について質問します。 エクセル2000です。 1000万までの範囲で素数を抽出したいと思いました。 そこで下記のようなコードを書きました。 最初は配列にいれず一個ずつセルに転記させたところ664,579個の素数抽出に1分37秒かかったので、配列を用意して下記のようにしたところ1分15秒まで短縮されました。 質問1:配列を使った割には劇的に短縮されないのはなぜでしょうか? 質問2:下記のコードでは最初に取り込んだ1次元外配列をシートに貼るために2次元に変換する際、2次元方向(列)は256で固定、1次元方向(行)は計算で求めたのですが、その結果、要素数が合わず、後の方のデータがない部分が0とシートに出てしまいます。 こうならない方法がありますか? 質問3:一次元配列をワークシートに配置するため二次元配列に変換するのに、もっと良い方法があったらご教示ください。 質問4:配列をワークシートに転記する場合   Application.ScreenUpdating = False   Application.Calculation = xlCalculationManual はあってもなくとも速度に変化がありませんでした。このような貼り付け(配列から一度に転記)には不要なのでしょうか? たくさん質問して申し訳ありません。 宜しくお願いいたします。 Sub test()   Dim t As Date   Dim a As Long, b As Long, c As Long, Num As Long, r As Long, i As Long, x As Long, y As Long   Dim buf As Boolean   Dim myPrm() As Long, myRng() As Long      t = Now()   c = 0   For Num = 2 To 10000000     a = Int(Sqr(Num)) '平方根算出     buf = True     For b = 2 To a '除数       If Num Mod b = 0 Then '割切れたら         buf = False '素数じゃない         Exit For       End If     Next b     If buf Then '割切れなかったら       ReDim Preserve myPrm(c) '添字追加       myPrm(c) = Num       c = c + 1 '素数カウント     End If   Next Num      r = Application.WorksheetFunction.RoundUp((UBound(myPrm) + 1) / 256, 0) '必要行数取得   ReDim myRng(1 To r, 1 To 256) '2次元配列のサイズ変更      For i = LBound(myPrm) To UBound(myPrm) '2次元配列に格納     x = IIf((i + 1) Mod 256 = 0, 256, (i + 1) Mod 256)     y = Application.WorksheetFunction.RoundUp((i + 1) / 256, 0)     myRng(y, x) = myPrm(i)   Next i      Application.ScreenUpdating = False   Application.Calculation = xlCalculationManual   Cells(1, 1).Resize(r, 256).Value = myRng() 'セル範囲に転記   Application.Calculation = xlCalculationAutomatic   Application.ScreenUpdating = True      MsgBox c & "個抽出しました。" & vbNewLine & "所要時間:" & Format(Now() - t, "hh:mm:ss") End Sub

  • 2次元配列を部分的に削除する方法

    VBAで配列のデータを部分的に削除してその削除した後のデータを前に詰めたいのです 配列のデータ 001 X 002 Y ←この行を削除した配列にしたい 003 Z 削除後の配列データ 001 X 003 Z こんなイメージなのですが、配列の削除して前につめるという処理はどのように すればいいでしょうか? 1行で実現できるような配列処理用のメソッドがあるのでしょうか? 2次元配列を行削除して前につめる処理なのですがアドバイス下さい

  • 多次元配列の意味がわかりません。

    プログラミング初心者です。 以下の配列の記述があったのですが、どのような配列なのか理解できていません。 すみません。教えていただけますでしょうか。 $n = count($entry_count); for($i=0;$i<$n;$i++){ for($j=$n-1;$j>$i;$j--){ if分が続きます。 } } 私の理解が間違っていなければ、iは行数jは列数と理解しています。 $nが何を示しているのか推測でしか言えませんが、列数と考えれば良いでしょうか? それともデータの件数と考えれば良いでしょうか? 内容はjの初期値がn-1(件数よりマイナス1)として、iより大きい間、jを1つずつ減らしていき iは1つずつ足していく様です。 分からないのは以下の点です。 ・$nはデータの件数でしょうか?  もしそうであればiは始めのfor分はその件数分繰り返すと考えると分かります。  但し、jはどのように理解すれば良いか分かりません。 ・$jがもし列数と考えれば、なぜ初期値が$jの値がマイナス1なのか。  配列のインデックスが0から始まるからでしょうか? ・$jをなぜ1つずつ減らしていくのでしょうか?  列数を1つずつ減らしていくというのは、そのデータの列を前から読み込んでいくという処理の  意味の記述でしょうか? 要するにiとjが何かが理解できていません。 よろしくお願いいたします。

    • ベストアンサー
    • PHP

専門家に質問してみよう