多次元動的配列

この講座は有料講座です。
講座の購入後ご覧になれます。

ログインアカウントの新規作成

解説

多次元動的配列について説明しています。

この教材についての過去の質問・感想

11676 : 小川慶一の回答 (2019-11-29 10:45:10)

受講生 さん:

>  Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
> →Set rH = rHall.Find(what:=rM.Value,LookIn:=xlValues, lookat:=xlWhole)
>
> とういうことで、上記のように変更しましたら無事動きました。
> ですが、やはり関数だと8分くらいかかりますので、一度関数を値貼付にして実行したところ16秒でできました!全然違うのですね。。

よく、気づかれましたね!

技術的には、「検索対象を、セルに埋め込まれた式ではなく式の計算結果とするには?」ということですね。
そこだけを焦点にしたサンプルコードを作りました。

また、 Application.Calculation プロパティの値を変更すると、開いているエクセルファイルでセルが編集されても、都度全セルの計算式を再計算しなくなります。
もしまだ活用されていないようでしたら、そのことによる高速化も期待できそうです。(発展編1テキスト参照)

以下を参考にしたコードを書いてみて、最終的にどんな結果になったか?またお聞かせください (^^

Sub SetNewData()
    Randomize
    
    '"一枚シート"という名称のworksheetが存在するという前提
    Dim ws As Worksheet
    Set ws = Worksheets("一枚シート")
    
    Dim c As Long
    With ws
        .Cells.Clear
        .Range("A1").Value = "ID"
        .Range("B1").Value = "col1"
        .Range("C1").Value = "col2"
        .Range("D1").Value = "col3"
        .Range("E1").Value = "rnd"
        .Range("F1").Value = "match"
        For c = 2 To 31
            .Range("A" & c).Value = "h-" & c - 1
            .Range("B" & c).Value = "data"
            .Range("C" & c).Value = c - 1
            .Range("D" & c).Formula = "=B" & c & "&C" & c
            .Range("E" & c).Value = Rnd()
        Next
        .Range("A1").CurrentRegion.Sort Key1:=Range("E1"), Order1:=xlAscending, Header:=xlYes
    
        .Range("H1").Value = "ID"
        .Range("I1").Value = "col1"
        .Range("J1").Value = "col2"
        .Range("K1").Value = "col3"
        .Range("L1").Value = "rnd"
        .Range("M1").Value = "match"
        For c = 2 To 21
            .Range("H" & c).Value = "m-" & c - 1
            .Range("I" & c).Value = "data"
            .Range("J" & c).Value = c - 1
            .Range("K" & c).Formula = "=I" & c & "&J" & c
'            .Range("L" & c).Value = Rnd()
        Next
        .Range("L2:L21").Value = .Range("K2:K21").Value '式で算出された値をそのまま値として貼りつけ(貼りつけ先として同じセルを指定するのもあり)
    End With
End Sub
Sub Find_By_Formula_Result()
    Dim rHall As Range, rMall As Range
    Dim rH As Range, rM As Range
    
    Dim ws As Worksheet
    Set ws = Worksheets("一枚シート")
    
    Application.Calculation = xlCalculationManual
    With ws
        Set rHall = .Range("D2:D31") '式が入っている
        Set rMall = .Range("L2:L21") '値が入っている
        For Each rM In rMall
            Set rH = rHall.Find(What:=rM.Value, Lookat:=xlWhole, LookIn:=xlValues)
            If Not rH Is Nothing Then
                rM.Offset(, 1).Value = rH.Row & "行目にありました!"
            Else
                rM.Offset(, 1).Value = "見つかりません"
            End If
        Next
        Columns(12).Delete Shift:=xlToLeft 'マクロでの処理の都合で一時的に追加していた列を削除
    End With
    Application.Calculation = xlCalculationAutomatic
End Sub




> 小川先生:
>
> お世話になります。
> 早速見ていただきありがとうございます。
>
> サンプルコードを検証しました。
> [3]でまた "失敗" となったところで、先生の「調査対象のデータの問題」の原因がわかりました。
>
> 実はもう一つ情報をお伝えしていなかったのですが、調査対象のコード列(C列)にはコードや名称など複数の列を結合する関数を入れております。
> (コードのみだど重複データができてしまい正確に転記できなくなるため)
> その関数の結合データの結果で当月⇔前月でマッチングさせておりました。[2]までは普通に動いたので気付かず、すみません。。。
>
>  Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
> →Set rH = rHall.Find(what:=rM.Value,LookIn:=xlValues, lookat:=xlWhole)
>
> とういうことで、上記のように変更しましたら無事動きました。
> ですが、やはり関数だと8分くらいかかりますので、一度関数を値貼付にして実行したところ16秒でできました!全然違うのですね。。
>
> 1列増やして一度値で貼りつけ他のセルを修正するか、[2]のForEachでも44秒なのでどちらか検討いたします。とても勉強になりました。
> 何度もサンプルデータをいただきありがとうございました。


11675 : 受講生さんのコメント (2019-11-26 23:27:02)

小川先生:

お世話になります。
早速見ていただきありがとうございます。

サンプルコードを検証しました。
[3]でまた "失敗" となったところで、先生の「調査対象のデータの問題」の原因がわかりました。

実はもう一つ情報をお伝えしていなかったのですが、調査対象のコード列(C列)にはコードや名称など複数の列を結合する関数を入れております。
(コードのみだど重複データができてしまい正確に転記できなくなるため)
その関数の結合データの結果で当月⇔前月でマッチングさせておりました。[2]までは普通に動いたので気付かず、すみません。。。

 Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
→Set rH = rHall.Find(what:=rM.Value,LookIn:=xlValues, lookat:=xlWhole)

とういうことで、上記のように変更しましたら無事動きました。
ですが、やはり関数だと8分くらいかかりますので、一度関数を値貼付にして実行したところ16秒でできました!全然違うのですね。。

1列増やして一度値で貼りつけ他のセルを修正するか、[2]のForEachでも44秒なのでどちらか検討いたします。とても勉強になりました。
何度もサンプルデータをいただきありがとうございました。


> これは、プログラムのロジックではなく、調査対象のデータの問題ではないかと思います。
> というのは、以下の[1], [2]からです。
>
> [1] 別シートにあるデータの比較も可能です
> [2] いただいたマクロが動作し得るサンプルデータを作り試してみましたが、[1]と同様に問題なく動作します
>
> 以下に示すサンプルコードを検証してください。
> そのうえで、手元の本番データで、前後の空白、大文字小文字、全角半角の違いが生じていないか?検証してください。
>
> この検証の際は、いきなりループでマッチングさせるのではなく、(ハナコのやり方を踏襲し)まずは絶対にマッチングするはずの2つのセルで比較を行い .Find がセルを1つ返すのところまで成功させるのに専念されるのが堅実かと思います。
> [3]を参考にしてください。
>

>
>

'[3] ハナコ
> Sub hanako1()
>     Dim rHall As Range
>     Dim rH As Range
>     Dim rM As Range
>     Dim wH As Worksheet
>     Dim wM As Worksheet
>     Set wH = Worksheets("当月対比")
>     Set wM = Worksheets("前月")
>     
>     Set rHall = wH.Range("C2") 'ID=2
>     Set rM = wM.Range("C13") 'ID=2 のレコードは13行目にあるとします
>     Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
>     If Not rH Is Nothing Then
>         rM.Offset(, 4).Value = rH.Offset(, 1).Value
>     Else
>         rM.Offset(, 4).Value = "失敗"
>     End If
> End Sub


11674 : 小川慶一の回答 (2019-11-26 06:00:32)

>(1)ForNext文→自分で以前に作成済(実行時間3分15秒)
>  →1セルずつなので結構かかります
>
>(2)ForEach文→先生のコードを参考に作成(実行時間44秒)
>  →こんなに短くなりました!!

これは、興味深いですね。

さて、いただいたさらなるご質問について。

これは、プログラムのロジックではなく、調査対象のデータの問題ではないかと思います。
というのは、以下の[1], [2]からです。

[1] 別シートにあるデータの比較も可能です
[2] いただいたマクロが動作し得るサンプルデータを作り試してみましたが、[1]と同様に問題なく動作します

以下に示すサンプルコードを検証してください。
そのうえで、手元の本番データで、前後の空白、大文字小文字、全角半角の違いが生じていないか?検証してください。

この検証の際は、いきなりループでマッチングさせるのではなく、(ハナコのやり方を踏襲し)まずは絶対にマッチングするはずの2つのセルで比較を行い .Find がセルを1つ返すのところまで成功させるのに専念されるのが堅実かと思います。
[3]を参考にしてください。

'[1]
Sub sample0_2() 'Sheet1, Sheet2で元データ投入
    Randomize
    
    Dim hida As Long
    
    Worksheets("Sheet1").Activate
    Range("A1").Value = "ID"
    Range("B1").Value = "val1"
    Range("C1").Value = "val2"
    Range("D1").Value = "val3"
    For hida = 2 To 201
        Range("A" & hida).Value = hida - 1
        Range("B" & hida).Value = "hida1 " & hida - 1
        Range("C" & hida).Value = "hida2 " & hida - 1
    Next

    Worksheets("Sheet2").Activate
    Range("F1").Value = "ID"
    Range("G1").Value = "val1"
    Range("H1").Value = "val2"
    Range("I1").Value = "val3"
    For hida = 2 To 251
        Range("F" & hida).Value = hida - 1
        Range("G" & hida).Value = "migi1 " & hida - 1
        Range("H" & hida).Value = Rnd()
    Next
    Range("F1").CurrentRegion.Sort key1:=Range("H1"), order1:=xlAscending, Header:=xlYes
End Sub
Sub sample4_3() '前回提供したsample3_3の、別シートにあるバージョン
    Dim rHall As Range
    Dim rMall As Range
    Dim rH As Range
    Dim rM As Range
    
    Set rHall = Worksheets("Sheet1").Range("A2:A201")
    Set rMall = Worksheets("Sheet2").Range("F2:F251")
    
    For Each rM In rMall
        Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
        If Not rH Is Nothing Then
            Debug.Print "Found"
            rM.Offset(, 3).Value = rH.Offset(, 1).Value
        Else
            Debug.Print "Not Found"
            rM.Offset(, 3).Value = "見つかりません"
        End If
    Next
End Sub
Sub Sheet1Active() 'Sheet1がアクティブな状態で実行し、Sheet2の状態を確認する
    Worksheets("Sheet1").Activate
    sample4_3
End Sub
Sub Sheet2Active() 'Sheet2がアクティブな状態で実行し、Sheet2の状態を確認する
    Worksheets("Sheet2").Activate
    sample4_3
End Sub


'[2] データ投入先シートは存在し、データ投入されていないという前提。
Option Explicit
Public ws1 As Worksheet
Public ws2 As Worksheet
Public tmax As Long
Public zmax As Long
Sub sample3_3()
    Dim rHall As Range
    Dim rMall As Range
    Dim rH As Range
    Dim rM As Range
     
    Set ws1 = Worksheets("当月対比")
    Set ws2 = Worksheets("前月")
    tmax = ws1.Range("F1048576").End(xlUp).Row
    zmax = ws2.Range("F1048576").End(xlUp).Row
     
    Set rHall = ws1.Range("C2", "C" & tmax)
    Set rMall = ws2.Range("C2", "C" & zmax)
      
    For Each rM In rMall
        Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
        If Not rH Is Nothing Then
            rH.Offset(, 3).Value = rM.Offset(, 3).Value
            rH.Offset(, 4).Value = rM.Offset(, 4).Value
        Else
            rM.Offset(, -2).Value = "見つかりません"
        End If
    Next
End Sub
Sub SetTestData()
    Randomize
    Dim c As Long
    Dim rHall As Range
    Dim rMall As Range
    
    Set ws1 = Worksheets("当月対比")
    Set ws2 = Worksheets("前月")
    
    With ws1
        .Range("C1").Value = "ID"
        .Range("D1").Value = "col1"
        .Range("E1").Value = "col2"
        .Range("F1").Value = "col3"
        .Range("G1").Value = "col4"
        For c = 2 To 31
            .Range("C" & c).Value = c
            .Range("D" & c).Value = "hida " & c
            .Range("E" & c).Value = "hida " & c
            .Range("F" & c).Value = Rnd()
        Next
    End With
    
    With ws2
        .Range("A1", "A" & .Range("A1048576").End(xlUp).Row).ClearContents '文字列"見つかりません"がある場合は削除
        .Range("C1").Value = "ID"
        .Range("D1").Value = "col1"
        .Range("E1").Value = "col2"
        .Range("F1").Value = "col3"
        .Range("G1").Value = "col4"
        For c = 2 To 51
            .Range("C" & c).Value = c
            .Range("D" & c).Value = "migi " & c
            .Range("E" & c).Value = "migi " & c
            .Range("F" & c).Value = Rnd()
        Next
        .Range("C1").CurrentRegion.Sort Key1:=.Range("F1"), Order1:=xlAscending, Header:=xlYes
    End With
    
    tmax = ws1.Range("F1048576").End(xlUp).Row
    zmax = ws2.Range("F1048576").End(xlUp).Row
    
    Set rHall = ws1.Range("C2", "C" & tmax)
    Set rMall = ws2.Range("C2", "C" & zmax)
    
    Debug.Print rHall.Count 'データ数検証。30になるはず。
    Debug.Print rMall.Count 'データ数検証。50になるはず。
End Sub


'[3] ハナコ
Sub hanako1()
    Dim rHall As Range
    Dim rH As Range
    Dim rM As Range
    Dim wH As Worksheet
    Dim wM As Worksheet
    Set wH = Worksheets("当月対比")
    Set wM = Worksheets("前月")
    
    Set rHall = wH.Range("C2") 'ID=2
    Set rM = wM.Range("C13") 'ID=2 のレコードは13行目にあるとします
    Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
    If Not rH Is Nothing Then
        rM.Offset(, 4).Value = rH.Offset(, 1).Value
    Else
        rM.Offset(, 4).Value = "失敗"
    End If
End Sub
Sub hanako2()
    Dim rHall As Range
    Dim rH As Range
    Dim rM As Range
    Dim wH As Worksheet
    Dim wM As Worksheet
    Set wH = Worksheets("当月対比")
    Set wM = Worksheets("前月")
    
    Set rHall = wH.Range("C2:C31") '調査範囲を拡大
    Set rM = wM.Range("C17") '2-31までの値を取る任意のセルを指定
    Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
    If Not rH Is Nothing Then
        rM.Offset(, 4).Value = rH.Offset(, 1).Value
    Else
        rM.Offset(, 4).Value = "失敗"
    End If
End Sub
Sub hanako3()
    Dim rMall As Range
    Dim rHall As Range
    Dim rH As Range
    Dim rM As Range
    Dim wH As Worksheet
    Dim wM As Worksheet
    Set wH = Worksheets("当月対比")
    Set wM = Worksheets("前月")
    
    Set rHall = wH.Range("C2:C31")
    Set rMall = wM.Range("C2:C51")
    For Each rM In rMall
        Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
        If Not rH Is Nothing Then
            rM.Offset(, 4).Value = rH.Offset(, 1).Value
        Else
            rM.Offset(, 4).Value = "失敗"
        End If
    Next
End Sub


11673 : 受講生さんのコメント (2019-11-25 21:25:26)

小川先生:

こんにちは。
サンプルコードまでたくさん記載いただきありがとうございます。

情報が少なくてすみませんでした。
先生の予想ですべて合っております。
・重複コードはなしです。
・発展1のForNext文で(1)と同じように作成済です。

まず、いただいたコードのとおり表を作り、(2)(3)を実行し動きがわかった上で、自分の5000行の2つのsheetにコードを置き換えて実行してみました。
(1)ForNext文→自分で以前に作成済(実行時間3分15秒)
  →1セルずつなので結構かかります

(2)ForEach文→先生のコードを参考に作成(実行時間44秒)
  →こんなに短くなりました!!

(3)ForEach文でFind関数で前月No→当月Noを検索し転記
  →実はここで引っかかりました。。1つのsheetでテストしたときは大丈夫でしたが、2つのsheetにわけて下記のように実行すると存在するNoもすべて(見つかりません)と前月sheetに書きこまれ、当月sheetには一つも転記されませんでした。どこが悪いかわかりますでしょうか?2つのsheetですが(2)のテストでは下記のような感じでもうまくいったので、ちょっと自分ではわかりません。。なお「rM」の上にカーソルを合わせるとデータが表示されましたが、「rH」の上ではNothingと表示されました。見て頂けると助かります。よろしくお願いいたします。
--------------------------------------
● ws1→当月⇔前月対比sheet(No:C列)F列から転記とする
● ws2→前月sheet(No:C列、Noなし:A列に見つかりません)
● 転記先20行目~の rHとrMのみ左右の場所を入れ替えました

Sub sample3_3()
    Public ws1 As Worksheet
    Public ws2 As Worksheet
    Public tmax As Long
    Public zmax As Long    
 ----------------------------
    Dim rHall As Range
    Dim rMall As Range
    Dim rH As Range
    Dim rM As Range
    
    Set ws1 = Worksheets("当月対比")
    Set ws2 = Worksheets("前月")
    tmax = ws1.Range("F1048576").End(xlUp).Row
    zmax = ws2.Range("F1048576").End(xlUp).Row
    
    Set rHall = ws1.Range("C2","C" & tmax) 
    Set rMall = ws2.Range("C2","C" & zmax) 
     
    For Each rM In rMall
        Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
        If Not rH Is Nothing Then
            rH.Offset(, 3).Value = rM.Offset(, 3).Value
    rH.Offset(, 4).Value = rM.Offset(, 4).Value
      ・
      ・
      
        Else
            rM.Offset(, -2).Value = "見つかりません" 
        End If
    Next
End Sub


*********************************


> 受講生 さん:
>
> こんにちは。
>
> For Next構文を複数組み合わせることでマッチングをできるようになった。
> ただし、データの件数が多いため、マクロ実行時間短縮のため、より高速にマッチングできる方法を求めている。
> そこで、配列を使うとマッチングを高速化できるのではなのではないかと考えた。
> ついては、この見立ては適切かどうか教えてほしい。
> また、適切だということならば、より具体的な方針について相談したい。
>
> ということかと思います。
>
> さて、では、マッチングのパフォーマンスが配列を使うと改善するか?というと。
> するにはしますが、そんなに劇的には変わらないかと思います。理由は、この回答の最後に示します。
>
>
> マッチングのパフォーマンスを上げるための進化のプロセスは、以下のとおりです。
>
> [1] For Next構文を複数組み合わせることでマッチングをできるようになる
> [2] For Each構文を複数組み合わせることでマッチングをできるようになる
> [3] Findメソッドを使うことでマッチングをできるようになる
> [4] SQLのSELECT文を使うことでマッチングできるようになる
>
> 以下、受講生さんは[1]はもうできるという前提で話を進めます。
> また、該当するNo.がない場合はデータの下部に転記するというところまでできるという前提です。
>
> 話を簡単にするため、同一シート内にある2つの表でマッチングするものとしましょう。
>
> 左の表はA-D列、2行目から201行目まで。
> 右の表はF-I列、2行目から251行目まで。
> A列とF列で値が一致したら、G列の値をD列に転記する。
> マッチするレコードは0件か1件。
>
> '【参考】以下は、デモデータ作成マクロ
>
Sub sample0()
>     Randomize
>     Dim hida As Long
>     For hida = 2 To 201
>         Range("A" & hida).Value = hida - 1
>         Range("B" & hida).Value = "hida1 " & hida - 1
>         Range("C" & hida).Value = "hida2 " & hida - 1
>     Next
> 
>     For hida = 2 To 251
>         Range("F" & hida).Value = hida - 1
>         Range("G" & hida).Value = "migi1 " & hida - 1
>         Range("H" & hida).Value = Rnd()
>     Next
>     Range("F1").CurrentRegion.Sort Key1:=Range("H1"), Order1:=xlAscending, Header:=xlYes
> End Sub

>
> すると、[1]では、以下の要領ですね。
>
>
Sub sample1()
>     Dim hida As Long
>     Dim migi As Long
>     For hida = 2 To 201
>         For migi = 2 To 251
>             If Range("A" & hida).Value = Range("F" & migi).Value Then
>                 Range("D" & hida).Value = Range("G" & migi).Value
>                 Exit For
>             End If
>         Next
>     Next
> End Sub

>
>
> [2] For Each構文を使ったほうが高速化はします。
> For Next構文だと、 Range("A" & hida) 等と指定する都度、該当するセルを探してメモリに格納する。
> 一方、For Each構文では、処理対象のセルのすべてへの参照をいったんメモリに格納し、それから処理するから。探索対象を実際にセルを見に行って割り出すか、Forループ開始時にあらかじめメモリに入れておいたリストから見つけるか?の違い。プログラム実行領域が確保しているメモリへのアクセスのほうが当然に高速です。
>
>
Sub sample2_1()
>     Dim rHall As Range
>     Dim rMall As Range
>     Dim rH As Range
>     Dim rM As Range
>     
>     Set rHall = Range("A2:A201")
>     Set rMall = Range("F2:F251")
>     
>     For Each rH In rHall
>         For Each rM In rMall
>             If rH.Value = rM.Value Then
>                 rH.Offset(, 3).Value = rM.Offset(, 1)
>                 Exit For
>             End If
>         Next
>     Next
> End Sub

>
> 以下でも結果は変わりません。
> 変数をむやみに宣言するのを嫌うならばこういう書き方もあり。
>
>
Sub sample2_2()
>     Dim rH As Range
>     Dim rM As Range
>     
>     For Each rH In Range("A2:A201")
>         For Each rM In Range("F2:F251")
>             If rH.Value = rM.Value Then
>                 rH.Offset(, 3).Value = rM.Offset(, 1)
>                 Exit For
>             End If
>         Next
>     Next
> End Sub

>
>
> [3] さて、次に、.Findメソッドです。
> 発展編1で学んだ要領で自動記録をしつつエクセル画面から検索をすると、 .Find メソッドのコードのサンプルを得られます。
>
> 以下は、B列セルのB2:B201を選択した状態で "hida1 171" をキーワードに完全一致で検索した場合に得られるコードの例。
> (エクセルのバージョンや環境によって得られるコードは多少異なります)
>
>
Sub Macro1()
> '
> ' Macro1 Macro
> '
> 
> '
>     Range("B2").Select
>     Range(Selection, Selection.End(xlDown)).Select
>     Selection.Find(What:="hida1 171", After:=ActiveCell, LookIn:=xlFormulas, _
>         LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
>         MatchCase:=False, MatchByte:=False, SearchFormat:=False).Activate
> End Sub

>
> 整形して不要部分を削除してみます。
>
> 以下でも動きます。
>
>
Sub FindSample()
>     Range("B2:B201").Find(What:="hida1 171", LookIn:=xlFormulas, LookAt:=xlWhole).Activate
> End Sub

> (本当は、 LookIn:=xlFormulas もこのケースでは不要です。MSDNの公式ヘルプ等でもご自身で調べてみてください
> https://docs.microsoft.com/ja-jp/office/vba/api/excel.range.find )
>
> 検索機能を使うことのメリットは、ループ内で値を拾って調べる処理を書かないでも、エクセルが一発で該当する値を見つけてくれることです。
>
> ということで、さきほどの[2]で提案したマクロは、以下のように書き換えられます。
> まずは、該当するレコードが、必ず、1件だけ存在する場合。
>
>
Sub sample3_1()
>     Dim rHall As Range
>     Dim rMall As Range
>     Dim rH As Range
>     
>     Set rHall = Range("A2:A201")
>     Set rMall = Range("F2:F251")
>     
>     For Each rH In rHall
>         rH.Offset(, 3).Value = rMall.Find(what:=rH.Value, lookat:=xlWhole).Offset(, 1).Value
>     Next
> End Sub

>
> 面倒なのは、以下のそれぞれの場合です。
> [3-A] 該当するレコードがみつからない場合
> [3-B] 該当するレコードが複数ある場合
>
> [3-A] でのNG例として、以下のコードを書いてみました。
> 左の表と右の表を比較して、マッチングしたら左の表の値を右の表に転記します。
> しかし、右の表でIDが200を超えるものについて処理しようとしたところでエラーになります。
> .Findメソッドの戻り値が Nothing (つまり、当該セルは存在しない)となるからです。
>
>
Sub sample3_2()
>     Dim rHall As Range
>     Dim rMall As Range
>     Dim rM As Range
>     
>     Set rHall = Range("A2:A201")
>     Set rMall = Range("F2:F251")
>     
>     For Each rM In rMall
>         rM.Offset(, 3).Value = rHall.Find(what:=rM.Value, lookat:=xlWhole).Offset(, 1).Value
>     Next
> End Sub

>
> このエラーの回避策は、.Findメソッドの戻り値が Nothing かどうかによって処理を分岐することです。
> 以下の要領。
>
>
Sub sample3_3()
>     Dim rHall As Range
>     Dim rMall As Range
>     Dim rH As Range
>     Dim rM As Range
>     
>     Set rHall = Range("A2:A201")
>     Set rMall = Range("F2:F251")
>     
>     For Each rM In rMall
>         Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
>         If Not rH Is Nothing Then
>             rM.Offset(, 3).Value = rH.Offset(, 1).Value
>         Else
>             rM.Offset(, 3).Value = "見つかりません"
>         End If
>     Next
> End Sub

>
> [3-B]の検索結果が複数存在する場合の処理については、前記MSDNサイトで「検索を繰り返すには、 FindNext および FindPrevious メソッドを使用できます。」という項目あたりを調べてみてください。
> ひとつのご質問への回答としてはそこまで書くとボリュームが大きくなりすぎるのでというのと、ご期待だった配列を使った解法からかなりそれた方法の提案ということもあるので、僕からの解説はこのくらいにします。
>
> SQLを使う方法の件についても、上記と同様の理由で省略します。外部連携講座の範囲になりますし。
> まずは上記[3]に習熟してもらえれば、と思います。
>
>
> 最後に、この課題で配列を使うと高速化するのか?という件について書きます。
> 配列に値なりセル範囲への参照なりを格納しても「各要素を順番に取り出して比較していく」というやり方だと[1], [2]と変わらないので、[3]の .Find メソッドには及びません。
>
>
> 以上です。
> 参考になれば、と思います。


11670 : 小川慶一の回答 (2019-11-24 14:00:10)

受講生 さん:

こんにちは。

For Next構文を複数組み合わせることでマッチングをできるようになった。
ただし、データの件数が多いため、マクロ実行時間短縮のため、より高速にマッチングできる方法を求めている。
そこで、配列を使うとマッチングを高速化できるのではなのではないかと考えた。
ついては、この見立ては適切かどうか教えてほしい。
また、適切だということならば、より具体的な方針について相談したい。

ということかと思います。

さて、では、マッチングのパフォーマンスが配列を使うと改善するか?というと。
するにはしますが、そんなに劇的には変わらないかと思います。理由は、この回答の最後に示します。


マッチングのパフォーマンスを上げるための進化のプロセスは、以下のとおりです。

[1] For Next構文を複数組み合わせることでマッチングをできるようになる
[2] For Each構文を複数組み合わせることでマッチングをできるようになる
[3] Findメソッドを使うことでマッチングをできるようになる
[4] SQLのSELECT文を使うことでマッチングできるようになる

以下、受講生さんは[1]はもうできるという前提で話を進めます。
また、該当するNo.がない場合はデータの下部に転記するというところまでできるという前提です。

話を簡単にするため、同一シート内にある2つの表でマッチングするものとしましょう。

左の表はA-D列、2行目から201行目まで。
右の表はF-I列、2行目から251行目まで。
A列とF列で値が一致したら、G列の値をD列に転記する。
マッチするレコードは0件か1件。

'【参考】以下は、デモデータ作成マクロ

Sub sample0()
    Randomize
    Dim hida As Long
    For hida = 2 To 201
        Range("A" & hida).Value = hida - 1
        Range("B" & hida).Value = "hida1 " & hida - 1
        Range("C" & hida).Value = "hida2 " & hida - 1
    Next

    For hida = 2 To 251
        Range("F" & hida).Value = hida - 1
        Range("G" & hida).Value = "migi1 " & hida - 1
        Range("H" & hida).Value = Rnd()
    Next
    Range("F1").CurrentRegion.Sort Key1:=Range("H1"), Order1:=xlAscending, Header:=xlYes
End Sub


すると、[1]では、以下の要領ですね。

Sub sample1()
    Dim hida As Long
    Dim migi As Long
    For hida = 2 To 201
        For migi = 2 To 251
            If Range("A" & hida).Value = Range("F" & migi).Value Then
                Range("D" & hida).Value = Range("G" & migi).Value
                Exit For
            End If
        Next
    Next
End Sub



[2] For Each構文を使ったほうが高速化はします。
For Next構文だと、 Range("A" & hida) 等と指定する都度、該当するセルを探してメモリに格納する。
一方、For Each構文では、処理対象のセルのすべてへの参照をいったんメモリに格納し、それから処理するから。探索対象を実際にセルを見に行って割り出すか、Forループ開始時にあらかじめメモリに入れておいたリストから見つけるか?の違い。プログラム実行領域が確保しているメモリへのアクセスのほうが当然に高速です。

Sub sample2_1()
    Dim rHall As Range
    Dim rMall As Range
    Dim rH As Range
    Dim rM As Range
    
    Set rHall = Range("A2:A201")
    Set rMall = Range("F2:F251")
    
    For Each rH In rHall
        For Each rM In rMall
            If rH.Value = rM.Value Then
                rH.Offset(, 3).Value = rM.Offset(, 1)
                Exit For
            End If
        Next
    Next
End Sub


以下でも結果は変わりません。
変数をむやみに宣言するのを嫌うならばこういう書き方もあり。

Sub sample2_2()
    Dim rH As Range
    Dim rM As Range
    
    For Each rH In Range("A2:A201")
        For Each rM In Range("F2:F251")
            If rH.Value = rM.Value Then
                rH.Offset(, 3).Value = rM.Offset(, 1)
                Exit For
            End If
        Next
    Next
End Sub



[3] さて、次に、.Findメソッドです。
発展編1で学んだ要領で自動記録をしつつエクセル画面から検索をすると、 .Find メソッドのコードのサンプルを得られます。

以下は、B列セルのB2:B201を選択した状態で "hida1 171" をキーワードに完全一致で検索した場合に得られるコードの例。
(エクセルのバージョンや環境によって得られるコードは多少異なります)

Sub Macro1()
'
' Macro1 Macro
'

'
    Range("B2").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.Find(What:="hida1 171", After:=ActiveCell, LookIn:=xlFormulas, _
        LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
        MatchCase:=False, MatchByte:=False, SearchFormat:=False).Activate
End Sub


整形して不要部分を削除してみます。

以下でも動きます。

Sub FindSample()
    Range("B2:B201").Find(What:="hida1 171", LookIn:=xlFormulas, LookAt:=xlWhole).Activate
End Sub

(本当は、 LookIn:=xlFormulas もこのケースでは不要です。MSDNの公式ヘルプ等でもご自身で調べてみてください
https://docs.microsoft.com/ja-jp/office/vba/api/excel.range.find )

検索機能を使うことのメリットは、ループ内で値を拾って調べる処理を書かないでも、エクセルが一発で該当する値を見つけてくれることです。

ということで、さきほどの[2]で提案したマクロは、以下のように書き換えられます。
まずは、該当するレコードが、必ず、1件だけ存在する場合。

Sub sample3_1()
    Dim rHall As Range
    Dim rMall As Range
    Dim rH As Range
    
    Set rHall = Range("A2:A201")
    Set rMall = Range("F2:F251")
    
    For Each rH In rHall
        rH.Offset(, 3).Value = rMall.Find(what:=rH.Value, lookat:=xlWhole).Offset(, 1).Value
    Next
End Sub


面倒なのは、以下のそれぞれの場合です。
[3-A] 該当するレコードがみつからない場合
[3-B] 該当するレコードが複数ある場合

[3-A] でのNG例として、以下のコードを書いてみました。
左の表と右の表を比較して、マッチングしたら左の表の値を右の表に転記します。
しかし、右の表でIDが200を超えるものについて処理しようとしたところでエラーになります。
.Findメソッドの戻り値が Nothing (つまり、当該セルは存在しない)となるからです。

Sub sample3_2()
    Dim rHall As Range
    Dim rMall As Range
    Dim rM As Range
    
    Set rHall = Range("A2:A201")
    Set rMall = Range("F2:F251")
    
    For Each rM In rMall
        rM.Offset(, 3).Value = rHall.Find(what:=rM.Value, lookat:=xlWhole).Offset(, 1).Value
    Next
End Sub


このエラーの回避策は、.Findメソッドの戻り値が Nothing かどうかによって処理を分岐することです。
以下の要領。

Sub sample3_3()
    Dim rHall As Range
    Dim rMall As Range
    Dim rH As Range
    Dim rM As Range
    
    Set rHall = Range("A2:A201")
    Set rMall = Range("F2:F251")
    
    For Each rM In rMall
        Set rH = rHall.Find(what:=rM.Value, lookat:=xlWhole)
        If Not rH Is Nothing Then
            rM.Offset(, 3).Value = rH.Offset(, 1).Value
        Else
            rM.Offset(, 3).Value = "見つかりません"
        End If
    Next
End Sub


[3-B]の検索結果が複数存在する場合の処理については、前記MSDNサイトで「検索を繰り返すには、 FindNext および FindPrevious メソッドを使用できます。」という項目あたりを調べてみてください。
ひとつのご質問への回答としてはそこまで書くとボリュームが大きくなりすぎるのでというのと、ご期待だった配列を使った解法からかなりそれた方法の提案ということもあるので、僕からの解説はこのくらいにします。

SQLを使う方法の件についても、上記と同様の理由で省略します。外部連携講座の範囲になりますし。
まずは上記[3]に習熟してもらえれば、と思います。


最後に、この課題で配列を使うと高速化するのか?という件について書きます。
配列に値なりセル範囲への参照なりを格納しても「各要素を順番に取り出して比較していく」というやり方だと[1], [2]と変わらないので、[3]の .Find メソッドには及びません。


以上です。
参考になれば、と思います。



> 小川先生お世話になります。
>
> 解釈があっているかの確認も含め、配列について質問させていただきます。
>
> 1つのExcelに2つのsheetがあり、1つの対比sheetには左に今月、右に前月のデータを横並びにし、差異を対比できるようにしています。
> データはNo.で管理しています。
> もう1つのsheetには前月のデータのみを入れています。
> 行はデータNo.で列は項目とし、列10列くらいは毎月変わりませんが、行は5000行以上あり毎月追加削除が発生するので変わります。
>
> 発展1を参考に対比sheetに今月データを貼り付けた後に、前月sheetからで該当するデータを転記する。
> 該当するNo.がない場合はデータの下部に転記する。
> 最後に横並びにしたデータを対比し差異に色をつける、というマクロを作りました。
> ですが、行も列も多くちょっと時間がかかるため、配列を使ってやってみようと思いました。
>
> そこで確認ですが、配列化するのはこの事例でいうと転記元の前月のデータ(5000行10列)を1つの配列とし、該当するNo.の必要な列を、今月列=前月列として転記する。
> で合っていますか?
>
> 転記先の対比sheetの転記列や、検索No.列も別の配列にしたほうがいいのかなど、配列にした方が良い基準がいまいちわからないのですが‥
> よろしくおねがいいたします。


11669 : 受講生さんのコメント (2019-11-23 12:31:28)

小川先生お世話になります。

解釈があっているかの確認も含め、配列について質問させていただきます。
1つのExcelに2つのsheetがあり、1つの対比sheetには左に今月、右に前月のデータを横並びにし、差異を対比できるようにしています。データはNo.で管理しています。もう1つのsheetには前月のデータのみを入れています。行はデータNo.で列は項目とし、列10列くらいは毎月変わりませんが、行は5000行以上あり毎月追加削除が発生するので変わります。
発展1を参考に対比sheetに今月データを貼り付けた後に、前月sheetからで該当するデータを転記する。該当するNo.がない場合はデータの下部に転記する。最後に横並びにしたデータを対比し差異に色をつける、というマクロを作りました。ですが、行も列も多くちょっと時間がかかるため、配列を使ってやってみようと思いました。

そこで確認ですが、配列化するのはこの事例でいうと転記元の前月のデータ(5000行10列)を1つの配列とし、該当するNo.の必要な列を、今月列=前月列として転記する。で合っていますか?

転記先の対比sheetの転記列や、検索No.列も別の配列にしたほうがいいのかなど、配列にした方が良い基準がいまいちわからないのですが‥
よろしくおねがいいたします。


9345 : 小川慶一の回答 (2018-01-16 16:16:56)

澤田 亨さん:

ひきつづき、よろしくお願いいたします。


9343 : 澤田 亨さんのコメント (2018-01-14 23:50:08)

小川慶一さん:
ありがとうございます。
このような細かいアドバイスをいただけるところがガラパゴスタディーの魅力と感じております。考え方もとても参考になります。鍛錬します。

> 澤田 亨さん:
>
> > preserve だとエラーになりますね。preserveしているか否かで最後のインデックスでなくても変更可能ですね。もう少しいじってみて理解を深めたいと思います。ありがとうございます。
>
> むしろ、僕のほうがこれにびっくりしました。
> ReDim だけだと、好きにインデックス変更できるんですね。
> (試したら、いったん三次元配列として ReDim した配列を 二次元配列として ReDim することも可能でした...)
>
> 実務でほぼ絶対にやらないようなことなので、僕も澤田さんにサンプルお渡しする前のテストがいい加減でした。
> 申し訳ありません。
>
>
> それから、当初のご質問に対して:
>
> >>redim tm(5,3,6)だとします。
> >>私は横に5マス、縦に3マスの方眼紙みたいなものが6枚重なっているような形をイメージしました。
> >>しかし間違っているようで、横に5マス、縦に6マスの方眼紙が3枚重なっている。そして縦のマスは増やせるが重なる枚数は増やせない。
> >例え話が適切なものか?はこれを読んだだけでは分かりませんでした。
> >しかし、僕ならそういう例え方はしませんね。そう僕が感じる明確な理由はありますが、多次元配列自体に対する理解がまだ浅いようなので、今はそれについてはお伝えするつもりはありません。
>
> 以下、preserveで再定義するという前提で話します。
>
> 配列でインデックスの値を変更できるのは、最後の引数だけです。
> 以下で、変数で示した値のみです。
>
> ReDim tm(5, 3, c)
>
> これは、澤田さんの例えに当てはめると、以下のとおりになります。
> 「横に5マス、縦にCマスの方眼紙が3枚重なっている。そして縦のマスは増やせるが重なる枚数は増やせない」
>
> 間違いではないですが、どうせ例えるなら以下ですかね。
>
> 「横に5マス、縦に3マスの方眼紙がC枚重なっている。そして、縦横のマスの大きさは変更できないが、枚数は増やせる」
>
> 澤田さんの例えは、たとえば100枚の原稿用紙があったとして、そのすべてについて、縦のマス数を変更するわけです。いびつですね。
> 僕の例えは、原稿用紙の枚数を増やすようなイメージですね。
>
> 手作業で一枚一枚の原稿用紙の縦サイズを変更するシーンを想像してみてください。
> 次に、手作業で原稿用紙を一枚一枚追加するシーンを想像してみてください。
> どちらのほうが、現実感を持ってイメージができるでしょう。
>
> >例え話が適切なものか?はこれを読んだだけでは分かりませんでした。
> >しかし、僕ならそういう例え方はしませんね。
>
> と書いたのは、そういう意味です。
> 例えとしてででてきた話が非現実的で、例えとして不適切です。
>
> あと、それ以前に、配列の宣言は 5, 3, c、例え話ででてくる値の順番は 5, c, 3。
> この順序の変更も不要な混乱を生じさせます。
>
> 形が韻を踏むように書いたほうが、マクロのコードも読みやすいですよね。
> マクロを学ぶ過程から、そういうところも学んでもらたいです。
> そういうところも意識しつつマクロをガンガン書けば、今後、こういうところも改善されていくものと思います。
>
> ひきつづき、がんばってください。
>


9342 : 小川慶一の回答 (2018-01-14 22:01:15)

澤田 亨さん:

> preserve だとエラーになりますね。preserveしているか否かで最後のインデックスでなくても変更可能ですね。もう少しいじってみて理解を深めたいと思います。ありがとうございます。

むしろ、僕のほうがこれにびっくりしました。
ReDim だけだと、好きにインデックス変更できるんですね。
(試したら、いったん三次元配列として ReDim した配列を 二次元配列として ReDim することも可能でした...)

実務でほぼ絶対にやらないようなことなので、僕も澤田さんにサンプルお渡しする前のテストがいい加減でした。
申し訳ありません。


それから、当初のご質問に対して:

>>redim tm(5,3,6)だとします。
>>私は横に5マス、縦に3マスの方眼紙みたいなものが6枚重なっているような形をイメージしました。
>>しかし間違っているようで、横に5マス、縦に6マスの方眼紙が3枚重なっている。そして縦のマスは増やせるが重なる枚数は増やせない。
>例え話が適切なものか?はこれを読んだだけでは分かりませんでした。
>しかし、僕ならそういう例え方はしませんね。そう僕が感じる明確な理由はありますが、多次元配列自体に対する理解がまだ浅いようなので、今はそれについてはお伝えするつもりはありません。

以下、preserveで再定義するという前提で話します。

配列でインデックスの値を変更できるのは、最後の引数だけです。
以下で、変数で示した値のみです。

ReDim tm(5, 3, c)

これは、澤田さんの例えに当てはめると、以下のとおりになります。
「横に5マス、縦にCマスの方眼紙が3枚重なっている。そして縦のマスは増やせるが重なる枚数は増やせない」

間違いではないですが、どうせ例えるなら以下ですかね。

「横に5マス、縦に3マスの方眼紙がC枚重なっている。そして、縦横のマスの大きさは変更できないが、枚数は増やせる」

澤田さんの例えは、たとえば100枚の原稿用紙があったとして、そのすべてについて、縦のマス数を変更するわけです。いびつですね。
僕の例えは、原稿用紙の枚数を増やすようなイメージですね。

手作業で一枚一枚の原稿用紙の縦サイズを変更するシーンを想像してみてください。
次に、手作業で原稿用紙を一枚一枚追加するシーンを想像してみてください。
どちらのほうが、現実感を持ってイメージができるでしょう。

>例え話が適切なものか?はこれを読んだだけでは分かりませんでした。
>しかし、僕ならそういう例え方はしませんね。

と書いたのは、そういう意味です。
例えとしてででてきた話が非現実的で、例えとして不適切です。

あと、それ以前に、配列の宣言は 5, 3, c、例え話ででてくる値の順番は 5, c, 3。
この順序の変更も不要な混乱を生じさせます。

形が韻を踏むように書いたほうが、マクロのコードも読みやすいですよね。
マクロを学ぶ過程から、そういうところも学んでもらたいです。
そういうところも意識しつつマクロをガンガン書けば、今後、こういうところも改善されていくものと思います。

ひきつづき、がんばってください。


9339 : 澤田 亨さんのコメント (2018-01-11 00:46:47)

小川慶一さん:

サンプルコードありがとうございます。
仕事から帰宅してこのようなメールを目にすると大変うれしいです。
早速検証してみます。

Sub hoge()
    Dim tm()
    ReDim tm(5, 3, 6)
    ReDim tm(7, 3, 6) '実験1。澤田さん自身の結果予想は? NG!
    ReDim tm(5, 7, 6) '実験2。澤田さん自身の結果予想は? NG!
 ReDim tm(5, 3, 7) '実験3。澤田さん自身の結果予想は? OK!

End Sub


の結果になると思いましたが「あれ?」実行時エラーが全く出ません(汗)
preserve だとエラーになりますね。preserveしているか否かで最後のインデックスでなくても変更可能ですね。もう少しいじってみて理解を深めたいと
思います。ありがとうございます。

> 澤田 亨さん:
>
> 二次元配列についての復習はいかがですか。
>
> > ですので、澤田さんがおっしゃりたいことをテストできるコードを自作してください。
> > コードを自作したら、それを実行し、その結果を報告ください。
> > そして、その結果を元にして理解を進めてください。
> > 理解が進むなり決定的に行き詰まるなりしたら、あらためて、報告なりその上での質問なりしてください。
> > それがいちばん理解の助けになります。
> > それがいちばん理解の助けになります。
>
> 上記について。
> 僕なら、以下のコードで検証しますね。
>
>
'お題:
> '横に5マス、縦に6マスの方眼紙が3枚重なっている。
> 'そして縦のマスは増やせるが重なる枚数は増やせない。
> 'この考え方であっていますか?
> 
> '以下の実験1-3について、上記の「考え方」に基づいた結果予想をしなさい。
> 'その後、実験をしなさい。
> '実験後、前記予想との比較検証をしなさい。
> Sub hoge()
>     Dim tm()
>     ReDim tm(5, 3, 6)
> 
>     ReDim tm(7, 3, 6) '実験1。澤田さん自身の結果予想は?
>     ReDim tm(5, 7, 6) '実験2。澤田さん自身の結果予想は?
>     ReDim tm(5, 3, 7) '実験3。澤田さん自身の結果予想は?
>     
> End Sub

>
> 自分で手を動かさないと、絶対に上達しません。
>


9336 : 小川慶一の回答 (2018-01-10 08:06:56)

澤田 亨さん:

二次元配列についての復習はいかがですか。

> ですので、澤田さんがおっしゃりたいことをテストできるコードを自作してください。
> コードを自作したら、それを実行し、その結果を報告ください。
> そして、その結果を元にして理解を進めてください。
> 理解が進むなり決定的に行き詰まるなりしたら、あらためて、報告なりその上での質問なりしてください。
> それがいちばん理解の助けになります。
> それがいちばん理解の助けになります。

上記について。
僕なら、以下のコードで検証しますね。

'お題:
'横に5マス、縦に6マスの方眼紙が3枚重なっている。
'そして縦のマスは増やせるが重なる枚数は増やせない。
'この考え方であっていますか?

'以下の実験1-3について、上記の「考え方」に基づいた結果予想をしなさい。
'その後、実験をしなさい。
'実験後、前記予想との比較検証をしなさい。
Sub hoge()
    Dim tm()
    ReDim tm(5, 3, 6)

    ReDim tm(7, 3, 6) '実験1。澤田さん自身の結果予想は?
    ReDim tm(5, 7, 6) '実験2。澤田さん自身の結果予想は?
    ReDim tm(5, 3, 7) '実験3。澤田さん自身の結果予想は?
    
End Sub


自分で手を動かさないと、絶対に上達しません。


9333 : 澤田 亨さんのコメント (2018-01-08 23:14:40)

まず復習します。
ありがとうございます。

小川慶一さん:

> 澤田 亨さん:
>
> > しかし間違っているようで、横に5マス、縦に6マスの方眼紙が3枚重なっている。そして縦のマスは増やせるが重なる枚数は増やせない。
>
> 例え話が適切なものか?はこれを読んだだけでは分かりませんでした。
> しかし、僕ならそういう例え方はしませんね。そう僕が感じる明確な理由はありますが、多次元配列自体に対する理解がまだ浅いようなので、今はそれについてはお伝えするつもりはありません。
>
> 三次元配列は三次元配列として理解するのがいちばん簡単です。
> 「重なった方眼紙」とみなさないと理解できないでいるということは、ご自身が手を動かして検証なり演習なり実務活用なりをした経験が足りないということです。
>
> ですので、澤田さんがおっしゃりたいことをテストできるコードを自作してください。
> コードを自作したら、それを実行し、その結果を報告ください。
> そして、その結果を元にして理解を進めてください。
> 理解が進むなり決定的に行き詰まるなりしたら、あらためて、報告なりその上での質問なりしてください。
> それがいちばん理解の助けになります。
>
> 先に二次元配列から復習したほうがいいでしょう。
> さらに言うと、テキストに載っている演習問題もしっかりやってからのほうが良いかと思います。
>


9332 : 小川慶一の回答 (2018-01-08 10:33:44)

澤田 亨さん:

> しかし間違っているようで、横に5マス、縦に6マスの方眼紙が3枚重なっている。そして縦のマスは増やせるが重なる枚数は増やせない。

例え話が適切なものか?はこれを読んだだけでは分かりませんでした。
しかし、僕ならそういう例え方はしませんね。そう僕が感じる明確な理由はありますが、多次元配列自体に対する理解がまだ浅いようなので、今はそれについてはお伝えするつもりはありません。

三次元配列は三次元配列として理解するのがいちばん簡単です。
「重なった方眼紙」とみなさないと理解できないでいるということは、ご自身が手を動かして検証なり演習なり実務活用なりをした経験が足りないということです。

ですので、澤田さんがおっしゃりたいことをテストできるコードを自作してください。
コードを自作したら、それを実行し、その結果を報告ください。
そして、その結果を元にして理解を進めてください。
理解が進むなり決定的に行き詰まるなりしたら、あらためて、報告なりその上での質問なりしてください。
それがいちばん理解の助けになります。

先に二次元配列から復習したほうがいいでしょう。
さらに言うと、テキストに載っている演習問題もしっかりやってからのほうが良いかと思います。


9331 : 澤田 亨さんのコメント (2018-01-07 22:05:05)

Chap02-42から質問しています。
3次元配列について確認したいことがあります。
redim tm(5,3,6)だとします。
私は横に5マス、縦に3マスの方眼紙みたいなものが6枚重なっているような形をイメージしました。
しかし間違っているようで、横に5マス、縦に6マスの方眼紙が3枚重なっている。そして縦のマスは増やせるが重なる枚数は増やせない。
この考え方であっていますか?先生の言う通り今後あまり使う機会はなさそうなのですが宜しくお願いします。


3日がかりのその仕事、3分で終わらせる方法教えます。ガラパゴスタディーオンライン講座 ユーザー登録

本講座の動画一覧

  1. 【動画1】 式と戻り値1-データ型のおさらい
    【動画1】 式と戻り値1-データ型のおさらい 未習得
  2. 【動画2】 式と戻り値2-「式」と「戻り値」
    【動画2】 式と戻り値2-「式」と「戻り値」 未習得
  3. 【動画3】 式と戻り値3-「式」と「戻り値のデータ型」
    【動画3】  式と戻り値3-「式」と「戻り値のデータ型」 未習得
  4. 【動画4】 式と戻り値4-「式」とは(その1)
    【動画4】 式と戻り値4-「式」とは(その1) 未習得
  5. 【動画5】 式と戻り値5-「式」とは(その2)
    【動画5】 式と戻り値5-「式」とは(その2) 未習得
  6. 【動画6】 式と戻り値6-戻り値を返す式、戻り値を返さない式
    【動画6】  式と戻り値6-戻り値を返す式、戻り値を返さない式 未習得
  7. 【動画7】 コレクションとインデックス
    【動画7】  コレクションとインデックス 未習得
  8. 【動画8】 配列
    【動画8】 配列 未習得
  9. 【動画9】 静的配列
    【動画9】 静的配列 未習得
  10. 【動画10】 動的配列1-動的配列の基本
    【動画10】 動的配列1-動的配列の基本 未習得
  11. 【動画11】 動的配列2-Preserveキーワード
    【動画11】 動的配列2-Preserveキーワード 未習得
  12. 【動画12】 動的配列3-演習
    【動画12】 動的配列3-演習 未習得
  13. 【動画13】 多次元配列の基本
    【動画13】 多次元配列の基本 未習得
  14. 【動画14】 多次元動的配列
    【動画14】 多次元動的配列 未習得
  15. 【動画15】 多次元配列のサイズを調べる
    【動画15】 多次元配列のサイズを調べる 未習得
  16. 【動画16】 配列操作の便利関数、オプション、その他
    【動画16】  配列操作の便利関数、オプション、その他 未習得
  17. 【動画17】 連想配列1-Dictionaryオブジェクトの仕様
    【動画17】 連想配列1-Dictionaryオブジェクトの仕様 未習得
  18. 【動画18】 連想配列2-Dictionaryオブジェクトの使用例
    【動画18】 連想配列2-Dictionaryオブジェクトの使用例 未習得
  19. 【動画19】 連想配列3-Microsoft Scripting Runtimeのへの参照設定
    【動画19】 連想配列3-Microsoft Scripting Runtimeのへの参照設定 未習得
  20. 【動画20】 「名前付き引数」と「名前なし引数」
    【動画20】 「名前付き引数」と「名前なし引数」 未習得
  21. 【動画21】 省略可能な引数とその初期値
    【動画21】 省略可能な引数とその初期値 未習得
  22. 【動画22】 引数のデータ型
    【動画22】 引数のデータ型 未習得
  23. 【動画23】 Functionプロシージャ
    【動画23】 Functionプロシージャ 未習得
  24. 【動画24】 引数がひとつまたは複数のFunctionプロシージャ
    【動画24】 引数がひとつまたは複数のFunctionプロシージャ 未習得
  25. 【動画25】 Functionプロシージャ演習中
    【動画25】 Functionプロシージャ演習中 未習得
  26. 【動画26】 引数として配列を受け取るFunctionプロシージャ
    【動画26】 引数として配列を受け取るFunctionプロシージャ 未習得
  27. 【動画27】 引数を受け取らないSubプロシージャと引数つきSubプロシージャ
    【動画27】 引数を受け取らないSubプロシージャと引数つきSubプロシージャ 未習得
  28. 【動画28】 Subプロシージャの基本構造
    【動画28】 Subプロシージャの基本構造 未習得
  29. 【動画29】 モジュールレベル変数との使い分け
    【動画29】 モジュールレベル変数との使い分け 未習得
  30. 【動画30】 補講1-ディクショナリーオブジェクトのさらなる活用
    【動画30】 補講1-ディクショナリーオブジェクトのさらなる活用 未習得
  31. 【動画31】 補講2-ディクショナリーオブジェクトの .Count プロパティ
    【動画31】 補講2-ディクショナリーオブジェクトの .Count プロパティ 未習得
  32. 【動画32】 補講3-連想配列によるオブジェクトへの参照設定 - 新しいキーに設定する場合
    【動画32】 補講3-連想配列によるオブジェクトへの参照設定 - 新しいキーに設定する場合 未習得
  33. 【動画33】 補講4-連想配列によるオブジェクトへの参照設定 - 既存の値を上書きする場合
    【動画33】 補講4-連想配列によるオブジェクトへの参照設定 - 既存の値を上書きする場合 未習得
  34. 【動画34】 補講5-複数セルの集合を作るための便利なメソッド2つ
    【動画34】 補講5-複数セルの集合を作るための便利なメソッド2つ 未習得
  35. 【動画35】 補講6-連想配列演習-取引先ごとに取引金額の合計を算出する
    【動画35】 補講6-連想配列演習-取引先ごとに取引金額の合計を算出する 未習得
  36. 【動画36】 補講7-ウォッチ式の活用
    【動画36】 補講7-ウォッチ式の活用 未習得
  37. 【動画37】 補講8-ウォッチ式で配列の状態を確認する
    【動画37】 補講8-ウォッチ式で配列の状態を確認する 未習得
  38. 【動画38】 補講9-たった1行のコードでセルのデータを配列に投入する
    【動画38】 補講9-たった1行のコードでセルのデータを配列に投入する 未習得

塾長 小川慶一

メニュー

コメント紹介

もっと見る

ページの先頭へ