Excel (VBA) |
![]() ![]() |
(Windows 10 Home : Excel 2016)
標準モジュールからユーザーフォームの値を受け渡す
投稿日時: 20/11/19 10:30:33
投稿者: ip8bk
|
---|---|
いつも大変お世話になっております。
Sub usf_access() UserForm1.TextBox1.Value = 3 End Sub |
![]() |
投稿日時: 20/11/19 10:59:58
投稿者: simple
|
---|---|
されたいことがよく分かりませんが、
|
![]() |
投稿日時: 20/11/19 11:38:30
投稿者: ip8bk
|
---|---|
早速ご回答ありがとうございます。
引用: はいそうです。 userform1のinitializeに下記callの一文を追加しましたが、値が反映されません。 どこが違っているのでしょうか、、、 Private Sub userform_initialize() Call usf_access End Sub |
![]() |
投稿日時: 20/11/19 14:55:05
投稿者: simple
|
---|---|
Call usf_access
|
![]() |
投稿日時: 20/11/19 15:09:24
投稿者: hatena
|
---|---|
そのユーザーフォームは既に開いているのか、開いていないのか。
|
![]() |
投稿日時: 20/11/19 15:20:47
投稿者: ip8bk
|
---|---|
ご回答ありがとうございます。
Sub call_usf() a = ActiveCell.Row b = Application.WorksheetFunction.CountIf(Columns(3), Cells(a, 3).Value) UserForms.Add("UserForm" & b).Show End Sub Sub call_usf2() UserForm1.Show vbModeless End Sub |
![]() |
投稿日時: 20/11/19 18:01:58
投稿者: WinArrow
|
---|---|
標準モジュールの変数の値をユーザーフォームのテキストボックスなど、コントロールにセットする方法
|
![]() |
投稿日時: 20/11/20 08:45:11
投稿者: Suzu
|
---|---|
ip8bk さんの引用: このコードの動作について、どのように認識されていますでしょうか? 開くフォームは、『UserForm1』に固定はされていません。 対して 引用: は、UserForm1 に固定されています。 違うフォームに値が入力されているのではありませんか? |
![]() |
投稿日時: 20/11/20 08:54:15
投稿者: ip8bk
|
---|---|
Suzu様
|
![]() |
投稿日時: 20/11/20 09:00:39
投稿者: ip8bk
|
---|---|
hatena様
引用: 順番的にはユーザーフォームを開いた後にモジュールを呼び出しています。 モードレスに関係なく、どちらでも値は入らない状況です。 |
![]() |
投稿日時: 20/11/20 10:02:31
投稿者: Suzu
|
---|---|
ip8bk さんの引用: そうなら良いです。 質問者の方には、コードを提示されて、動作内容を理解できていない状態で質問をされてる方もいらっしゃらって、確認させて頂きました。 コードを作成し確認しましたところ 1. usf() にて フォームを呼び出し 2. フォームの Initialize にて、usf_access 呼び出し 3. usf_access の UserForm1.TextBox1.Value = 3 実施時フォームの Initialize発生 4. フォームの Initialize にて、usf_access 呼び出し 5. usf_access の UserForm1.TextBox1.Value = 3 実施 の流れになり、Initialize が2回発生していませんか? まぁ、確かに Initialize の段階で 初期化 なので、外(標準モジュール)から見たら まだ実体化していない扱いなのかもしれませんね。 WinArrow さんが提示してくださっている様に、Initialize で 変数を読みに行くのが簡単ですね。 あとは、・・ Private Sub userform_initialize() Call usf_access(Me) End Sub Sub usf_access(frm As UserForm) frm.TextBox1.Value = 3 End Sub とか。 |
![]() |
投稿日時: 20/11/20 10:29:11
投稿者: hatena
|
---|---|
UserForms.Add("UserForm1").Show
Dim usf1 As UserForm1 Sub call_usf() Set usf1 = UserForms.Add("UserForm1") usf1.Show End Sub Sub usf_access() usf1.TextBox1.Value = 3 End Sub これで、call_usf を実行してフォームを開いた後、usf_access を実行したら3が代入されます。 変数の宣言の型が UserForm1 になっていることに注意してください。 もし、複数のフォームがありそれを使い分けたいなら、その分だけ変数の宣言が必要になります。コードも下記のように複雑になります。 Dim usf1 As UserForm1 Dim usf2 As UserForm2 Sub call_usf() Dim a, b a = ActiveCell.Row b = Application.WorksheetFunction.CountIf(Columns(3), Cells(a, 3).Value) Select Case b Case 1 Set usf1 = UserForms.Add("UserForm1") usf1.Show Case 2 Set usf2 = UserForms.Add("UserForm2") usf2.Show End Select End Sub Sub usf1_access() usf1.TextBox1.Value = 3 End Sub Sub usf2_access() usf2.TextBox1.Value = 3 End Sub わざわざこのように複雑にするぐらいなら下記のコードの方がよほどスッキリします。 Sub call_usf() Dim a, b a = ActiveCell.Row b = Application.WorksheetFunction.CountIf(Columns(3), Cells(a, 3).Value) Select Case b Case 1 UserForm1.Show Case 2 UserForm2.Show End Select End Sub Sub usf1_access() UserForm1.Value = 3 End Sub Sub usf2_access() UserForm2.Value = 3 End Sub ちなみに、上記のコードはユーザーフォームのShowModalプロパティはFalseに設定されている前提です。ShowModalがTrue(モーダル)の場合は、ユーザーフォームが開いている間はユーザーフォーム以外操作できないし、ユーザーフォーム以外からコードを実行することもできませんので。 実際にやりたいことを簡略化して質問ているのだと思いますが簡略しすぎているので、これらのコード自体あまり意味があることとは思えません。もう少しやりたいことの全体像を提示してもらうともう少し有意義な回答ができると思います。 |
![]() |
投稿日時: 20/11/20 10:37:12
投稿者: hatena
|
---|---|
訂正
Sub usf1_access() UserForm1.Value = 3 End Sub Sub usf2_access() UserForm2.Value = 3 End Sub (正) Sub usf1_access() UserForm1.TextBox1.Value = 3 End Sub Sub usf2_access() UserForm2.TextBox1.Value = 3 End Sub |
![]() |
投稿日時: 20/11/20 10:38:00
投稿者: WinArrow
|
---|---|
引用: 「usf_access()」に、どうしてもこだわるのでしたら ↓のようにコードを変更することをお勧めします。 Function usf_access() usf_access = 3 End Sub 引用: ↓ Private Sub userform_initialize() Me.TextBox1.Value = usf_access End Sub |
![]() |
投稿日時: 20/11/20 11:13:08
投稿者: hatena
|
---|---|
引用: call_usf() でユーザーフォームをモードレスで開いて、ユーザーがシート上でなにか操作した後、usf_access() を呼び出しているということですよね。(私はそう解釈しました。) それともユーザーフォームを開くとき(initializeイベント)に usf_access を呼び出すということですか。 それを明確にしてください。 まあ、どちらにしても意味のあることではないと思いますので、やりたいことの全体像を提示したほうがいいかと思います。 |
![]() |
投稿日時: 20/11/20 11:23:16
投稿者: ip8bk
|
---|---|
皆様
Sub usf1_access() UserForm1.Value = 3 End Sub Sub usf2_access() UserForm2.Value = 3 End Sub |
![]() |
投稿日時: 20/11/20 11:40:25
投稿者: hatena
|
---|---|
ip8bk さんの引用: それを最初に言ってほしかったです。 でユーザーフォームはいくつぐらいになる予定ですか。 また、そのユーザーフォームはすべて構成や役割が異なるのですか。 また、そのユーザーフォームはモーダルですか。モードレスですか。 sf_access()を呼び出すのは、ユーザーフォームを開く時ですか。それとも開いた後、なんからの処理か操作があった後ですか。 上記の点を明確にしてください。 |
![]() |
投稿日時: 20/11/20 12:00:47
投稿者: ip8bk
|
---|---|
説明が遅くなり申し訳ございません。
引用: 10個ぐらいになる予定です。テキストボックスの数が違うだけです。 21個ずつ増えていきます。 引用: いまのところモーダルで使っていく予定です。 引用: ユーザーフォームを開くときです。 |
![]() |
投稿日時: 20/11/20 12:51:40
投稿者: WinArrow
|
---|---|
[quote]
|
![]() |
投稿日時: 20/11/20 13:31:31
投稿者: ip8bk
|
---|---|
ご回答ありがとうございます。
引用: まったく同じコードを使用します。 なので、変数も同じになります。 usf_accessは1つだけ作成することを考えております。 共通化してあるので、どのユーザーフォムでも同じコードが使えるようになっています。 下記変数Bで、forで回す回数(for1回で21個分のテキストボックスに入力するコードにしています)、呼び出すユーザーフォームを特定しています。 Sub call_usf() a = ActiveCell.Row b = Application.WorksheetFunction.CountIf(Columns(3), Cells(a, 3).Value) UserForms.Add("UserForm" & b).Show End Sub |
![]() |
投稿日時: 20/11/20 13:45:34
投稿者: WinArrow
|
---|---|
引用: は、 >Sub call_usf() の部分ではないでしょうか? 引用: ↑の部分は、テキストボックスが1つですよね? どのように共通化するのですか? |
![]() |
投稿日時: 20/11/20 14:32:17
投稿者: hatena
|
---|---|
やりたいことをまとめると、
Public Sub call_usf(usfName As String) Dim usf As Object Set usf = UserForms.Add("UserForm" & 1) '以下共通処理 usf.TextBox1.Value = 3 usf.Show End Sub 上記の共通関数を標準モジュールに記述しておいて、下記のように呼び出せばいいでしょう。 Sub Test() Dim a as Long, b As Long a = ActiveCell.Row b = Application.WorksheetFunction.CountIf(Columns(3), Cells(a, 3).Value) call_usf "UserForm" & b End Sub |
![]() |
投稿日時: 20/11/20 15:15:25
投稿者: WinArrow
|
---|---|
引用: ↑について、 もう一度、質問します。 ユーザーフォームを10個 連続して開こうとしていりことは、理解できます。 しかし、VbModeLessをつけなくて、開くと、 1番目のユーザーフォームを閉じないと、2番目のユーザーフォームが開けません。 VbModeLessで、開くことです。 再掲 私の投稿 投稿日時: 20/11/20 10:38:00 をもう一度、読んで、理解してください。 |
![]() |
投稿日時: 20/11/20 15:19:19
投稿者: ip8bk
|
---|---|
ユーザーフォームは連続してではなく、該当のものを1つ開くだけです。
|
![]() |
投稿日時: 20/11/20 15:35:38
投稿者: WinArrow
|
---|---|
ip8bk さんの引用: ごめんなさい。勘違いしていました。 |
![]() |
投稿日時: 20/11/20 16:34:35
投稿者: ip8bk
|
---|---|
こちらこ簡潔に説明できてなくて申し訳ございません。
|
![]() |
投稿日時: 20/11/20 17:40:04
投稿者: hatena
|
---|---|
投稿日時: 20/11/20 14:32:17 のコードに間違いがありましたので、下記に修正します。
Public Sub call_usf(usfName As String) Dim usf As Object Set usf = UserForms.Add(usfName) '以下共通処理 usf.TextBox1.Value = 3 usf.Show End Sub Sub Test() Dim a As Long, b As Long a = ActiveCell.Row b = Application.WorksheetFunction.CountIf(Columns(3), Cells(a, 3).Value) call_usf "UserForm" & b End Sub 簡単に解説しておきますと、 Set usf = UserForms.Add(usfName) でusfName引数で指定したユーザーフォームを非表示で開き、オブジェクト変数に格納します。 この時点で、usfを通じてユーザーフォーム上のコントロールにアクセスできます。 ここで、共通処理を記述します。 その後、usf.Show でフォームをモーダルで表示させます。 これ以降はユーザーフォームにアクセスできませんので、それ以前に処理を済ませておきます。 |
![]() |
投稿日時: 20/11/20 17:46:58
投稿者: WinArrow
|
---|---|
hatena さんの案をお借りしますが、
|
![]() |
投稿日時: 20/11/20 17:57:42
投稿者: ip8bk
|
---|---|
Public Sub call_usf(usfName As String) カッコの中で宣言したことがないのですが、これはどのような意味(どのような場合に使うのでしょうか?)になりますでしょうか? |
![]() |
投稿日時: 20/11/20 18:28:26
投稿者: hatena
|
---|---|
ip8bk さんの引用: 引数というものです。 関数を呼び出すときにここに記述した値などを関数内で使うことができます。 今回は呼び出すときにユーザーフォーム名を記述して、関数内で利用しています。 VBA 関数に引数を渡す https://www.tipsfound.com/vba/02002 |
![]() |
投稿日時: 20/11/20 18:38:51
投稿者: hatena
|
---|---|
いままでやり取りしていて、どうも納得いかないことは、
|
![]() |
投稿日時: 20/11/20 19:51:55
投稿者: ip8bk
|
---|---|
ご回答ありがとうございます。
|
![]() |
投稿日時: 20/11/20 20:37:12
投稿者: WinArrow
|
---|---|
ip8bk さんの引用: 意味わかんない!!!! 無理に説明してくださいとはいいませんが、 本題に戻そう 引用: この中のコードが問題だということ 理解できましたか? |
![]() |
投稿日時: 20/11/21 04:52:52
投稿者: ip8bk
|
---|---|
ご回答ありがとうございます。
引用: モーダルの場合、ユーザーフォームを開いてからテキストボックスなどに入力できないからでは無いでしょうか? このコードが問題なのではなく、このコードがイニシャライズに入っていたことが問題、というのが私の理解ですが、間違っていますでしょうか? |
![]() |
投稿日時: 20/11/21 05:04:33
投稿者: hatena
|
---|---|
ip8bk さんの引用: 共通化するということは、当然、テキストボックスも共通化するということです。 UserForms.Add("UserForm" & b).Show の b の値によってテキストボックスの数が変化するというのなら、テキストボックスを最大数配置しておいて必要な分だけ表示させて、あとは非表示にしておくとか。 おそらくテキストボックスに入力して値はシートに転記するのだと思いますが、転記先が異なるなのなら、転記先を前にも説明して引数を利用して渡すとか。 方法はいろいろあります。 |
![]() |
投稿日時: 20/11/21 05:08:56
投稿者: ip8bk
|
---|---|
作成いただきました下記のコードで上手く動くことが確認できました。
Public Sub call_usf(usfName As String) Dim usf As Object Set usf = UserForms.Add(usfName) '以下共通処理 usf.TextBox1.Value = 3 usf.Show End Sub Sub Test() Dim a As Long, b As Long a = ActiveCell.Row b = Application.WorksheetFunction.CountIf(Columns(3), Cells(a, 3).Value) call_usf "UserForm" & b End Sub |
![]() |
投稿日時: 20/11/21 05:25:15
投稿者: hatena
|
---|---|
ip8bk さんの引用: イニシャライズに入っていることは問題ではないです。 モーダルの場合入力できないのは、表示させた後(show)、標準モジュールから入力しようとした場合です。 ユーザーフォーム内のコードなら、自身のテキストボックスにはいつでも入力できます。 問題なのは、 UserForms.Add("UserForm1").Show という方法で開いた場合は、UserForm1 ではアクセスできないということと、 そもそもフォームを共通化したいといってるのに、UserForm1というアクセスではユーザーフォームが固定されていること、 です。 この問題を解決する方法として、 フォーム名は引数で渡す、UserForms.Addで開いたフォームを変数に格納する、それを使ってShowする前にアクセスする、 という方法を 投稿日時: 20/11/20 17:40:04 で提案しています。 イニシャライズで記述するなら、Suzuさんの 投稿日時: 20/11/20 10:02:31 の投稿の自身のフォーム(Me)を引数で渡すという方法になります。 |
![]() |
投稿日時: 20/11/21 05:47:05
投稿者: ip8bk
|
---|---|
原因はイニシャライズではありませんね。
引用: 下記のコードのことでしょうか? Set usf = UserForms.Add(usfName) |