20240521 エクセル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
とか、したかったのですが、それはできないようです。
(どっちもユーザーフォーム立った状態ならできるかなと思ったのですが・・・)
で、今回は、やはりシートから読み込むシンプルな形にするかなと(考えがぐるぐる元に戻る・・・)。