Microsoft Access 掲示板

サブフォームの値をすぐに計算など

11 コメント
views
4 フォロー

アクセス初心者です。
メイン・サブフォームがあります(メインIDでリレーション)。サブフォームにはフィールドがいくつかあります(F1・F2・・・)。F2とF4には金額の入力をしてまして各合計金額をサブフォームのフッタに表示させています。最終的に(メインID毎に)その合計が合致する必要があるために。再更新(Requery)ボタンで確認してます。出来ましたらF2、F4入力後すぐに計算ができたらいいのと、合致していなければフォームを閉じる時やメイン移動時に警告メッセージが出るようにしたいと思い投稿しました。

ヒトシ
作成: 2024/01/26 (金) 14:48:14
通報 ...
1

「その合計が合致する必要がある」とは、具体的に何と何が一致する必要があるのでしょうか。
サブフォームのフッターに表示させているF2の集計値とF4の集計値でしょうか。

「F2、F4入力後すぐに計算」とは、F2テキストボックスで入力した直後(レコード保存する前)に集計値に反映させたいということでしょうか。

とりあえず「再更新(Requery)ボタン」に設定してあるコードを提示して、こ処理でどの部分をどのように改善したいのかを説明してもらうと回答しやすいです。

2
ヒトシ 2024/01/26 (金) 15:54:13 ddfe5@127a8

すみません説明不足でした。サブは下記のイメージです
F1   F2     F3    F4
摘要A  ¥100   摘要B   ¥50
摘要C  ¥20    摘要D   ¥70
このF2とF4の各合計値が合致する必要があります(サブフッターには各Sum値をテキストボックス)。金額入力ミスのチェックをしたいのです。
再更新ボタンもサブフッターに配置しており、単純に” Me.Requery” の記述だけです。
改善したいことはサブに金額入力したらすぐにサブフッターのテキストボックスに反映したいのと(再更新ボタン押さなくても)、合計値が合致していない状態でフォームを閉じたりメインに配置してます移動ボタン(新規レコード含む)で移動できない様に入力チェックが出来ないかなと思いまして。

3

改善したいことはサブに金額入力したらすぐにサブフッターのテキストボックスに反映したい

Accessの仕様としては、F2、F4に金額を入力しただけではフッターの集計には反映されません。
レコード移動するとか、[Shift]+[Enter]キーを押す、レコードセレクタをクリック、・・・などなど
のレコード保存アクションを起こすと反映されます。

このレコード保存アクションを起こす前に、テキストボックスで金額を入力した直後に反映させたいなら、下記のリンク先の方法を参考にしてください。

フォームでの集計をレコード保存する前に反映させる - hatena chips

ただ、通常はそこまでしなくてもいいように思います。

合計値が合致していない状態でフォームを閉じたりメインに配置してます移動ボタン(新規レコード含む)で移動できない様に入力チェックが出来ないかなと思いまして。

サブフォームコントロールのフォーカス喪失時のイベントで合計値をチェックして合致していなかったら、イベントをキャンセルすればいいでしょう。
あとフォームの読み込み解除時でもチェックする必要があります。

サブフォームコントロール名(サブフォームを埋め込んでいるコントロールの名前)を「埋め込み1」、
サブフォームのフッターの集計テキストボックスの名前を SumF2, SumF4 と仮定した場合のサンプルコードです。
メインフォームのモジュールに記述します。

Private Sub Form_Unload(Cancel As Integer)
    If Me.埋め込み1.Form!SumF2.Value <> Me.埋め込み1.Form!SumF4.Value Then
        Cancel = True
        Me.埋め込み1.Form!SumF2.SetFocus
    End If
End Sub

Private Sub 埋め込み1_Exit(Cancel As Integer)
    Me.埋め込み1.Form.Requery 'レコード保存
    If Me.埋め込み1.Form!SumF2.Value <> Me.埋め込み1.Form!SumF4.Value Then
        Cancel = True
        MsgBox "F2とF4の合計が合っていません!"
    End If
End Sub

サブフォームコントロール名の確認法は下記を参考に。

サブフォームとサブフォームコントロールの違いとは? - hatena chips

4
ヒトシ 2024/01/29 (月) 08:54:55 ddfe5@72804

ありがとうございます。[OldValue]の事は全くしりませんでした。イベント使わずに計算が反映しますので、これは便利です。それと”フォーカス喪失時”と”フォームの読み込み解除時”のイベントの違いを教えて頂けますでしょうか(知識不足でフォームの流れがわかっていないのですみません)。
あと質問と異なるのですが、このフォームでメインにだけ入力してサブにはレコードが1件もない状態を回避したい場合、どうすると効果的でしょうか?(閉じたり、メインレコード移動時にメッセージを出したい)

5
ヒトシ 2024/01/29 (月) 10:40:26 ddfe5@72804

すみません、合計値が合致していない時は"F2とF4の合計が合っていません!"のメッセージが出て先に進めなくて狙い通りなのですが、合致している(正常の合計値)場合にフォーム閉じると ”メソッドまたはデータ メンバが見つかりません。” のコンパイルエラーとなり Private Sub Form_Unload(Cancel As Integer)のIf Me.埋め込み1(サブフォームコントロール名)の部分が示されます。メイン・サブに未入力で閉じても同じエラーとなります。
この回避はどうするといいでしょうか?

7

Private Sub Form_Unload(Cancel As Integer)
はメインフォームのモジュールに記述してますか。
サブフォームのモジュールに記述しているのなら、メインフォームの方へ移動させてください。

6

それと”フォーカス喪失時”と”フォームの読み込み解除時”のイベントの違いを教えて頂けますでしょうか(知識不足でフォームの流れがわかっていないのですみません)。

一般論ではなく前回の回答の”フォーカス喪失時”と”フォームの読み込み解除時”についてということで回答します。

その前にメイン/サブフォーム形式のフォームのフォーカス関係のイベントについて。
まずフォームを開いた直後は、メインフォームのタブオーダーが1番目のコントロールにフォーカスがあります。
メインフォームの入力を終えてサブフォームの入力に移るためにサブフォームのコントロールをクリックしたとします。
フォーカス関係イベントは下記のように発生します。

メインフォーム上のサブフォームコントロールのフォーカス取得時(Enter)イベント

サブフォーム上のコントロールのフォーカス取得時(Enter)イベント

サブフォーム上のコントロールのフォーカス取得後(GotFocus)イベント

サブフォームの入力を終了してメインフォームのコマンドボタンやテキストボックスをクリックしてメインフォームへフォーカスを移動したとき

サブフォーム上のコントロールのフォーカス喪失時(Exit)イベント

サブフォーム上のコントロールのフォーカス喪失後(LostFocus)イベント

メインフォーム上のサブフォームコントロールのフォーカス喪失時(Exit)イベント※

クリックしたメインフォーム上のコントロールのフォーカス取得時(Enter)イベント

前回の回答では上記の※の時に、2つの合計をチェックして不一致の場合は、Cancel = Trueでイベントをキャンセルします。イベントがキャンセルされるとそれ以降のイベントは発生せずフォーカスはサブフォームから移動しません。

フォームの読み込み解除時イベントはフォームの右上のクローズボタンをクリックするなどフォームを閉じようとするアクションを起こすと発生します。サブフォームにフォーカスがある場合は、その前にメインフォームへフォーカスが移動することになります。イベントの発生順は下記のようになります。

サブフォーム上のコントロールのフォーカス喪失時(Exit)イベント

サブフォーム上のコントロールのフォーカス喪失後(LostFocus)イベント

メインフォーム上のサブフォームコントロールのフォーカス喪失時(Exit)イベント※

メインフォームの読み込み解除時(Unload)イベント

この場合も※のところで合計チェックをして不一致ならイベントをキャンセルしますが、読み込み解除時イベントは発生してしまいます。ということは合計が不一致のまま閉じてレコード保存されてしまうことになります。

それを防ぐために、読み込み解除時でも合計をチェックして不一致ならイベントをキャンセル(Cancel = True)してフォーカスをサブフォームへ戻しておきます。これで合計が不一致の場合はフォームを閉じることができなくなります。

8
ヒトシ 2024/01/29 (月) 13:00:29 ddfe5@72804

ありがとうございます。メインにコード記述したらいけました。落ち着いて考えたら分かることなのに、すみませんでした。
イベントの説明もお手数かけました。フォーム閉じる時はこれでカバーできたのですが、メインに配置してますレコード移動ボタンに対してはどう対処したらいいでしょうか? 合計が合致してない場合、移動も出来なくなる様にしたいのです。

9
ヒトシ 2024/01/29 (月) 13:20:37 ddfe5@72804

重ね重ねすみません、記述位置をミスしてました。埋め込み1_Exit***のコードをメインに記述してました。失礼しました。
これで移動も規制できました。
このフォームでメインにだけ入力してサブにはレコードが1件もない状態を回避したい場合、どうすると効果的でしょうか?(閉じたり、メインレコード移動時にメッセージを出したい)

10

3で提示したコードの条件にレコード件数が0もつけ加えるといいでしょう。

Private Sub Form_Unload(Cancel As Integer)
    If Me.埋め込み1.Form.Recordset.RecordCount = 0 Or Me.埋め込み1.Form!SumF2.Value <> Me.埋め込み1.Form!SumF4.Value Then
        Cancel = True
        Me.埋め込み1.SetFocus
    End If
End Sub

Private Sub 埋め込み1_Exit(Cancel As Integer)

    Me.埋め込み1.Form.Requery 'レコード保存
     If Me.埋め込み1.Form.Recordset.RecordCount = 0 Then
        Cancel = True
        MsgBox "明細データを1件以上入力してください"
    ElseIf Me.埋め込み1.Form!SumF2.Value <> Me.埋め込み1.Form!SumF4.Value Then
        Cancel = True
        MsgBox "F2とF4の合計が合っていません!"
    End If
End Sub

これでサブフォームのレコード件数が0のときはフォームを閉じれなくなります。

ただし、これだけではメインレコード移動は規制できません。
レコード移動時イベントでは、レコード移動した後に発生するしキャンセルできないので。

いろいろ考えてみましたが、難しそうですね。
レコード移動時イベントで、サブのレコード件数が0のメインのレコードがないかチェックして、あればそこにレコード移動するという感じでするとか、ぐらいかな。
ちょっと面倒そうですね。

11
ヒトシ 2024/01/30 (火) 12:28:18 ddfe5@72804

度々ありがとうございました。イベントの説明も大変参考になりました。個々のレコード移動時イベントにコード記述して対応してみます。お世話になりました。