VBAでユーザーフォームはふつう、単一のオブジェクトとして扱う。
たとえば以下のようなフォームを作ったとしよう。
オブジェクト名は「frm成績」としたので、このフォームを表示させるコードはこうだ。
Sub hoge() frm成績.Show End Sub
この時フォームは、「frm成績」オブジェクトとして扱われいてる。
さて、たとえばこのフォームを3つ同時に起動させたいとする。
どうすればいいか。
まずフォームのShowModalがTrueのままでは3つ同時に表示させることはできないので、これをFalseにしておく。
ShowModalとは、フォームを表示させた際にそのフォームを閉じるまで次に進めないか、それとも次のコードをそのまま実行させるかというプロパティで、FalseにするとフォームをShowしたあと閉じられるのを待たずに次のコードに進む。
そして記述するコードは次のとおり。
Sub hoge() Dim f As frm成績 Set f = New frm成績 f.Show Set f = New frm成績 f.Show Set f = New frm成績 f.Show End Sub
実行するとフォームは1つに見えるが、重なっているだけでずらしてみるとこのとおり。
つまりユーザーフォームはオブジェクト(インスタンス)でありながら、クラスのようにも振る舞うことができるのだ。なんとも不思議な特性である。クラスモジュールはインスタンス化して初めてつかえる。シートなどのオブジェクトモジュールは単一オブジェクトとしてのみ扱え、Newはできない。対してフォームモジュールは単一オブジェクトとして扱うこともできるし、クラス(オブジェクトのひな形)として扱うこともできるのだ。
さて、これが何に使えるのかというとそこはみなさんの創造力次第。
私がひとつ思いついたのは、データをフォームに読み取ってカードのように並べて表示させたいケース。
単一フォームで対応するのは難しいが、この手法なら大丈夫。
たとえばSheet1に以下のようなデータがあるとする。
Sheet1モジュールに以下のコードを記入し、
Enum 列 名前 = 1 国語 数学 理科 社会 End Enum Sub FormからFormをNew() Dim C As Collection Set C = New Collection Dim frm As frm成績 Dim i For i = 2 To 4 Set frm = New frm成績 frm.lblName = Cells(i, 列.名前).Value frm.txt国語 = Cells(i, 列.国語).Value frm.txt数学 = Cells(i, 列.数学).Value frm.txt理科 = Cells(i, 列.理科).Value frm.txt社会 = Cells(i, 列.社会).Value frm.Show frm.Left = frm.Left + (i - 3) * frm.Width Next End Sub
実行するとこのとおり。
あるいはデータを格納するためのPersonクラスを作成し、そのクラスにフォームのインスタンスを持たせるとか。。
そうすれば各Personインスタンスがそれぞれ別個のユーザーインターフェースを持つことができる。
他にも工夫次第で色々と面白いことができそうな気がする。