• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:効率の良い配列格納方法)

効率の良い配列格納方法

このQ&Aのポイント
  • excelvbaで配列を勉強中の質問者です。配列を使って効率よくプログラムを書きたいと思っています。
  • 質問者は、応募者データから特定の項目のみを取り出して配列に格納したいと考えています。取り込む項目はa~c,h~m,rです。
  • 具体的な配列の格納方法についてアドバイスを求めています。20人のデータを一度に取り込む方法があれば教えてほしいと述べています。

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

  • ベストアンサー
  • kagakusuki
  • ベストアンサー率51% (2610/5101)
回答No.4

>配列bbbのように1個に格納したいのです。  残念ながら、私は「連続していない」複数のセル範囲のデータを、For~Nextも使わずに、1個の配列変数に"直接的に"格納する術を存じ上げません。(方法が無いと断言している訳では御座いません)  そこで、一時的に新しいワークシートを作成して、そこに「セル範囲が連続する様に」データのコピーを取り、そのコピーしたデータを配列変数に取り込むという方法では如何でしょうか? Sub Macro () Dim シート枚数 As Integer Dim 最終行 As Long 最終行 = Application.WorksheetFunction.Match(9E+99, Sheets("Sheet1").Columns("C:C")) Dim 配列A() As Variant ReDim 配列A(1 To 最終行 - 1, 1 To 10) Sheets.Add After:=Sheets(Sheets.Count) Sheets(Sheets.Count).Range("A2:C" & 最終行).Value = Sheets("Sheet1").Range("A2:C" & 最終行).Value Sheets(Sheets.Count).Range("D2:I" & 最終行).Value = Sheets("Sheet1").Range("H2:M" & 最終行).Value Sheets(Sheets.Count).Range("J2:J" & 最終行).Value = Sheets("Sheet1").Range("R2:R" & 最終行).Value 配列A() = Sheets(Sheets.Count).Range("A2:J" & 最終行).Value Application.DisplayAlerts = False Sheets(Sheets.Count).Delete Application.DisplayAlerts = True End Sub  因みに、上記のマクロは元データがSheet1に存在していて、Sheet1の1行目に「応募者氏名」~「アピールしたい内容」といった項目名が入力されている場合を想定したものです。  Sheet1の1行目の項目名は、配列変数に格納する必要がないものとしているため、配列変数に格納する事できる行数の限界の設定を 1 To 最終行 - 1 としております。  もし、Sheet1の項目名が、例えば3行目に入力されている場合には、配列変数に格納する事できる行数の限界の設定は 1 To 最終行 - 3 となります。

nagahaha
質問者

お礼

何回も何回もしつこくて済みません。 また、それにお応えいただき、大変感謝しております。 >私は「連続していない」複数のセル範囲のデータを、For~Nextも使わずに、1個の配列変数に"直接的に"格納する術 やはり無いのですね、了解しました。 これに対応する方法もご教示いただき、有り難うございました。 教えていただいたマクロはよく分かります。 また、先に教えていただいた雛形を作っておき、オートフィルする方法は 昨日一日掛かって理解できました。 今回はつまらない質問事から、素晴らしい考え方、コーディングを得ました。 世の中凄い人が居るな、というのが実感です。 お時間を取らせて申し訳在りませんでした。 深謝です。 有り難うございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • kagakusuki
  • ベストアンサー率51% (2610/5101)
回答No.3

>実は、質問の項目毎の格納で、a~c、およびh~mは連続したセルです。 >このため、今はfor nextでループさせていますが、一発で出来ないか、ということでした。  ですから、 Dim 配列A As Variant Dim 配列B As Variant Dim 配列C As Variant 配列A = Range("A2:C21") 配列B = Range("H2:M21") 配列C = Range("R2:R21") とした場合において、例えば 配列B(3,4)の値はK4セルの値となり、実際、 Range("T1").Value = 配列B(3,4) としますと、T1セルにはK4セルと同じ値が表示されるのですが、それでは駄目なのでしょうか?

nagahaha
質問者

お礼

今帰ってきました。 またまた、返事を頂き有り難うございます。 まだ、朝お礼したとおり、内容を全て読み切っていませんが、 最後にした質問が、言葉足りずで申し訳在りません。 教えていただいている内容は理解できています。 ただ、配列がA,B,Cと3個在りますが、 配列bbbのように1個に格納したいのです。 それとも、(私が分かっていないだけで) 配列A,B,Cはまた配列bbbにまとめられるのでしょうか。 とにかく最終的には、配列は1個にまとめたいのです。 →書いていませんが、私の書いたその後のプログラムでは、 1個の配列としてコーディングしていますので。 何回もしつこくて済みません。 ここだけ何とかクリアできればと思います。 宜しくお願いします。

全文を見る
すると、全ての回答が全文表示されます。
  • kagakusuki
  • ベストアンサー率51% (2610/5101)
回答No.2

 ただ単にデータを配列変数に格納するだけでしたら、 Dim 配列A As Variant Dim 配列B As Variant Dim 配列C As Variant 配列A = Range("A2:C21") 配列B = Range("H2:M21") 配列C = Range("R2:R21") の様な形式になると思いますが、配列変数に格納しただけでは、セル範囲にデータが存在している場合と大して状況は変わりませんから、どの行のデータを取捨選択するのかを決める段階で、結局、For~Nextを使い、1行ずつ判定を行う作業を繰り返す羽目になるのではないかと思います。  もし、配列変数を使用する事には拘らず、兎に角、一括して処理を行うだけでも良いというのでしたら、適当な作業列に、判定を行う働きをするワークシート関数を、一時的に一括して入力し、そのワークシート関数の結果を基準とするオートフィルターで、行を取捨選択する様なマクロは如何でしょうか?(For~Nextの繰り返し回数が多過ぎるよりは高速化が可能です) >その中からある条件に合致する行(応募者)を取り出してゆく という箇所で述べられている「ある条件」が、どの様なものなのかが不明なため、例えとして、仮に 「生年月日」が1994/3/31以前」で、「質問への応え1」が「はい」となっていて、「質問への応え2」が「いいえ」ではなく、且つ、「質問への応え3」~「質問への応え6」の中に「はい」が2つ以上ある行の中で、先着の20行を取り出すものとします。  又、応募者の元データが入力されているシートがSheet1であり、その1行目には「応募者氏名」~「アピールしたい内容」といった各項目名が入力されていて、実際の応募者のデータは2行目以下に入力されているものとします。  又、条件を満たしている応募者のデータを取り出した結果は、Sheet2のA1~R21(1行目は項目名の表示に使用する)に表示するものとします。  又、Sheet1のIV列を作業列として使用するものとします。  その場合のマクロの一例は、次の様なものとなります。 Sub 条件による抽出() Dim lr As Long lr = Application.WorksheetFunction.Match(9E+99, Sheets("Sheet1").Columns("C:C"), 1) Sheets("Sheet2").Range("A1:S" & lr + 1).Clear With Sheets("Sheet1").Range("IV1:IV" & lr) .Offset(1).FormulaR1C1 = "=AND(COUNTIF(R1C:R[-1]C,TRUE)<20,RC3<""1994/4/1""+0,AND(RC8=""はい"",RC9<>""いいえ"",COUNTIF(RC10:RC13,""はい"")>1))" .AutoFilter .AutoFilter Field:=1, Criteria1:="TRUE" Sheets("Sheet1").Range("A1:R" & lr).Copy Sheets("Sheet2").Range("A1").PasteSpecial Paste:=xlPasteValues Sheets("Sheet2").Range("A1").PasteSpecial Paste:=xlPasteFormats Application.CutCopyMode = False .AutoFilter .ClearContents End With End Sub  尚、当然の事ながら、行を取り出すのか否かの基準は、あくまで仮のものですので、5行目の "=AND(COUNTIF(R1C:R[-1]C,TRUE)<20,RC3<""1994/4/1""+0,AND(RC8=""はい"",RC9<>""いいえ"",COUNTIF(RC10:RC13,""はい"")>1))" の部分は、実際の条件に合わせて適時修正して下さい。

nagahaha
質問者

お礼

早速有り難うございました。 また、事細かに例まで作っていただき、感謝です。 正月から仕事で、先ほど帰ってきました、お礼が遅くなりました。 細かくは見ておらず、またすぐ出掛けなければならず、 あとでゆっくり見させていただきますが、要旨は理解できました。 配列という概念が効率/速さ共に、、、と聞いていたのですが、 オートフィルターという概念もあるのですね。 一つ雛形を作り、それを全データーに当てはめてゆく、ということでしょうか。 今回作っていただいた例題はサンプル集に保管し、今後の宝にします。 その前にじっくり内容の理解が必要ですが。 また、「在る条件」で端折ってしまったことで、 多大なるお手間をお掛けし、まことに申し訳在りませんでした。 「ある条件」とは、応募者データ限りで満足させられず、社内の基準との比較等があります。 これについても条件の設定を考えれば済むことでしょうが。 お礼と感想は以上ですが、 (十分解決は出来たのですが) これだけよく分かっておられて、さらにご親切な方がいらっしゃったので、 本当に聞きたかったことを言わせていただきます。 実は、質問の項目毎の格納で、 a~c、およびh~mは連続したセルです。 このため、今はfor nextでループさせていますが、一発で出来ないか、 ということでした。 (こんな命令はないと思いますが)  配列bbb(n,1(3)) = range("ax:cx").value  配列bbb(n,4(6)) = range("hx:mx").value の様な。 とにかく、後日じっくり勉強させていただき、お礼を述べさせていただきます。 とりあえず、見たということでお礼させていただきました。 大変有り難うございました。

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

これを変数に登録と言うことなら配列もだけど構造体(VBAではユーザー定義型と言うみたいだけど)も理解する必要がある。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • VBAの配列の格納について

    エクセルのVBAで、セルのデータを配列に格納するスピードを向上したいと思います。 例えば、A1~A10000のセルにデータを書き出す場合、 For 行番号 = 1 To 10000 Cells(行番号, 1).Value = 1 Next よりも、一旦、配列に書き込んだ後、一気にセルに書き込んだ方法が早いのですが、 For 行番号 = 1 To 10000 HAIRETU(行番号, 1) = 1 Next Range("A1:A10000").Value = HAIRETU() 今度は、A1~A10000に書き込んだデータを、再度、配列に格納する場合、 For 行番号 = 1 To 10000 HAIRETU(行番号, 1) = Cells(行番号, 1).Value Next とすると時間がかかるので、 HAIRETU() = Range("A1:A10000").Value というような処理をしたいのですが、うまくいきません。 よい方法がありましたら、ご教授ください。 よろしくお願いします。

  • 配列の並び替え

    下のように5つの配列がA~E列まであって、2、3行目にデータが入っています。このときに、2行目の値が3行目の値より小さい配列で、かつ、2行目の値が小さい順に並べる。その後に、3行目より、2行目の値の方が大きい配列を3行目の値が大きい順に並べるマクロコードを教えてください。   A B C D E←列      1  1 2 3 4 5←配列番号 2  4 9 8 6 2 3  1 5 7 10 3      ↑ 行    ↓     A B C D E 1  5 4 3 2 1 2  2 6 8 9 4 3  3 10 7 5 1

  • 配列の要素の入り方

    こんばんは。 現在C言語のプログラミングを勉強しています。 まだまだ初心者で基礎も十分には理解できていないので、とても基本なのかもしれませんが質問させていただきます… 例えば以下のような、配列に文字を入力するだけのプログラムを作ったとします。 --------------------------------- #include<stdio.h> main(){  int data[10];  printf("input - ");  fgets(data,10,stdin); } --------------------------------- これを実行し、 input - abc のように「abc」と入力すると、配列にはどのように入るのですか?  data[0]=a, data[1]=b, data[2]=c となるまではわかるのですが、data[3]からdata[9]には何が入るのでしょうか。配列のクリアはしていない状態です。 改行とnullが入る、というように聞いたのですが、これらはどのような順(?)で配列に入っているのかがわかりません。 よろしくお願いします。

  • Domを使うか配列を使うか・・

    あるテキストデータの変換プログラムを作成しています。 条件によって・・  ・ ある項目を別の項目に置き換える  ・ ある項目と別の項目の並び順を入れ替える  ・ あふ項目に別の項目を付加する など、データの編集が必要なのですが、このとき 元のデータをXMLに置き換えてDomを使用して編集を行うのと 配列に入れて編集を行うのとではどちらが効率的でしょうか? 個人的には配列をちまちまと整理していくよりも Domを使ったほうが簡単な気がするのですが、あまり詳しくないので よろしくお願いします  

    • ベストアンサー
    • XML
  • Dictionaryのitemを効率よく配列に格納

    まだエクセル2000です。 A列に商品名(約1,000種類) B列に分類名(10種類) C列に売上高 がある表があります。 (実際はその他の欄もありますが、質問のため単純化しています) 1行1レコードで時系列順に記載されていますので商品名も分類名も重複しています。 (もちろんデータ自体は重複していません。) 行数は不定です。 このデータから、各商品ごとに各分類別の売上高一覧(同一商品名でも分類が違えば別に集計)を作成するため、Dictionaryオブジェクトを利用して以下のマクロを書きました、 Sub test01()   Dim myDic As Object   Dim myV, myW, myX   Dim i As Long, n As Long   Dim ws As Worksheet   With Sheets("Test01")     myV = .Range("A1", .Cells(Rows.Count, "C").End(xlUp)).Value '対象範囲を配列に   End With   ReDim myW(1 To UBound(myV), 1 To 3) '一覧データ格納用2次元配列サイズ設定   Set myDic = CreateObject("Scripting.Dictionary")   For i = 1 To UBound(myV)     If Not myDic.Exists(myV(i, 1) & myV(i, 2)) Then '商品+分類が初出なら       myDic.Add myV(i, 1) & myV(i, 2), myV(i, 3) 'keyに追加、itemに売上       n = n + 1 'カウント       myW(n, 1) = myV(i, 1) '配列に商品名       myW(n, 2) = myV(i, 2) '配列に分類名     Else '商品+分類が既出なら       myDic(myV(i, 1) & myV(i, 2)) = myDic(myV(i, 1) & myV(i, 2)) + myV(i, 3) 'itemに売上加算     End If   Next i   ReDim myX(0 To UBound(myDic.Items)) 'item配列格納用1次元配列サイズ設定   myX = myDic.Items '1次元配列にItem格納   For i = 1 To UBound(myDic.Items) + 1     myW(i, 3) = myX(i - 1) '配列から配列へitemデータ複写   Next i   Set ws = Sheets.Add 'シート追加   ws.Range("A1").Resize(UBound(myDic.keys) + 1, 3).Value = myW '配列張り付け   Set myDic = Nothing   Set ws = Nothing End Sub これで正常かつ高速に作動するのですが、疑問点があります。 itemのデータを2次元配列、myWの3列目に格納するのに、いったん1次元配列myXを経由しなくともよい方法はないのかということです。 ここを変えてみても多分実行速度にほとんど影響はないとは思いますが、何か無駄なことをしているようで気になります。 itemを配列myWにとりこまず、直接ワークシートのC1以下にApplication.Transpose(myDic.items)で張るのが効率的と思いますが、わたしのエクセルがまだ2000のため、Transpose関数の限界、5461個にひっかかるおそれがあり、使えません。 どうかご教示ください。

  • forの中でforをループしてそれぞれ配列に格納したい

    お世話になります。 5レコードずつのデータをテーブルに吐き、テーブル自体を4個 横に並べて表示したいです。 ひとつめのforを使って最初の5行を取得しテーブルに収めることは できたのですが、6-10行目のレコードは、また同じようなforを 書いて、隣のテーブルに書かないといけないでしょうか。 配列の引数に配列もしくは変数を用いて書けば、何度も同じような コードを書かなくて済むと思ったのですが、記述しても膨大な 計算をしているらしく、タイムアウト?か、真っ白な画面を出して きます。 No 氏名 No 氏名 No 氏名 1 山田  6 川田  11 谷田 2 山下  7 川上  12 谷川 3 山本  8 川本  13 谷本 5行まで 要するに、1つのテーブルがいっぱいになったら(ここでは5行) となりのテーブルに行ってほしいのです。1-5を第1テーブル、 6-10を第2テーブル・・・とすると、第1と第2のコードはループ 2回で取れないでしょうか。 $start = 0; for ($A = 0; 3; $A++){  //テーブル4個分のループ //1テーブル5行分のループ for ($recno = $start + ($A * 5); $recno < $start + 5 + ($A * 5); $recno++){ if (! $row =& $res->fetchRow(db_fechtmode_assoc,$recno)) { break; } $body['$A'].="<tr>"; $body['$A'].="<td>".$row["No"]."</td>"; $body['$A'].="<td>".$row["氏名"]."</td>"; $body['$A'].="</tr>\n"; } } で、$body[0]の第1テーブルを書き出し、$body[1]の第2テーブルを 書き出し・・・と、そのまま使えたら楽だと思ったのです。 そもそも、$body[0]の中にはNoと氏名とは2つ入らないでしょうか・・・。 PHP5.2.6 と PEAR です。よろしくお願いします。

    • ベストアンサー
    • PHP
  • データベースに配列を格納する

    私はデータベースを本で勉強していたのですが物にするため、実際にデータベースのプログラムをくんでみようと設計を考えたのですが、疑問があります。 私はデータベースに、プログラム上で取り扱っているサイズがことなる複数の配列内のデータを格納したいのですが、これはデータベースにどのように格納すればよいのか分からず困っています。 図で説明すると 例えば {1} {12 33 24 21} {13 56 0 1} という3つの配列を同じデータベースに入れようとした場合 ID int1 int2 int3 int4 1 1 null null null 2 12 33 24 21 3 13 56 0 1 という形で入れる事になると思いますが、ここにサイズが5の配列をいれようとした場合は列が増えることになってしまいます。すると色々めんどくさいことになるのではないかと思います。 このようなデータベースに入れるデータのサイズが分からない場合は、どのようにするべきなのでしょうか?(なおJDBCを使い、SQLiteに入れています) やや抽象的かつ、意味がわかりにくい質問ですが不足な点は説明させていただきますので、ご回答よろしくお願いします。

    • ベストアンサー
    • MySQL
  • VBAでエクセルのいくつかの表を同じ配列に格納する

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

  • VBA配列 印のついた列番号を格納して利用したい

    Excel VBAで下記処理を作成しました。配列を使えば処理が高速化できるのでは?と思い調べたのですが、配列を使ったことが無く、挫折しましたのでどなたかご教示いただけませんでしょうか。 <対象データ>(添付画像の黄色いセルが処理対象) ・処理対象の行は「区分」列に「0」が入っている ・処理対象の列は、1行目に「●」が入っている <作成した処理> ・ループ(1):データ開始行(画像では3行目)から順に見ていく  ・IF:「区分」列が「0」なら下記に進む(0以外なら次の行へ)   ・ループ(2):列を左から順に見ていく    ・IF:その列の1行目が「●」なら処理を行う For i = 3 To 10000 If Cells(i , 1) = 0 And Cells(i , 1) <> "" Then その行に対する処理の下準備のコード(記載省略) For j = 2 To 500 If Cells(1 , j) = "●" Then Cells(i , j)に対する処理(記載省略) End If Next j End If Next i <問題点> データ量が数千行×数百列と相応にあるため、処理実行に数秒かかります。今後、処理をより複雑にしたいため、高速化できないかと考えています。 <質問> 対象行について毎回、ループ(2)で各列の1行目を調べて●だったら処理する、としているのが非効率かも知れないと思いました。 1行目に●が入っている列番号を調べるのは1度で良いので、それを配列に格納して、ループ(2)の部分で使うことはできますでしょうか? ご存じの方、ご教示いただけますと幸いです。よろしくお願いいたします。

  • Excelのシートにある1行のデータを複数行に分割したい

    例えば次のようなことがしたいのですが、VBA以外ではできないでしょうか? 何か方法があったら教えてください。 ・A:コード B:氏名 C:生年月日 D:住所 E:TEL というように横に並んだデータがあるとします。 ・一番上の行は標題部分になっており、次の行からデータが縦に100行分程度あります。 ・この1行分のデータを2行(すべてに標題をつけたいので実質は4行)に返還したいのです。 (1行目:標題)A:コード B:氏名 C:生年月日 (2行目) 標題に対応したデータ (3行目:標題)D:住所 E:TEL  (4行目) 標題に対応したデータ これで意味がわかるでしょうか? よろしくお願いします。