• ベストアンサー

Excel VBA 配列の分割について

Excel VBAでコーディングしていますが 行き詰っているのでお助け下さい。 (1)二次元配列に格納されている値の中から 特定の値が格納されている位置をループを使わず 取得したいのですがその方法が分かりません。 <例>  Dim x(2,2) As Valiant   x(0,0) = "あああ"   x(0,1) = "いいい"   x(0,2) = "ううう"   x(1,1) = "えええ"      ・      ・      ・ この配列から"えええ"が格納されている位置をループを使わず 取得する方法を教えてください。 ⇒ 1, 1 (2)二次元配列の指定した列(?)を一次元配列に 格納する方法も重ねて教えてください。 以上、よろしくお願いします。

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

  • ベストアンサー
回答No.5

(1)について 最低限、列のループは必要ですが、下記のコードを試して下さい。 Sub Test() '配列セット Dim x(2, 4) As Variant x(0, 0) = "A": x(0, 1) = "B": x(0, 2) = "C": x(0, 3) = "D": x(0, 4) = "E" x(1, 0) = "F": x(1, 1) = "G": x(1, 2) = "H": x(1, 3) = "I": x(1, 4) = "J" x(2, 0) = "K": x(2, 1) = "L": x(2, 2) = "M": x(2, 3) = "N": x(2, 4) = "A" '列をループして検索 Dim i As Integer Dim m As Long Dim c As New Collection On Error Resume Next For i = 1 To UBound(x, 2) + 1 Err = 0 m = Application.Match("A", Application.Index(x, 0, i), False) If Err = 0 Then c.Add i & "," & m Next On Error GoTo 0 '結果表示 For i = 1 To c.Count If MsgBox("列,行=" & c(i), vbInformation + vbOKCancel, i & "/" & c.Count) = vbCancel Then Exit For Next End Sub

san2228405
質問者

お礼

お礼が遅くなり申し訳ありません。 上記の方法を利用したところ 思う通りのパフォーマンスを実現出来ました。 アドバイスありがとうございます。

その他の回答 (4)

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.4

(1) について。 > 二次元配列に格納されている値の中から特定の値が格納されている > 位置をループを使わず取得したい 無理ですね... 現状のコードは? もともとの配列はどのように生成しているのですか? 配列のソースがセルなら Find が使えますし...データソースによっては 改善策があるかも。 (2) について。 > 配列が100×20,000と大きな配列なので... 20,000項目のデータが100レコードとは考えにくいので、 100項目のデータが20,000レコードと考えてよろしいですか? ワークシート関数を VBA で利用します。 書式) Application.Index(配列, RowIndex, ColumnIndex) Sub Sample()   Dim Buf(20000, 100) As Variant   Dim Array2D   As Variant   Dim Array1D   As Variant   ' // サンプルデータをセット   Buf(20000, 100) = "TEST"   ' // Index 関数で100列目を切り抜く   ' // ※ 1オリジンで考え、ColumnIndex には101を指定   Array2D = Application.Index(Buf, 0, 101)   ' // Index 関数により1列のみの2次元配列となる   MsgBox Array2D(20001, 1)   ' // これをさらに Transpose 関数で1次元配列化   Array1D = Application.Transpose(Array2D)   MsgBox Array1D(20001) End Sub ただし、Index 関数の制約で Excel2000 の場合、要素数が5461個 までの配列にしか使えません。Excel2002 以降ではこの制限が大幅 に改善されましたが... なお、Index 関数で切り抜かれる配列はソース配列が 0 オリジンで あっても必ず 1 オリジンになります。これは Index 関数がワーク シート関数であるが故です。 ※ RowIndex も ColumnIndex も 1 から始まる。

san2228405
質問者

お礼

お礼が遅くなり申し訳ありません。 教えて頂いた方法で 二次元配列を一次元配列に格納することが出来ました。 ありがとうございます。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.3

こんばんは。 >この配列から"えええ"が格納されている位置をループを使わず取得する方法を教えてください。 ⇒ 1, 1 純粋に、プログラムで解決するなら、ループしかありません。 >本来であればOracleやせめてAccessで処理をしたいのですが >仕様上Excelでの処理しか出来ないもので悩んでいます。 元のデータは何かにもよりますね。Excelからでも、ADO は、使えるはずです。 100×20,000 なら、一旦、Excelに書き出して、AdvancedFilter という方法もあります。

san2228405
質問者

お礼

お礼が遅くなり申し訳ありません。 >>Excelからでも、ADO は、使えるはずです。 SOX法対応としてDBへの接続は禁止されておりまして。。。 やはり一度Excelに書き出すべきでしょうか。

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.2

No.1です。 回答してから気づいたのですが、Excel2003まででは、列の最大値は256で、行の最大値は65536なので、それを超える大きさの配列ではNo.1のやり方ではできません。(Excel2007では範囲は拡張されてますが) ループを使いたくない、ということはけっこう大きな配列なのですかね…。

san2228405
質問者

お礼

ご回答ありがとうございます。 当方の環境はExcel2000なのですが、 ご推測の通り配列が100×20,000と大きな配列なので パフォーマンスの観点からセルの利用・ループは避けたいと 考えています。 こう言った背景から、(2)の質問のようにMatch関数を 上手く使う方法もあるのかな?とも思った次第です。 本来であればOracleやせめてAccessで処理をしたいのですが 仕様上Excelでの処理しか出来ないもので悩んでいます。 引き続きご教授願えれば幸いです。

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.1

あまりスマートなやり方ではないかもしれなないですが、(1)だけ。 配列をいったんセルに格納して、Findメソッドで検索してみてはいかがでしょうか。 以下はサンプルです。dummyという名前のシートを作って、マクロを実行してみてください。dummyシートが目障りなら非表示にしておけばいいでしょう。 Sub Test()  Dim TmpRng As Range, R As Range  Dim x(2, 2) As Variant  Dim i As Integer, j As Integer  Dim SearchStr As String    x(0, 0) = "あああ"  x(0, 1) = "いいい"  x(0, 2) = "ううう"  x(1, 0) = "えええ"  x(1, 1) = "おおお"  x(1, 2) = "かかか"  x(2, 0) = "ききき"  x(2, 1) = "くくく"  x(2, 2) = "けけけ"  SearchStr = InputBox("検索する文字を入力してください")    Set TmpRng = Worksheets("dummy").Cells(1, 1).Resize(3, 3) '配列を格納するセル  TmpRng.ClearContents '念のため格納先のセルをクリア  TmpRng.Value = x 'セルに配列を代入    Set R = TmpRng.Find(What:=SearchStr, LookAt:=xlWhole) 'セル範囲から値を検索  If Not R Is Nothing Then   i = R.Row - 1   j = R.Column - 1   MsgBox ("x(" & i & "," & j & ") = " & SearchStr)  Else   MsgBox ("配列xに「" & SearchStr & "」はありません")  End If End Sub

関連するQ&A

  • VBAでエクセルのいくつかの表を同じ配列に格納する

    VBA初心者です。 調べてみましたがどうにも情報に行きあたらなく、ご質問をさせていただきます。 添付のようなエクセル上の同一シート上にある3つの表をコピーし、VBAで同じ配列の各列として取り込みをしたいと考えております。 大分類、中分類、小分類のそれぞれの行は同じもののそれぞれの内容を記載しており、 できればこれらを同じ配列の1列目、2列目、3列目に格納をしたいと思っております。 これらの表が1つの表にまとまっていれば、 Dim 配列(1,10) as Variant 配列 =range("A1:C10") で事足りると思うのですが、別々のためこの方法がとれません。 セル指定で行うことも考えましたが、データが10万行を超える場合もあるため、できれば避けたいと思っています。 各表を指定し、配列の1列目、2列目、3列目に一括して代入をご存じでしたらら、どうぞ教えていただきたいと思います。 どうぞよろしくお願いします。

  • 二次元配列のVBA

    二次元配列のVBAの書き方がよくわからないのですが、 私が作ったサンプルプログラムのSub 二次元()において 二次元配列で表すにはどうすればいいのでしょうか? Sub 二次元()では 配列を格納する変数はtmpしか使っていませんが もう一つ配列を格納する用の変数を作ればいいのでしょうか? 数字とアルファベットは別々に取り出したいです。 ----------------------------------------------------- Sub 一次元() Dim myStr As String Dim tmp As Variant Dim i As Long For i = 1 To 5 myStr = myStr & "," & i Next myStr = Mid(myStr, 2) tmp = Split(myStr, ",") For i = LBound(tmp) To UBound(tmp) Debug.Print tmp(i) Next i End Sub Sub 二次元() Dim myStr As String Dim tmp As Variant Dim i As Long For i = 1 To 5 myStr = myStr & "," & i & "と" & Chr(64 + i) Next myStr = Mid(myStr, 2) tmp = Split(myStr, ",") For i = LBound(tmp) To UBound(tmp) Debug.Print tmp(i) Next i End Sub

  • VBAの動的配列について

    いつもお世話になっております。 エクセルVBAを学習中の者です。 動的配列についてお伺いします。 添付資料を見て頂きたいのですが、 シート名1~4に同一レイアウトの表があります。 これらの表をを2次元配列に格納し、その後、同一レイアウトのシートに一括転記したいと考えています。 転記の事を考えて、条件としては、 シート1から2行目以降のデータを配列『data』に格納、変数『dataCnt』が転記先の行番号と同じになるように考えています。 当初は、配列の定義を『Dim data(100,3) As Variant』と、多めに要素数を定義して、コードを記述していました。 正直、凄く気持ちが悪い感じでした・・・ 最近、動的配列を学習しまして、 シートごとにデータの行数を変数『lastRow』に格納して、配列を再定義して【データ数=要素数】とならないか? と思い、下記のようなコードを書いてみました。 が、『ReDim Preserve~』で実行エラーが発生してしまいます。 原因がなぜかわかりません! そもそも、動的配列はこのような使い方は出来ないのでしょうか? Sub テスト() Dim data() As Variant Dim x As Long Dim i As Long Dim ii As Long Dim lastRow As Long Dim dataCnt As Long dataCnt = 2 For x = 2 To 5 Worksheets(x).Activate lastRow = Cells(Rows.Count, 1).End(xlUp).Row If x = 2 Then ReDim data(2 To lastRow, 3) Else ReDim Preserve data(2 To dataCnt + lastRow - 1, 3) End If For i = 2 To lastRow For ii = 1 To 3 data(dataCnt, ii) = Cells(i, ii) Next ii dataCnt = dataCnt + 1 Next i Next x End Sub どなたかご指導をよろしくお願いいたします。

  • 配列のつなげ方

    配列をつなげて文字列にしたいと思っています。 Dim abc() As String Dim i As String Dim namae As String i=0 ここでDBに接続してループでまわしながらデータを取得してきます。 Do while y > z abc(i) = X i = i+1 loop Xはループがまわる毎に違う値がセットされます。例えば1回目のループでリンゴ、2回目のループでミカンといった具合にです。 つまり、abc(0)=リンゴ、abc(1)=ミカン、abc(2)=メロン といった具合にです。 最終的には namae="リンゴ、ミカン、メロン、・・・・"といった具合にnamaeに代入したいと思っています。namae = abc(0) & "," & abc(1) & ","....と やれば実現できるのはわかります。 Xにはデータがいくつはいっているかわかりません。どうやった式をたてれば、実現できるでしょうか?

  • Excel VBA 2次元配列の一部をセルに出す

    Excel VBAで2次元配列中の一つの次元をセルに一発(For等でループせずに)で縦方向に書きたいのですが、何か良い方法は有るでしょうか。 例 Dim tmp(2, 2) As String tmp(0, 0) = "A"     : tmp(0, 1) = "B"  :  tmp(0, 2) = "C" tmp(1, 0) = "D"    : tmp(1, 1) = "E"    : tmp(1, 2) = "F" tmp(2, 0) = "G"    : tmp(2, 1) = "H" :   tmp(2, 2) = "I"   セル B1 ~ B3 に tmp(1,0)~temp(1,2)の出力したい ( セル B1に D、セルB2に E、 セル B31に F が入る) Transposeをみたのですが、一次元配列が前提のようです。 2次元配列の要素の一つを一次元にする方法でも構いません。   よろしくお願いします。

  • VBAで配列内のマッチ

    VBAでfor文などループを使わないで配列の文字列とマッチするかの判定を行いたいのですが、良い方法はありますか? Dim vrnArray As Variant vrnArray = Array("A", "B", "C", "D", "E", "F", "G") で ret = match???? (vrnArray, "C") retは真 のようなことがしたいです。

  • コンボボックスの値をVBAで配列に格納したい

    コンボボックスの値をVBAで配列に格納したいのですが どういうコードにすればいいでしょうか? コンボボックスの参照元を格納するのではなく、 現在コンボボックスに表示されてるデータを格納したいです。 今、 Sub test() Dim varComb As Variant varComb = ActiveSheet.ComboBox1.Value End Sub というコードを作ったのですが、 これだと「aaa」しか取得できません。 varCombに"aaa,bbb,ccc"とカンマ区切りで格納するにはどうすればいいでしょうか? ComboBox1に表示されるデータ数を取得し、 ループさせ、 varComb = varComb & "," & ActiveSheet.ComboBox1.Value で格納していくイメージですが、コードが作れません。 よろしくお願いします。

  • 配列について(VBA)

    ExcelもVBAも初心者です。 配列を使ってセルの値を取得したいです。 Range(A1:A5).Value=a は出来るようですが、 dim a(4) as date a = Range(A1:A5).Value は出来ないみたいです?(謎 明日までには完成しなければならないので、 どなたかヒントだけでもいただけませんでしょうか? よろしくお願いします。

  • 以下のデータがあり、これをExcel VBAの連想配列として格納したい

    以下のデータがあり、これをExcel VBAの連想配列として格納したいと考えています。 MsgBoxでキーとアイテムを表示させると表示されるのですが、 最後に一例としてExistsで確認するとFalseが返ってきます。 これは配列に格納されていないのでしょうか。 また格納されていないとすると、どうすれば格納できるのでしょうか。 A 列   B列 35   apple 37   orange 40   banana 以下がコードです。 sub test() Dim i as integer Dim myDic as Object Dim keys as Variant Set myDic = CreateObject("Scripting.Dictionary") For i = 1 to 3 myDic.Add Cells(i, 1), Cells(i, 2) Next i keys = myDic.keys For Each keys In myDic MsgBox "キー名:" & keys & vbCr & "値:" & myDic.Item(keys) Next keys MsgBox myDic.Exists(35) End Sub

  • EXCEL(2003)VBAで配列貼り付け

    EXCEL2003を使用してます VBAでCSVファイルを読み込み セルに書き込む動きを作成しました 当初、FOR~NEXTでまわしてセルに一つ一つ書き込んで ましたが、速度向上の為 配列に格納して貼り付けをしています 例: Dim aryStrings() As String ReDim aryStrings(16) 'デリミタ[,]でデータ分割 aryStrings = Split(rec, ",") .Range(Cells(1, 3), Cells(1, 18)) = aryStrings() EXCEL上では数値として扱いたいのですが CSV読み込み時に文字列として扱うため配列は String型になっております ※セルの書式設定は数値型を設定済 配列貼り付け後確認するともちろんですが文字列として張り付いてます (該当セルで編集+ENTERでEXCELが数値に変換してくれますが) 下記の3つの方法で可能な事はありますか? (1)CSV読み込み時に数値に変換して配列に格納 (2)配列を一気に数値型に変換 (3)文字列配列を数値型に変換しながらEXCELに一気に  配列貼り付け ご存知の方、いらっしゃいましたらアドバイスお願い致します

専門家に質問してみよう