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

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

ただいまの
回答率

89.11%

dictionary変数を用いたフォームの生成では、Activateイベントが呼ばれません。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 113

jkjksan

score 19

はじめに

伝票+伝票明細の画面を作っています。画面の見た目はよくあるタイプです。ここでは伝票フォーム、伝票明細フォームというオブジェクト名にとします。

メインフォーム(非連結、単票モード)
+サブフォーム(帳票モード)
で構成しています。

多画面生成を実現するためにdictionary変数を用いており、簡単に言うと次のような方法を取っています。

'Form_画面管理用のフォームオブジェクト
Public dic As New dictionary
Public Sub 画面を生成()
 Dim key As String
 key = Timer
 With Me.dic
  .Add key, New 伝票フォーム

   With .Item(key)
    .Tag = Key
    .伝票ID = Call 伝票IDを取得する処理()
    'その他初期化処理
    .Visible = True '画面表示開始
   End With

 End With

End Sub

やりたいこと

サブフォームの指定フィールドに初期値(DefaultValue)を設定したい。
具体的には、伝票明細フォームのコントロール(TextBox,伝票ID,リレーション用の外部キーです。)
やりたい事をコードで説明するなら、以下のようになります。

'生成された伝票フォームオブジェクトのActivateイベント
Me.伝票明細フォーム.Form.伝票ID.DefaultValue = Me.伝票ID.Value

何故実現できないのか

冒頭でDictionaryを用いて初期化している時、サブフォームまでは潜れないようでした。(参照できない)

伝票フォームオブジェクトのOpenイベントにしかけても、参照できないエラーが発生します。

Activateイベントに引っ掛けようとしても、Activateイベント自体が呼ばれませんでした。別画面に切り替え等の操作を行ったとしてもです。

画面が表示された後、親フォームに設置した何かしらのコントロールが起こすChangeイベントでは、子フォームへ対する参照が通りますが、実装としては人による操作が開始される前が望ましいと考えています。

他のアプローチがある場合、アドバイスを頂きたく。

宜しくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

私が過去に作ったcollectionを使って多重new Formするサンプル引っ張ってきましたが
activateイベントは普通に反応しました。

Me.伝票明細フォーム.Form.伝票ID.DefaultValue = Me.伝票ID.Value


これをせずにリンク親フィールド、リンク子フィールドを使って伝票IDを設定してはいけないんですか?
このやり方はOpenArgsも使えないので初期値関連は渡せないのでめちゃくちゃ不便なんですよね…

タイミングが許すのであればここで設定すればいいかと

   With .Item(key)
    .Tag = Key
    .伝票ID = Call 伝票IDを取得する処理()
    'その他初期化処理
    .Visible = True '画面表示開始
    .伝票明細フォーム.Form.伝票ID.DefaultValue = .伝票ID
   End With

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/06/30 22:34

    私もsousukeさんのリンク親フィールドをリンク子フィールドを設定しておくという案に同意です。
    ひょっとするとメインフォームが非連結の場合はリンクフィールドが設定できないと思っているのかな?
    そんなことないですよ。リンク親フィールドにコントロール名を設定すればリンクできます。
    リンクしておけば DefaultValue も自動で設定されます。

    キャンセル

  • 2020/07/01 19:05

    回答ありがとうございます。
    疲れがピークに達したため、リフレッシュしておりました。

    頂きました回答を参考に検証を進めていく中で判明したことは、
    物凄くお恥ずかしい話ですが、参照先のオブジェクト名を間違えておりました。
    サブフォームに「伝票ID」というオブジェクト(TextBox)は存在しておらず、実際のオブジェクト名は「ID」になっていました。これはUIデザインを同時進行で編集していたため、どこかで操作ミスを起こしていたと思います。
    提示していたソースコードでは参照エラーが出て、私以外では検証してもエラーが出ないのも当然です。

    また、質問当時に頭が煮詰まって休憩中でPCから離れており、スマートフォンにて記憶を頼りにソースコードを提示していたため、不必要に検証させてしまった事についてお詫び申し上げます。

    オブジェクト名を間違えていたことに気付かなった原因として、DictionaryやCollection等ではインテリセンスが効かない方法であったため、コードもオブジェクトも間違えていないと強い思い込みをしたことによる検証不足です。

    相当にスパゲッティな処理と開発手順であったことを反省し、「多重 New Form」の使いどころも考え直す事にしました。

    「リンク親フィールドをリンク子フィールドを設定しておくという案」についてですが、
    メインフォームにレコードソースを設定していないため、埋め込み(サブフォーム)に対してリンク親フィールド及びリンク子フィールドを設定することが出来ません。
    レコードソースを設定していない理由については、忘れてしまいました。
    恐らく、伝票フォームを新規登録として開きたい場合では、
    ```VBA
    DoCmd.GoToRecord acDataForm, Me.Name, acNewRec
    '多重フォーム状況下では、別のウィンドウ(Hwnd)に対して処理が掛かってしまう
    ```
    ということがありますので、個別に代入するしかないと考えました。
    これ以上の事は考えておりませんでした。

    キャンセル

  • 2020/07/01 19:57

    hatena19氏もおっしゃっていますが「リンク親フィールド」を設定するのにメインフォームにレコードソースは必須ではありません。「リンク子フィールド」はサブフォームのレコードソースにあるフィールド名をする必要がありますが、「リンク親フィールド」はフィールド名である必要がなくテキストボックス名などを指定できます。「リンク親フィールド」に「Tempvars!テスト」など書いても普通に動きます。
    また「DictionaryやCollection等ではインテリセンスが効かない方法」であるのは
    単純にキャストしてないからです。汎用性は乏しいですが伝票フォームの「コード保持」を[はい]にして

    dim f as Form_伝票フォーム
    ' Dictionaryからキャストして受け取る
    set f = .Item(key)
    with f
    (ここでドットを打てば伝票フォームのインテリセンスがききます。)

    こんな感じで書けばインテリセンスききますし存在しないプロパティやコントロールを
    書けばコンパイル段階でエラーを吐きます。

    キャンセル

  • 2020/07/02 09:24 編集

    >「リンク親フィールド」を設定するのにメインフォームにレコードソースは必須ではありません。
    直打ちすれば入るんですね、初めて知りました。

    キャストについても閃きませんでした。

    質問の内容としては、教えていただいた意図した動作を出来るようになりましたので締めようと思います。

    おかげさまで非常に助かりました。ありがとうございました。

    キャンセル

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

  • ただいまの回答率 89.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる