Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


12902 / 13644 ツリー ←次へ | 前へ→

【8037】Arrayへのデータ追加について kawata 03/9/27(土) 9:43 質問
【8042】Re:Arrayへのデータ追加について ichinose 03/9/27(土) 17:08 発言
【8044】Re:Arrayへのデータ追加について kawata 03/9/27(土) 17:23 お礼
【8047】Re:Arrayへのデータ追加について bykin 03/9/27(土) 20:36 回答
【8060】Re:Arrayへのデータ追加について kawata 03/9/29(月) 8:31 お礼
【8069】Re:Arrayへのデータ追加について kawata 03/9/29(月) 11:35 お礼

【8037】Arrayへのデータ追加について
質問  kawata  - 03/9/27(土) 9:43 -

引用なし
パスワード
   kawataです、お世話になっております、よろしくお願いします。
(Windows2000/Excel2000)

ただいま配列勉強中です、多少でも使えるようになると
これまでのコードもガラッと変わってしまいます、
データ量が多いときの処理速度は圧倒的で、もう元に
戻れませんね(少ないデータの時は、使いやすいほうを
選択していますけども)。

で、質問なんですが、

  With Sheets("sheet1")
    myArray = .Range("a1:a10")
    .Range("b1").Resize(, UBound(myArray)) = Application.Transpose(myArray)
  End With

セルA1〜A10の値を、B1から横に書き出すものなんですが、
このA1〜A10のデータをループさせて、条件の合うものだけ
Array配列に追加していきたいと考えているのですが、
このArray配列への継ぎ足しの記述がわかりません。

  myArray() = myArray() + a ← やりたいことのイメージです(^^;。

ぜひ、よろしくお願いします。

【8042】Re:Arrayへのデータ追加について
発言  ichinose  - 03/9/27(土) 17:08 -

引用なし
パスワード
   ▼kawata さん:
>kawataです、お世話になっております、よろしくお願いします。
>(Windows2000/Excel2000)
>
>ただいま配列勉強中です、多少でも使えるようになると
>これまでのコードもガラッと変わってしまいます、
>データ量が多いときの処理速度は圧倒的で、もう元に
>戻れませんね(少ないデータの時は、使いやすいほうを
>選択していますけども)。
>
>で、質問なんですが、
>
>  With Sheets("sheet1")
>    myArray = .Range("a1:a10")
>    .Range("b1").Resize(, UBound(myArray)) = Application.Transpose(myArray)
>  End With
>
>セルA1〜A10の値を、B1から横に書き出すものなんですが、
>このA1〜A10のデータをループさせて、条件の合うものだけ
>Array配列に追加していきたいと考えているのですが、
>このArray配列への継ぎ足しの記述がわかりません。
>
>  myArray() = myArray() + a ← やりたいことのイメージです(^^;。
>
>ぜひ、よろしくお願いします。
例にあげられたような仕様なら(セルA1〜A10の範囲で条件に合った値をセルB1から右方向に移すのに配列変数を問屋さんにする)、
仮にA1:A10には、1〜10が入っていたとしましょう。
例は、値が5から7のデータをB1から横に並べるものです。
‘======================================================
Sub test()
  Dim myarray()
  jdx = 1
  For idx = 1 To 10
    With Cells(idx, 1)
     If .Value >= 5 And .Value <= 7 Then
       ReDim Preserve myarray(1 To jdx)
       myarray(jdx) = .Value
       jdx = jdx + 1
       End If
     End With
    Next idx
  If UBound(myarray()) > 0 Then
    Range("b1").Resize(, UBound(myarray())).Value = myarray()
    End If
End Sub

なんて方法で可能ですが、
見ればおわかりかと思いますが、
上記のコードの配列は、1次元配列です。

>    myArray = .Range("a1:a10")

の配列とは次元が違ってしまいます。

RedimステートメントのHELPの引用
「Preserve   省略可能です。既存の配列に格納されている値を失うことなく、配列の最後の次元の要素数を変更する場合に使用する、キーワードです。」
のとおり、Preserve使用のmyarray(x,y)のxの要素数の変更は、無理なようです。

最初に条件に合ったセルの数がわかっていれば
‘=======================================================
Sub samp()
'これは、条件にあったセルをB列に移す
  Dim myarray()
  jdx = 1
  With Range("a1:a10")
    cnt = Application.Evaluate( _
      "=SumProduct((a1:a10 >= 5) * (a1:a10 <= 7))")
    End With
  If cnt > 1 Then
    ReDim myarray(1 To cnt, 1 To 1)
    jdx = 1
    For idx = 1 To 10
     With Cells(idx, 1)
       If .Value >= 5 And .Value <= 7 Then
        myarray(jdx, 1) = .Value
        jdx = jdx + 1
        End If
       End With
     Next idx
    Range("b1").Resize(UBound(myarray())).Value = myarray()
    End If
  
End Sub

というコードを書くことができますが・・・・。
こんな情報でよろしいでしょうか?

【8044】Re:Arrayへのデータ追加について
お礼  kawata  - 03/9/27(土) 17:23 -

引用なし
パスワード
   kawataです、よろしくお願いします。

ichinoseさん、ありがとうございます、恐縮です。

実際の運用は、もう少しデータが多くなります。
3列、不定行にデータがあって、種類別に振り分けて
書き出そうとしています。

>というコードを書くことができますが・・・・。
>こんな情報でよろしいでしょうか?

と、いつもながら・・・・・・・・・。
まず、パッと見ただけでは理解できない(^^;。
これから、コードを解読にかかります、ぜひともものに
したいところです。
結果報告します、しばらく時間くださいです(^^;、

※またSumProductが使われていました、このあたりの
理解も徹底しておかねば、復習せねば(^^;。

とりあえず、お礼まで。
ありがとうございました!!。

【8047】Re:Arrayへのデータ追加について
回答  bykin  - 03/9/27(土) 20:36 -

引用なし
パスワード
   こんばんわ。

解決してるんかな?(^^;;

>データ量が多いときの処理速度は圧倒的

これは Value プロパティでセルの値を読み書きするのが遅いってこと。
せやから速度重視にするんやったら、セルの読み書きは
最初と最後だけにするってのがコツです。
途中のコードの中(ループの中は特に)には Value プロパティを書かんほうが
ええってことです。
ループは変数の世界だけでやったほうが速いです。

例えばA1:A10に数値が入ってて、そのうちの5以上の値だけを
B1から横にならべるんやったら、こんな感じでっしゃろか?

Sub test()
  Dim MyArray As Variant
  Dim MyArray2() As Variant
  Dim i As Long
  Dim j As Long
  
  With Sheets("Sheet1")
    MyArray = .Range("A1:A10").Value
    j = 1
    For i = LBound(MyArray, 1) To UBound(MyArray, 1)
      If MyArray(i, 1) >= 5 Then
        ReDim Preserve MyArray2(1 To 1, 1 To j)
        MyArray2(1, j) = MyArray(i, 1)
        j = j + 1
      End If
    Next
    .Range("B1").Resize(, UBound(MyArray2, 2)).Value = MyArray2
  End With
End Sub

セルから取得した配列から条件にあったデータを別の配列に取り込んで
最終的にそれをセルに書き込んでます。
セル範囲に対応する配列はたとえ1行または1列であっても2次元配列であるってことに
気ぃつけて、Ubound の第2引数を適切に使えばええんとちゃいまっか?
第2引数の使い方はヘルプで調べてみてな。

ichinose はんもおっしゃってるように ReDim で Preserve が使えるのは最後の次元だけです。
上記例ではたまたま横への展開やったから ReDim Preserve がそのまま使えたけど
縦に展開するんやったら中間処理用の1次元配列を用意して一旦そこに取り込んでから
さらに書き込み用配列にデータを移すといったような処理が必要になります。
(最初から抽出する件数がわかってたらもうちょっと楽でっけど)

あ、それと Value プロパティは Range オブジェクトのデフォルトのプロパティやから
kawata はんのコードみたいに省略しても構わんのやけど、やっぱし明記したほうが
コードがわかりやすくなると思うよ。わては必ず書くようにしてます。

ほな。

【8060】Re:Arrayへのデータ追加について
お礼  kawata  - 03/9/29(月) 8:31 -

引用なし
パスワード
   kawataです、よろしくお願いします。

bikynさん、ありがとうございました。
お返事遅れました、どうもすいません。

まずは、先にお礼を。
ichinoseさんの回答とともに、何とも感激する内容をいただきまして
ありがとうございます。

いまいち配列を使いこなせていない私ですが、これを機会に基礎を徹底
して学習しておこうかと思います。
また、よろしくお願いします。

>これは Value プロパティでセルの値を読み書きするのが遅いってこと。
>せやから速度重視にするんやったら、セルの読み書きは
>最初と最後だけにするってのがコツです。
>途中のコードの中(ループの中は特に)には Value プロパティを書かんほうが
>ええってことです。
>ループは変数の世界だけでやったほうが速いです。

了解しました。おっしゃっておられることすべてがギクッとくるのですよね。
現在はダメな見本そのままのコードを書いているような感じです(^^;。

>セル範囲に対応する配列はたとえ1行または1列であっても2次元配列であるってことに
>気ぃつけて、Ubound の第2引数を適切に使えばええんとちゃいまっか?
>第2引数の使い方はヘルプで調べてみてな。

了解しました。

>あ、それと Value プロパティは Range オブジェクトのデフォルトのプロパティやから
>kawata はんのコードみたいに省略しても構わんのやけど、やっぱし明記したほうが
>コードがわかりやすくなると思うよ。わては必ず書くようにしてます。

了解しました。

今、やろうとしていることに対する疑問・不明なポイントに的確なアドバイスは、
ほんとうにありがたいものです。

ichinoseさん、bikynさん、どうもありがとうございました、
また、よろしくお願いします。

※上の「了解しました」は理解しましたじゃなくて・・・・・・・
これから勉強します・・・・ということで(^^;。
なんかすごく重要なポイントを指摘されているような気もします、
気合いれて頑張ります!!。

【8069】Re:Arrayへのデータ追加について
お礼  kawata  - 03/9/29(月) 11:35 -

引用なし
パスワード
   kawataです、よろしくお願いします。

ichinoseさん、bikynさん、どうもありがとうございました、
どうにかこうにか、やりたいことの形が見えてきました。

<データ>
   a   b   c
1  a001     a002    a003
2  b001     b002    c001
3  c002      b003    c003
4  a004  b004    c004
(以下、続く)

Sub testz()
  Dim MyArray As Variant
  Dim MyArray1() As Variant
  Dim MyArray2() As Variant
  Dim MyArray3() As Variant
  Dim m As Long, n As Long
  Dim j1 As Long, j2 As Long, j3 As Long
 
  With Sheets("Sheet2")
    e_row = .UsedRange.Rows.Count
    MyArray = .Range("a1:c" & e_row).Value
    j1 = 1: j2 = 1: j3 = 1
    For n = 1 To e_row
      For m = 1 To 3
        chk = Left(MyArray(n, m), 1)
        Select Case chk
          Case "a"
            ReDim Preserve MyArray1(1 To 1, 1 To j1)
            MyArray1(1, j1) = MyArray(n, m)
            j1 = j1 + 1
          Case "b"
            ReDim Preserve MyArray2(1 To 1, 1 To j2)
            MyArray2(1, j2) = MyArray(n, m)
            j2 = j2 + 1
          Case "c"
            ReDim Preserve MyArray3(1 To 1, 1 To j3)
            MyArray3(1, j3) = MyArray(n, m)
            j3 = j3 + 1
        End Select
        j = j + 1
      Next
    Next
    .Range("d1").Resize(, UBound(MyArray1, 2)).Value = MyArray1
    .Range("d2").Resize(, UBound(MyArray2, 2)).Value = MyArray2
    .Range("d3").Resize(, UBound(MyArray3, 2)).Value = MyArray3
  End With
End Sub

まだまだスッキリしたコードとはいえませんが、とにかく配列を習得したいが
ためにということで数をこなしていきたいと思います。(^^;。

ありがとうございました!!。
またよろしくお願いします。

12902 / 13644 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free