Microsoft Access 掲示板

メインフォーム上に置いたサブフォームコントロールのレコード移動時

16 コメント
views

メインフォーム上のヘッダに検索条件などを設定するエリアがあり、
該当するレコードをサブフォームコントロールに表示(社員リストのようなもの)しています。

メインフォームのヘッダに、顔社員を表示するのに、
通常のサブフォームであれば、レコード移動時のイベントが発生するので、
このタイミングで写真を切り替えれば済む簡単な話なのですが、
サブフォームコントロールですと、そのイベントがなく、
現状、サブフォームコントロールをサブフォームに作り替えるのはしたくないので、
何か工夫でレコード移動時に写真を切り替える方法はございませんでしょうか。

ちなみに、写真ファイルは全てクラウド上にありまして、ActiveXのWebbrowserコントロールを使っています。
現状、写真の下部に更新ボタンを置いて、更新イベントで表示を切り替えています。

よろしくお願いいたします。

はづき
作成: 2025/04/17 (木) 10:09:51
通報 ...
1
hiroton 2025/04/17 (木) 10:26:32 6230f@f966d

サブフォームコントロールのイベントではなく、サブフォームそのものでレコード移動時のイベントが発生します
サブフォームからはMe.Parentで親フォームが参照できます

2
はづき 2025/04/17 (木) 10:44:20 69f3e@da8eb >> 1

ありがとうございます。
すみません、全く理解できておりませんで。
情報が不足しておりましたので追記させていただくと、メインフォームは非連結フォームです。

>サブフォームそのものでレコード移動時のイベントが発生します

初歩的なご質問で恐縮です、このイベントにコードを書くのに、どのように呼び出す(表示)できますか。

3

メインフォームは閉じておいて、サブフォームをデザインビューで開いて、そのレコード移動時にイベントプロシージャを設定すればいいでしょう。

もし、メインフォームのイメージコントロールに顔写真を表示させていて、サブフォームには画像ファイルのパスが格納されているなら、
VBAを使うわなくても、イメージコントロールのコントロールソースにサブフォームの画像パスフィールドを参照するようにすればご希望のことは実現できると思います。

=[サブフォームコントロール名].Form![画像ファイルパスフィールド名]
4
はづき 2025/04/17 (木) 11:22:53 69f3e@da8eb >> 3

ありがとうごいざいます。

そういうことですね。つまりは、サブフォームコントロールではできないってことですか。
サブフォームとか単純なイメージコントロールが使えればこの問題はないのですが、
画像ファイルがクラウド上にありまして、ActiveXのwebbrowserコントロールを使う想定です。
画像を縮小したりもするので、イベントで制御しないと、と感じております。

5

そういうことですね。つまりは、サブフォームコントロールではできないってことですか。

サブフォームコントロールにはサブフォームが埋め込まれているので、そのサブフォームのイベントに設定すればご希望のことは可能です。
サブフォームに設定したレコード移動イベントは、メインフォームを開いてサブフォームでレコード移動させれば発生します。

まずはやってみてうまくいかないなら、どのようにしたのか、記述したコード、どのようにうまくいかないのか説明してください。

6
はづき 2025/04/17 (木) 11:40:43 69f3e@da8eb >> 5

なるほどです。すみません、説明不足でした。
サブフォームコントロールのソースオブジェクトは、サブフォームではなく、
クエリ(データシート)を設定しています。

サブフォームは作っていなくて、そもそもこれを作って設定すれば、
カレントのイベントが取れるというのは、冒頭でもお話した通り、理解はしております。

サブフォームコントロールにクエリ(データシート)を設定した場合、
代替案はないでしょうか?というのが冒頭での質問の本意です。

7
hiroton 2025/04/17 (木) 11:47:40 6230f@f966d

なるほど、把握しました
ソースオブジェクトにフォームを指定しない場合は、明示的にイベントを発生させることができないので基本的には無理ですね

8
はづき 2025/04/17 (木) 11:55:52 69f3e@da8eb >> 7

はやりそうですよね、当初の理解通りではありました。
現状、ボタンクリック時に呼び込みはできているので、
このためだめにサブフォームを作って、ロジックも変えないといけない工数が大きいので、
暫くは様子をみます。

9
hatena 2025/04/17 (木) 12:26:04 修正

サブフォームコントロールにクエリ(データシート)を設定した場合、
代替案はないでしょうか?というのが冒頭での質問の本意です。

そういうことでしたか。
ソースオブジェクトにテーブルやクエリを設定した場合、メインフォームを開いたときに自動でサブフォームオブジェクトが生成されますので、それにイベントを設定することができます。
Accessのフォームの場合、イベントプロパティにFunctionを設定できますので、それを利用すればご希望のことは実現可能です。

まず、標準モジュールに下記のFunctionを記述してください。

Function CurentEvent()
    With CodeContextObject
        Debug.Print "レコード移動しました!IDは" & !ID
        .Parent!テキスト1.Value = !ID
   End With
End Function

CodeContextObject はFunctionが呼び出されたオブジェクトを返します。

メインフォームの読み込み時イベントに下記のコードを設定してください。

Private Sub Form_Load()
    Me.サブフォームコントロール名.Form.OnCurrent = "=CurentEvent()"
End Sub

クエリにはIDフィールドがあり、メインフォームには「テキスト1」というテキストボックスがあるという前提です。

メインフォームを開いてサブフォームでレコード移動してみてください。
イベントが発生しているのが確認できるでしょう。

10
hiroton 2025/04/17 (木) 13:20:42 da23d@f966d >> 9

あー、なるほど、そういう仕組みありましたねぇ。使わないとパッと出てこないです
サブフォームを作る労力とどのくらい差があるかなぁとも思っていしまいますし

11

サブフォームを作る労力とどのくらい差があるかなぁとも思っていしまいますし

ですよね。
フォームウィザードでデータシートビューで作成すれば1分もかからずに作成できますからね。
現状のロジックも参照先を変更するだけでそのまま使えるはずですし。

12
はづき 2025/04/17 (木) 13:44:01 69f3e@da8eb >> 9

なな、なんと。そんなやり方ありましたか。
確認させていただきます。

13
はづき 2025/04/17 (木) 14:45:48 69f3e@da8eb >> 12

できないと思って原因を探ったところ、
メインフォームの読み込み時に、UserNameによって、見える範囲(列)を動的に設定しています。
あくまで簡易的なアクセス制限ですので、非表示で隠してあるテーブルとかクエリを直接見ることはできるのですが。

具体的には、これが影響していると思われます。
サブフォームコントロールのレコードソース:Qry_名簿です。
UserNameに応じて、見せる属性をstrFileldsで生成して、クエリを置き換えています。

currentdb.QueryDefs("Qry_名簿").SQL="select " & strFilelds & " from Mtbl_名簿"
Me.サブフォームコントロール名.form.recordSource = "select * from Qry_名簿"

Me.サブフォームコントロール名.Form.OnCurrent = "=CurentEvent()" ←------この場所で入れてもダメですか?

上記の動的に変えているところを削除すると、イベントが発生することは画にしました。
人により、列の属性数がかなり変わるので、見せない人には見せない属性の存在も知らせたくない、
といったこともあり、パターンを網羅した固定サブフォームは作り難いという背景もありました。

14
hatena 2025/04/17 (木) 18:16:30 修正 >> 12

簡単なサンプルを作成して動作確認してみました。

テーブル
 Mtbl_名簿 (ID, F1, F2, F3, F4)

クエリ Qry_名簿
 SELECT ID, F1 FROM Mtbl_名簿;

メインフォーム
 テキストボックス テキスト1

コンボボックス cbFilelds
 値集合タイプ 値リスト
 値集合ソース F2;F3;F4
 規定値 "F2"

サブフォームコントロール SF1
 ソースオブジェクト 空欄

メインフォームのフォームモジュール

Option Compare Database
Option Explicit

Private Sub Form_Load()
    SetSFList
End Sub

Private Sub cbFilelds_AfterUpdate()
    SetSFList
End Sub

Public Sub SetSFList()
    Dim strFilelds As String
    strFilelds = "ID, F1, " & Me.cbFilelds

    CurrentDb.QueryDefs("Qry_名簿").SQL = "select " & strFilelds & " from Mtbl_名簿"
    Me.SF1.SourceObject = "クエリ.Qry_名簿"
    Me.SF1.Form.OnCurrent = "=CurentEvent()"
End Sub

標準モジュール

Function CurentEvent()
    With CodeContextObject
        Debug.Print "レコード移動しました!IDは" & !ID
        .Parent!テキスト1.Value = !ID
   End With
End Function

仕様
サブフォームのリストには ID, F1 フィールドは常に表示
コンボボックスで選択されたフィールドが表示

上記でメインフォームを開くと、ID, F1, F2列が表示されている
レコード移動するとイベントが発生してテキスト1にカレントのIDが表示される

コンボボックスでフィールド名を変更するとサブフォームの表示も変更される
レコード移動イベントも発生する。

というように動作確認できました。

15

ポイントは、下記ですね。

Me.SF1.Form.RecordSource = "SELECT ・・・・"
というようにサブフォームの RecordSource を書き換えてもサブフォームオブジェクトは再生成されない。
Me.SF1.SourceObject = "クエリ.Qry_名簿"
というようにソースオブジェクトを設定すると再生成される。
再生成される前にサブフォームのレコードソースのクエリのSQLを書き換えておく。
その後、
Me.SF1.Form.OnCurrent = "=CurentEvent()"
というようにイベントを設定する。

16
はづき 2025/04/18 (金) 06:56:14 3a7d2@da8eb >> 12

ポイントの通りの順番でやったらできました。
完璧です!
勉強になりました、どうもありがとうごいざいました。