UserForm1の中で使うワークシート変数を統一したいと思っています。
そのため宣言セクションで画像のように宣言してみましたが、エラーが出ます。
要するに「変数の宣言は出来るけれど、変数への代入は宣言セクションでは出来ない」
ということだと思います。
この場合「Ls_sh」という変数をワークシート変数として宣言したので、
UserForm1のプロシージャーの中では「Ls_sh」という変数名を
長整数型や文字列型で使えないというメリットがあるのは理解出来ます。
ですが宣言セクションで変数にシート名を割り当てることができないため
Set Ls_sh = Worksheets("Sheet10")
を各プロシージャーに毎回書くことになってしまいます。
おまけに、間違えて
Set Ls_sh = Worksheets("Sheet11")
とセットしてしまう可能性があり、あまり意味がないように思います。
ワークシート名(変数)の間違い防止のため、ユーザーフォームの中での
シート名の変数を一括管理したいのですが、
こういう場合、上級者の方はどういう方法で管理しているのでしょうか?
やっぱり各プロシージャーの中で、毎回
Set Ls_sh = Worksheets("Sheet10")
を行って、変数の割り当てをしているのでしょうか?
抽象的な質問なので返答しにくいと思いますが
何かアドバイスやお勧めの方法があれば教えて下さい。
以下のサイトも見たのですが、ちょっと違うような気がするので
質問してみました。
http://officetanaka.net/excel/vba/tips/tips94.htm
追記
可能でしたら、コードで説明して頂ければうれしいです。
※急いでおりません。
No.2ベストアンサー
- 回答日時:
No.1です。
でもユーザーフォームモジュールのみでも
Dim Ls_sh As Worksheet
Private Sub UserForm_Initialize()
Set Ls_sh = Worksheets("Sheet1")
End Sub
Private Sub CommandButton1_Click()
MsgBox Ls_sh.Name
End Sub
Private Sub UserForm_Terminate()
Set Ls_sh = Nothing
End Sub
ユーザーフォームが開かれる際のイベントでセットを行なえば、個々のイベントで宣言の必要はなくなるからこちらの方が楽ですかね。
でも標準モジュールの方でPublicで宣言すれば、ユーザーフォームを複数作成したとか標準モジュール内でも使用させたい時には有利になりますし、
目的次第って所かもです。
・標準モジュール
Option Explicit
Public Ls_sh As Worksheet
・ユーザーフォームモジュール(ユーザーフォーム1)
Private Sub UserForm_Initialize()
Set Ls_sh = Worksheets("Sheet1")
End Sub
Private Sub CommandButton1_Click()
MsgBox Ls_sh.Name
UserForm2.Show
End Sub
Private Sub UserForm_Terminate()
Set Ls_sh = Nothing
End Sub
・ユーザーフォームモジュール(ユーザーフォーム2)
Private Sub CommandButton1_Click()
MsgBox Ls_sh.Name
End Sub
みたいな。
あとは確か・・・クラスモジュールと組み合わせたい時とかでも使われたような気はします。
No.4
- 回答日時:
No.1のお礼に対して。
No.3さんの回答を読んで『そういう事態もあり得るんだ』とちょっとビビってしまっている状態ではあるのですが。
取り敢えず疑問点について。
>Private Sub UserForm_Initialize()
>Private Sub UserForm1_Initialize()
仮に複数のユーザーフォームをデザイン画面で作成したとしても、『UserFoam』と言う大元のオブジェクト名は変わる事はないため、
任意にFoamコントロールのオブジェクト名を変更してもその部分は変えられないと思います。
VisualBasic(.NET)の似たようなイベント(Load)では、Foamの名前を変更すれば
Private Sub abcdefg_Load(ByVal ~
みたいに変わるのですがね。
VBAはもっと古いVBをベースにしているので、開発の際に『そこまでの必要性』が当時なかったのではないか・・・と思います。(言い切れなくてごめんなさい)
No.3さんのご意見はVB.NETには標準モジュールに似たクラスを追加すれば私が回答した方法もできますが、まずその方法を行なうような解説は見つからなかったですね。
キチンとFoam間での明確な値のやり取りを解説されてます。
その点から行くとやはりお薦めできる方法ではなかったのかもですが、であればどうコード化するか?となっても直ぐには思いつかなかったです。
ご解答ありがとうございます。
再度、ご解答を頂きありがとうございます。
>Private Sub UserForm_Initialize()
>Private Sub UserForm1_Initialize()
仮に複数のユーザーフォームをデザイン画面で作成したとしても、『UserFoam』と言う大元のオブジェクト名は変わる事はないため、
任意にFoamコントロールのオブジェクト名を変更してもその部分は変えられないと思います。
>
わかりました。
プロシージャーの名前というより、
>Private Sub UserForm_Initialize()
自体がコマンドのようなものですね。
No.3さんのご意見を見て驚いたのですが、お礼に記載したとおり、
特に深刻な問題ではありません。
なのでNo.2で教えて頂いたテクニックを
一部のワークシートで部分的に使ってみようと思います。
バージョンアップ時に、ワークシートの変数名の整理の
目印になる部分があった方がいいと思いますので。
今回はご解答頂きありがとうございます。
機会がありましたら、またお願いします
※何かあるかもしれないので、しばらく質問は開けておきます。
No.3
- 回答日時:
こんにちは。
ふつうは、モジュール・スコープでも、オブジェクト型の変数はしないですね。
テクニックでは、#1,#2さんで、示された通りですが、
Office Tanaka で示されているのは、
http://officetanaka.net/excel/vba/tips/tips94.htm
プロシージャで引き数で渡す方法(参照渡し)で、なぜそうするかといとう、モジュール・スコープでも、グローバル変数(用語に問題あり)でも、オブジェクト型は、壊れやすいからです。そのために、確実に渡す方法以外は、それをプロシージャ間で回して使うことはしません。*グローバル変数とはいっても、通常は、1つのプロジェクト内だけです。そして、私自身は、ほとんどグローバル定数(Const) のみに限られます。
クラスモジュールで定義する方法もありますが、クラスでインスタンス生成のように変化・変性しないものならともかく、一般的なオブジェクトは、とても長期では保持できるものではないと思うのです。
何らかのエラーが、オブジェクトの取りこぼしにつながるケーズが本当に多いのです。つまり、どこかでエラーが走れば、オブジェクト型の変数はこわれてしまうのです。
実際に私が以前書いていた、とてもみっともないコードですが、プロシージャの始めに、
以下のようなチェックプログラムを置くことになってしまいました。
If sh Is Nothing Then
Set sh = Worksheets("Sheet1") '実際はもうちょっと複雑でサブルーチンにしました。
End If
その愚かさに気づくのに、数年掛かりました。とても大掛かりなものだったので、最初のAuto_Open から書き直す気持ちが起きませんでした。限られたモジュール内では、もしかしたらトラブルなく通せるかもしれませんが、なかなかそうはいかないように思うのです。これがベストとは言いません。プログラムが大きくなればなるほど、そのように考えたくなるのはやむを得ないことです。
言葉で說明してもなかなか実感が分からないと思います。何度となく試してみることで、自分なりのスタイルが見つかるかもしれません。
ご解答ありがとうございます。
ふつうは、モジュール・スコープでも、オブジェクト型の変数はしないですね。
テクニックでは、#1,#2さんで、示された通りですが、
Office Tanaka で示されているのは、
http://officetanaka.net/excel/vba/tips/tips94.htm
プロシージャで引き数で渡す方法(参照渡し)で、なぜそうするかといとう、モジュール・スコープでも、グローバル変数(用語に問題あり)でも、
オブジェクト型は、壊れやすいからです。そのために、確実に渡す方法以外は、それをプロシージャ間で回して使うことはしません。
>
知りませんでした。
今まで、いろいろ教えて頂いているのですが、みなさんのコードは変数を使ったり
withステートメントを使ったりで能率化されています。
なので、今回も「こうしているよ」みたいな方法があると思っていたので意外でした。
正直なところ、変数の名前が統一されていませんが
大きな問題はありません。
変数の名前が違うのはリストや表を作成する時に、
デザインや機能が決まってないからです。
「動作する」、「自力で作れる」ということが一番大事なので、
※みなさんに教えて頂いておりますが(笑)
とりあえず能率アップ出来そうなところから取り組んでいます。
作りながら「やっぱり必要ない」ということもあれば、
「こういう表示がいる」ということが出てきたりします。
変数名はその時の機能でわかりやすい名前を割り当てているため違うのですが、
動作上も問題ないし、ちょっと考えればわかるので問題はありません。
ですがデザインや機能が固まってくると、変数名のルールもおのずと決まってくるため、
気分的に「統一した方がいいかも」という程度です。
今回はインターフェイスの変更で、標準モジュールにあったコードを
順次、ユーザーフォームに引っ越すことになったので、
この機会に上級者のみなさんがどうされているのか聞いてみました。
今回はいろいろ教えて頂き、ありがとうございます。
機会がありましたら、またお願いします。
すごくためになりました。
No.1
- 回答日時:
変数に対してSheetが固定で良いなら。
・『標準モジュール』で Private ではなく Public で変数『だけを』宣言します。
Option Explicit
Public Ls_sh As Worksheet
・ユーザーフォームモジュールにて
Private Sub UserForm_Initialize() 'ユーザーフォームが開かれる際のイベントでセット
Set Ls_sh = Worksheets("Sheet1")
End Sub
Private Sub CommandButton1_Click() '任意のイベントで変数を使用
MsgBox Ls_sh.Name
End Sub
Private Sub UserForm_Terminate() 'ユーザーフォームが閉じられる際のイベントで解放
Set Ls_sh = Nothing
End Sub
とかならやりますよ。(上級者ではなく初級レベルの者ですので、必ずこれが良いとは胸を張っては言えませんけど)
ご解答ありがとうございます。
返信が遅くなりすいません。
こんな方法があるんですね。
知りませんでした。
1つ教えて頂きたいことがあります。
動作チェックのために
Private Sub UserForm_Initialize() 'ユーザーフォームが開かれる際のイベントでセット
Set Ls_sh = Worksheets("Sheet1")
End Sub
~
Private Sub UserForm_Terminate() 'ユーザーフォームが閉じられる際のイベントで解放
Set Ls_sh = Nothing
End Sub
をコピー&ペーストしたところ問題なく動作しました。
ところが、「これは便利!」と思って、
プロシージャーの名前を
Private Sub UserForm1_Initialize()
にすると
実行時エラー91
オブジェクト変数またはWithブロック変数が設定されていません
というエラーメッセージで止まってしまいます。
読み込むだけで、ボタン等で呼び出すわけではないので、
Private Sub ○○△△()
~~
End Sub
「○○△△」の部分は標準モジュールのSubプロシージャーのように、
任意の名前にできると思ったのですが違うのでしょうか?
お手数ですが、この件について
何かアドバイスがあれば教えて下さい。
ご面倒でしたらスルーでOKです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) エクセルのマクロで対象ごとにシート分けしてその内容をセルに書き込みたい 9 2022/08/24 13:23
- Visual Basic(VBA) Excel VBA 複数ブックシートごとにデータを統合する方法について 4 2022/05/20 14:23
- Visual Basic(VBA) 特定の文字を含むシートだけマクロ処理をしたい 1 2023/05/22 01:43
- Visual Basic(VBA) 【Excel VBA】自動メール送信の機能追加 5 2022/09/29 12:53
- Visual Basic(VBA) マクロVBA 1シートをまとめる 閉じ方 初心者 SOS! 1 2022/06/17 14:54
- Visual Basic(VBA) VBAで時間(00:00形式)を積算(足し算)したい 1 2022/11/15 17:04
- Visual Basic(VBA) コード名シートA列と集計シートA列のコードが一致したら、コード名シートA5からk12の範囲をコピーし 1 2022/08/29 23:46
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- Visual Basic(VBA) 集めたシートのシート名を変更したい。 下記のコードでサブフォルダにあるファイルのSheet3を集めて 6 2022/08/23 10:38
- Visual Basic(VBA) 別シートのデータを参照して値を入れたい。 まとめデータシートのC列D列の値を商品一覧シートのコードが 7 2022/08/17 13:20
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・「みんな教えて! 選手権!!」開催のお知らせ
- ・漫画をレンタルでお得に読める!
- ・【選手権お題その2】この漫画の2コマ目を考えてください
- ・2024年に成し遂げたこと
- ・3分あったら何をしますか?
- ・何歳が一番楽しかった?
- ・治せない「クセ」を教えてください
- ・【大喜利】看板の文字を埋めてください
- ・【大喜利】【投稿~12/17】 ありそうだけど絶対に無いことわざ
- ・【選手権お題その1】これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
- ・【穴埋めお題】恐竜の新説
- ・我がまちの「給食」自慢を聞かせてっ!
- ・冬の健康法を教えて!
- ・一番好きな「クリスマスソング」は?
- ・集合写真、どこに映る?
- ・自分の通っていた小学校のあるある
- ・フォントについて教えてください!
- ・これが怖いの自分だけ?というものありますか?
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・10代と話して驚いたこと
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Excel VBA インデックスの境...
-
エクセル:VBAで月変わりで、自...
-
excelの差込印刷で可視セルだけ...
-
VBAで条件が一致する行のデータ...
-
エクセルVBAで SendKeys "{TAB}"
-
VBA 貼付先範囲(行)がいっぱ...
-
Excel で行を指定回数だけコピ...
-
EXCELマクロで全シート対...
-
エクセルVBA 別シートの複数の...
-
Excelでデータの抽出&別シート...
-
歯抜けの時間を埋めて行の挿入
-
VBA別シートの最終行の下行へ貼...
-
VBA 最終行取得からの繰り返し貼付
-
エクセルVBAでの日付順のデ...
-
Excel VBAでシート内全体に非表...
-
エクセル シート保護後コメン...
-
VBAで複数シート選択
-
代替機にキズ
-
スマホ機種変更で旧機種のGoogl...
-
ケータイの電源がいきなり落ち...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Excel で行を指定回数だけコピ...
-
excelの差込印刷で可視セルだけ...
-
Excel VBA インデックスの境...
-
エクセル:VBAで月変わりで、自...
-
VBA別シートの最終行の下行へ貼...
-
VBA:同じ文字列データの比...
-
エクセルVBAで SendKeys "{TAB}"
-
エクセルVBAで 2種のリストを...
-
エクセルVBA 別シートの複数の...
-
Excel VBA 複数条件にマッチし...
-
Excelマクロで空白セルを詰めて...
-
VBA 貼付先範囲(行)がいっぱ...
-
歯抜けの時間を埋めて行の挿入
-
VBAで 任意図形のみ残してその...
-
VBA 最終行取得からの繰り返し貼付
-
VBAで複数シート選択
-
Excelマクロ データが上書きさ...
-
エクセル2007で、マクロで、結...
-
【WORD差し込み印刷】複数レコ...
-
VBAで条件が一致する行のデータ...
おすすめ情報