質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

2回答

2650閲覧

VBA:親フォームから値を渡して呼び出した子フォーム内のコードが飛ばされる

kolobokkule

総合スコア19

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2019/03/05 09:36

前提・実現したいこと

Excel VBAにて呼び出し元のフォームの値を引き継いで、子フォームのリストボックスやラベルに値を引き継ぐコードを書いています。
親フォームから子フォームを呼び出した際に、子フォーム内にあるPrivate Sub UserForm_Activate()における、並び替えの関数がなぜか飛ばされて実行されてしまい、ラベルの値をうまく更新することができずにいます。
(並び替えの関数(フィルタオプション)は
Sheets("児童マスタ").Range("A1").CurrentRegion.AdvancedFilter Action:=xlFilterCopy, _
CriteriaRange:=Range("A1:M2"), CopyToRange:=Range("A10:M10"), Unique:=True
のコードです。これが飛ばされて次に移ってしまいます)

この原因と対処法について教えていただきたいです。
よろしくお願いいたします。

発生している問題・エラーメッセージ

エラーメッセージは出ていません。

呼び出し元(親フォーム)のボタンのコード

Excel

1 2Private Sub btnInd_Click() 3 '親フォーム 4 With frmCRecordSearch.lstRecord 5 Dim targetRow As Integer 6 targetRow = .ListIndex 7 8 Dim indForm As frmIndAll 9 Set indForm = New frmIndAll 10 11 Call indForm.ShowWithParams( _ 12 .List(targetRow, 1), _ 13 .List(targetRow, 2), _ 14 .List(targetRow, 3), _ 15 .List(targetRow, 4), _ 16 .List(targetRow, 5), _ 17 .List(targetRow, 9) _ 18 ) 19 End With 20End Sub

呼び出し先(子フォーム)のフォームのコード

'frmIndAll Public Sub ShowWithParams( _ nenCaption As String, _ kumiCaption As String, _ numCaption As String, _ sexCaption As String, _ nameCaption As String, _ remark As Variant _ ) Me.lblNen.Caption = nenCaption Me.lblKumi.Caption = kumiCaption Me.lblNum.Caption = numCaption Me.lblSex.Caption = sexCaption Me.lblName.Caption = nameCaption Me.lblRemark = remark UserForm_Initialize Me.Show End Sub Private Sub UserForm_Initialize() Dim t As String t = "記録検索" '記録日付の新しい順にソートして抽出 Worksheets("記録検索").Activate Range("B2:M2").Clear Range("O2").Clear Range("H2").Value = Me.lblName.Caption '抽出 Sheets("ポートフォリオ").Range("A1").CurrentRegion.AdvancedFilter Action:=xlFilterCopy, _ CriteriaRange:=Range("A1:O2"), CopyToRange:=Range("A10:N10"), Unique:=True '抽出結果をソート SortChildI "A10" '「記録一覧」リストボックスの設定 With lstIndRecord .Clear 'リストボックス内のクリア .ColumnCount = 10 .ColumnWidths = "70;20;20;20;20;60;60;60;100;0" .TextAlign = fmTextAlignLeft .Font.Size = 10 Dim startRow As Integer Dim LastRow As Integer startRow = 11 LastRow = Worksheets(t).Range("A65536").End(xlUp).Row Dim i As Integer For i = startRow To LastRow .AddItem Cells(i, 3) '日付 .List(.ListCount - 1, 1) = Cells(i, 4).Value '年 .List(.ListCount - 1, 2) = Cells(i, 5).Value '組 .List(.ListCount - 1, 3) = Cells(i, 6).Value '出席番号 .List(.ListCount - 1, 4) = Cells(i, 7).Value '性別 .List(.ListCount - 1, 5) = Cells(i, 8).Value '氏名 .List(.ListCount - 1, 6) = Cells(i, 10).Value 'カテゴリ .List(.ListCount - 1, 7) = Cells(i, 11).Value '詳細カテゴリ .List(.ListCount - 1, 8) = Cells(i, 12).Value '記録内容 .List(.ListCount - 1, 9) = Cells(i, 13).Value '備考 Next End With '日付を記入 txtDate.Text = Format(Now, "mm/dd") End Sub Private Sub UserForm_Activate() '記録数のラベルの設定 '名前と出席番号を抽出条件にして抽出 Worksheets("児童抽出").Activate With lstIndRecord Range("B2:H2").Clear Range("J2:M2").Clear Range("G2").Value = .List(0, 5) Range("D2").Value = .List(0, 3) End With '抽出(フィルタオプション) Sheets("児童マスタ").Range("A1").CurrentRegion.AdvancedFilter Action:=xlFilterCopy, _ CriteriaRange:=Range("A1:M2"), CopyToRange:=Range("A10:M10"), Unique:=True '各ラベルの更新 Dim aInt As Integer Dim pInt As Integer Dim nInt As Integer Dim oInt As Integer With Me aInt = Range("J11").Value .lblAllRecord.Caption = aInt pInt = Range("K11").Value .lblPRecord.Caption = pInt nInt = Range("L11").Value .lblNRecord.Caption = nInt oInt = Range("M11").Value .lblOtherRecord.Caption = oInt If aInt <> 0 Then .lblPRatio.Caption = pInt / aInt * 100 .lblNRatio.Caption = nInt / aInt * 100 End If End With End Sub

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ExcelVBAer

2019/03/06 02:43

「これが飛ばされて次に移ってしまいます」を具体的に記載してください。 ステップ実行時に直前の「End With」から、直後の「With Me」へ移るということでしょうか?? そもそも、ブレークポイント、ステップ実行をご存知でしょうか??
kolobokkule

2019/03/06 03:32

'抽出(フィルタオプション) Sheets("児童マスタ").Range("A1").CurrentRegion.AdvancedFilter Action:=xlFilterCopy, _ CriteriaRange:=Range("A1:M2"), CopyToRange:=Range("A10:M10"), Unique:=True のみを飛ばして次へ移ってしまいます。  ステップインで一つずつ確認したところ、そのように見えた、ということです。
ExcelVBAer

2019/03/06 08:09

では、「Sheets("児童マスタ").Range("A1") ・・・」にブレークポイントをセットして実行しても、 そこでは止まらないのでしょうか??
kolobokkule

2019/03/06 08:11

はい、そういうことになります。
ExcelVBAer

2019/03/07 00:05

逆に、直前の「End With」、直後の「With Me」にブレークポイントをセットすると、そこでは止まるのでしょうか?? ※あり得ない動作に出会った時は、基本的な事を1つずつ確認していくものなので。
guest

回答2

0

コードが飛ばされるということはありません。
単純にRangeと記述するとアクティブシートが対象になるので、それが原因ではないでしょうか。

VBA

1 Sheets("児童マスタ").Range("A1").CurrentRegion.AdvancedFilter Action:=xlFilterCopy, _ 2 CriteriaRange:=Range("A1:M2"), CopyToRange:=Range("A10:M10"), Unique:=True

ここのコードでは直前で児童抽出シートをアクティブにしているので、そちらを参照している可能性があります。
明示的にシートを指定するようにしたほうがよいでしょう。

VBA

1 Set jidou = Worksheets("児童マスタ") 2 jidou.Range("A1").CurrentRegion.AdvancedFilter Action:=xlFilterCopy, _ 3 CriteriaRange:=jidou.Range("A1:M2"), CopyToRange:=jidou.Range("A10:M10"), Unique:=True

もしくはWithを使って書くとか。

VBA

1 With Sheets("児童マスタ") 2 .Range("A1").CurrentRegion.AdvancedFilter Action:=xlFilterCopy, _ 3 CriteriaRange:=.Range("A1:M2"), CopyToRange:=.Range("A10:M10"), Unique:=True

ここに以外にもラベルに設定するところとかも直でRangeを使っているので、全体的に見直してください。

それから余談ですが、イベントの発生順序についても考えたほうがよいです。
気づいていないかもしれませんが、UserForm_Initializeが2回呼ばれています。
Newしたときと、ShowWithParamsの中で意図的に呼び出しているときです。
おそらく動作に影響はないと思いますが、よからぬ不具合の原因にもなるので、イベントの発生タイミングについては熟知しておいたほうがよいでしょう。

投稿2019/03/06 00:32

ttyp03

総合スコア16996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kolobokkule

2019/03/06 02:07

回答ありがとうございます。 実際にいアクティブシートを参照する目的で書いているため、Rangeは直で書いていました。 全体を見直しては見ましたが、それが原因ではないようです。 飛ばされることがないということは、デバッグの際にこの関数に印すらつかないのはどういう原因でしょうか。 initializeの件ですが、Newを消してもも動作するので、消してしまっても構わないという認識でよいでしょうか。
ttyp03

2019/03/06 02:47

関係なさそうでしたか。 他にも何か原因があるか確認してみます。 それとは別にアクティブを前提とした処理はあまり喜ばれません。ちょっとしたことで処理が破綻しやすいです。 回答したとおりシートをキチンと指定してあげるようにしてください。 「飛ばされることがない」というのは、UserForm_Activateイベントが呼ばれてさえいれば、必ず実行されるでしょう、ということです。 コードを見た限りでは無効になるような条件があるわけでもなさそうですし。 少なくとも私の環境ではブレイクポイントを設定することはできました。 Newの処理は消しても問題ないと思います。
kolobokkule

2019/03/06 03:35

ありがとうございます。 もっと全体を見直してみたいと思います。 何かあれば追記いたします。
guest

0

ttyp03さんへのコメントより
initializeの件ですが、Newを消してもも動作するので、消してしまっても構わないという認識でよいでしょうか。

New を消しても、Call indForm.ShowWithParams とメソッドを呼び出した時に自動でNewされてインスタンス生成してからメソッドが実行されますので、その時点で Initialize が発生します。その後、ShowWithParams の中で UserForm_Initialize が Call されているので、Initializeが2回実行されているのは変わりません。
その後、Me.Showでフォームが表示されて Activate イベントが実行されます。

提示のコードからは、シートの状況が分かりませんので、具体的に何をしたいのか読み取れませんが、フォームを開いたときに、どの処理をどのような順番にしたいのかを先に決めて、また、イベントの発生順序を理解して、適切なイベント、または独自のメソッドに処理を記述するようにしましょう。

今回、実行したい処理の順序が、

  1. ShowWithParams に記述してある処理
  2. UserForm_Initialize に記述してある処理
  3. UserForm_Activate に記述してある処理

ということなら、UserForm_Initialize、UserForm_Activate内のコードを ShowWithParams 内の最後に、その順で移動させれば間違いないと思います。

ShowWithParams のコードが長くなるので、それぞれをSubプロシージャに分割して、呼び出すようにしてもいいでしょう。

投稿2019/03/06 05:37

hatena19

総合スコア33610

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kolobokkule

2019/03/06 05:45

回答ありがとうございます。 その方法も試したのですが、うまく動いてくれませんでした。 全体を見直す必要があるかもしれません。
ttyp03

2019/03/06 06:00

hatena19さん> Newの補足ありがとうございます。 そうでした、単純に消しても意味ありませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問