質問: エクセルVBAで開発したエクセルのシステムがあります。 このシステムでは、シート上に設置した多くのコマンドボタンをクリックすることで、ボタンに応じた様々なモーダルフォームを表示し、使用者に諸々の値の入力を促すようになっています。 ただ、このシステムには問題があり、このシステムでモーダルフォームを表示している状態でユーザーが別のエクセルブックを開こうとしても開くことができないことがあったり、既に開いている別のブックのウィンドウをアクティブにしようとすると不具合が出て不安定になるなどの事象が発生しています。 やはり、同時にいくつかのファイルを開くことが多いエクセルで、モーダルフォームを次々に表示するようなシステムを作ったことじたい全体が見えてなかったのではないかと問題になっています。 この弊害への対策として、まず、できる限りモーダルフォームの利用を廃し、ユーザーからの入力を促すだけならほとんどのセルをロックしまくったシートで代用させることを検討しましたが、シートを新設し、多量のテキストボックスを並べて作ってきたフォームをいちいちシートに移していくのも手間だし、いっそ、各フォームだけを集めてVisualBasic.NETでexeファイルを作成してしまえばいいのではないかと思い当たりました。 つまり、元のエクセル.xlsmはフォームを自分で持つことをやめ、必要に応じてパートナーである自作VBNETシステム.exeを(そのとき起動してないなら)起動させて、必要なフォームを表示してもらう、という形にした方がいいのではないか。そうしたら、エクセルとしてはモーダルフォームを出すことはないから、同時に開いている別ブックやそのウィンドウに不当な影響を与えることはないのではないか、と。 これまでエクセルでフォームを表示させていた場面では、これからは、そのエクセルのVBAから自作VBNETシステム.exeを起動させて「あなたが所持している○○というフォームを表示しろ」と命令することにし、なおかつ、「そのフォームの各テキストボックスコントロールの初期値はわがエクセルファイルの××というシートのこのセルの値にしておきなさい」としておく形にし、 逆に自作VB.NET.exeの方では、「フォームにあるこの"決定"コマンドボタンがクリックされたときは、今開かれているはずの相棒エクセル.xlsmの、××というシートの該当セルに、我がフォームのテキストボックスコントロールの値を挿入し、なおかつ、そのエクセルシステムにある○○というプロシージャを実行させて、自らは閉じてしまえ」と命令を書いておけばいいのではないかというアイデアを思いつきました。 すべては、元々のエクセルで作ったシステムの中でフォームを用いないことで「同時に開いている他のエクセルブックさんたちに迷惑をかけない」のが目的です。 私は、VBAの経験だけでVB.NETの経験はまったくありませんが、同じVB仲間だし何とかなるのではないかと、この方法の現実性について調べ始めました。 しかし、必要な情報をすべて得ることはできず、ここで質問させてもらいたいです。 1. エクセルのVBAから、自分とは別のexeファイル(起動しているかどうかわからない。起動していないなら起動させたうえで)に対し、「○○というフォームを表示させろ。そしてそのフォーム上のコントロールの初期値には我がブックの(非表示のときもある)○○シートの値を取得して設定しろ」という命令が可能なのか 2. 逆に、VB.NETで作ったexeファイルの方からは、相棒であるはずのエクセル.xlsm(開かれているはず)ファイルのシートから値を取得したり、与えたり、また、そのエクセルにあるプロシージャを実行させるということが可能なのか 3. そもそも、こうやってフォームだけを別に集めて別exe化するだけで、エクセルの挙動は安定するのか 4. エクセルVBAのエディタからは、既存のフォームを.frmファイルとして外部保存できるようだが、VB.NETの開発時にこのままそのフォームのデータを取り入れることができるのではないか。けっこう凝って作ったフォームだから、そのままVB.NETの開発に使えればありがたいがどうだろうか 以上4点の疑問が、ネットで調べたかぎりでははっきりしません。 知識のある方、同様の経験のある方、教えていただきたいです。 なお「VBAしかできない素人のくせにVB.NETのコードが書けるのか」という点については、「フォームを表示していくつかのデータをやりとりする程度のものだから、なんとかなるんじゃないか」と楽観しています。 よろしくお願いいたします。
回答: 問題点は、モーダルフォームを開くことで、別ブックの操作に問題がでるということですよね。 ならばモーダルではなくモードレスで開けばいいのでは。 そうすれば別ブックの操作に影響はないはずです。 ``` UserForm1.Show vbModeless ``` ユーザーフォームが開いているとき、自ブックを操作できないようにするには、ユーザーフォームのInitializeですべてのシートに保護をかけて、Terminateで保護を解除すればいいでしょう。 ``` Private Sub UserForm_Initialize() Dim ws As Worksheet For Each ws In ThisWorkbook.Worksheets ws.Protect UserInterfaceOnly:=True ws.EnableSelection = xlNoSelection Next End Sub Private Sub UserForm_Terminate() Dim ws As Worksheet For Each ws In ThisWorkbook.Worksheets ws.Unprotect ws.EnableSelection = xlUnlockedCells Next End Sub ```