エクセルVBAクラス備忘録 ユーザーフォーム間の配列等の渡し方 パブリック変数以外で受け渡す方法

20240521 エクセルVBAクラス備忘録 ユーザーフォーム間の配列等の渡し方
パブリック変数以外で受け渡す方法
 
 
<前書き>
エクセルVBAオブジェクト指向、初心者です。
VBA自体は、以前から使用していました。
オブジェクト指向というものがあることは、知っていましたが、ネットなどを見てもよく分からず、挫折した過去あり。
<以上前書き>
 
(素人なので間違っているかもしれません。汗。)
 
今回:
いつも悩むユーザーフォーム間のデータの渡し方です。
自分用のメモなので分かりにくいです。
オブジェクト指向とは、少し、かすっています。汗)
 
 
 
 
 
何回か書いたかもしれないが、昔作ったVBAマクロで、ユーザーフォーム間で、データ(配列)の受け渡しがあり、どうしてもできず、
仕方なく、標準モジュールに、パブリック変数を置いた。
 
public hito() As Variant
 
みたいに置いた。
 
 
今回リファクタリングするにあたって、どうしようかと思った。
 
(注:今回は、実際には、元の配列をエクセルシートに配置して、ユーザーフォームごとに読み込んでもいいかなと思っている。(一番簡単))
(注:実際受け渡ししたい配列は2次元配列ですが、この記事では1次元配列を例に書いています。多分2次元でも同じだと思う。(思いたい。汗))
 
 
 
 
方法としては、上記のパブリック変数を使う以外に、いくつかできそうだが、やはりユーザーフォーム間の配列のやり取りはややこしい。
 
**********************************
配列でなく、テキストボックスの値などコントロールに関するものなら、ユーザーフォーム1で、userform2.showの前に、コードを書けば受け渡しできる。
 
 
Private Sub CommandButton1_Click()
 
    UserForm2.TextBox1.Value = "受け渡しOK"
 
    UserForm2.Show
End Sub
 
こんな感じ。
 
リストボックスでも可能なので、
 
 
Private Sub CommandButton1_Click()
    UserForm2.ListBox1.Clear
    On Error Resume Next   'リストがない場合
    For i = 1 To UBound(hito)
        UserForm2.ListBox1.AddItem hito(i, 3)
    Next i
    
     If Err.Number Then
        Err.Clear
    End If
    
    
    UserForm2.ListBox1.ListIndex = -1
 
    UserForm2.Show
    
End Sub
 
 
上記もできる。
でも、配列のまま渡したい。
 
************************************
その他の方法として、タグ(tag)が使えるが、少し変則的。
 
Private Sub UserForm_Initialize()
    ' 配列を初期化
    Dim MyArray() As Variant
    ReDim MyArray(1 To 3)
    MyArray(1) = "Apple"
    MyArray(2) = "Banana"
    MyArray(3) = "Cherry"
    
    ' 配列をTagプロパティに設定
    Me.Tag = Join(MyArray, ";") ' セミコロンは適切な区切り文字を選んでください
End Sub
 
 
Private Sub UserForm_Initialize()
 
PassedArray = UserForm1.Tag
 
Debug.Print PassedArray
 
End Sub
 
 
これで、配列を渡せるけど、tagは文字列しかダメらしい。上記例だと、
Apple;Banana;Cherry
という文字列をまた、配列に戻してやる必要がある。(しかも1次元配列だし。)
 
******************************************
で、他の方法を探すと、ネットで「ほげーむわーく」様のブログに、
【エクセルVBA】ユーザーフォーム間で配列を受け渡す方法
というのがあった。
(感謝いたします。紹介記事に不都合があれば即削除します。)
 
そこでは、一度、標準モジュールを介して配列を送っていました。
 
送り側のユーザーフォームで配列を設定する
送り側ユーザーフォームからプロシージャに配列を渡す
受け側のユーザーフォームから配列が設定されたプロシージャを読み出す
 
Private変数を活用し、標準モジュールのプロシージャに配列と受けと送りの役割(sub とfunction)をそれぞれ持たせ、配列をリレーさせています。
(実際の記事は直接お読み下さい。)
 
*****************************************
で、上記のプログラムを見た時、これ、「プロパティ」でできるのかもと思って、書いたのが下記です。
 
 
'標準モジュール(標準モジュールは抜粋)
Private marray送受 As Variant
 
'let
Public Property Let array送受(parray送受 As Variant)
     marray送受 = parray送受
End Property
 
'get
Public Property Get array送受() As Variant
     array送受 = marray送受
End Property
 
 
' UserForm1のコードモジュール
Option Explicit
Dim MyArray() As Variant
 
 
Private Sub CommandButton1_Click()
 
    array送受 = MyArray
 
    UserForm2.Show
End Sub
 
Private Sub UserForm_Initialize()
    ' 配列を初期化
    
    ReDim MyArray(1 To 3)
    MyArray(1) = "Apple"
    MyArray(2) = "Banana"
    MyArray(3) = "Cherry"
 
End Sub
 
 
' UserForm2のコードモジュール
Option Explicit
 
Private Sub UserForm_Initialize()
   
    Dim chkary() As Variant
 
    chkary = array送受
    Stop
 
End Sub
 
 
*****************************************
で、プロパティをクラスに入れたのが下記です。
 
'クラス「配列送受」
Private marray送受 As Variant
 
 
'let
Public Property Let array送受(parray送受 As Variant)
     marray送受 = parray送受
End Property
 
'get
Public Property Get array送受() As Variant
     array送受 = marray送受
End Property
 
 
'標準モジュール
Option Explicit
Dim v配列送受 As 配列送受    'これなら取れる
 
Sub フォーム1_open()
 
    UserForm1.Show
End Sub
 
 
Sub 受け(myary As Variant)   
    Set v配列送受 = New 配列送受
 
    v配列送受.array送受 = myary
 
End Sub
 
 
Function 渡し() As Variant
    渡し = v配列送受.array送受
 
End Function
 
 
' UserForm1のコードモジュール
Option Explicit
Dim MyArray() As Variant
 
 
Private Sub CommandButton1_Click()
 
    Call 受け(MyArray)
    
    UserForm2.Show
End Sub
 
Private Sub UserForm_Initialize()
    ' 配列を初期化
    
    ReDim MyArray(1 To 3)
    MyArray(1) = "Apple"
    MyArray(2) = "Banana"
    MyArray(3) = "Cherry"
    
End Sub
 
 
***************************************************以下メモ
標準モジュールを経由するので、いまいちか?
エクセルVBAのuserform_initialize()に引数が渡せないのが痛い?
userform_initializeの中に、init()などサブルーチンを用意したとしても、
やはり配列の受け渡しには、工夫が必要か(考えがぐるぐる元に戻る・・・)。
 
 
本当は、
userform2.配列2 =userform1.配列1
とか、したかったのですが、それはできないようです。
(どっちもユーザーフォーム立った状態ならできるかなと思ったのですが・・・)
 
 
 
で、今回は、やはりシートから読み込むシンプルな形にするかなと(考えがぐるぐる元に戻る・・・)。