メインフォームに「変更」という名前のボタンを作成し、このボタンを押すと「変更」というフォームが表示されるコードを作成しました。
以前こちらのサイトでアドバイスいただき、クラスにコントロールを登録するメソッドを作成し、そこに必要な場合、Range等のデータを飛ばすことが可能なこと、このデータをイベントに挿入し、新たに作成したフォームにも活用できることをご教授いただきました。
今回、この「Range」の部分を、Longに変更し、新たに開いたフォームで活用したいのですが、この「新たに開いたフォーム」では、データが「0」となってしまいます。
Long型を飛ばすことは可能なのでしょうか?様々なシーンで多用したいと思っており、可能であれば、データ型、String型などでも飛ばせる様に習得したいのですが、解決法、やアドバイスなどありましたらお願いします。
コードは以下の通りです。
クラス(ステップインで確認したところ、中断のプロシージャ(コメント部)まではデータがとんでいます。)
Private WithEvents tgtctrl As MsForms.CommandButton Private tgtRow As Long Public Sub Setctrl(new_ctrl As MsForms.CommandButton, new_Long As Long) Set tgtctrl = new_ctrl tgtRow = new_Long 'ここの部分は当初Set tgtrange = new Rangeで正常に動いていました。 End Sub Private Sub tgtctrl_Click() ChangeForm.Show vbModeless ChangeForm.tgtRow = tgtRow'ここはRangeを飛ばすときの記載を単純に変更しました。 meinForm.Hide End Sub
フォーム「変更」
Option Explicit Public tgtRow As Long Sub UserForm_Initialize() MsgBox tgtRow ’この時点での表示が0となってしまいます。 ・・・以下ボタン等のプロパティ EndSub
よろしくお願いします。
で、しつもんはなんでしょうか
肝心の"tgtctrl"クラスのVBAコードが無いと回答できませんので
追加記載お願いします。
返信遅くなり申し訳ありません。
下部にある、Private Sub tgtctrl_Click()がそのクラスになります。
クラス中段にあるSetctrl内のtgtRow迄はデータが飛んでいるのに、Private Sub tgtctrl_Click()とユーザーフォーム(変更)にはデータが飛んでいなく(0と表示されてしまいます。)原因が知りたいです。
> Private WithEvents tgtctrl As MsForms.CommandButton
コマンドボタンのイベント発生型のクラスという事は
いきなりラッパークラス作成しようとしているのですか?
質問者様は通常のクラスの知識はありますか?
そうでないと「ラッパークラス」=「クラスの上にクラスをかぶせる」仕組みから理解してもらわないといけなくなりますが...
とてもお恥ずかしいですが、知識はほとんどありません。
作成したいマクロを調べながら作り、わからない部分をこちらのサイトでご教授いただき、教えていただいたコードを調べて手を加える→更にわからないところをサイトで聞く・・・
という流れで学習していました。
クラスの基本的な使い方もままならない状態です。
初心者でも分かり易いクラスについての書籍やサイトなど有りましたら紹介いただけますでしょうか・・。
う~ん。
クラスは本来「標準モジュールで関数を作成」→「標準モジュールの関数ではできない事が出てきた」→「それじゃクラスで対応するか」という流れなんですね
質問者様の今の状態でクラスの解説を見ても「標準モジュールでなにができるのか?」が判らないと「クラス」を使う意味が理解できないように思います。
質問者様の内容ですと十分「標準モジュールの関数」で対応が可能だと思われますが
やはり「クラス」のやり方にこだわりますか?(せめて標準クラスなら良いのですが...)
以前に「データの数だけボタンを増やす」という少し変わった質問をした際にご教授いただいた方法を、そのまま使いましたので、その関係ですべて「アッパークラス」というものになっていたのかもしれません。
もし「標準モジュール」で作成する場合ですが、Private Sub tgtctrl_Click()は、新規に作成した「標準モジュール」に入れた方が良いでしょうか。
その場合、通常のプロシージャと同じように「Call.〇〇」で呼び出し、飛ばしたいデータは()内に入れる形で問題ないでしょうか。
無知な為変な質問かもしれませんが回答いただけると助かります。
「アッパークラス」=上位のクラス
なので元の「クラス」の概念が理解できないと意味がないんですよ...
(「データの数だけボタンを増やす」で「アッパークラス」を使うのは効率的です。)
>Private Sub tgtctrl_Click()は、新規に作成した「標準モジュール」に入れた方が良いでしょうか。
考え方が逆でボタンのクリックイベントが「Private Sub tgtctrl_Click()」なんですね、その中に共通で作った関数を指定してあげるんです。
その場合引数とかで必要な情報を関数側に渡してあげて...ってできるんですが、覚える順番が逆になってしまっているのでどう説明すればよいか困っているわけです。
全体の流れとして、
1、シートのある列を右クリックでフォーム1起動
2、フォーム1の「変更」ボタンを押してフォーム2起動←今ここです。
3、フォーム2の「更新」ボタンを押してシートに反映
とういものを作りたいと思っていました。
シートから、「フォーム1」→「変更ボタンイベント」→「フォーム2」→「更新ボタンイベント」→「シート」という流れで「クリックしたセルの行番号」のデータを飛ばすのが目的ですが、今回「行番号以外のデータも飛ばしたい時」のコードの書き方も覚えたく、(今後、フォーム2に記載したデータをシートに書き込み可能にしたいので・・・。)このコードを作成しました。
クラスの概念についてですが、「他のプロシージャでも使える変数の変わらない(その都度初期化される)メソッド、プロパティを格納するもの」という覚え方をしていました。
現在の構成として、
左クリックで起動 → シートモジュール
フォームのボタン配置 → フォームモジュール
ボタンのイベント → クラスモジュール
という構成で作っていますが、
ボタンのイベントについては、「データの数だけ増えるボタンのイベント」以外は「標準モジュール」に切り替え、「渡したいデータ」を「クラスモジュール」に格納するという構成に変えるのが理想でしょうか。
アッパークラスのある場所として、「フォームモジュール内」ということは有りますでしょうか。
アッパークラスも「クラスモジュール」に記載があるものでしょうか。
長々とした返信申し訳ありません。上記の内容で間違いのある部分や、畑違いな返信など、ご指摘いただければ幸いです。
よろしくお願いします。
・左クリックで起動 → シートモジュール
はい間違いありません
フォームのボタン配置 → フォームモジュール
フォームのボタンはVBAで作成せずに、コントロールの追加で初めから準備しておきます。
(レイアウトやプロパティがせっかく保存できるのですから)
ボタンのイベント → クラスモジュール
フォームモジュールにイベント関数を書くことができますのでそこ処理を行います。
基本の形はこの様な構成なんです。
(Windowアプリみても複数ボタンとかないでしょ?)
ここから初めて問題が発生したり書き方とかになれたら「クラス」→「アッパークラス」に移行というのが正規のルートなんです。
「クラス」の概念はボタンなどにある「プロパティ」と「メゾット(関数)」を用意した一つの塊を
自分で作れると思えば判りやすいと思います。(表示のないコントロール)
「クラス」にすると「ボタン」を複製したようにプロパティ(値)をクラス内で保持でき
処理自体を同じにできる利点があります。
で「アッパークラス」は今回の場合「ボタンが持っているクラス」に対して上位のクラスを設定してあげる事でボタンに「今あるボタン標準機能に新たに機能追加する」となるようにする仕組みなんです。
その為「ラッパークラス」(上にかぶせるクラス)や「アッパークラス」(上位のクラス)と呼ばれています。
ただこの方式のメリットは「同じ処理を複数に設定する」場合であって、単一の処理に対しては「単に複雑になる」デメリットが存在します。完全の覚えてしまえば問題ないのですが...
できれば質問者様には一度ふつうに「Excelでフォーム作成して処理を行う」処理のサンプルが
ネットにはたくさんあります。
一度その方式に戻されたほうが良いのではないかと思います。
このままではVBAの書き方の問題で止まってしまい、その先のどの様に処理すれば良いかまでたどり着けない様な気がします。
一旦基礎に戻ります。
ありがとうございました。
回答1件
あなたの回答
tips
プレビュー