プロが教えるわが家の防犯対策術!

ACCESS2000で単票系メインフォームと帳票系サブフォームを連結し、サブフォームに入力した明細(複数レコード)の金額累計(サブフォームフッターの非連結コントロール)をメイン側へ登録する処理を行っています。メイン側(マスターテーブル)への保存は保存用のコマンドボタンで行っています。サブフォーム側で完全に編集完了した場合(カーソルが次レコードの入力ラインにある)は正常に処理されますが、編集途中のレコードの金額は累計されないで保存されてしまいます。また保存コマンドボタンでサブフォームにRequeryをかけると累計金額がクリアされてしまいます。編集途中(つまり入力後エンタキーを押さないで直接コマンドボタンを押下)でもちゃんと累計されるような方法をご指導ください。よろしくお願いします。

A 回答 (6件)

#5です



基本的なデータ構成は#4でのものに、#5のサブフォームにボタン「btn01」を追加した状態。
(btn01 名がサブ・メイン両方にありますがご容赦を)

追加で、メインフォームに非連結のテキストボックス txt03 を配置しておきます。


サブフォームへ記述している内容)

Private Sub btn01_Click()
  Dim sTmp As String

  If (Me.Dirty = True) Then
'    Me.Parent.Form.txt03 = Me.txt01 ' ★1
    MsgBox "累計 : " & Me.txt01   ' ★2
    sTmp = Me.BeforeUpdate
    Me.BeforeUpdate = ""
    DoCmd.RunCommand acCmdSaveRecord
    Me.BeforeUpdate = sTmp
  End If
End Sub

Private Sub Form_AfterUpdate()
  Me.Recalc
End Sub

Private Sub Form_BeforeUpdate(Cancel As Integer)
  Cancel = True
End Sub


この状態での動きは、

サブフォーム側で編集状態になると、メイン側ボタンは押せなくなります。
ボタン btn01 (編集の確定)をクリックするまでは、他に制御が移りません。
数量または金額を打ち込んでいる最中、ボタン btn01 をクリックすると、
★2 でのメッセージ表示は最新のものになってますが、メイン側の txt02 は以前のままです。
★1 で、最新のものをメイン側に表示することができます。

ので、
> 1.サブフォーム側に展開しているレコードが複数の場合、1レコードづつ確定しなければならない
> 4.NewRecにフォーカスが移動して更新済みの場合でも場合でも更新ボタンを押す必要がある
は、その通りで #5でさらっと書きましたが、操作性は悪く?なる 部分となります。
でも、#5最後に書きましたが、複数レコードのある単票形式のフォームで、マウススクロールを無効にしているかのような処理ができます。


> 2.キャンンセルボタンも操作出来なくなる
は、サブフォーム側にボタン設置できれば以下内容でフォームを閉じることはできます。
(ボタン名を btn02 とした場合:編集中のものは反映されません)

Private Sub btn02_Click()
  DoCmd.Close acForm, Me.Parent.Name, acSaveNo
End Sub


> 3.更新前処理での入力チェックにおいてエラーの場合でも更新確定されてしまう
は、ちょっと意味がわかりませんでした。

更新前処理は2つあって、入力項目それぞれでのもの、レコードとしてのものがあります。

1)入力項目それぞれでのもの
例えば、金額の入力で 100 単位のチェックを行うものとします。

Private Sub 金額_BeforeUpdate(Cancel As Integer)
  If ((Me.金額 Mod 100) <> 0) Then
    Cancel = True
    MsgBox "100円単位で入れてください"
  End If
End Sub

とか、画面デザインでのテキストボックス(金額)のプロパティ
「入力規則」に、 ([金額] Mod 100)=0
「エラーメッセージ」に、 100円単位で入れてください

とか。(入力規則は更新前処理の直前で判別されるようです(同じ判別を両方に設定しても意味ありません))

この Cancel = True を返す、入力規則に反する場合は、その項目から他へ制御が移らないので btn01 は押せません。

2)レコードとしてのもの
Form_BeforeUpdate のことです。
今回、常に Cancel = True を返すようにしたので、従来の処理は★部分に記述します。
チェックをして OK の時に、★以下の4行を実行するようにします。


以下にイベントの発生順が記述されていますので、眺めてみてください。
http://office.microsoft.com/ja-jp/access/HA10238 …
    • good
    • 0
この回答へのお礼

ありがとうございます。

問題点1については、メインとの整合性チェック処理とCloseをサブフォーム側の編集確定処理に続けて行う事により解決出来そうですね。
(つまり、メインフォーム側には保存ボタンを設けないで、サブフォーム側だけにボタンを設ける)

問題点2につきましても、ご指摘のようにサブフォーム側にボタンを設ける事により解決出来ました。

問題点3は、私の勘違いで、ボタンの処理内にチェック処理を移す事により解決出来ました。

問題点4は、この考え方を採用する場合はどうしようもないという事ですね・・・。
この点につきましては、ユーザと調整してみます。

貴重なアドバイスを頂いて、大変勉強になりました。
とりあえず、この質問はクローズさせていただきますが、今後もまた質問させていただきますので、お目にとまりましたら、どうぞよろしくお願いします。
ありがとうございました。

お礼日時:2009/07/21 14:53

まだ閉じられていなかったので、




おまけ)

操作性は悪く?なりますが、編集中にはメインのボタンなど操作できないようにする方法もあります。

サブフォーム側に、更新/登録用のコマンドボタンを新設します。
編集後には、このボタンで確定動作を行います。
(これ以外ではレコードの更新/登録はできません)
(レコードが連結されたフォームであることが前提です)


細工1)サブフォームの更新前処理では必ず Cancel = True を返します

Private Sub Form_BeforeUpdate(Cancel As Integer)
  Cancel = True
End Sub

従来チェック処理等入れていたら、以下細工2)へ移動します。
(記述する位置は適当に)


細工2)更新/登録用ボタンでの処理(ボタン名:btn01 とした場合)

Private Sub btn01_Click()
  Dim sTmp As String

  If (Me.Dirty = True) Then
    sTmp = Me.BeforeUpdate
    Me.BeforeUpdate = ""
    DoCmd.RunCommand acCmdSaveRecord
    Me.BeforeUpdate = sTmp
  End If
End Sub

内容)編集中なら更新前処理を無効にし、レコードを保存後、更新前処理を有効に戻す。

レコードが編集中であった場合、そのレコード以外へ制御が移るのを抑止します。
(サブフォーム内のボタン等は、操作できるようです)

この方法は、マウスのスクロールでレコードが移動するのを防ぐ時にも使える方法です。
(複数レコードのある単票形式のフォームの時など)
    • good
    • 0
この回答へのお礼

なるほど、この考え方だと手動でサブフォームの更新確定を制御するわけですから、メイン側で余計なサブフォームの動きを気にする必要はなくなりますね。
さらに、サブフォーム側の処理でメインフォームとの整合性チェックなども出来ると良いのですが・・・。
ただし、以下の点が問題だと思われます。
1.サブフォーム側に展開しているレコードが複数の場合、1レコードづつ確定しなければならない
2.キャンンセルボタンも操作出来なくなる
3.更新前処理での入力チェックにおいてエラーの場合でも更新確定されてしまう
4.NewRecにフォーカスが移動して更新済みの場合でも場合でも更新ボタンを押す必要がある

このようなケースの対処法が何かあるのでしょうか?それとも私の設定ミス?

なお、サブホーム側の金額を変更した場合にはメインフォーム(マスタレコード)との整合性チェックを行いエラーの場合は、修正入力を行うか、キャンセルボタンでCloseする方法を考えています。
当然、このフォームはメイン・サブともにダミーテーブルで処理しています。

このような事を考えると、やはりRecalcでの対処法がよいのでしょうか?

色々とアドバイスを頂き非常に感謝しております。

お礼日時:2009/07/20 23:49

#3です



解決した方法は DoEvents を使ってループするものだったでしょうか。



以下、参考程度で)


テーブル名:T1
フィールド名:品名、数量、金額
レコード数:567件

サブフォーム名:F_S1
レコードソース:T1
帳票形式
フィールド名とテキストボックス名は同じ

ヘッダー部に累計用テキストボックス「txt01」を配置(書式:通貨)
コントロールソースは以下

=Sum([数量]*[金額])+(Nz([数量])*Nz([金額]))-(Nz([数量].[OldValue])*Nz([金額].[OldValue]))

フォームの更新後処理に Recalc
Private Sub Form_AfterUpdate()
  Me.Recalc
End Sub


メインフォーム名:F_M1
サブフォームコントロール名:fsub
ソースオブジェクト:F_S1
単票形式
確認用ボタン名:btn01

ボタンのクリック処理は以下
Private Sub btn01_Click()
  MsgBox "累計 : " & Me.fsub.Form.txt01
End Sub


検証)

サブフォームの編集中等にかかわらず、最終の値がメッセージボックスに表示。



追加1)メインフォームにテキストボックス txt02 (書式:通貨)を配置し、
 コントロールソースを以下

 =[fsub].[Form]![txt01]

この状態で再度検証

編集中(他に移動しない:数量または金額を打ち込んでいる最中)にボタンを押すと
txt02 は、\0 の表示となった状態でメッセージボックスが表示。
メッセージの表示内容は正しい。
メッセージボックスを閉じると、txt02 の表示が更新される。



追加2)メッセージボックス表示で、参照先を以下のように変更
Private Sub btn01_Click()
  MsgBox "累計 : " & Me.txt02
End Sub

この状態で再度検証

txt02 表示、およびメッセージボックスでの表示は正しい。
(但し、txt02 の表示は若干遅れるがメッセージボックスが表示された時には同じ)



戻り1)最初の状態に戻り、サブフォームの更新後処理 Recalc を無効にしてみる

この状態で再度検証

編集中(他に移動しない:数量または金額を打ち込んでいる最中)にボタンを押すと
編集前の累計が表示される。
メッセージボックスを閉じてから、最終結果が表示される。


以上 メインフォームの構成もわからないのに回答してました。

※ この動きは私の環境だけかもしれませんが
(Access2000+Win2k/Access2007+Vista のどちらも同じでしたけど)
    • good
    • 0
この回答へのお礼

更なる詳細なフォローアップ恐れ入ります。

私も色々と検証してきた状況はご指摘のとおりです。
DoEventsでタイミングをずらすのでも解決しますが、100%ではないように思えますので、Recalc メソッドでの処理にしました。

色々とありがとうございました。

お礼日時:2009/07/19 18:30

#2です。



解決された方法を紹介してもらえませんか。

サブフォーム側に入れた処理と、
特にメイン側-保存ボタンでのサブフォームに対しての処理内容について、
お願いします。

※保存ボタンでのサブフォームへの処理は要らなかったと思いますが
    • good
    • 0
この回答へのお礼

フォローアップありがとうございます。
色々と試してみましたが、最終的にはご指摘いただきましたRecalc メソッドで解決できました。
保存ボタンでのサブフォーム処理は参照だけになりました。

改めてありがとうございました。

お礼日時:2009/07/19 18:05

#1です



サブフォーム側のフォームの更新後処理で再計算させてみてください。

Private Sub Form_AfterUpdate()
  Me.Recalc
End Sub
    • good
    • 0
この回答へのお礼

大変ありがとうございました。
現在悩んでいた問題は解決いたしました。

新たに別途の問題が発生しましたが、これはもう少し自分なりに調査・検討して、どうしようもなくなりましたら、また質問させていただきます。

今後もよろしくお願いします。

お礼日時:2009/07/18 16:52

細かい動きは質問内容からわかりませんが、以下の応用でできる気がします。




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


そもそも

> 編集途中のレコードの金額は累計されないで保存されてしまいます

の操作を可能とさせているのかが、いまひとつ分かりません。
    • good
    • 0
この回答へのお礼

早速のご回答ありがとうございました。
長い間悩んでいたことが、少し前に進むことが出来ました。

ただ、ご紹介のサンプルで試しましたが、レコードが更新される前にフォーカスが移動すると累計も更新されますが、フォーカスが移動しない場合はやはり累計は更新されません。
金額のコントロールなので自動タブも効きませんし・・・
金額入力後フォーカスが移動しない状態でメイン側の保存ボタンで強制的にRequeryさせる方法はありませんでしょうか?
保存ボタンのクリックイベントを
   サブフォームコントロール名.SetFocus
   サブフォームコントロール名.Requery
   ---マスタとサブフォームの整合性チェック処理
   ---サブフォーム金額累計でマスター金額更新処理
というように試してみましたが、サブフォームフッターの金額累計はクリアされてしまい、チェック処理、更新処理が正常に行われませんでした。
抜けた後は、編集中のサブレコードは新規レコードとして作成され、サブフォームの表示は正しく表示されます。
  
あるいは、サブフォームの入力中レコードが完全に確定しない状態を、マスターが更新される前にエラーにする方法は無いでしょうか? 

ちなみに、編集途中のレコードを保存可能にしている理由は、最終項目をエンターキーを押下しないまま保存ボタンを押してしまうケースもあるので、入力データが正しければ保存しても良いかなと思ってそうしています。 
当然入力チェックはしています。
このようなケースを編集だという事でエラーに出来るのならばそれでもいいです。

再度、ご指導をよろしくお願いします。
 

    
 

 

お礼日時:2009/07/17 12:23

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A