動的配列の勉強

「配列」の処理はプログラムロジックを作る上で避けて通れない重要なものです。
配列操作は「苦手」ですか?それとも「初めて」ですか?   「配列操作」はどのようなプログラム言語でも登場するもので、VBA特有のものではありません。
この「配列操作」をマスターすることは、プログラム作成を進める上で重要な要素です。「ループ処理」や「判断・分岐」などと組み合わせて事前に件数が分からない配列を取り扱うのが「動的配列」ですが、 VBAの初心者にとっては一対一でないことで理解しにくいばかりか、動作検証もやりにくいもので嫌われると思いますが、マスターしてしまえばいろいろな処理に駆使することができて「幅」が広がることは間違いありません。
その上、「動的配列」とはその要素数が可変となる配列のことです。
まずは「静的配列」をおさらいしておきます。
ここでのサンプルコードは特に動作効率などを考えてはいないもので、最終的にシートに値を転記させるなら特に配列変数などを用いずに直接セルに書き込めば良いことなのですが、 ここでは配列変数の使い方を学ぶわけであって、シートへの値転記は変数への格納結果の確認ということで利用しています。

まずは、配列変数を知らない、使わない場合はどうなるでしょう。


'***************************************************************************************************
'* 処理名 :TEST1
'* 機能  :固定配列のサンプル@
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2006年11月07日
'* 作成者 :井上 治
'* 更新日 :2020年02月11日
'* 更新者 :井上 治
'* 機能説明:⇒配列変数を使わない、あるいは知らない場合は?
'* 注意事項:
'***************************************************************************************************
Sub TEST1()
    '-----------------------------------------------------------------------------------------------
    Dim lngRow As Long                                              ' 行INDEX
    Dim tblItem1 As String                                          ' 文字列WORK@
    Dim tblItem2 As String                                          ' 文字列WORKA
    Dim tblItem3 As String                                          ' 文字列WORKB
    Dim tblItem4 As String                                          ' 文字列WORKC
    Dim tblItem5 As String                                          ' 文字列WORKD
    ' シートのクリア
    Cells.ClearContents
    ' 配列の各要素に値を格納
    tblItem1 = "あああ"
    tblItem2 = "いいい"
    tblItem3 = "ううう"
    tblItem4 = "えええ"
    tblItem5 = "おおお"
    ' 結果をシートに展開してみる
    For lngRow = 1 To 5
        ' 変数名に番号が表意していてもループ処理の意味がない!
        Select Case lngRow
            Case 1: Cells(lngRow, 1).Value = tblItem1
            Case 2: Cells(lngRow, 1).Value = tblItem2
            Case 3: Cells(lngRow, 1).Value = tblItem3
            Case 4: Cells(lngRow, 1).Value = tblItem4
            Case 5: Cells(lngRow, 1).Value = tblItem5
        End Select
    Next lngRow
End Sub

おそらく、このように変数名に配列要素番号が表意したような変数名を付けて利用されるでしょうが、変数名に「番号」を表意させてもループ処理などでその「番号」が利用できるわけではありません。 ここでは要素数5件の配列なので記述に困るわけではありませんが、要素数が多かったり、参照箇所が多い場合にその記述が大変になることを想像して下さい。

では、要素数5件と決まった「静的配列」の処理を見てみましょう。まずは配列の要素番号をシートの行列と同じように「1」始まりにしたサンプルです。


'***************************************************************************************************
'* 処理名 :TEST2
'* 機能  :固定配列のサンプルA
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2006年11月07日
'* 作成者 :井上 治
'* 更新日 :2020年02月11日
'* 更新者 :井上 治
'* 機能説明:⇒シートの行列と同様に要素番号を1から始まる配列としてみる。
'* 注意事項:
'***************************************************************************************************
Sub TEST2()
    '-----------------------------------------------------------------------------------------------
    Dim lngRow As Long                                              ' 行INDEX
    Dim tblItem(1 To 5) As String                                   ' 要素数5個(1〜5)の配列
    ' シートのクリア
    Cells.ClearContents
    ' 配列の各要素に値を格納
    tblItem(1) = "あああ"
    tblItem(2) = "いいい"
    tblItem(3) = "ううう"
    tblItem(4) = "えええ"
    tblItem(5) = "おおお"
    ' 配列の要素番号範囲の確認
    Debug.Print LBound(tblItem) & "〜" & UBound(tblItem)
    ' 結果をシートに展開してみる
    For lngRow = 1 To 5
        Cells(lngRow, 1).Value = tblItem(lngRow)
    Next lngRow
End Sub

このように、配列変数の宣言(Dimステートメント)段階で要素番号範囲を「1」から「5」だと決めてしまいます。

VBAWindows系開発言語一般のデフォルトでは、配列変数の要素番号はゼロ始まりです。


'***************************************************************************************************
'* 処理名 :TEST3
'* 機能  :固定配列のサンプルB
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2006年11月07日
'* 作成者 :井上 治
'* 更新日 :2020年02月11日
'* 更新者 :井上 治
'* 機能説明:⇒要素番号を0から始まる配列としてみる。(これがデフォルト)
'* 注意事項:
'***************************************************************************************************
Sub TEST3()
    '-----------------------------------------------------------------------------------------------
    Dim lngRow As Long                                              ' 行INDEX
    Dim lngIx As Long                                               ' テーブルINDEX
    Dim tblItem(4) As String                                        ' 要素数5個(0〜4)の配列
    ' シートのクリア
    Cells.ClearContents
    ' 配列の各要素に値を格納
    tblItem(0) = "あああ"
    tblItem(1) = "いいい"
    tblItem(2) = "ううう"
    tblItem(3) = "えええ"
    tblItem(4) = "おおお"
    ' 配列の要素番号範囲の確認
    Debug.Print LBound(tblItem) & "〜" & UBound(tblItem)
    ' 結果をシートに展開してみる
    For lngIx = 0 To 4
        lngRow = lngIx + 1                      ' 行番号は「1」始まり
        Cells(lngRow, 1).Value = tblItem(lngIx)
    Next lngIx
End Sub

5個の要素を持つ配列の場合、要素番号は「0」〜「4」となるのがデフォルトですが、この場合はセルへの格納などでは行番号が「1」始まりなので余分な加算が必要になります。

もうひとつ、前にも紹介していますが「Array関数」をご紹介しておきます。


'***************************************************************************************************
'* 処理名 :TEST4
'* 機能  :固定配列のサンプルC
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2006年11月07日
'* 作成者 :井上 治
'* 更新日 :2020年02月11日
'* 更新者 :井上 治
'* 機能説明:⇒定数的な件数の少ない配列はArray関数で作成することも可能
'* 注意事項:
'***************************************************************************************************
Sub TEST4()
    '-----------------------------------------------------------------------------------------------
    Dim lngRow As Long                                              ' 行INDEX
    Dim lngIx As Long                                               ' テーブルINDEX
    Dim tblItem As Variant                                          ' 要素数不定の配列
    ' シートのクリア
    Cells.ClearContents
    ' 配列の各要素に値を格納(要素0〜4となる)
    tblItem = Array("あああ", "いいい", "ううう", "えええ", "おおお")
    ' 配列の要素番号範囲の確認
    Debug.Print LBound(tblItem) & "〜" & UBound(tblItem)
    ' 結果をシートに展開してみる
    For lngIx = 0 To 4
        lngRow = lngIx + 1                      ' 行番号は「1」始まり
        Cells(lngRow, 1).Value = tblItem(lngIx)
    Next lngIx
End Sub

これはプロシージャ内で件数の限られている配列変数を「定数」的に利用する場合の要素内容の取り込みに便利な方法です。

この後で「動的配列」について説明しますが....


'***************************************************************************************************
'* 処理名 :TEST5
'* 機能  :固定配列のサンプルD
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2006年11月07日
'* 作成者 :井上 治
'* 更新日 :2020年02月11日
'* 更新者 :井上 治
'* 機能説明:⇒宣言段階では要素数を決めないサンプル
'* 注意事項:
'***************************************************************************************************
Sub TEST5()
    '-----------------------------------------------------------------------------------------------
    Dim lngRow As Long                                              ' 行INDEX
    Dim lngIx As Long                                               ' テーブルINDEX
    Dim tblItem As Variant                                          ' 要素数不定の配列
    ' シートのクリア
    Cells.ClearContents
    ' 先に要素数を決定する
    ReDim tblItem(4)
    ' 配列の各要素に値を格納
    tblItem(0) = "あああ"
    tblItem(1) = "いいい"
    tblItem(2) = "ううう"
    tblItem(3) = "えええ"
    tblItem(4) = "おおお"
    ' 配列の要素番号範囲の確認
    Debug.Print LBound(tblItem) & "〜" & UBound(tblItem)
    ' 結果をシートに展開してみる
    For lngIx = 0 To 4
        lngRow = lngIx + 1                      ' 行番号は「1」始まり
        Cells(lngRow, 1).Value = tblItem(lngIx)
    Next lngIx
End Sub

宣言時に要素数を決定しない配列変数は「動的配列」なのか、というとちょっと疑問です。 この書き方はこの上で説明した4件のコードと同じ結果となる上、配列要素に内容を格納する前に要素数は決定されて以降に変動することはないので、用途としては「静的配列」に属するものだと思います。

「静的配列」の説明の最後に「Option Base」による配列要素範囲の変更について説明しておきます。


'***************************************************************************************************
'   配列の勉強                                                      Module2(Module)
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'06/11/07(1.00)新規作成
'16/11/19(1.10)*.xlsm化
'20/02/11(1.11)記述整理等
'***************************************************************************************************
Option Explicit
Option Base 1                   ' 配列要素の最小値を「1」とする宣言

'***************************************************************************************************
'* 処理名 :TEST6
'* 機能  :固定配列のサンプルE
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2006年11月07日
'* 作成者 :井上 治
'* 更新日 :2020年02月11日
'* 更新者 :井上 治
'* 機能説明:⇒シートの行列と同様に要素番号を1から始まる配列としてみる。
'* 注意事項:
'***************************************************************************************************
Sub TEST6()
    '-----------------------------------------------------------------------------------------------
    Dim lngRow As Long                                              ' 行INDEX
    Dim tblItem(5) As String                                        ' 要素数5個(1〜5)の配列
    ' シートのクリア
    Cells.ClearContents
    ' 配列の各要素に値を格納
    tblItem(1) = "あああ"
    tblItem(2) = "いいい"
    tblItem(3) = "ううう"
    tblItem(4) = "えええ"
    tblItem(5) = "おおお"
    ' 配列の要素番号範囲の確認
    Debug.Print LBound(tblItem) & "〜" & UBound(tblItem)
    ' 結果をシートに展開してみる
    For lngRow = 1 To 5
        Cells(lngRow, 1).Value = tblItem(lngRow)
    Next lngRow
End Sub

'***************************************************************************************************
'* 処理名 :TEST7
'* 機能  :固定配列のサンプルF
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2006年11月07日
'* 作成者 :井上 治
'* 更新日 :2020年02月11日
'* 更新者 :井上 治
'* 機能説明:⇒定数的な件数の少ない配列はArray関数で作成することも可能
'* 注意事項:
'***************************************************************************************************
Sub TEST7()
    '-----------------------------------------------------------------------------------------------
    Dim lngRow As Long                                              ' 行INDEX
    Dim lngIx As Long                                               ' テーブルINDEX
    Dim tblItem As Variant                                          ' 要素数不定の配列
    ' シートのクリア
    Cells.ClearContents
    ' 配列の各要素に値を格納(要素0〜4となる?)
    tblItem = Array("あああ", "いいい", "ううう", "えええ", "おおお")
    ' 配列の要素番号範囲の確認
    Debug.Print LBound(tblItem) & "〜" & UBound(tblItem)
    ' 結果をシートに展開してみる
    lngRow = 0
    For lngIx = LBound(tblItem) To UBound(tblItem)
        lngRow = lngRow + 1                     ' 行番号は「1」始まり
        Cells(lngRow, 1).Value = tblItem(lngIx)
    Next lngIx
End Sub

'------------------------------------------<< End of Source >>--------------------------------------

モジュールの先頭で「Option Base 1」を宣言していますが、これにより配列の要素番号の最小値はデフォルトで「1」となります。 「TEST6」と「TEST2」を比較してもらうと判ると思います。
もちろん、「Option Base 1」を宣言しないで「TEST6」を動作させても何も問題ありませんが、その場合は要素番号「0」の配列要素が作られて何も利用されないという無駄が発生するということです。

では、「動的配列」を扱うサンプルを見てみましょう。
「動的配列」とは、ソースコード上で要素数が固定されていない配列だと考えれば良いと思います。
動的配列のサンプル
この「元データ」シートのA列の値を使って、重複しない値だけを配列に格納しておき、最後にその結果を「処理結果」シートのA列に書き出すサンプルです。 まずはワークシート上と「感覚」を揃える意味であえて配列の要素番号を「1」始まりにして処理してみます。


'***************************************************************************************************
'   配列の勉強  ※重複のない値だけ配列に格納するサンプル@          Module1(Module)
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'06/11/07(1.00)新規作成
'16/11/19(1.10)*.xlsm化
'20/01/17(1.11)記述整理等
'***************************************************************************************************
Option Explicit
'Option Base 1                   ' 配列の最小要素番号を「1」に固定する宣言(本サンプルでは使用しない)
'===================================================================================================
Private Const g_cnsSh1 As String = "元データ"
Private Const g_cnsSh2 As String = "処理結果"

'***************************************************************************************************
'   ■■■ シート側からの起動処理 ■■■
'***************************************************************************************************
'* 処理名 :TEST1
'* 機能  :重複のない値だけ配列に格納するサンプル@
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2006年11月07日
'* 作成者 :井上 治
'* 更新日 :2020年01月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:⇒シートの行列と同様に要素番号を1から始まる配列としてみる。
'***************************************************************************************************
Sub TEST1()
    '-----------------------------------------------------------------------------------------------
    Dim objSh1 As Worksheet                                         ' 元データシート
    Dim objSh2 As Worksheet                                         ' 処理結果シート
    Dim lngRow As Long                                              ' 行INDEX
    Dim lngIx As Long                                               ' テーブルINDEX
    Dim lngIxMax As Long                                            ' テーブルINDEX上限
    Dim strText As String                                           ' テキストWORK
    Dim tblText() As String                                         ' テキストテーブル
    Set objSh1 = Worksheets(g_cnsSh1)                   ' 元データ
    Set objSh2 = Worksheets(g_cnsSh2)                   ' 処理結果
    ' 処理結果をクリア
    objSh2.Cells.ClearContents
    ' 配列要素とインデックスをクリア(最小要素番号を「1」とする)
    lngIxMax = 0
    ReDim tblText(1 To 1)
    '-----------------------------------------------------------------------------------------------
    ' 配列格納ループ(元データ最終行まで繰り返し)
    For lngRow = 1 To objSh1.Range("$A$" & objSh1.Rows.Count).End(xlUp).Row
        ' Object参照を最小限にするため値(A列)を変数に格納
        strText = Trim(objSh1.Cells(lngRow, 1).Value)
        ' 探し出しループ
        lngIx = 1
        Do While lngIx <= lngIxMax
            ' 見つかったらループ脱出
            If tblText(lngIx) = strText Then Exit Do
            ' 次へ
            lngIx = lngIx + 1
        Loop
        ' 見つからない(途中脱出でない)時は配列に追加
        If lngIx > lngIxMax Then
            ' 配列要素を加算してセット
            lngIxMax = lngIx
            ReDim Preserve tblText(1 To lngIxMax)
            ' イミディエイトに処理状態を出力
            Debug.Print "(" & lngIxMax & ")=" & strText
            tblText(lngIxMax) = strText
        End If
    Next lngRow
    ' イミディエイトに配列要素数を出力
    Debug.Print LBound(tblText) & "〜" & UBound(tblText)
    '-----------------------------------------------------------------------------------------------
    lngRow = 1
    ' 作成した配列を処理結果にセット(実際は一括でセットできるが記述サンプルなので....)
    Do While lngRow <= lngIxMax
        objSh2.Cells(lngRow, 1).Value = tblText(lngRow)
        ' 次の行へ
        lngRow = lngRow + 1
    Loop
    '-----------------------------------------------------------------------------------------------
    ' 終了
    objSh2.Activate
    Set objSh1 = Nothing
    Set objSh2 = Nothing
End Sub

'------------------------------------------<< End of Source >>--------------------------------------

このような条件成立ごとに要素数を増やして値を格納するような処理では、「ReDim Perserve」ステートメントによって要素数を増減させます。 一般に「ReDim」ステートメントでは配列自体を初期化してしまうため、以前に格納された値などは無効になってしまいますが、 「Perserve」キーワードが付加される場合は要素数だけが変更できて有効要素番号に格納されている内容は影響を受けません。

ですが、先の「静的配列」でも説明した通り、VBAWindows系開発言語一般のデフォルトでは、配列変数の要素番号はゼロ始まりです。このゼロ始まりにままの処理も確認してみましょう。


'***************************************************************************************************
'   配列の勉強  ※重複のない値だけ配列に格納するサンプルA          Module2(Module)
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'06/11/07(1.00)新規作成
'16/11/19(1.10)*.xlsm化
'20/01/17(1.11)記述整理等
'***************************************************************************************************
Option Explicit
'===================================================================================================
Private Const g_cnsSh1 As String = "元データ"
Private Const g_cnsSh2 As String = "処理結果"

'***************************************************************************************************
'   ■■■ シート側からの起動処理 ■■■
'***************************************************************************************************
'* 処理名 :TEST2
'* 機能  :重複のない値だけ配列に格納するサンプルA
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2006年11月07日
'* 作成者 :井上 治
'* 更新日 :2020年01月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:⇒要素番号を0から始まる配列としてみる。(この方法がデフォルト)
'***************************************************************************************************
Sub TEST2()
    '-----------------------------------------------------------------------------------------------
    Dim objSh1 As Worksheet                                         ' 元データシート
    Dim objSh2 As Worksheet                                         ' 処理結果シート
    Dim lngRow As Long                                              ' 行INDEX
    Dim lngIx As Long                                               ' テーブルINDEX
    Dim lngIxMax As Long                                            ' テーブルINDEX上限
    Dim strText As String                                           ' テキストWORK
    Dim tblText() As String                                         ' テキストテーブル
    Set objSh1 = Worksheets(g_cnsSh1)                   ' 元データ
    Set objSh2 = Worksheets(g_cnsSh2)                   ' 処理結果
    ' 処理結果をクリア
    objSh2.Cells.ClearContents
    ' 配列要素とインデックスをクリア
    lngIxMax = -1
    ReDim tblText(0)
    '-----------------------------------------------------------------------------------------------
    ' 配列格納ループ(元データ最終行まで繰り返し)
    For lngRow = 1 To objSh1.Range("$A$" & objSh1.Rows.Count).End(xlUp).Row
        ' Object参照を最小限にするため値を変数に格納
        strText = Trim(objSh1.Cells(lngRow, 1).Value)
        ' 探し出しループ
        lngIx = 0
        Do While lngIx <= lngIxMax
            ' 見つかったらループ脱出
            If tblText(lngIx) = strText Then Exit Do
            ' 次へ
            lngIx = lngIx + 1
        Loop
        ' 見つからない(途中脱出でない)時は配列に追加
        If lngIx > lngIxMax Then
            ' 配列要素を加算してセット
            lngIxMax = lngIx
            ReDim Preserve tblText(lngIxMax)
            ' イミディエイトに処理状態を出力
            Debug.Print "(" & lngIxMax & ")=" & strText
            tblText(lngIxMax) = strText
        End If
    Next lngRow
    ' イミディエイトに配列要素数を出力
    Debug.Print LBound(tblText) & "〜" & UBound(tblText)
    '-----------------------------------------------------------------------------------------------
    lngIx = 0
    ' 作成した配列を処理結果にセット(実際は一括でセットできるが記述サンプルなので....)
    Do While lngIx <= lngIxMax
        ' 行番号は1始まりなので1を加える
        lngRow = lngIx + 1
        objSh2.Cells(lngRow, 1).Value = tblText(lngIx)
        ' 次へ
        lngIx = lngIx + 1
    Loop
    '-----------------------------------------------------------------------------------------------
    ' 終了
    objSh2.Activate
    Set objSh1 = Nothing
    Set objSh2 = Nothing
End Sub

'------------------------------------------<< End of Source >>--------------------------------------

最後に「処理結果」シートに書き出すのに行番号を別途加算しなくてはなりませんが、それ以外の違いはありません。

さて、今回の「重複のない値だけ格納」にはDictionaryオブジェクトを使う方法があります。
「配列」の話とは離れてしまいますが、ちょうど良い機会なのでサンプルを挙げておきます。


'***************************************************************************************************
'   配列の勉強  ※重複のない値だけ配列に格納するサンプルB          Module3(Module)
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'   [参照設定]
'   ・Microsoft Scripting Runtime
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'06/11/07(1.00)新規作成
'16/11/19(1.10)*.xlsm化
'20/01/17(1.11)記述整理等
'***************************************************************************************************
Option Explicit
'===================================================================================================
Private Const g_cnsSh1 As String = "元データ"
Private Const g_cnsSh2 As String = "処理結果"

'***************************************************************************************************
'   ■■■ シート側からの起動処理 ■■■
'***************************************************************************************************
'* 処理名 :TEST3
'* 機能  :重複のない値だけ配列に格納するサンプルB
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2006年11月07日
'* 作成者 :井上 治
'* 更新日 :2020年01月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:⇒配列ではないが同用途なのでDictionaryオブジェクトを使ってみる。
'***************************************************************************************************
Sub TEST3()
    '-----------------------------------------------------------------------------------------------
    Dim objSh1 As Worksheet                                         ' 元データシート
    Dim objSh2 As Worksheet                                         ' 処理結果シート
    Dim objDic As Scripting.Dictionary                              ' Dictionaryオブジェクト
    Dim lngRow As Long                                              ' 行INDEX
    Dim strText As String                                           ' テキストWORK
    Dim vntItem As Variant                                          ' Dictionaryの1要素WORK
    Set objSh1 = Worksheets(g_cnsSh1)                   ' 元データ
    Set objSh2 = Worksheets(g_cnsSh2)                   ' 処理結果
    ' Dictionaryオブジェクトの初期化
    Set objDic = New Scripting.Dictionary
    '-----------------------------------------------------------------------------------------------
    ' Dictionary格納ループ(元データ最終行まで繰り返し)
    For lngRow = 1 To objSh1.Range("$A$" & objSh1.Rows.Count).End(xlUp).Row
        strText = Trim(objSh1.Cells(lngRow, 1).Value)
        ' 既に格納済みか判定する
        If objDic.Exists(strText) <> True Then
            ' 未格納なら加える
            objDic.Add strText, strText
            ' イミディエイトに処理状態を出力
            Debug.Print strText
        End If
    Next lngRow
    '-----------------------------------------------------------------------------------------------
    ' 作成した配列を処理結果にセット
    lngRow = 0
    For Each vntItem In objDic.Items
        ' 行INDEXを加算して格納
        lngRow = lngRow + 1
        objSh2.Cells(lngRow, 1).Value = vntItem
    Next vntItem
    '-----------------------------------------------------------------------------------------------
    ' 終了
    objSh2.Activate
    Set objDic = Nothing
    Set objSh1 = Nothing
    Set objSh2 = Nothing
End Sub

'------------------------------------------<< End of Source >>--------------------------------------

このような方法は、私自身は使いません。上記のような配列操作ができれば処理上で問題ないことなのです。コードに記述上ではシンプルに見えますが、特段にお勧めするものではありません。
ただ、件数が多い場合などでどちらが効率が良いのかなどの問題となる場合や、バージョンによる動作可否などを含めて必要だと思われる場合は検討してみて下さい。
VBAの「配列」は一次元だけなのか?   たとえば「ワークシート」はExcel2007以降の場合、1048576行×16384列の「二次元配列」と考えられますが、配列変数は「二次元」あるいはそれ以上の次元で扱えないのでしょうか。
ヘルプの説明を調べると、本当は最大60次元までの配列を扱えるようです。 ですが、これを「動的配列」とする場合は問題があります。ここで説明している「動的配列」とは、以前に登録した値に影響なく配列の要素数を増やせることを指します。(減らすことはなくても問題ないので)
何が「問題」かと言うと、Preserveキーワードで要素数を変更できるのが「最終次元」に限られてしまうということなのです。つまり1048576行×16384列の配列なら、16384列の方は変更できるが1048576行は変えられないということになります。
普通、データ量の増減は「行」の方向のことであって「列」ではありません。では「列」×「行」とすれば一見、解決しますが、これはこれでワークシートに展開する時に1セルずつ渡すとかの問題が起きてしまいます。
ではどうするか、の一つの解決方法として、Variant型の柔軟さを利用して一次元の配列の1要素の中に別の配列を入れてしまうという方法があります。一般にJAG配列」と呼ぶらしいです。